1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 #include <com/sun/star/text/HoriOrientation.hpp> 28 #include <com/sun/star/chart2/XChartDocument.hpp> 29 #include <hintids.hxx> 30 31 #define _ZFORLIST_DECLARE_TABLE 32 #include <editeng/brshitem.hxx> 33 #include <editeng/lrspitem.hxx> 34 #include <editeng/protitem.hxx> 35 #include <editeng/boxitem.hxx> 36 #include <tools/fract.hxx> 37 #include <fmtfsize.hxx> 38 #include <fmtornt.hxx> 39 #include <doc.hxx> 40 #include <cntfrm.hxx> 41 #include <tabfrm.hxx> 42 #include <frmtool.hxx> 43 #include <pam.hxx> 44 #include <swtable.hxx> 45 #include <ndtxt.hxx> 46 #include <tblsel.hxx> 47 #include <fldbas.hxx> 48 #include <swundo.hxx> 49 #include <rowfrm.hxx> 50 #include <ddefld.hxx> 51 #include <hints.hxx> 52 #include <UndoTable.hxx> 53 #include <cellatr.hxx> 54 #include <mvsave.hxx> 55 #include <swtblfmt.hxx> 56 #include <swddetbl.hxx> 57 #include <poolfmt.hxx> 58 #include <tblrwcl.hxx> 59 #include <unochart.hxx> 60 #include <boost/shared_ptr.hpp> 61 #include <switerator.hxx> 62 63 using namespace com::sun::star; 64 using namespace com::sun::star::uno; 65 66 67 #define COLFUZZY 20 68 #define ROWFUZZY 10 69 70 using namespace ::com::sun::star; 71 72 #ifndef DBG_UTIL 73 #define CHECK_TABLE(t) 74 #else 75 #ifdef DEBUG 76 #define CHECK_TABLE(t) (t).CheckConsistency(); 77 #else 78 #define CHECK_TABLE(t) 79 #endif 80 #endif 81 82 typedef SwTableLine* SwTableLinePtr; 83 SV_DECL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr, 16, 16 ) 84 SV_IMPL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr ); 85 86 SV_IMPL_PTRARR( _SwShareBoxFmts, SwShareBoxFmt* ) 87 88 // fuers setzen der Frame-Formate an den Boxen reicht es, das aktuelle 89 // im Array zu suchen. Ist es vorhanden, so gebe das neue zurueck 90 struct _CpyTabFrm 91 { 92 union { 93 SwTableBoxFmt *pFrmFmt; // fuer CopyCol 94 SwTwips nSize; // fuer DelCol 95 } Value; 96 SwTableBoxFmt *pNewFrmFmt; 97 98 _CpyTabFrm( SwTableBoxFmt* pAktFrmFmt ) : pNewFrmFmt( 0 ) 99 { Value.pFrmFmt = pAktFrmFmt; } 100 101 _CpyTabFrm& operator=( const _CpyTabFrm& ); 102 103 sal_Bool operator==( const _CpyTabFrm& rCpyTabFrm ) 104 { return (sal_uLong)Value.nSize == (sal_uLong)rCpyTabFrm.Value.nSize; } 105 sal_Bool operator<( const _CpyTabFrm& rCpyTabFrm ) 106 { return (sal_uLong)Value.nSize < (sal_uLong)rCpyTabFrm.Value.nSize; } 107 }; 108 109 struct CR_SetBoxWidth 110 { 111 SwSelBoxes aBoxes; 112 SwSortTableLines aLines; 113 SvUShorts aLinesWidth; 114 SwShareBoxFmts aShareFmts; 115 SwTableNode* pTblNd; 116 SwUndoTblNdsChg* pUndo; 117 SwTwips nDiff, nSide, nMaxSize, nLowerDiff; 118 TblChgMode nMode; 119 sal_uInt16 nTblWidth, nRemainWidth, nBoxWidth; 120 sal_Bool bBigger, bLeft, bSplittBox, bAnyBoxFnd; 121 122 CR_SetBoxWidth( sal_uInt16 eType, SwTwips nDif, SwTwips nSid, SwTwips nTblW, 123 SwTwips nMax, SwTableNode* pTNd ) 124 : pTblNd( pTNd ), 125 nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 ), 126 nTblWidth( (sal_uInt16)nTblW ), nRemainWidth( 0 ), nBoxWidth( 0 ), 127 bSplittBox( sal_False ), bAnyBoxFnd( sal_False ) 128 { 129 bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) || 130 nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ); 131 bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER ); 132 nMode = pTblNd->GetTable().GetTblChgMode(); 133 } 134 CR_SetBoxWidth( const CR_SetBoxWidth& rCpy ) 135 : pTblNd( rCpy.pTblNd ), 136 pUndo( rCpy.pUndo ), 137 nDiff( rCpy.nDiff ), nSide( rCpy.nSide ), 138 nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ), 139 nMode( rCpy.nMode ), nTblWidth( rCpy.nTblWidth ), 140 nRemainWidth( rCpy.nRemainWidth ), nBoxWidth( nBoxWidth ), 141 bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft ), 142 bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd ) 143 { 144 aLines.Insert( &rCpy.aLines ); 145 aLinesWidth.Insert( &rCpy.aLinesWidth, 0 ); 146 } 147 148 SwUndoTblNdsChg* CreateUndo( SwUndoId eUndoType ) 149 { 150 return pUndo = new SwUndoTblNdsChg( eUndoType, aBoxes, *pTblNd ); 151 } 152 153 void LoopClear() 154 { 155 nLowerDiff = 0; nRemainWidth = 0; 156 } 157 158 void AddBoxWidth( const SwTableBox& rBox, sal_uInt16 nWidth ) 159 { 160 SwTableLinePtr p = (SwTableLine*)rBox.GetUpper(); 161 sal_uInt16 nFndPos; 162 if( aLines.Insert( p, nFndPos )) 163 aLinesWidth.Insert( nWidth, nFndPos ); 164 else 165 aLinesWidth[ nFndPos ] = aLinesWidth[ nFndPos ] + nWidth; 166 } 167 168 sal_uInt16 GetBoxWidth( const SwTableLine& rLn ) const 169 { 170 SwTableLinePtr p = (SwTableLine*)&rLn; 171 sal_uInt16 nFndPos; 172 if( aLines.Seek_Entry( p, &nFndPos ) ) 173 nFndPos = aLinesWidth[ nFndPos ]; 174 else 175 nFndPos = 0; 176 return nFndPos; 177 } 178 }; 179 180 sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam, 181 SwTwips nDist, sal_Bool bCheck ); 182 sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam, 183 SwTwips nDist, sal_Bool bCheck ); 184 sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, 185 SwTwips nDist, sal_Bool bCheck ); 186 sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, 187 SwTwips nDist, sal_Bool bCheck ); 188 sal_Bool lcl_DelSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, 189 SwTwips nDist, sal_Bool bCheck ); 190 sal_Bool lcl_DelOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, 191 SwTwips nDist, sal_Bool bCheck ); 192 193 typedef sal_Bool (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, sal_Bool ); 194 195 #if defined(DBG_UTIL) || defined( JP_DEBUG ) 196 197 void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize ); 198 199 #define CHECKBOXWIDTH \ 200 { \ 201 SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth(); \ 202 for( sal_uInt16 nTmp = 0; nTmp < aLines.Count(); ++nTmp ) \ 203 ::_CheckBoxWidth( *aLines[ nTmp ], nSize ); \ 204 } 205 206 #define CHECKTABLELAYOUT \ 207 { \ 208 for ( sal_uInt16 i = 0; i < GetTabLines().Count(); ++i ) \ 209 { \ 210 SwFrmFmt* pFmt = GetTabLines()[i]->GetFrmFmt(); \ 211 SwIterator<SwRowFrm,SwFmt> aIter( *pFmt ); \ 212 for (SwRowFrm* pFrm=aIter.First(); pFrm; pFrm=aIter.Next())\ 213 { \ 214 if ( pFrm->GetTabLine() == GetTabLines()[i] ) \ 215 { \ 216 ASSERT( pFrm->GetUpper()->IsTabFrm(), \ 217 "Table layout does not match table structure" ) \ 218 } \ 219 } \ 220 } \ 221 } 222 223 #else 224 225 #define CHECKBOXWIDTH 226 #define CHECKTABLELAYOUT 227 228 #endif 229 230 231 struct CR_SetLineHeight 232 { 233 SwSelBoxes aBoxes; 234 SwShareBoxFmts aShareFmts; 235 SwTableNode* pTblNd; 236 SwUndoTblNdsChg* pUndo; 237 SwTwips nMaxSpace, nMaxHeight; 238 TblChgMode nMode; 239 sal_uInt16 nLines; 240 sal_Bool bBigger, bTop, bSplittBox, bAnyBoxFnd; 241 242 CR_SetLineHeight( sal_uInt16 eType, SwTableNode* pTNd ) 243 : pTblNd( pTNd ), pUndo( 0 ), 244 nMaxSpace( 0 ), nMaxHeight( 0 ), nLines( 0 ), 245 bSplittBox( sal_False ), bAnyBoxFnd( sal_False ) 246 { 247 bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ); 248 bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER ); 249 if( eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL ) 250 bBigger = !bBigger; 251 nMode = pTblNd->GetTable().GetTblChgMode(); 252 } 253 CR_SetLineHeight( const CR_SetLineHeight& rCpy ) 254 : pTblNd( rCpy.pTblNd ), pUndo( rCpy.pUndo ), 255 nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ), 256 nMode( rCpy.nMode ), nLines( rCpy.nLines ), 257 bBigger( rCpy.bBigger ), bTop( rCpy.bTop ), 258 bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd ) 259 {} 260 261 SwUndoTblNdsChg* CreateUndo( SwUndoId nUndoType ) 262 { 263 return pUndo = new SwUndoTblNdsChg( nUndoType, aBoxes, *pTblNd ); 264 } 265 }; 266 267 sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam, 268 SwTwips nDist, sal_Bool bCheck ); 269 sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam, 270 SwTwips nDist, sal_Bool bCheck ); 271 sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam, 272 SwTwips nDist, sal_Bool bCheck ); 273 274 typedef sal_Bool (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, sal_Bool ); 275 276 _CpyTabFrm& _CpyTabFrm::operator=( const _CpyTabFrm& rCpyTabFrm ) 277 { 278 pNewFrmFmt = rCpyTabFrm.pNewFrmFmt; 279 Value = rCpyTabFrm.Value; 280 return *this; 281 } 282 283 SV_DECL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm, 0, 50 ) 284 SV_IMPL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm ) 285 286 void lcl_DelCpyTabFrmFmts( _CpyTabFrm& rArr ); 287 288 // --------------------------------------------------------------- 289 290 struct _CpyPara 291 { 292 boost::shared_ptr< std::vector< std::vector< sal_uLong > > > pWidths; 293 SwDoc* pDoc; 294 SwTableNode* pTblNd; 295 _CpyTabFrms& rTabFrmArr; 296 SwTableLine* pInsLine; 297 SwTableBox* pInsBox; 298 sal_uLong nOldSize, nNewSize; // zum Korrigieren der Size-Attribute 299 sal_uLong nMinLeft, nMaxRight; 300 sal_uInt16 nCpyCnt, nInsPos; 301 sal_uInt16 nLnIdx, nBoxIdx; 302 sal_uInt8 nDelBorderFlag; 303 sal_Bool bCpyCntnt; 304 305 _CpyPara( SwTableNode* pNd, sal_uInt16 nCopies, _CpyTabFrms& rFrmArr, 306 sal_Bool bCopyContent = sal_True ) 307 : pDoc( pNd->GetDoc() ), pTblNd( pNd ), rTabFrmArr(rFrmArr), 308 pInsLine(0), pInsBox(0), nOldSize(0), nNewSize(0), 309 nMinLeft(ULONG_MAX), nMaxRight(0), 310 nCpyCnt(nCopies), nInsPos(0), 311 nLnIdx(0), nBoxIdx(0), 312 nDelBorderFlag(0), bCpyCntnt( bCopyContent ) 313 {} 314 _CpyPara( const _CpyPara& rPara, SwTableLine* pLine ) 315 : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd), 316 rTabFrmArr(rPara.rTabFrmArr), pInsLine(pLine), pInsBox(rPara.pInsBox), 317 nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ), 318 nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0), 319 nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ), 320 nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt ) 321 {} 322 _CpyPara( const _CpyPara& rPara, SwTableBox* pBox ) 323 : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd), 324 rTabFrmArr(rPara.rTabFrmArr), pInsLine(rPara.pInsLine), pInsBox(pBox), 325 nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize), 326 nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ), 327 nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx), 328 nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt ) 329 {} 330 void SetBoxWidth( SwTableBox* pBox ); 331 }; 332 333 334 sal_Bool lcl_CopyCol( const _FndBox*& rpFndBox, void* pPara ) 335 { 336 _CpyPara* pCpyPara = (_CpyPara*)pPara; 337 338 // suche das FrmFmt im Array aller Frame-Formate 339 SwTableBox* pBox = (SwTableBox*)rpFndBox->GetBox(); 340 _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pBox->GetFrmFmt() ); 341 342 sal_uInt16 nFndPos; 343 if( pCpyPara->nCpyCnt ) 344 { 345 if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos )) 346 { 347 // fuer das verschachtelte Kopieren sicher auch das neue Format 348 // als alt. 349 SwTableBoxFmt* pNewFmt = (SwTableBoxFmt*)pBox->ClaimFrmFmt(); 350 351 // suche die selektierten Boxen in der Line: 352 _FndLine* pCmpLine = NULL; 353 SwFmtFrmSize aFrmSz( pNewFmt->GetFrmSize() ); 354 355 bool bDiffCount = false; 356 if( pBox->GetTabLines().Count() ) 357 { 358 pCmpLine = rpFndBox->GetLines()[ 0 ]; 359 if ( pCmpLine->GetBoxes().Count() != pCmpLine->GetLine()->GetTabBoxes().Count() ) 360 bDiffCount = true; 361 } 362 363 if( bDiffCount ) 364 { 365 // die erste Line sollte reichen 366 _FndBoxes& rFndBoxes = pCmpLine->GetBoxes(); 367 long nSz = 0; 368 for( sal_uInt16 n = rFndBoxes.Count(); n; ) 369 nSz += rFndBoxes[ --n ]->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth(); 370 aFrmSz.SetWidth( aFrmSz.GetWidth() - 371 nSz / ( pCpyPara->nCpyCnt + 1 ) ); 372 pNewFmt->SetFmtAttr( aFrmSz ); 373 aFrmSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) ); 374 375 // fuer die neue Box ein neues Format mit der Groesse anlegen! 376 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pNewFmt->GetDoc()-> 377 MakeTableLineFmt(); 378 *aFindFrm.pNewFrmFmt = *pNewFmt; 379 aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz ); 380 } 381 else 382 { 383 aFrmSz.SetWidth( aFrmSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) ); 384 pNewFmt->SetFmtAttr( aFrmSz ); 385 386 aFindFrm.pNewFrmFmt = pNewFmt; 387 pCpyPara->rTabFrmArr.Insert( aFindFrm ); 388 aFindFrm.Value.pFrmFmt = pNewFmt; 389 pCpyPara->rTabFrmArr.Insert( aFindFrm ); 390 } 391 } 392 else 393 { 394 aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]; 395 // aFindFrm.pNewFrmFmt->Add( pBox ); 396 pBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt ); 397 } 398 } 399 else 400 { 401 if( pCpyPara->nDelBorderFlag && 402 pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos )) 403 aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]; 404 else 405 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt(); 406 } 407 408 if( rpFndBox->GetLines().Count() ) 409 { 410 pBox = new SwTableBox( aFindFrm.pNewFrmFmt, 411 rpFndBox->GetLines().Count(), pCpyPara->pInsLine ); 412 pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++); 413 _CpyPara aPara( *pCpyPara, pBox ); 414 aPara.nDelBorderFlag &= 7; 415 416 ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyRow, &aPara ); 417 } 418 else 419 { 420 ::_InsTblBox( pCpyPara->pDoc, pCpyPara->pTblNd, pCpyPara->pInsLine, 421 aFindFrm.pNewFrmFmt, pBox, pCpyPara->nInsPos++ ); 422 423 const _FndBoxes& rFndBxs = rpFndBox->GetUpper()->GetBoxes(); 424 if( 8 > pCpyPara->nDelBorderFlag 425 ? pCpyPara->nDelBorderFlag 426 : rpFndBox == rFndBxs[ rFndBxs.Count() - 1 ] ) 427 { 428 const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox(); 429 if( 8 > pCpyPara->nDelBorderFlag 430 ? rBoxItem.GetTop() 431 : rBoxItem.GetRight() ) 432 { 433 aFindFrm.Value.pFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt(); 434 435 SvxBoxItem aNew( rBoxItem ); 436 if( 8 > pCpyPara->nDelBorderFlag ) 437 aNew.SetLine( 0, BOX_LINE_TOP ); 438 else 439 aNew.SetLine( 0, BOX_LINE_RIGHT ); 440 441 if( 1 == pCpyPara->nDelBorderFlag || 442 8 == pCpyPara->nDelBorderFlag ) 443 { 444 // es wird dahinter kopiert, bei allen Boxen die 445 // TopBorderLine loeschen 446 pBox = pCpyPara->pInsLine->GetTabBoxes()[ 447 pCpyPara->nInsPos - 1 ]; 448 } 449 450 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt(); 451 452 // ansonsten wird davor kopiert und die erste Line behaelt 453 // die TopLine und an der originalen wird sie entfernt 454 pBox->ClaimFrmFmt()->SetFmtAttr( aNew ); 455 456 if( !pCpyPara->nCpyCnt ) 457 pCpyPara->rTabFrmArr.Insert( aFindFrm ); 458 } 459 } 460 } 461 return sal_True; 462 } 463 464 sal_Bool lcl_CopyRow( const _FndLine*& rpFndLine, void* pPara ) 465 { 466 _CpyPara* pCpyPara = (_CpyPara*)pPara; 467 SwTableLine* pNewLine = new SwTableLine( 468 (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(), 469 rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox ); 470 if( pCpyPara->pInsBox ) 471 { 472 pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ ); 473 } 474 else 475 { 476 pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine, 477 pCpyPara->nInsPos++ ); 478 } 479 480 _CpyPara aPara( *pCpyPara, pNewLine ); 481 ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyCol, &aPara ); 482 483 pCpyPara->nDelBorderFlag &= 0xf8; 484 return sal_True; 485 } 486 487 //----------------------------------------------------------- 488 489 void lcl_InsCol( _FndLine* pFndLn, _CpyPara& rCpyPara, sal_uInt16 nCpyCnt, 490 sal_Bool bBehind ) 491 { 492 // Bug 29124: nicht nur in den Grundlines kopieren. Wenns geht, so weit 493 // runter wie moeglich. 494 _FndBox* pFBox; 495 if( 1 == pFndLn->GetBoxes().Count() && 496 !( pFBox = pFndLn->GetBoxes()[ 0 ] )->GetBox()->GetSttNd() ) 497 { 498 // eine Box mit mehreren Lines, also in diese Lines einfuegen 499 for( sal_uInt16 n = 0; n < pFBox->GetLines().Count(); ++n ) 500 lcl_InsCol( pFBox->GetLines()[ n ], rCpyPara, nCpyCnt, bBehind ); 501 } 502 else 503 { 504 rCpyPara.pInsLine = pFndLn->GetLine(); 505 SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ? 506 pFndLn->GetBoxes().Count()-1 : 0 ]->GetBox(); 507 rCpyPara.nInsPos = pFndLn->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pBox ); 508 if( bBehind ) 509 ++rCpyPara.nInsPos; 510 511 for( sal_uInt16 n = 0; n < nCpyCnt; ++n ) 512 { 513 if( n + 1 == nCpyCnt && bBehind ) 514 rCpyPara.nDelBorderFlag = 9; 515 else 516 rCpyPara.nDelBorderFlag = 8; 517 pFndLn->GetBoxes().ForEach( &lcl_CopyCol, &rCpyPara ); 518 } 519 } 520 } 521 522 SwRowFrm* GetRowFrm( SwTableLine& rLine ) 523 { 524 SwIterator<SwRowFrm,SwFmt> aIter( *rLine.GetFrmFmt() ); 525 for( SwRowFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() ) 526 if( pFrm->GetTabLine() == &rLine ) 527 return pFrm; 528 return 0; 529 } 530 531 532 sal_Bool SwTable::InsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind ) 533 { 534 ASSERT( rBoxes.Count() && nCnt, "keine gueltige Box-Liste" ); 535 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); 536 if( !pTblNd ) 537 return sal_False; 538 539 sal_Bool bRes = sal_True; 540 if( IsNewModel() ) 541 bRes = NewInsertCol( pDoc, rBoxes, nCnt, bBehind ); 542 else 543 { 544 // suche alle Boxen / Lines 545 _FndBox aFndBox( 0, 0 ); 546 { 547 _FndPara aPara( rBoxes, &aFndBox ); 548 GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); 549 } 550 if( !aFndBox.GetLines().Count() ) 551 return sal_False; 552 553 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 554 555 //Lines fuer das Layout-Update herausuchen. 556 aFndBox.SetTableLines( *this ); 557 aFndBox.DelFrms( *this ); 558 559 // TL_CHART2: nothing to be done since chart2 currently does not want to 560 // get notified about new rows/cols. 561 562 _CpyTabFrms aTabFrmArr; 563 _CpyPara aCpyPara( pTblNd, nCnt, aTabFrmArr ); 564 565 for( sal_uInt16 n = 0; n < aFndBox.GetLines().Count(); ++n ) 566 lcl_InsCol( aFndBox.GetLines()[ n ], aCpyPara, nCnt, bBehind ); 567 568 // dann raeume die Struktur dieser Line noch mal auf, generell alle 569 GCLines(); 570 571 //Layout updaten 572 aFndBox.MakeFrms( *this ); 573 574 CHECKBOXWIDTH 575 CHECKTABLELAYOUT 576 bRes = sal_True; 577 } 578 579 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); 580 if (pPCD && nCnt) 581 pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind ); 582 pDoc->UpdateCharts( GetFrmFmt()->GetName() ); 583 584 return bRes; 585 } 586 587 sal_Bool SwTable::_InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, 588 sal_uInt16 nCnt, sal_Bool bBehind ) 589 { 590 ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltige Box-Liste" ); 591 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); 592 if( !pTblNd ) 593 return sal_False; 594 595 // suche alle Boxen / Lines 596 _FndBox aFndBox( 0, 0 ); 597 { 598 _FndPara aPara( rBoxes, &aFndBox ); 599 GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); 600 } 601 if( !aFndBox.GetLines().Count() ) 602 return sal_False; 603 604 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 605 606 _FndBox* pFndBox = &aFndBox; 607 { 608 _FndLine* pFndLine; 609 while( 1 == pFndBox->GetLines().Count() && 610 1 == ( pFndLine = pFndBox->GetLines()[ 0 ])->GetBoxes().Count() ) 611 { 612 // nicht zu weit runter, eine Line mit Boxen muss nachbleiben!! 613 _FndBox* pTmpBox = pFndLine->GetBoxes()[ 0 ]; 614 if( pTmpBox->GetLines().Count() ) 615 pFndBox = pTmpBox; 616 else 617 break; 618 } 619 } 620 621 //Lines fuer das Layout-Update herausuchen. 622 const sal_Bool bLayout = !IsNewModel() && 623 0 != SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() ); 624 625 if ( bLayout ) 626 { 627 aFndBox.SetTableLines( *this ); 628 if( pFndBox != &aFndBox ) 629 aFndBox.DelFrms( *this ); 630 // TL_CHART2: nothing to be done since chart2 currently does not want to 631 // get notified about new rows/cols. 632 } 633 634 _CpyTabFrms aTabFrmArr; 635 _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr ); 636 637 SwTableLine* pLine = pFndBox->GetLines()[ bBehind ? 638 pFndBox->GetLines().Count()-1 : 0 ]->GetLine(); 639 if( &aFndBox == pFndBox ) 640 aCpyPara.nInsPos = GetTabLines().C40_GETPOS( SwTableLine, pLine ); 641 else 642 { 643 aCpyPara.pInsBox = pFndBox->GetBox(); 644 aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().C40_GETPOS( SwTableLine, pLine ); 645 } 646 647 if( bBehind ) 648 { 649 ++aCpyPara.nInsPos; 650 aCpyPara.nDelBorderFlag = 1; 651 } 652 else 653 aCpyPara.nDelBorderFlag = 2; 654 655 for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt ) 656 { 657 if( bBehind ) 658 aCpyPara.nDelBorderFlag = 1; 659 pFndBox->GetLines().ForEach( &lcl_CopyRow, &aCpyPara ); 660 } 661 662 // dann raeume die Struktur dieser Line noch mal auf, generell alle 663 if( !pDoc->IsInReading() ) 664 GCLines(); 665 666 //Layout updaten 667 if ( bLayout ) 668 { 669 if( pFndBox != &aFndBox ) 670 aFndBox.MakeFrms( *this ); 671 else 672 aFndBox.MakeNewFrms( *this, nCnt, bBehind ); 673 } 674 675 CHECKBOXWIDTH 676 CHECKTABLELAYOUT 677 678 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); 679 if (pPCD && nCnt) 680 pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind ); 681 pDoc->UpdateCharts( GetFrmFmt()->GetName() ); 682 683 return sal_True; 684 } 685 686 sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara ); 687 688 sal_Bool _FndBoxAppendRowBox( const SwTableBox*& rpBox, void* pPara ) 689 { 690 _FndPara* pFndPara = (_FndPara*)pPara; 691 _FndBox* pFndBox = new _FndBox( (SwTableBox*)rpBox, pFndPara->pFndLine ); 692 if( rpBox->GetTabLines().Count() ) 693 { 694 _FndPara aPara( *pFndPara, pFndBox ); 695 pFndBox->GetBox()->GetTabLines().ForEach( &_FndBoxAppendRowLine, &aPara ); 696 if( !pFndBox->GetLines().Count() ) 697 delete pFndBox; 698 } 699 else 700 pFndPara->pFndLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, 701 pFndPara->pFndLine->GetBoxes().Count() ); 702 return sal_True; 703 } 704 705 sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara ) 706 { 707 _FndPara* pFndPara = (_FndPara*)pPara; 708 _FndLine* pFndLine = new _FndLine( (SwTableLine*)rpLine, pFndPara->pFndBox ); 709 _FndPara aPara( *pFndPara, pFndLine ); 710 pFndLine->GetLine()->GetTabBoxes().ForEach( &_FndBoxAppendRowBox, &aPara ); 711 if( pFndLine->GetBoxes().Count() ) 712 { 713 pFndPara->pFndBox->GetLines().C40_INSERT( _FndLine, pFndLine, 714 pFndPara->pFndBox->GetLines().Count() ); 715 } 716 else 717 delete pFndLine; 718 return sal_True; 719 } 720 721 722 sal_Bool SwTable::AppendRow( SwDoc* pDoc, sal_uInt16 nCnt ) 723 { 724 SwTableNode* pTblNd = (SwTableNode*)aSortCntBoxes[0]->GetSttNd()->FindTableNode(); 725 if( !pTblNd ) 726 return sal_False; 727 728 // suche alle Boxen / Lines 729 _FndBox aFndBox( 0, 0 ); 730 { 731 const SwTableLine* pLLine = GetTabLines()[ GetTabLines().Count()-1 ]; 732 733 const SwSelBoxes* pBxs = 0; // Dummy !!! 734 _FndPara aPara( *pBxs, &aFndBox ); 735 736 _FndBoxAppendRowLine( pLLine, &aPara ); 737 } 738 if( !aFndBox.GetLines().Count() ) 739 return sal_False; 740 741 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 742 743 //Lines fuer das Layout-Update herausuchen. 744 bool bLayout = 0 != SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() ); 745 if( bLayout ) 746 { 747 aFndBox.SetTableLines( *this ); 748 // TL_CHART2: nothing to be done since chart2 currently does not want to 749 // get notified about new rows/cols. 750 } 751 752 _CpyTabFrms aTabFrmArr; 753 _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr ); 754 aCpyPara.nInsPos = GetTabLines().Count(); 755 aCpyPara.nDelBorderFlag = 1; 756 757 for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt ) 758 { 759 aCpyPara.nDelBorderFlag = 1; 760 aFndBox.GetLines().ForEach( &lcl_CopyRow, &aCpyPara ); 761 } 762 763 // dann raeume die Struktur dieser Line noch mal auf, generell alle 764 if( !pDoc->IsInReading() ) 765 GCLines(); 766 767 //Layout updaten 768 if ( bLayout ) 769 { 770 aFndBox.MakeNewFrms( *this, nCnt, sal_True ); 771 } 772 // TL_CHART2: need to inform chart of probably changed cell names 773 pDoc->UpdateCharts( GetFrmFmt()->GetName() ); 774 775 CHECKBOXWIDTH 776 CHECKTABLELAYOUT 777 778 return sal_True; 779 } 780 781 782 void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset, 783 sal_Bool bFirst, SwShareBoxFmts& rShareFmts ); 784 785 void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const long nOffset, 786 sal_Bool bFirst, SwShareBoxFmts& rShareFmts ) 787 { 788 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 789 ::lcl_LastBoxSetWidth( rLines[i]->GetTabBoxes(), nOffset, bFirst, 790 rShareFmts ); 791 } 792 793 void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset, 794 sal_Bool bFirst, SwShareBoxFmts& rShareFmts ) 795 { 796 SwTableBox& rBox = *rBoxes[ bFirst ? 0 : rBoxes.Count() - 1 ]; 797 if( !rBox.GetSttNd() ) 798 ::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset, 799 bFirst, rShareFmts ); 800 801 //Die Box anpassen 802 SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(); 803 SwFmtFrmSize aNew( pBoxFmt->GetFrmSize() ); 804 aNew.SetWidth( aNew.GetWidth() + nOffset ); 805 SwFrmFmt *pFmt = rShareFmts.GetFormat( *pBoxFmt, aNew ); 806 if( pFmt ) 807 rBox.ChgFrmFmt( (SwTableBoxFmt*)pFmt ); 808 else 809 { 810 pFmt = rBox.ClaimFrmFmt(); 811 812 pFmt->LockModify(); 813 pFmt->SetFmtAttr( aNew ); 814 pFmt->UnlockModify(); 815 816 rShareFmts.AddFormat( *pBoxFmt, *pFmt ); 817 } 818 } 819 820 void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* pUndo, 821 sal_Bool bCalcNewSize, const sal_Bool bCorrBorder, 822 SwShareBoxFmts* pShareFmts ) 823 { 824 do { 825 SwTwips nBoxSz = bCalcNewSize ? 826 pBox->GetFrmFmt()->GetFrmSize().GetWidth() : 0; 827 SwTableLine* pLine = pBox->GetUpper(); 828 SwTableBoxes& rTblBoxes = pLine->GetTabBoxes(); 829 sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox ); 830 SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper(); 831 832 // Sonderbehandlung fuer Umrandung: 833 if( bCorrBorder && 1 < rTblBoxes.Count() ) 834 { 835 sal_Bool bChgd = sal_False; 836 const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox(); 837 838 if( rBoxItem.GetLeft() || rBoxItem.GetRight() ) 839 { 840 //JP 02.04.97: 1.Teil fuer Bug 36271 841 // zuerst die linken/rechten Kanten 842 if( nDelPos + 1 < rTblBoxes.Count() ) 843 { 844 SwTableBox* pNxtBox = rTblBoxes[ nDelPos + 1 ]; 845 const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox(); 846 847 SwTableBox* pPrvBox = nDelPos ? rTblBoxes[ nDelPos - 1 ] : 0; 848 849 if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() && 850 ( !pPrvBox || !pPrvBox->GetFrmFmt()->GetBox().GetRight()) ) 851 { 852 SvxBoxItem aTmp( rNxtBoxItem ); 853 aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft() 854 : rBoxItem.GetRight(), 855 BOX_LINE_LEFT ); 856 if( pShareFmts ) 857 pShareFmts->SetAttr( *pNxtBox, aTmp ); 858 else 859 pNxtBox->ClaimFrmFmt()->SetFmtAttr( aTmp ); 860 bChgd = sal_True; 861 } 862 } 863 if( !bChgd && nDelPos ) 864 { 865 SwTableBox* pPrvBox = rTblBoxes[ nDelPos - 1 ]; 866 const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox(); 867 868 SwTableBox* pNxtBox = nDelPos + 1 < rTblBoxes.Count() 869 ? rTblBoxes[ nDelPos + 1 ] : 0; 870 871 if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() && 872 ( !pNxtBox || !pNxtBox->GetFrmFmt()->GetBox().GetLeft()) ) 873 { 874 SvxBoxItem aTmp( rPrvBoxItem ); 875 aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft() 876 : rBoxItem.GetRight(), 877 BOX_LINE_RIGHT ); 878 if( pShareFmts ) 879 pShareFmts->SetAttr( *pPrvBox, aTmp ); 880 else 881 pPrvBox->ClaimFrmFmt()->SetFmtAttr( aTmp ); 882 } 883 } 884 } 885 886 } 887 888 // erst die Box, dann die Nodes loeschen!! 889 SwStartNode* pSttNd = (SwStartNode*)pBox->GetSttNd(); 890 if( pShareFmts ) 891 pShareFmts->RemoveFormat( *rTblBoxes[ nDelPos ]->GetFrmFmt() ); 892 rTblBoxes.DeleteAndDestroy( nDelPos ); 893 894 if( pSttNd ) 895 { 896 // ist das UndoObject zum speichern der Section vorbereitet? 897 if( pUndo && pUndo->IsDelBox() ) 898 ((SwUndoTblNdsChg*)pUndo)->SaveSection( pSttNd ); 899 else 900 pSttNd->GetDoc()->DeleteSection( pSttNd ); 901 } 902 903 // auch die Zeile noch loeschen ?? 904 if( rTblBoxes.Count() ) 905 { 906 // dann passe noch die Frame-SSize an 907 sal_Bool bLastBox = nDelPos == rTblBoxes.Count(); 908 if( bLastBox ) 909 --nDelPos; 910 pBox = rTblBoxes[nDelPos]; 911 if( bCalcNewSize ) 912 { 913 SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() ); 914 aNew.SetWidth( aNew.GetWidth() + nBoxSz ); 915 if( pShareFmts ) 916 pShareFmts->SetSize( *pBox, aNew ); 917 else 918 pBox->ClaimFrmFmt()->SetFmtAttr( aNew ); 919 920 if( !pBox->GetSttNd() ) 921 { 922 // dann muss es auch rekursiv in allen Zeilen, in allen 923 // Zellen erfolgen! 924 SwShareBoxFmts aShareFmts; 925 ::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz, 926 !bLastBox, 927 pShareFmts ? *pShareFmts 928 : aShareFmts ); 929 } 930 } 931 break; // nichts mehr loeschen 932 } 933 // loesche die Line aus Tabelle/Box 934 if( !pUpperBox ) 935 { 936 // dann loesche auch noch die Line aus der Tabelle 937 nDelPos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine ); 938 if( pShareFmts ) 939 pShareFmts->RemoveFormat( *rTbl.GetTabLines()[ nDelPos ]->GetFrmFmt() ); 940 rTbl.GetTabLines().DeleteAndDestroy( nDelPos ); 941 break; // mehr kann nicht geloescht werden 942 } 943 944 // dann loesche auch noch die Line 945 pBox = pUpperBox; 946 nDelPos = pBox->GetTabLines().C40_GETPOS( SwTableLine, pLine ); 947 if( pShareFmts ) 948 pShareFmts->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrmFmt() ); 949 pBox->GetTabLines().DeleteAndDestroy( nDelPos ); 950 } while( !pBox->GetTabLines().Count() ); 951 } 952 953 SwTableBox* lcl_FndNxtPrvDelBox( const SwTableLines& rTblLns, 954 SwTwips nBoxStt, SwTwips nBoxWidth, 955 sal_uInt16 nLinePos, sal_Bool bNxt, 956 SwSelBoxes* pAllDelBoxes, sal_uInt16* pCurPos ) 957 { 958 SwTableBox* pFndBox = 0; 959 do { 960 if( bNxt ) 961 ++nLinePos; 962 else 963 --nLinePos; 964 SwTableLine* pLine = rTblLns[ nLinePos ]; 965 SwTwips nFndBoxWidth = 0; 966 SwTwips nFndWidth = nBoxStt + nBoxWidth; 967 sal_uInt16 nBoxCnt = pLine->GetTabBoxes().Count(); 968 969 pFndBox = pLine->GetTabBoxes()[ 0 ]; 970 for( sal_uInt16 n = 0; 0 < nFndWidth && n < nBoxCnt; ++n ) 971 { 972 pFndBox = pLine->GetTabBoxes()[ n ]; 973 nFndWidth -= (nFndBoxWidth = pFndBox->GetFrmFmt()-> 974 GetFrmSize().GetWidth()); 975 } 976 977 // suche die erste ContentBox 978 while( !pFndBox->GetSttNd() ) 979 { 980 const SwTableLines& rLowLns = pFndBox->GetTabLines(); 981 if( bNxt ) 982 pFndBox = rLowLns[ 0 ]->GetTabBoxes()[ 0 ]; 983 else 984 pFndBox = rLowLns[ rLowLns.Count() - 1 ]->GetTabBoxes()[ 0 ]; 985 } 986 987 if( Abs( nFndWidth ) > COLFUZZY || 988 Abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY ) 989 pFndBox = 0; 990 else if( pAllDelBoxes ) 991 { 992 // falls der Vorganger auch geloscht wird, ist nicht zu tun 993 sal_uInt16 nFndPos; 994 if( !pAllDelBoxes->Seek_Entry( pFndBox, &nFndPos ) ) 995 break; 996 997 // sonst noch mal weitersuchen 998 // Die Box muessen wir aber nicht nochmal abpruefen 999 pFndBox = 0; 1000 if( nFndPos <= *pCurPos ) 1001 --*pCurPos; 1002 pAllDelBoxes->Remove( nFndPos ); 1003 } 1004 } while( bNxt ? ( nLinePos + 1 < rTblLns.Count() ) : nLinePos ); 1005 return pFndBox; 1006 } 1007 1008 void lcl_SaveUpperLowerBorder( SwTable& rTbl, const SwTableBox& rBox, 1009 SwShareBoxFmts& rShareFmts, 1010 SwSelBoxes* pAllDelBoxes = 0, 1011 sal_uInt16* pCurPos = 0 ) 1012 { 1013 //JP 16.04.97: 2.Teil fuer Bug 36271 1014 sal_Bool bChgd = sal_False; 1015 const SwTableLine* pLine = rBox.GetUpper(); 1016 const SwTableBoxes& rTblBoxes = pLine->GetTabBoxes(); 1017 const SwTableBox* pUpperBox = &rBox; 1018 sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pUpperBox ); 1019 pUpperBox = rBox.GetUpper()->GetUpper(); 1020 const SvxBoxItem& rBoxItem = rBox.GetFrmFmt()->GetBox(); 1021 1022 // dann die unteren/oberen Kanten 1023 if( rBoxItem.GetTop() || rBoxItem.GetBottom() ) 1024 { 1025 bChgd = sal_False; 1026 const SwTableLines* pTblLns; 1027 if( pUpperBox ) 1028 pTblLns = &pUpperBox->GetTabLines(); 1029 else 1030 pTblLns = &rTbl.GetTabLines(); 1031 1032 sal_uInt16 nLnPos = pTblLns->GetPos( pLine ); 1033 1034 // bestimme die Attr.Position der akt. zu loeschenden Box 1035 // und suche dann in der unteren / oberen Line die entspr. 1036 // Gegenstuecke 1037 SwTwips nBoxStt = 0; 1038 for( sal_uInt16 n = 0; n < nDelPos; ++n ) 1039 nBoxStt += rTblBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth(); 1040 SwTwips nBoxWidth = rBox.GetFrmFmt()->GetFrmSize().GetWidth(); 1041 1042 SwTableBox *pPrvBox = 0, *pNxtBox = 0; 1043 if( nLnPos ) // Vorgaenger? 1044 pPrvBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth, 1045 nLnPos, sal_False, pAllDelBoxes, pCurPos ); 1046 1047 if( nLnPos + 1 < pTblLns->Count() ) // Nachfolger? 1048 pNxtBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth, 1049 nLnPos, sal_True, pAllDelBoxes, pCurPos ); 1050 1051 if( pNxtBox && pNxtBox->GetSttNd() ) 1052 { 1053 const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox(); 1054 if( !rNxtBoxItem.GetTop() && ( !pPrvBox || 1055 !pPrvBox->GetFrmFmt()->GetBox().GetBottom()) ) 1056 { 1057 SvxBoxItem aTmp( rNxtBoxItem ); 1058 aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop() 1059 : rBoxItem.GetBottom(), 1060 BOX_LINE_TOP ); 1061 rShareFmts.SetAttr( *pNxtBox, aTmp ); 1062 bChgd = sal_True; 1063 } 1064 } 1065 if( !bChgd && pPrvBox && pPrvBox->GetSttNd() ) 1066 { 1067 const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox(); 1068 if( !rPrvBoxItem.GetTop() && ( !pNxtBox || 1069 !pNxtBox->GetFrmFmt()->GetBox().GetTop()) ) 1070 { 1071 SvxBoxItem aTmp( rPrvBoxItem ); 1072 aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop() 1073 : rBoxItem.GetBottom(), 1074 BOX_LINE_BOTTOM ); 1075 rShareFmts.SetAttr( *pPrvBox, aTmp ); 1076 } 1077 } 1078 1079 } 1080 } 1081 1082 1083 sal_Bool SwTable::DeleteSel( 1084 SwDoc* pDoc 1085 , 1086 const SwSelBoxes& rBoxes, 1087 const SwSelBoxes* pMerged, SwUndo* pUndo, 1088 const sal_Bool bDelMakeFrms, const sal_Bool bCorrBorder ) 1089 { 1090 ASSERT( pDoc, "No doc?" ); 1091 SwTableNode* pTblNd = 0; 1092 if( rBoxes.Count() ) 1093 { 1094 pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); 1095 if( !pTblNd ) 1096 return sal_False; 1097 } 1098 1099 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 1100 1101 //Lines fuer das Layout-Update herausuchen. 1102 _FndBox aFndBox( 0, 0 ); 1103 if ( bDelMakeFrms ) 1104 { 1105 if( pMerged && pMerged->Count() ) 1106 aFndBox.SetTableLines( *pMerged, *this ); 1107 else if( rBoxes.Count() ) 1108 aFndBox.SetTableLines( rBoxes, *this ); 1109 aFndBox.DelFrms( *this ); 1110 } 1111 1112 SwShareBoxFmts aShareFmts; 1113 1114 // erst die Umrandung umsetzen, dann loeschen 1115 if( bCorrBorder ) 1116 { 1117 SwSelBoxes aBoxes; 1118 aBoxes.Insert( &rBoxes ); 1119 for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n ) 1120 ::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFmts, 1121 &aBoxes, &n ); 1122 } 1123 1124 PrepareDelBoxes( rBoxes ); 1125 1126 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); 1127 // 1128 // delete boxes from last to first 1129 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 1130 { 1131 sal_uInt16 nIdx = rBoxes.Count() - 1 - n; 1132 1133 // first adapt the data-sequence for chart if necessary 1134 // (needed to move the implementation cursor properly to it's new 1135 // position which can't be done properly if the cell is already gone) 1136 if (pPCD && pTblNd) 1137 pPCD->DeleteBox( &pTblNd->GetTable(), *rBoxes[nIdx] ); 1138 1139 // ... then delete the boxes 1140 _DeleteBox( *this, rBoxes[nIdx], pUndo, sal_True, bCorrBorder, &aShareFmts ); 1141 } 1142 1143 // dann raeume die Struktur aller Lines auf 1144 GCLines(); 1145 1146 if( bDelMakeFrms && aFndBox.AreLinesToRestore( *this ) ) 1147 aFndBox.MakeFrms( *this ); 1148 1149 // TL_CHART2: now inform chart that sth has changed 1150 pDoc->UpdateCharts( GetFrmFmt()->GetName() ); 1151 1152 CHECKTABLELAYOUT 1153 CHECK_TABLE( *this ) 1154 1155 return sal_True; 1156 } 1157 1158 1159 // --------------------------------------------------------------- 1160 1161 sal_Bool SwTable::OldSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, 1162 sal_Bool bSameHeight ) 1163 { 1164 ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" ); 1165 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); 1166 if( !pTblNd ) 1167 return sal_False; 1168 1169 // TL_CHART2: splitting/merging of a number of cells or rows will usually make 1170 // the table to complex to be handled with chart. 1171 // Thus we tell the charts to use their own data provider and forget about this table 1172 pDoc->CreateChartInternalDataProviders( this ); 1173 1174 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 1175 1176 // If the rows should get the same (min) height, we first have 1177 // to store the old row heights before deleting the frames 1178 long* pRowHeights = 0; 1179 if ( bSameHeight ) 1180 { 1181 pRowHeights = new long[ rBoxes.Count() ]; 1182 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 1183 { 1184 SwTableBox* pSelBox = *( rBoxes.GetData() + n ); 1185 const SwRowFrm* pRow = GetRowFrm( *pSelBox->GetUpper() ); 1186 ASSERT( pRow, "wo ist der Frm von der SwTableLine?" ) 1187 SWRECTFN( pRow ) 1188 pRowHeights[ n ] = (pRow->Frm().*fnRect->fnGetHeight)(); 1189 } 1190 } 1191 1192 //Lines fuer das Layout-Update herausuchen. 1193 _FndBox aFndBox( 0, 0 ); 1194 aFndBox.SetTableLines( rBoxes, *this ); 1195 aFndBox.DelFrms( *this ); 1196 1197 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 1198 { 1199 SwTableBox* pSelBox = *( rBoxes.GetData() + n ); 1200 ASSERT( pSelBox, "Box steht nicht in der Tabelle" ); 1201 1202 // dann fuege in die Box nCnt neue Zeilen ein 1203 SwTableLine* pInsLine = pSelBox->GetUpper(); 1204 SwTableBoxFmt* pFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt(); 1205 1206 // Hoehe der Line beachten, gegebenenfalls neu setzen 1207 SwFmtFrmSize aFSz( pInsLine->GetFrmFmt()->GetFrmSize() ); 1208 if ( bSameHeight && ATT_VAR_SIZE == aFSz.GetHeightSizeType() ) 1209 aFSz.SetHeightSizeType( ATT_MIN_SIZE ); 1210 1211 sal_Bool bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight; 1212 if ( bChgLineSz ) 1213 aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) / 1214 (nCnt + 1) ); 1215 1216 SwTableBox* pNewBox = new SwTableBox( pFrmFmt, nCnt, pInsLine ); 1217 sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox ); 1218 pInsLine->GetTabBoxes().Remove( nBoxPos ); // alte loeschen 1219 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox, nBoxPos ); 1220 1221 // Hintergrund- / Rand Attribut loeschen 1222 SwTableBox* pLastBox = pSelBox; // zum verteilen der TextNodes !! 1223 // sollte Bereiche in der Box stehen, dann bleibt sie so bestehen 1224 // !! FALLS DAS GEAENDERT WIRD MUSS DAS UNDO ANGEPASST WERDEN !!! 1225 sal_Bool bMoveNodes = sal_True; 1226 { 1227 sal_uLong nSttNd = pLastBox->GetSttIdx() + 1, 1228 nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex(); 1229 while( nSttNd < nEndNd ) 1230 if( !pDoc->GetNodes()[ nSttNd++ ]->IsTxtNode() ) 1231 { 1232 bMoveNodes = sal_False; 1233 break; 1234 } 1235 } 1236 1237 SwTableBoxFmt* pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt(); 1238 sal_Bool bChkBorder = 0 != pCpyBoxFrmFmt->GetBox().GetTop(); 1239 if( bChkBorder ) 1240 pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt(); 1241 1242 for( sal_uInt16 i = 0; i <= nCnt; ++i ) 1243 { 1244 // also erstmal eine neue Linie in der neuen Box 1245 SwTableLine* pNewLine = new SwTableLine( 1246 (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pNewBox ); 1247 if( bChgLineSz ) 1248 { 1249 pNewLine->ClaimFrmFmt()->SetFmtAttr( aFSz ); 1250 } 1251 1252 pNewBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, i ); 1253 // dann eine neue Box in der Line 1254 if( !i ) // haenge die originale Box ein 1255 { 1256 pSelBox->SetUpper( pNewLine ); 1257 pNewLine->GetTabBoxes().C40_INSERT( SwTableBox, pSelBox, 0 ); 1258 } 1259 else 1260 { 1261 ::_InsTblBox( pDoc, pTblNd, pNewLine, pCpyBoxFrmFmt, 1262 pLastBox, 0 ); 1263 1264 if( bChkBorder ) 1265 { 1266 pCpyBoxFrmFmt = (SwTableBoxFmt*)pNewLine->GetTabBoxes()[ 0 ]->ClaimFrmFmt(); 1267 SvxBoxItem aTmp( pCpyBoxFrmFmt->GetBox() ); 1268 aTmp.SetLine( 0, BOX_LINE_TOP ); 1269 pCpyBoxFrmFmt->SetFmtAttr( aTmp ); 1270 bChkBorder = sal_False; 1271 } 1272 1273 if( bMoveNodes ) 1274 { 1275 const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode(); 1276 if( pLastBox->GetSttIdx()+2 != pEndNd->GetIndex() ) 1277 { 1278 // TextNodes verschieben 1279 SwNodeRange aRg( *pLastBox->GetSttNd(), +2, *pEndNd ); 1280 pLastBox = pNewLine->GetTabBoxes()[0]; // neu setzen 1281 SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 ); 1282 pDoc->GetNodes()._MoveNodes(aRg, pDoc->GetNodes(), aInsPos, sal_False); 1283 pDoc->GetNodes().Delete( aInsPos, 1 ); // den leeren noch loeschen 1284 } 1285 } 1286 } 1287 } 1288 // in Boxen mit Lines darf es nur noch Size/Fillorder geben 1289 pFrmFmt = (SwTableBoxFmt*)pNewBox->ClaimFrmFmt(); 1290 pFrmFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 ); 1291 pFrmFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 ); 1292 } 1293 1294 delete[] pRowHeights; 1295 1296 GCLines(); 1297 1298 aFndBox.MakeFrms( *this ); 1299 1300 CHECKBOXWIDTH 1301 CHECKTABLELAYOUT 1302 return sal_True; 1303 } 1304 1305 sal_Bool SwTable::SplitCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt ) 1306 { 1307 ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" ); 1308 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); 1309 if( !pTblNd ) 1310 return sal_False; 1311 1312 // TL_CHART2: splitting/merging of a number of cells or rows will usually make 1313 // the table to complex to be handled with chart. 1314 // Thus we tell the charts to use their own data provider and forget about this table 1315 pDoc->CreateChartInternalDataProviders( this ); 1316 1317 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 1318 SwSelBoxes aSelBoxes; 1319 aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count()); 1320 ExpandSelection( aSelBoxes ); 1321 1322 //Lines fuer das Layout-Update herausuchen. 1323 _FndBox aFndBox( 0, 0 ); 1324 aFndBox.SetTableLines( aSelBoxes, *this ); 1325 aFndBox.DelFrms( *this ); 1326 1327 _CpyTabFrms aFrmArr; 1328 SvPtrarr aLastBoxArr; 1329 sal_uInt16 nFndPos; 1330 for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n ) 1331 { 1332 SwTableBox* pSelBox = *( aSelBoxes.GetData() + n ); 1333 ASSERT( pSelBox, "Box steht nicht in der Tabelle" ); 1334 1335 // We don't want to split small table cells into very very small cells 1336 if( pSelBox->GetFrmFmt()->GetFrmSize().GetWidth()/( nCnt + 1 ) < 10 ) 1337 continue; 1338 1339 // dann teile die Box nCnt in nCnt Boxen 1340 SwTableLine* pInsLine = pSelBox->GetUpper(); 1341 sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox ); 1342 1343 // suche das FrmFmt im Array aller Frame-Formate 1344 SwTableBoxFmt* pLastBoxFmt; 1345 _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pSelBox->GetFrmFmt() ); 1346 if( !aFrmArr.Seek_Entry( aFindFrm, &nFndPos )) 1347 { 1348 // aender das FrmFmt 1349 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt(); 1350 SwTwips nBoxSz = aFindFrm.pNewFrmFmt->GetFrmSize().GetWidth(); 1351 SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 ); 1352 aFindFrm.pNewFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, 1353 nNewBoxSz, 0 ) ); 1354 aFrmArr.Insert( aFindFrm ); 1355 1356 pLastBoxFmt = aFindFrm.pNewFrmFmt; 1357 if( nBoxSz != ( nNewBoxSz * (nCnt + 1))) 1358 { 1359 // es bleibt ein Rest, also muss fuer die letzte Box ein 1360 // eigenes Format definiert werden 1361 pLastBoxFmt = new SwTableBoxFmt( *aFindFrm.pNewFrmFmt ); 1362 pLastBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, 1363 nBoxSz - ( nNewBoxSz * nCnt ), 0 ) ); 1364 } 1365 void* p = pLastBoxFmt; 1366 aLastBoxArr.Insert( p, nFndPos ); 1367 } 1368 else 1369 { 1370 aFindFrm = aFrmArr[ nFndPos ]; 1371 pSelBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt ); 1372 pLastBoxFmt = (SwTableBoxFmt*)aLastBoxArr[ nFndPos ]; 1373 } 1374 1375 // dann fuege mal an der Position die neuen Boxen ein 1376 for( sal_uInt16 i = 1; i < nCnt; ++i ) 1377 ::_InsTblBox( pDoc, pTblNd, pInsLine, aFindFrm.pNewFrmFmt, 1378 pSelBox, nBoxPos + i ); // dahinter einfuegen 1379 1380 ::_InsTblBox( pDoc, pTblNd, pInsLine, pLastBoxFmt, 1381 pSelBox, nBoxPos + nCnt ); // dahinter einfuegen 1382 1383 // Sonderbehandlung fuer die Umrandung: 1384 const SvxBoxItem& aSelBoxItem = aFindFrm.pNewFrmFmt->GetBox(); 1385 if( aSelBoxItem.GetRight() ) 1386 { 1387 pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrmFmt(); 1388 1389 SvxBoxItem aTmp( aSelBoxItem ); 1390 aTmp.SetLine( 0, BOX_LINE_RIGHT ); 1391 aFindFrm.pNewFrmFmt->SetFmtAttr( aTmp ); 1392 1393 // und dann das Format aus dem "cache" entfernen 1394 for( sal_uInt16 i = aFrmArr.Count(); i; ) 1395 { 1396 const _CpyTabFrm& rCTF = aFrmArr[ --i ]; 1397 if( rCTF.pNewFrmFmt == aFindFrm.pNewFrmFmt || 1398 rCTF.Value.pFrmFmt == aFindFrm.pNewFrmFmt ) 1399 { 1400 aFrmArr.Remove( i ); 1401 aLastBoxArr.Remove( i ); 1402 } 1403 } 1404 } 1405 } 1406 1407 //Layout updaten 1408 aFndBox.MakeFrms( *this ); 1409 1410 CHECKBOXWIDTH 1411 CHECKTABLELAYOUT 1412 return sal_True; 1413 } 1414 1415 // --------------------------------------------------------------- 1416 1417 /* 1418 ----------------------- >> MERGE << ------------------------ 1419 Algorithmus: 1420 ist in der _FndBox nur eine Line angegeben, nehme die Line 1421 und teste die Anzahl der Boxen 1422 - ist mehr als 1 Box angegeben, so wird auf Boxenebene zusammen- 1423 gefasst, d.H. die neue Box wird so Breit wie die alten. 1424 - Alle Lines die ueber/unter dem Bereich liegen werden in die 1425 Box als Line + Box mit Lines eingefuegt 1426 - Alle Lines die vor/hinter dem Bereich liegen werden in 1427 die Boxen Left/Right eingetragen 1428 1429 ----------------------- >> MERGE << ------------------------ 1430 */ 1431 1432 void lcl_CpyLines( sal_uInt16 nStt, sal_uInt16 nEnd, 1433 SwTableLines& rLines, 1434 SwTableBox* pInsBox, 1435 sal_uInt16 nPos = USHRT_MAX ) 1436 { 1437 for( sal_uInt16 n = nStt; n < nEnd; ++n ) 1438 rLines[n]->SetUpper( pInsBox ); 1439 if( USHRT_MAX == nPos ) 1440 nPos = pInsBox->GetTabLines().Count(); 1441 pInsBox->GetTabLines().Insert( &rLines, nPos, nStt, nEnd ); 1442 rLines.Remove( nStt, nEnd - nStt ); 1443 } 1444 1445 void lcl_CpyBoxes( sal_uInt16 nStt, sal_uInt16 nEnd, 1446 SwTableBoxes& rBoxes, 1447 SwTableLine* pInsLine, 1448 sal_uInt16 nPos = USHRT_MAX ) 1449 { 1450 for( sal_uInt16 n = nStt; n < nEnd; ++n ) 1451 rBoxes[n]->SetUpper( pInsLine ); 1452 if( USHRT_MAX == nPos ) 1453 nPos = pInsLine->GetTabBoxes().Count(); 1454 pInsLine->GetTabBoxes().Insert( &rBoxes, nPos, nStt, nEnd ); 1455 rBoxes.Remove( nStt, nEnd - nStt ); 1456 } 1457 1458 void lcl_CalcWidth( SwTableBox* pBox ) 1459 { 1460 // Annahme: jede Line in der Box ist gleich gross 1461 SwFrmFmt* pFmt = pBox->ClaimFrmFmt(); 1462 ASSERT( pBox->GetTabLines().Count(), "Box hat keine Lines" ); 1463 1464 SwTableLine* pLine = pBox->GetTabLines()[0]; 1465 ASSERT( pLine, "Box steht in keiner Line" ); 1466 1467 long nWidth = 0; 1468 for( sal_uInt16 n = 0; n < pLine->GetTabBoxes().Count(); ++n ) 1469 nWidth += pLine->GetTabBoxes()[n]->GetFrmFmt()->GetFrmSize().GetWidth(); 1470 1471 pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 )); 1472 1473 // in Boxen mit Lines darf es nur noch Size/Fillorder geben 1474 pFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 ); 1475 pFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 ); 1476 } 1477 1478 1479 1480 struct _InsULPara 1481 { 1482 SwTableNode* pTblNd; 1483 SwTableLine* pInsLine; 1484 SwTableBox* pInsBox; 1485 sal_Bool bUL_LR : 1; // Upper-Lower(sal_True) oder Left-Right(sal_False) ? 1486 sal_Bool bUL : 1; // Upper-Left(sal_True) oder Lower-Right(sal_False) ? 1487 1488 SwTableBox* pLeftBox; 1489 SwTableBox* pRightBox; 1490 SwTableBox* pMergeBox; 1491 1492 _InsULPara( SwTableNode* pTNd, sal_Bool bUpperLower, sal_Bool bUpper, 1493 SwTableBox* pLeft, SwTableBox* pMerge, SwTableBox* pRight, 1494 SwTableLine* pLine=0, SwTableBox* pBox=0 ) 1495 : pTblNd( pTNd ), pInsLine( pLine ), pInsBox( pBox ), 1496 pLeftBox( pLeft ), pRightBox( pRight ), pMergeBox( pMerge ) 1497 { bUL_LR = bUpperLower; bUL = bUpper; } 1498 1499 void SetLeft( SwTableBox* pBox=0 ) 1500 { bUL_LR = sal_False; bUL = sal_True; if( pBox ) pInsBox = pBox; } 1501 void SetRight( SwTableBox* pBox=0 ) 1502 { bUL_LR = sal_False; bUL = sal_False; if( pBox ) pInsBox = pBox; } 1503 void SetUpper( SwTableLine* pLine=0 ) 1504 { bUL_LR = sal_True; bUL = sal_True; if( pLine ) pInsLine = pLine; } 1505 void SetLower( SwTableLine* pLine=0 ) 1506 { bUL_LR = sal_True; bUL = sal_False; if( pLine ) pInsLine = pLine; } 1507 }; 1508 1509 1510 sal_Bool lcl_Merge_MoveBox( const _FndBox*& rpFndBox, void* pPara ) 1511 { 1512 _InsULPara* pULPara = (_InsULPara*)pPara; 1513 SwTableBoxes* pBoxes; 1514 1515 sal_uInt16 nStt = 0, nEnd = rpFndBox->GetLines().Count(); 1516 sal_uInt16 nInsPos = USHRT_MAX; 1517 if( !pULPara->bUL_LR ) // Left/Right 1518 { 1519 sal_uInt16 nPos; 1520 SwTableBox* pFndBox = (SwTableBox*)rpFndBox->GetBox(); 1521 pBoxes = &pFndBox->GetUpper()->GetTabBoxes(); 1522 if( pULPara->bUL ) // Left ? 1523 { 1524 // gibt es noch davor Boxen, dann move sie 1525 if( 0 != ( nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) ) 1526 lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine ); 1527 } 1528 else // Right 1529 // gibt es noch dahinter Boxen, dann move sie 1530 if( (nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) +1 < pBoxes->Count() ) 1531 { 1532 nInsPos = pULPara->pInsLine->GetTabBoxes().Count(); 1533 lcl_CpyBoxes( nPos+1, pBoxes->Count(), 1534 *pBoxes, pULPara->pInsLine ); 1535 } 1536 } 1537 // Upper/Lower und gehts noch tiefer ?? 1538 else if( rpFndBox->GetLines().Count() ) 1539 { 1540 // suche nur die Line, ab der Verschoben werden muss 1541 nStt = pULPara->bUL ? 0 : rpFndBox->GetLines().Count()-1; 1542 nEnd = nStt+1; 1543 } 1544 1545 pBoxes = &pULPara->pInsLine->GetTabBoxes(); 1546 1547 // geht es noch eine weitere Stufe runter? 1548 if( rpFndBox->GetBox()->GetTabLines().Count() ) 1549 { 1550 SwTableBox* pBox = new SwTableBox( 1551 (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt(), 0, pULPara->pInsLine ); 1552 _InsULPara aPara( *pULPara ); 1553 aPara.pInsBox = pBox; 1554 ((_FndBox*)rpFndBox)->GetLines().ForEach( nStt, nEnd, 1555 &lcl_Merge_MoveLine, &aPara ); 1556 if( pBox->GetTabLines().Count() ) 1557 { 1558 if( USHRT_MAX == nInsPos ) 1559 nInsPos = pBoxes->Count(); 1560 pBoxes->C40_INSERT( SwTableBox, pBox, nInsPos ); 1561 lcl_CalcWidth( pBox ); // bereche die Breite der Box 1562 } 1563 else 1564 delete pBox; 1565 } 1566 return sal_True; 1567 } 1568 1569 sal_Bool lcl_Merge_MoveLine( const _FndLine*& rpFndLine, void* pPara ) 1570 { 1571 _InsULPara* pULPara = (_InsULPara*)pPara; 1572 SwTableLines* pLines; 1573 1574 sal_uInt16 nStt = 0, nEnd = rpFndLine->GetBoxes().Count(); 1575 sal_uInt16 nInsPos = USHRT_MAX; 1576 if( pULPara->bUL_LR ) // UpperLower ? 1577 { 1578 sal_uInt16 nPos; 1579 SwTableLine* pFndLn = (SwTableLine*)rpFndLine->GetLine(); 1580 pLines = pFndLn->GetUpper() ? 1581 &pFndLn->GetUpper()->GetTabLines() : 1582 &pULPara->pTblNd->GetTable().GetTabLines(); 1583 1584 SwTableBox* pLBx = rpFndLine->GetBoxes()[0]->GetBox(); 1585 SwTableBox* pRBx = rpFndLine->GetBoxes()[ 1586 rpFndLine->GetBoxes().Count()-1]->GetBox(); 1587 sal_uInt16 nLeft = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pLBx ); 1588 sal_uInt16 nRight = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pRBx ); 1589 1590 // if( ( nLeft && nRight+1 < pFndLn->GetTabBoxes().Count() ) || 1591 // ( !nLeft && nRight+1 >= pFndLn->GetTabBoxes().Count() ) ) 1592 if( !nLeft || nRight == pFndLn->GetTabBoxes().Count() ) 1593 { 1594 if( pULPara->bUL ) // Upper ? 1595 { 1596 // gibt es noch davor Zeilen, dann move sie 1597 if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) ) 1598 lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox ); 1599 } 1600 else 1601 // gibt es noch dahinter Zeilen, dann move sie 1602 if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() ) 1603 { 1604 nInsPos = pULPara->pInsBox->GetTabLines().Count(); 1605 lcl_CpyLines( nPos+1, pLines->Count(), *pLines, 1606 pULPara->pInsBox ); 1607 } 1608 } 1609 else if( nLeft ) 1610 { 1611 // es gibt links noch weitere Boxen, also setze Left- 1612 // und Merge-Box in eine Box und Line, fuege davor/dahinter 1613 // eine Line mit Box ein, in die die oberen/unteren Lines 1614 // eingefuegt werden 1615 SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper(); 1616 SwTableBox* pLMBox = new SwTableBox( 1617 (SwTableBoxFmt*)pULPara->pLeftBox->GetFrmFmt(), 0, pInsLine ); 1618 SwTableLine* pLMLn = new SwTableLine( 1619 (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pLMBox ); 1620 pLMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE ); 1621 1622 pLMBox->GetTabLines().C40_INSERT( SwTableLine, pLMLn, 0 ); 1623 1624 lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn ); 1625 1626 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLMBox, 0 ); 1627 1628 if( pULPara->bUL ) // Upper ? 1629 { 1630 // gibt es noch davor Zeilen, dann move sie 1631 if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) ) 1632 lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 ); 1633 } 1634 else 1635 // gibt es noch dahinter Zeilen, dann move sie 1636 if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() ) 1637 lcl_CpyLines( nPos+1, pLines->Count(), *pLines, 1638 pLMBox ); 1639 lcl_CalcWidth( pLMBox ); // bereche die Breite der Box 1640 } 1641 else if( nRight+1 < pFndLn->GetTabBoxes().Count() ) 1642 { 1643 // es gibt rechts noch weitere Boxen, also setze Right- 1644 // und Merge-Box in eine Box und Line, fuege davor/dahinter 1645 // eine Line mit Box ein, in die die oberen/unteren Lines 1646 // eingefuegt werden 1647 SwTableLine* pInsLine = pULPara->pRightBox->GetUpper(); 1648 SwTableBox* pRMBox; 1649 if( pULPara->pLeftBox->GetUpper() == pInsLine ) 1650 { 1651 pRMBox = new SwTableBox( 1652 (SwTableBoxFmt*)pULPara->pRightBox->GetFrmFmt(), 0, pInsLine ); 1653 SwTableLine* pRMLn = new SwTableLine( 1654 (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pRMBox ); 1655 pRMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE ); 1656 pRMBox->GetTabLines().C40_INSERT( SwTableLine, pRMLn, 0 ); 1657 1658 lcl_CpyBoxes( 1, 3, pInsLine->GetTabBoxes(), pRMLn ); 1659 1660 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 ); 1661 } 1662 else 1663 { 1664 // Left und Merge wurden schon zusammengefuegt, also move 1665 // Right auch mit in die Line 1666 1667 pInsLine = pULPara->pLeftBox->GetUpper(); 1668 sal_uInt16 nMvPos = pULPara->pRightBox->GetUpper()->GetTabBoxes(). 1669 C40_GETPOS( SwTableBox, pULPara->pRightBox ); 1670 lcl_CpyBoxes( nMvPos, nMvPos+1, 1671 pULPara->pRightBox->GetUpper()->GetTabBoxes(), 1672 pInsLine ); 1673 pRMBox = pInsLine->GetUpper(); 1674 1675 // sind schon Lines vorhanden, dann muessen diese in eine 1676 // neue Line und Box 1677 nMvPos = pRMBox->GetTabLines().C40_GETPOS( SwTableLine, pInsLine ); 1678 if( pULPara->bUL ? nMvPos 1679 : nMvPos+1 < pRMBox->GetTabLines().Count() ) 1680 { 1681 // alle Lines zu einer neuen Line und Box zusammenfassen 1682 SwTableLine* pNewLn = new SwTableLine( 1683 (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pRMBox ); 1684 pNewLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE ); 1685 pRMBox->GetTabLines().C40_INSERT( SwTableLine, pNewLn, 1686 pULPara->bUL ? nMvPos : nMvPos+1 ); 1687 pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn ); 1688 pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 ); 1689 1690 sal_uInt16 nPos1, nPos2; 1691 if( pULPara->bUL ) 1692 nPos1 = 0, 1693 nPos2 = nMvPos; 1694 else 1695 nPos1 = nMvPos+2, 1696 nPos2 = pNewLn->GetUpper()->GetTabLines().Count(); 1697 1698 lcl_CpyLines( nPos1, nPos2, 1699 pNewLn->GetUpper()->GetTabLines(), pRMBox ); 1700 lcl_CalcWidth( pRMBox ); // bereche die Breite der Box 1701 1702 pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn ); 1703 pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 1704 pNewLn->GetTabBoxes().Count() ); 1705 } 1706 } 1707 if( pULPara->bUL ) // Upper ? 1708 { 1709 // gibt es noch davor Zeilen, dann move sie 1710 if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) ) 1711 lcl_CpyLines( 0, nPos, *pLines, pRMBox, 0 ); 1712 } 1713 else 1714 // gibt es noch dahinter Zeilen, dann move sie 1715 if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() ) 1716 lcl_CpyLines( nPos+1, pLines->Count(), *pLines, 1717 pRMBox ); 1718 lcl_CalcWidth( pRMBox ); // bereche die Breite der Box 1719 } 1720 else { 1721 ASSERT( sal_False , "Was denn nun" ); 1722 } 1723 } 1724 // Left/Right 1725 else 1726 { 1727 // suche nur die Line, ab der Verschoben werden muss 1728 nStt = pULPara->bUL ? 0 : rpFndLine->GetBoxes().Count()-1; 1729 nEnd = nStt+1; 1730 } 1731 pLines = &pULPara->pInsBox->GetTabLines(); 1732 1733 SwTableLine* pNewLine = new SwTableLine( 1734 (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(), 0, pULPara->pInsBox ); 1735 _InsULPara aPara( *pULPara ); // kopieren 1736 aPara.pInsLine = pNewLine; 1737 ((_FndLine*)rpFndLine)->GetBoxes().ForEach( nStt, nEnd, 1738 &lcl_Merge_MoveBox, &aPara ); 1739 if( pNewLine->GetTabBoxes().Count() ) 1740 { 1741 if( USHRT_MAX == nInsPos ) 1742 nInsPos = pLines->Count(); 1743 pLines->C40_INSERT( SwTableLine, pNewLine, nInsPos ); 1744 } 1745 else 1746 delete pNewLine; 1747 1748 return sal_True; 1749 } 1750 1751 1752 sal_Bool SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes, 1753 SwTableBox* pMergeBox, SwUndoTblMerge* pUndo ) 1754 { 1755 ASSERT( rBoxes.Count() && pMergeBox, "keine gueltigen Werte" ); 1756 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); 1757 if( !pTblNd ) 1758 return sal_False; 1759 1760 // suche alle Boxen / Lines 1761 _FndBox aFndBox( 0, 0 ); 1762 { 1763 _FndPara aPara( rBoxes, &aFndBox ); 1764 GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); 1765 } 1766 if( !aFndBox.GetLines().Count() ) 1767 return sal_False; 1768 1769 // TL_CHART2: splitting/merging of a number of cells or rows will usually make 1770 // the table to complex to be handled with chart. 1771 // Thus we tell the charts to use their own data provider and forget about this table 1772 pDoc->CreateChartInternalDataProviders( this ); 1773 1774 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 1775 1776 if( pUndo ) 1777 pUndo->SetSelBoxes( rBoxes ); 1778 1779 //Lines fuer das Layout-Update herausuchen. 1780 aFndBox.SetTableLines( *this ); 1781 aFndBox.DelFrms( *this ); 1782 1783 _FndBox* pFndBox = &aFndBox; 1784 while( 1 == pFndBox->GetLines().Count() && 1785 1 == pFndBox->GetLines()[0]->GetBoxes().Count() ) 1786 pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0]; 1787 1788 SwTableLine* pInsLine = new SwTableLine( 1789 (SwTableLineFmt*)pFndBox->GetLines()[0]->GetLine()->GetFrmFmt(), 0, 1790 !pFndBox->GetUpper() ? 0 : pFndBox->GetBox() ); 1791 pInsLine->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE ); 1792 1793 // trage die neue Line ein 1794 SwTableLines* pLines = pFndBox->GetUpper() ? 1795 &pFndBox->GetBox()->GetTabLines() : &GetTabLines(); 1796 1797 SwTableLine* pNewLine = pFndBox->GetLines()[0]->GetLine(); 1798 sal_uInt16 nInsPos = pLines->C40_GETPOS( SwTableLine, pNewLine ); 1799 pLines->C40_INSERT( SwTableLine, pInsLine, nInsPos ); 1800 1801 SwTableBox* pLeftBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine ); 1802 SwTableBox* pRightBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine ); 1803 pMergeBox->SetUpper( pInsLine ); 1804 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLeftBox, 0 ); 1805 pLeftBox->ClaimFrmFmt(); 1806 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pMergeBox, 1 ); 1807 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRightBox, 2 ); 1808 pRightBox->ClaimFrmFmt(); 1809 1810 // in diese kommen alle Lines, die ueber dem selektierten Bereich stehen 1811 // Sie bilden also eine Upper/Lower Line 1812 _InsULPara aPara( pTblNd, sal_True, sal_True, pLeftBox, pMergeBox, pRightBox, pInsLine ); 1813 1814 // move die oben/unten ueberhaengenden Lines vom selektierten Bereich 1815 pFndBox->GetLines()[0]->GetBoxes().ForEach( &lcl_Merge_MoveBox, 1816 &aPara ); 1817 aPara.SetLower( pInsLine ); 1818 sal_uInt16 nEnd = pFndBox->GetLines().Count()-1; 1819 pFndBox->GetLines()[nEnd]->GetBoxes().ForEach( &lcl_Merge_MoveBox, 1820 &aPara ); 1821 1822 // move die links/rechts hereinreichenden Boxen vom selektierten Bereich 1823 aPara.SetLeft( pLeftBox ); 1824 pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara ); 1825 1826 aPara.SetRight( pRightBox ); 1827 pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara ); 1828 1829 if( !pLeftBox->GetTabLines().Count() ) 1830 _DeleteBox( *this, pLeftBox, 0, sal_False, sal_False ); 1831 else 1832 { 1833 lcl_CalcWidth( pLeftBox ); // bereche die Breite der Box 1834 if( pUndo && pLeftBox->GetSttNd() ) 1835 pUndo->AddNewBox( pLeftBox->GetSttIdx() ); 1836 } 1837 if( !pRightBox->GetTabLines().Count() ) 1838 _DeleteBox( *this, pRightBox, 0, sal_False, sal_False ); 1839 else 1840 { 1841 lcl_CalcWidth( pRightBox ); // bereche die Breite der Box 1842 if( pUndo && pRightBox->GetSttNd() ) 1843 pUndo->AddNewBox( pRightBox->GetSttIdx() ); 1844 } 1845 1846 DeleteSel( pDoc, rBoxes, 0, 0, sal_False, sal_False ); 1847 1848 // dann raeume die Struktur dieser Line noch mal auf: 1849 // generell alle Aufraeumen 1850 GCLines(); 1851 1852 GetTabLines()[0]->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 ); 1853 1854 aFndBox.MakeFrms( *this ); 1855 1856 CHECKBOXWIDTH 1857 CHECKTABLELAYOUT 1858 1859 return sal_True; 1860 } 1861 1862 // --------------------------------------------------------------- 1863 1864 void lcl_CheckRowSpan( SwTable &rTbl ) 1865 { 1866 sal_uInt16 nLineCount = rTbl.GetTabLines().Count(); 1867 sal_uInt16 nMaxSpan = nLineCount; 1868 long nMinSpan = 1; 1869 while( nMaxSpan ) 1870 { 1871 SwTableLine* pLine = rTbl.GetTabLines()[ nLineCount - nMaxSpan ]; 1872 for( sal_uInt16 nBox = 0; nBox < pLine->GetTabBoxes().Count(); ++nBox ) 1873 { 1874 SwTableBox* pBox = pLine->GetTabBoxes()[nBox]; 1875 long nRowSpan = pBox->getRowSpan(); 1876 if( nRowSpan > nMaxSpan ) 1877 pBox->setRowSpan( nMaxSpan ); 1878 else if( nRowSpan < nMinSpan ) 1879 pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan ); 1880 } 1881 --nMaxSpan; 1882 nMinSpan = -nMaxSpan; 1883 } 1884 } 1885 1886 sal_uInt16 lcl_GetBoxOffset( const _FndBox& rBox ) 1887 { 1888 // suche die erste Box 1889 const _FndBox* pFirstBox = &rBox; 1890 while( pFirstBox->GetLines().Count() ) 1891 pFirstBox = pFirstBox->GetLines()[ 0 ]->GetBoxes()[ 0 ]; 1892 1893 sal_uInt16 nRet = 0; 1894 // dann ueber die Lines nach oben die Position bestimmen 1895 const SwTableBox* pBox = pFirstBox->GetBox(); 1896 do { 1897 const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes(); 1898 const SwTableBox* pCmp; 1899 for( sal_uInt16 n = 0; pBox != ( pCmp = rBoxes[ n ] ); ++n ) 1900 nRet = nRet + (sal_uInt16) pCmp->GetFrmFmt()->GetFrmSize().GetWidth(); 1901 pBox = pBox->GetUpper()->GetUpper(); 1902 } while( pBox ); 1903 return nRet; 1904 } 1905 1906 sal_uInt16 lcl_GetLineWidth( const _FndLine& rLine ) 1907 { 1908 sal_uInt16 nRet = 0; 1909 for( sal_uInt16 n = rLine.GetBoxes().Count(); n; ) 1910 nRet = nRet + (sal_uInt16)rLine.GetBoxes()[ --n ]->GetBox()->GetFrmFmt() 1911 ->GetFrmSize().GetWidth(); 1912 return nRet; 1913 } 1914 1915 void lcl_CalcNewWidths( const _FndLines& rFndLines, _CpyPara& rPara ) 1916 { 1917 rPara.pWidths.reset(); 1918 sal_uInt16 nLineCount = rFndLines.Count(); 1919 if( nLineCount ) 1920 { 1921 rPara.pWidths = boost::shared_ptr< std::vector< std::vector< sal_uLong > > > 1922 ( new std::vector< std::vector< sal_uLong > >( nLineCount )); 1923 // First we collect information about the left/right borders of all 1924 // selected cells 1925 for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine ) 1926 { 1927 std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ]; 1928 const _FndLine *pFndLine = rFndLines[ nLine ]; 1929 if( pFndLine && pFndLine->GetBoxes().Count() ) 1930 { 1931 const SwTableLine *pLine = pFndLine->GetLine(); 1932 if( pLine && pLine->GetTabBoxes().Count() ) 1933 { 1934 sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count(); 1935 sal_uLong nPos = 0; 1936 // The first selected box... 1937 const SwTableBox *pSel = pFndLine->GetBoxes()[0]->GetBox(); 1938 sal_uInt16 nBox = 0; 1939 // Sum up the width of all boxes before the first selected box 1940 while( nBox < nBoxCount ) 1941 { 1942 SwTableBox* pBox = pLine->GetTabBoxes()[nBox++]; 1943 if( pBox != pSel ) 1944 nPos += pBox->GetFrmFmt()->GetFrmSize().GetWidth(); 1945 else 1946 break; 1947 } 1948 // nPos is now the left border of the first selceted box 1949 if( rPara.nMinLeft > nPos ) 1950 rPara.nMinLeft = nPos; 1951 nBoxCount = pFndLine->GetBoxes().Count(); 1952 rWidth = std::vector< sal_uLong >( nBoxCount+2 ); 1953 rWidth[ 0 ] = nPos; 1954 // Add now the widths of all selected boxes and store 1955 // the positions in the vector 1956 for( nBox = 0; nBox < nBoxCount; ) 1957 { 1958 nPos += pFndLine->GetBoxes()[nBox] 1959 ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth(); 1960 rWidth[ ++nBox ] = nPos; 1961 } 1962 // nPos: The right border of the last selected box 1963 if( rPara.nMaxRight < nPos ) 1964 rPara.nMaxRight = nPos; 1965 if( nPos <= rWidth[ 0 ] ) 1966 rWidth.clear(); 1967 } 1968 } 1969 } 1970 } 1971 // Second step: calculate the new widths for the copied cells 1972 sal_uLong nSelSize = rPara.nMaxRight - rPara.nMinLeft; 1973 if( nSelSize ) 1974 { 1975 for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine ) 1976 { 1977 std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ]; 1978 sal_uInt16 nCount = (sal_uInt16)rWidth.size(); 1979 if( nCount > 2 ) 1980 { 1981 rWidth[ nCount - 1 ] = rPara.nMaxRight; 1982 sal_uLong nLastPos = 0; 1983 for( sal_uInt16 nBox = 0; nBox < nCount; ++nBox ) 1984 { 1985 sal_uInt64 nNextPos = rWidth[ nBox ]; 1986 nNextPos -= rPara.nMinLeft; 1987 nNextPos *= rPara.nNewSize; 1988 nNextPos /= nSelSize; 1989 rWidth[ nBox ] = (sal_uLong)(nNextPos - nLastPos); 1990 nLastPos = (sal_uLong)nNextPos; 1991 } 1992 } 1993 } 1994 } 1995 } 1996 1997 sal_Bool lcl_CopyBoxToDoc( const _FndBox*& rpFndBox, void* pPara ) 1998 { 1999 _CpyPara* pCpyPara = (_CpyPara*)pPara; 2000 2001 // Calculation of new size 2002 sal_uLong nRealSize; 2003 sal_uLong nDummy1 = 0; 2004 sal_uLong nDummy2 = 0; 2005 if( pCpyPara->pTblNd->GetTable().IsNewModel() ) 2006 { 2007 if( pCpyPara->nBoxIdx == 1 ) 2008 nDummy1 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][0]; 2009 nRealSize = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++]; 2010 if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx].size()-1 ) 2011 nDummy2 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx]; 2012 } 2013 else 2014 { 2015 nRealSize = pCpyPara->nNewSize; 2016 nRealSize *= rpFndBox->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth(); 2017 nRealSize /= pCpyPara->nOldSize; 2018 } 2019 2020 sal_uLong nSize; 2021 bool bDummy = nDummy1 > 0; 2022 if( bDummy ) 2023 nSize = nDummy1; 2024 else 2025 { 2026 nSize = nRealSize; 2027 nRealSize = 0; 2028 } 2029 do 2030 { 2031 // suche das Frame-Format in der Liste aller Frame-Formate 2032 _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt() ); 2033 2034 SwFmtFrmSize aFrmSz; 2035 sal_uInt16 nFndPos; 2036 if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ) || 2037 ( aFrmSz = ( aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]).pNewFrmFmt-> 2038 GetFrmSize()).GetWidth() != (SwTwips)nSize ) 2039 { 2040 // es ist noch nicht vorhanden, also kopiere es 2041 aFindFrm.pNewFrmFmt = pCpyPara->pDoc->MakeTableBoxFmt(); 2042 aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndBox->GetBox()->GetFrmFmt() ); 2043 if( !pCpyPara->bCpyCntnt ) 2044 aFindFrm.pNewFrmFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE ); 2045 aFrmSz.SetWidth( nSize ); 2046 aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz ); 2047 pCpyPara->rTabFrmArr.Insert( aFindFrm ); 2048 } 2049 2050 SwTableBox* pBox; 2051 if( rpFndBox->GetLines().Count() ) 2052 { 2053 pBox = new SwTableBox( aFindFrm.pNewFrmFmt, 2054 rpFndBox->GetLines().Count(), pCpyPara->pInsLine ); 2055 pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++ ); 2056 _CpyPara aPara( *pCpyPara, pBox ); 2057 aPara.nNewSize = nSize; // hole die Groesse 2058 ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyLineToDoc, &aPara ); 2059 } 2060 else 2061 { 2062 // erzeuge eine leere Box 2063 pCpyPara->pDoc->GetNodes().InsBoxen( pCpyPara->pTblNd, pCpyPara->pInsLine, 2064 aFindFrm.pNewFrmFmt, 2065 (SwTxtFmtColl*)pCpyPara->pDoc->GetDfltTxtFmtColl(), 2066 0, pCpyPara->nInsPos ); 2067 pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ]; 2068 if( bDummy ) 2069 pBox->setDummyFlag( true ); 2070 else if( pCpyPara->bCpyCntnt ) 2071 { 2072 // dann kopiere mal den Inhalt in diese leere Box 2073 pBox->setRowSpan( rpFndBox->GetBox()->getRowSpan() ); 2074 2075 // der Inhalt kopiert wird, dann koennen auch Formeln&Values 2076 // kopiert werden. 2077 { 2078 SfxItemSet aBoxAttrSet( pCpyPara->pDoc->GetAttrPool(), 2079 RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2080 aBoxAttrSet.Put( rpFndBox->GetBox()->GetFrmFmt()->GetAttrSet() ); 2081 if( aBoxAttrSet.Count() ) 2082 { 2083 const SfxPoolItem* pItem; 2084 SvNumberFormatter* pN = pCpyPara->pDoc->GetNumberFormatter( sal_False ); 2085 if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet. 2086 GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) ) 2087 { 2088 sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue(); 2089 sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx ); 2090 if( nNewIdx != nOldIdx ) 2091 aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx )); 2092 } 2093 pBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet ); 2094 } 2095 } 2096 SwDoc* pFromDoc = rpFndBox->GetBox()->GetFrmFmt()->GetDoc(); 2097 SwNodeRange aCpyRg( *rpFndBox->GetBox()->GetSttNd(), 1, 2098 *rpFndBox->GetBox()->GetSttNd()->EndOfSectionNode() ); 2099 SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 ); 2100 2101 pFromDoc->CopyWithFlyInFly( aCpyRg, 0, aInsIdx, sal_False ); 2102 // den initialen TextNode loeschen 2103 pCpyPara->pDoc->GetNodes().Delete( aInsIdx, 1 ); 2104 } 2105 ++pCpyPara->nInsPos; 2106 } 2107 if( nRealSize ) 2108 { 2109 bDummy = false; 2110 nSize = nRealSize; 2111 nRealSize = 0; 2112 } 2113 else 2114 { 2115 bDummy = true; 2116 nSize = nDummy2; 2117 nDummy2 = 0; 2118 } 2119 } 2120 while( nSize ); 2121 return sal_True; 2122 } 2123 2124 sal_Bool lcl_CopyLineToDoc( const _FndLine*& rpFndLine, void* pPara ) 2125 { 2126 _CpyPara* pCpyPara = (_CpyPara*)pPara; 2127 2128 // suche das Format in der Liste aller Formate 2129 _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndLine->GetLine()->GetFrmFmt() ); 2130 sal_uInt16 nFndPos; 2131 if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos )) 2132 { 2133 // es ist noch nicht vorhanden, also kopiere es 2134 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pCpyPara->pDoc->MakeTableLineFmt(); 2135 aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndLine->GetLine()->GetFrmFmt() ); 2136 pCpyPara->rTabFrmArr.Insert( aFindFrm ); 2137 } 2138 else 2139 aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]; 2140 2141 SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)aFindFrm.pNewFrmFmt, 2142 rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox ); 2143 if( pCpyPara->pInsBox ) 2144 { 2145 pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ ); 2146 } 2147 else 2148 { 2149 pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine, 2150 pCpyPara->nInsPos++ ); 2151 } 2152 2153 _CpyPara aPara( *pCpyPara, pNewLine ); 2154 2155 if( pCpyPara->pTblNd->GetTable().IsNewModel() ) 2156 { 2157 aPara.nOldSize = 0; // will not be used 2158 aPara.nBoxIdx = 1; 2159 } 2160 else if( rpFndLine->GetBoxes().Count() == 2161 rpFndLine->GetLine()->GetTabBoxes().Count() ) 2162 { 2163 // hole die Size vom Parent 2164 const SwFrmFmt* pFmt; 2165 2166 if( rpFndLine->GetLine()->GetUpper() ) 2167 pFmt = rpFndLine->GetLine()->GetUpper()->GetFrmFmt(); 2168 else 2169 pFmt = pCpyPara->pTblNd->GetTable().GetFrmFmt(); 2170 aPara.nOldSize = pFmt->GetFrmSize().GetWidth(); 2171 } 2172 else 2173 // errechne sie 2174 for( sal_uInt16 n = 0; n < rpFndLine->GetBoxes().Count(); ++n ) 2175 aPara.nOldSize += rpFndLine->GetBoxes()[n] 2176 ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth(); 2177 2178 ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyBoxToDoc, &aPara ); 2179 if( pCpyPara->pTblNd->GetTable().IsNewModel() ) 2180 ++pCpyPara->nLnIdx; 2181 return sal_True; 2182 } 2183 2184 sal_Bool SwTable::CopyHeadlineIntoTable( SwTableNode& rTblNd ) 2185 { 2186 // suche alle Boxen / Lines 2187 SwSelBoxes aSelBoxes; 2188 SwTableBox* pBox = GetTabSortBoxes()[ 0 ]; 2189 pBox = GetTblBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 ); 2190 SelLineFromBox( pBox, aSelBoxes, sal_True ); 2191 2192 _FndBox aFndBox( 0, 0 ); 2193 { 2194 _FndPara aPara( aSelBoxes, &aFndBox ); 2195 ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara ); 2196 } 2197 if( !aFndBox.GetLines().Count() ) 2198 return sal_False; 2199 2200 { 2201 // Tabellen-Formeln in die relative Darstellung umwandeln 2202 SwTableFmlUpdate aMsgHnt( this ); 2203 aMsgHnt.eFlags = TBL_RELBOXNAME; 2204 GetFrmFmt()->GetDoc()->UpdateTblFlds( &aMsgHnt ); 2205 } 2206 2207 _CpyTabFrms aCpyFmt; 2208 _CpyPara aPara( &rTblNd, 1, aCpyFmt, sal_True ); 2209 aPara.nNewSize = aPara.nOldSize = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth(); 2210 // dann kopiere mal 2211 if( IsNewModel() ) 2212 lcl_CalcNewWidths( aFndBox.GetLines(), aPara ); 2213 aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara ); 2214 if( rTblNd.GetTable().IsNewModel() ) 2215 { // The copied line must not contain any row span attributes > 1 2216 SwTableLine* pLine = rTblNd.GetTable().GetTabLines()[0]; 2217 sal_uInt16 nColCount = pLine->GetTabBoxes().Count(); 2218 ASSERT( nColCount, "Empty Table Line" ) 2219 for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol ) 2220 { 2221 SwTableBox* pTableBox = pLine->GetTabBoxes()[nCurrCol]; 2222 ASSERT( pTableBox, "Missing Table Box" ); 2223 pTableBox->setRowSpan( 1 ); 2224 } 2225 } 2226 2227 return sal_True; 2228 } 2229 2230 sal_Bool SwTable::MakeCopy( SwDoc* pInsDoc, const SwPosition& rPos, 2231 const SwSelBoxes& rSelBoxes, sal_Bool bCpyNds, 2232 sal_Bool bCpyName ) const 2233 { 2234 // suche alle Boxen / Lines 2235 _FndBox aFndBox( 0, 0 ); 2236 { 2237 _FndPara aPara( rSelBoxes, &aFndBox ); 2238 ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara ); 2239 } 2240 if( !aFndBox.GetLines().Count() ) 2241 return sal_False; 2242 2243 // erst die Poolvorlagen fuer die Tabelle kopieren, damit die dann 2244 // wirklich kopiert und damit die gueltigen Werte haben. 2245 SwDoc* pSrcDoc = GetFrmFmt()->GetDoc(); 2246 if( pSrcDoc != pInsDoc ) 2247 { 2248 pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE ) ); 2249 pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN ) ); 2250 } 2251 2252 SwTable* pNewTbl = (SwTable*)pInsDoc->InsertTable( 2253 SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 1 ), 2254 rPos, 1, 1, GetFrmFmt()->GetHoriOrient().GetHoriOrient(), 2255 0, 0, sal_False, IsNewModel() ); 2256 if( !pNewTbl ) 2257 return sal_False; 2258 2259 SwNodeIndex aIdx( rPos.nNode, -1 ); 2260 SwTableNode* pTblNd = aIdx.GetNode().FindTableNode(); 2261 aIdx++; 2262 ASSERT( pTblNd, "wo ist denn nun der TableNode?" ); 2263 2264 pTblNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() ); 2265 2266 if( IS_TYPE( SwDDETable, this )) 2267 { 2268 // es wird eine DDE-Tabelle kopiert 2269 // ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ? 2270 SwFieldType* pFldType = pInsDoc->InsertFldType( 2271 *((SwDDETable*)this)->GetDDEFldType() ); 2272 ASSERT( pFldType, "unbekannter FieldType" ); 2273 2274 // tauschen am Node den Tabellen-Pointer aus 2275 pNewTbl = new SwDDETable( *pNewTbl, 2276 (SwDDEFieldType*)pFldType ); 2277 pTblNd->SetNewTable( pNewTbl, sal_False ); 2278 } 2279 2280 pNewTbl->GetFrmFmt()->CopyAttrs( *GetFrmFmt() ); 2281 pNewTbl->SetTblChgMode( GetTblChgMode() ); 2282 2283 //Vernichten der Frms die bereits angelegt wurden. 2284 pTblNd->DelFrms(); 2285 2286 { 2287 // Tabellen-Formeln in die relative Darstellung umwandeln 2288 SwTableFmlUpdate aMsgHnt( this ); 2289 aMsgHnt.eFlags = TBL_RELBOXNAME; 2290 pSrcDoc->UpdateTblFlds( &aMsgHnt ); 2291 } 2292 2293 SwTblNumFmtMerge aTNFM( *pSrcDoc, *pInsDoc ); 2294 2295 // Namen auch kopieren oder neuen eindeutigen erzeugen 2296 if( bCpyName ) 2297 pNewTbl->GetFrmFmt()->SetName( GetFrmFmt()->GetName() ); 2298 2299 _CpyTabFrms aCpyFmt; 2300 _CpyPara aPara( pTblNd, 1, aCpyFmt, bCpyNds ); 2301 aPara.nNewSize = aPara.nOldSize = GetFrmFmt()->GetFrmSize().GetWidth(); 2302 2303 if( IsNewModel() ) 2304 lcl_CalcNewWidths( aFndBox.GetLines(), aPara ); 2305 // dann kopiere mal 2306 aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara ); 2307 2308 // dann setze oben und unten noch die "richtigen" Raender: 2309 { 2310 _FndLine* pFndLn = aFndBox.GetLines()[ 0 ]; 2311 SwTableLine* pLn = pFndLn->GetLine(); 2312 const SwTableLine* pTmp = pLn; 2313 sal_uInt16 nLnPos = GetTabLines().GetPos( pTmp ); 2314 if( USHRT_MAX != nLnPos && nLnPos ) 2315 { 2316 // es gibt eine Line davor 2317 SwCollectTblLineBoxes aLnPara( sal_False, HEADLINE_BORDERCOPY ); 2318 2319 pLn = GetTabLines()[ nLnPos - 1 ]; 2320 pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara ); 2321 2322 if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ), 2323 lcl_GetLineWidth( *pFndLn )) ) 2324 { 2325 aLnPara.SetValues( sal_True ); 2326 pLn = pNewTbl->GetTabLines()[ 0 ]; 2327 pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara ); 2328 } 2329 } 2330 2331 pFndLn = aFndBox.GetLines()[ aFndBox.GetLines().Count() -1 ]; 2332 pLn = pFndLn->GetLine(); 2333 pTmp = pLn; 2334 nLnPos = GetTabLines().GetPos( pTmp ); 2335 if( nLnPos < GetTabLines().Count() - 1 ) 2336 { 2337 // es gibt eine Line dahinter 2338 SwCollectTblLineBoxes aLnPara( sal_True, HEADLINE_BORDERCOPY ); 2339 2340 pLn = GetTabLines()[ nLnPos + 1 ]; 2341 pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara ); 2342 2343 if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ), 2344 lcl_GetLineWidth( *pFndLn )) ) 2345 { 2346 aLnPara.SetValues( sal_False ); 2347 pLn = pNewTbl->GetTabLines()[ pNewTbl->GetTabLines().Count()-1 ]; 2348 pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara ); 2349 } 2350 } 2351 } 2352 2353 // die initiale Box muss noch geloescht werden 2354 _DeleteBox( *pNewTbl, pNewTbl->GetTabLines()[ 2355 pNewTbl->GetTabLines().Count() - 1 ]->GetTabBoxes()[0], 2356 0, sal_False, sal_False ); 2357 2358 if( pNewTbl->IsNewModel() ) 2359 lcl_CheckRowSpan( *pNewTbl ); 2360 // Mal kurz aufraeumen: 2361 pNewTbl->GCLines(); 2362 2363 pTblNd->MakeFrms( &aIdx ); // erzeuge die Frames neu 2364 2365 CHECKTABLELAYOUT 2366 2367 return sal_True; 2368 } 2369 2370 2371 2372 // --------------------------------------------------------------- 2373 2374 // suche ab dieser Line nach der naechsten Box mit Inhalt 2375 SwTableBox* SwTableLine::FindNextBox( const SwTable& rTbl, 2376 const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const 2377 { 2378 const SwTableLine* pLine = this; // fuer M800 2379 SwTableBox* pBox; 2380 sal_uInt16 nFndPos; 2381 if( GetTabBoxes().Count() && pSrchBox && 2382 USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) && 2383 nFndPos + 1 != GetTabBoxes().Count() ) 2384 { 2385 pBox = GetTabBoxes()[ nFndPos + 1 ]; 2386 while( pBox->GetTabLines().Count() ) 2387 pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0]; 2388 return pBox; 2389 } 2390 2391 if( GetUpper() ) 2392 { 2393 nFndPos = GetUpper()->GetTabLines().GetPos( pLine ); 2394 ASSERT( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" ); 2395 // gibts eine weitere Line 2396 if( nFndPos+1 >= GetUpper()->GetTabLines().Count() ) 2397 return GetUpper()->GetUpper()->FindNextBox( rTbl, GetUpper(), bOvrTblLns ); 2398 pLine = GetUpper()->GetTabLines()[nFndPos+1]; 2399 } 2400 else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ? 2401 { 2402 // suche in der Tabelle nach der naechsten Line 2403 nFndPos = rTbl.GetTabLines().GetPos( pLine ); 2404 if( nFndPos + 1 >= rTbl.GetTabLines().Count() ) 2405 return 0; // es gibt keine weitere Box mehr 2406 2407 pLine = rTbl.GetTabLines()[ nFndPos+1 ]; 2408 } 2409 else 2410 return 0; 2411 2412 if( pLine->GetTabBoxes().Count() ) 2413 { 2414 pBox = pLine->GetTabBoxes()[0]; 2415 while( pBox->GetTabLines().Count() ) 2416 pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0]; 2417 return pBox; 2418 } 2419 return pLine->FindNextBox( rTbl, 0, bOvrTblLns ); 2420 } 2421 2422 // suche ab dieser Line nach der vorherigen Box 2423 SwTableBox* SwTableLine::FindPreviousBox( const SwTable& rTbl, 2424 const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const 2425 { 2426 const SwTableLine* pLine = this; // fuer M800 2427 SwTableBox* pBox; 2428 sal_uInt16 nFndPos; 2429 if( GetTabBoxes().Count() && pSrchBox && 2430 USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) && 2431 nFndPos ) 2432 { 2433 pBox = GetTabBoxes()[ nFndPos - 1 ]; 2434 while( pBox->GetTabLines().Count() ) 2435 { 2436 pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1]; 2437 pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1]; 2438 } 2439 return pBox; 2440 } 2441 2442 if( GetUpper() ) 2443 { 2444 nFndPos = GetUpper()->GetTabLines().GetPos( pLine ); 2445 ASSERT( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" ); 2446 // gibts eine weitere Line 2447 if( !nFndPos ) 2448 return GetUpper()->GetUpper()->FindPreviousBox( rTbl, GetUpper(), bOvrTblLns ); 2449 pLine = GetUpper()->GetTabLines()[nFndPos-1]; 2450 } 2451 else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ? 2452 { 2453 // suche in der Tabelle nach der naechsten Line 2454 nFndPos = rTbl.GetTabLines().GetPos( pLine ); 2455 if( !nFndPos ) 2456 return 0; // es gibt keine weitere Box mehr 2457 2458 pLine = rTbl.GetTabLines()[ nFndPos-1 ]; 2459 } 2460 else 2461 return 0; 2462 2463 if( pLine->GetTabBoxes().Count() ) 2464 { 2465 pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1]; 2466 while( pBox->GetTabLines().Count() ) 2467 { 2468 pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1]; 2469 pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1]; 2470 } 2471 return pBox; 2472 } 2473 return pLine->FindPreviousBox( rTbl, 0, bOvrTblLns ); 2474 } 2475 2476 // suche ab dieser Line nach der naechsten Box mit Inhalt 2477 SwTableBox* SwTableBox::FindNextBox( const SwTable& rTbl, 2478 const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const 2479 { 2480 if( !pSrchBox && !GetTabLines().Count() ) 2481 return (SwTableBox*)this; 2482 return GetUpper()->FindNextBox( rTbl, pSrchBox ? pSrchBox : this, 2483 bOvrTblLns ); 2484 2485 } 2486 2487 // suche ab dieser Line nach der naechsten Box mit Inhalt 2488 SwTableBox* SwTableBox::FindPreviousBox( const SwTable& rTbl, 2489 const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const 2490 { 2491 if( !pSrchBox && !GetTabLines().Count() ) 2492 return (SwTableBox*)this; 2493 return GetUpper()->FindPreviousBox( rTbl, pSrchBox ? pSrchBox : this, 2494 bOvrTblLns ); 2495 } 2496 2497 2498 sal_Bool lcl_BoxSetHeadCondColl( const SwTableBox*& rpBox, void* ) 2499 { 2500 // in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen 2501 const SwStartNode* pSttNd = rpBox->GetSttNd(); 2502 if( pSttNd ) 2503 pSttNd->CheckSectionCondColl(); 2504 else 2505 ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_LineSetHeadCondColl, 0 ); 2506 return sal_True; 2507 } 2508 2509 sal_Bool lcl_LineSetHeadCondColl( const SwTableLine*& rpLine, void* ) 2510 { 2511 ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 ); 2512 return sal_True; 2513 } 2514 2515 /* */ 2516 2517 SwTwips lcl_GetDistance( SwTableBox* pBox, sal_Bool bLeft ) 2518 { 2519 sal_Bool bFirst = sal_True; 2520 SwTwips nRet = 0; 2521 SwTableLine* pLine; 2522 while( pBox && 0 != ( pLine = pBox->GetUpper() ) ) 2523 { 2524 sal_uInt16 nStt = 0, nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox ); 2525 2526 if( bFirst && !bLeft ) 2527 ++nPos; 2528 bFirst = sal_False; 2529 2530 while( nStt < nPos ) 2531 nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrmFmt() 2532 ->GetFrmSize().GetWidth(); 2533 pBox = pLine->GetUpper(); 2534 } 2535 return nRet; 2536 } 2537 2538 sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam, 2539 SwTwips nDist, sal_Bool bCheck ) 2540 { 2541 SwTableBoxes& rBoxes = pLine->GetTabBoxes(); 2542 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 2543 { 2544 SwTableBox* pBox = rBoxes[ n ]; 2545 SwFrmFmt* pFmt = pBox->GetFrmFmt(); 2546 const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); 2547 SwTwips nWidth = rSz.GetWidth(); 2548 sal_Bool bGreaterBox = sal_False; 2549 2550 if( bCheck ) 2551 { 2552 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 2553 if( !::lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam, 2554 nDist, sal_True )) 2555 return sal_False; 2556 2557 // dann noch mal alle "ContentBoxen" sammeln 2558 if( ( 0 != ( bGreaterBox = TBLFIX_CHGABS != rParam.nMode && ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) || 2559 ( !rParam.bBigger && ( Abs( nDist + (( rParam.nMode && rParam.bLeft ) ? 0 : nWidth ) - rParam.nSide ) < COLFUZZY ) ) ) 2560 { 2561 rParam.bAnyBoxFnd = sal_True; 2562 SwTwips nLowerDiff; 2563 if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode ) 2564 { 2565 // die "anderen Boxen" wurden angepasst, 2566 // also sich um diesen Betrag aendern 2567 nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide; 2568 nLowerDiff *= rParam.nDiff; 2569 nLowerDiff /= rParam.nMaxSize; 2570 nLowerDiff = rParam.nDiff - nLowerDiff; 2571 } 2572 else 2573 nLowerDiff = rParam.nDiff; 2574 2575 if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY ) 2576 return sal_False; 2577 } 2578 } 2579 else 2580 { 2581 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff; 2582 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 2583 { 2584 rParam.nLowerDiff = 0; 2585 lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam, nDist, sal_False ); 2586 2587 if( nLowerDiff < rParam.nLowerDiff ) 2588 nLowerDiff = rParam.nLowerDiff; 2589 } 2590 rParam.nLowerDiff = nOldLower; 2591 2592 2593 if( nLowerDiff || 2594 ( 0 != ( bGreaterBox = !nOldLower && TBLFIX_CHGABS != rParam.nMode && 2595 ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) || 2596 ( Abs( nDist + ( (rParam.nMode && rParam.bLeft) ? 0 : nWidth ) 2597 - rParam.nSide ) < COLFUZZY )) 2598 { 2599 // in dieser Spalte ist der Cursor - also verkleinern / vergroessern 2600 SwFmtFrmSize aNew( rSz ); 2601 2602 if( !nLowerDiff ) 2603 { 2604 if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode ) 2605 { 2606 // die "anderen Boxen" wurden angepasst, 2607 // also sich um diesen Betrag aendern 2608 nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide; 2609 nLowerDiff *= rParam.nDiff; 2610 nLowerDiff /= rParam.nMaxSize; 2611 nLowerDiff = rParam.nDiff - nLowerDiff; 2612 } 2613 else 2614 nLowerDiff = rParam.nDiff; 2615 } 2616 2617 rParam.nLowerDiff += nLowerDiff; 2618 2619 if( rParam.bBigger ) 2620 aNew.SetWidth( nWidth + nLowerDiff ); 2621 else 2622 aNew.SetWidth( nWidth - nLowerDiff ); 2623 rParam.aShareFmts.SetSize( *pBox, aNew ); 2624 break; 2625 } 2626 } 2627 2628 if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide ) 2629 break; 2630 2631 nDist += nWidth; 2632 2633 // wenns groesser wird, dann wars das 2634 if( ( TBLFIX_CHGABS == rParam.nMode || !rParam.bLeft ) && 2635 nDist >= rParam.nSide ) 2636 break; 2637 } 2638 return sal_True; 2639 } 2640 2641 sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam, 2642 SwTwips nDist, sal_Bool bCheck ) 2643 { 2644 SwTableBoxes& rBoxes = pLine->GetTabBoxes(); 2645 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 2646 { 2647 SwTableBox* pBox = rBoxes[ n ]; 2648 SwFrmFmt* pFmt = pBox->GetFrmFmt(); 2649 const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); 2650 SwTwips nWidth = rSz.GetWidth(); 2651 2652 if( bCheck ) 2653 { 2654 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 2655 if( !::lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ], 2656 rParam, nDist, sal_True )) 2657 return sal_False; 2658 2659 if( rParam.bBigger && ( TBLFIX_CHGABS == rParam.nMode 2660 ? Abs( nDist - rParam.nSide ) < COLFUZZY 2661 : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY 2662 : nDist >= rParam.nSide - COLFUZZY )) ) 2663 { 2664 rParam.bAnyBoxFnd = sal_True; 2665 SwTwips nDiff; 2666 if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport. 2667 { 2668 // relativ berechnen 2669 nDiff = nWidth; 2670 nDiff *= rParam.nDiff; 2671 nDiff /= rParam.nMaxSize; 2672 } 2673 else 2674 nDiff = rParam.nDiff; 2675 2676 if( nWidth < nDiff || nWidth - nDiff < MINLAY ) 2677 return sal_False; 2678 } 2679 } 2680 else 2681 { 2682 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff; 2683 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 2684 { 2685 rParam.nLowerDiff = 0; 2686 lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ], rParam, 2687 nDist, sal_False ); 2688 2689 if( nLowerDiff < rParam.nLowerDiff ) 2690 nLowerDiff = rParam.nLowerDiff; 2691 } 2692 rParam.nLowerDiff = nOldLower; 2693 2694 if( nLowerDiff || 2695 ( TBLFIX_CHGABS == rParam.nMode 2696 ? Abs( nDist - rParam.nSide ) < COLFUZZY 2697 : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY 2698 : nDist >= rParam.nSide - COLFUZZY) 2699 ) ) 2700 { 2701 SwFmtFrmSize aNew( rSz ); 2702 2703 if( !nLowerDiff ) 2704 { 2705 if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport. 2706 { 2707 // relativ berechnen 2708 nLowerDiff = nWidth; 2709 nLowerDiff *= rParam.nDiff; 2710 nLowerDiff /= rParam.nMaxSize; 2711 } 2712 else 2713 nLowerDiff = rParam.nDiff; 2714 } 2715 2716 rParam.nLowerDiff += nLowerDiff; 2717 2718 if( rParam.bBigger ) 2719 aNew.SetWidth( nWidth - nLowerDiff ); 2720 else 2721 aNew.SetWidth( nWidth + nLowerDiff ); 2722 2723 rParam.aShareFmts.SetSize( *pBox, aNew ); 2724 } 2725 } 2726 2727 nDist += nWidth; 2728 if( ( TBLFIX_CHGABS == rParam.nMode || rParam.bLeft ) && 2729 nDist > rParam.nSide ) 2730 break; 2731 } 2732 return sal_True; 2733 } 2734 2735 /**/ 2736 2737 sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, 2738 SwTwips nDist, sal_Bool bCheck ) 2739 { 2740 SwTableBoxes& rBoxes = pLine->GetTabBoxes(); 2741 sal_uInt16 n, nCmp; 2742 for( n = 0; n < rBoxes.Count(); ++n ) 2743 { 2744 SwTableBox* pBox = rBoxes[ n ]; 2745 SwTableBoxFmt* pFmt = (SwTableBoxFmt*)pBox->GetFrmFmt(); 2746 const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); 2747 SwTwips nWidth = rSz.GetWidth(); 2748 2749 if( bCheck ) 2750 { 2751 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 2752 if( !::lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam, 2753 nDist, sal_True )) 2754 return sal_False; 2755 2756 // dann noch mal alle "ContentBoxen" sammeln 2757 if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth ) 2758 - rParam.nSide ) < COLFUZZY ) 2759 nCmp = 1; 2760 else if( nDist + ( rParam.bLeft ? 0 : nWidth/2 ) > rParam.nSide ) 2761 nCmp = 2; 2762 else 2763 nCmp = 0; 2764 2765 if( nCmp ) 2766 { 2767 rParam.bAnyBoxFnd = sal_True; 2768 if( pFmt->GetProtect().IsCntntProtected() ) 2769 return sal_False; 2770 2771 if( rParam.bSplittBox && 2772 nWidth - rParam.nDiff <= COLFUZZY + 2773 ( 567 / 2 /* min. 0,5 cm Platz lassen*/) ) 2774 return sal_False; 2775 2776 if( pBox->GetSttNd() ) 2777 rParam.aBoxes.Insert( pBox ); 2778 2779 break; 2780 } 2781 } 2782 else 2783 { 2784 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff; 2785 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 2786 { 2787 rParam.nLowerDiff = 0; 2788 lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam, nDist, sal_False ); 2789 2790 if( nLowerDiff < rParam.nLowerDiff ) 2791 nLowerDiff = rParam.nLowerDiff; 2792 } 2793 rParam.nLowerDiff = nOldLower; 2794 2795 if( nLowerDiff ) 2796 nCmp = 1; 2797 else if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth ) 2798 - rParam.nSide ) < COLFUZZY ) 2799 nCmp = 2; 2800 else if( nDist + nWidth / 2 > rParam.nSide ) 2801 nCmp = 3; 2802 else 2803 nCmp = 0; 2804 2805 if( nCmp ) 2806 { 2807 // in dieser Spalte ist der Cursor - also verkleinern / vergroessern 2808 if( 1 == nCmp ) 2809 { 2810 if( !rParam.bSplittBox ) 2811 { 2812 // die akt. Box auf 2813 SwFmtFrmSize aNew( rSz ); 2814 aNew.SetWidth( nWidth + rParam.nDiff ); 2815 rParam.aShareFmts.SetSize( *pBox, aNew ); 2816 } 2817 } 2818 else 2819 { 2820 ASSERT( pBox->GetSttNd(), "Das muss eine EndBox sein!"); 2821 2822 if( !rParam.bLeft && 3 != nCmp ) 2823 ++n; 2824 2825 ::_InsTblBox( pFmt->GetDoc(), rParam.pTblNd, 2826 pLine, pFmt, pBox, n ); 2827 2828 SwTableBox* pNewBox = rBoxes[ n ]; 2829 SwFmtFrmSize aNew( rSz ); 2830 aNew.SetWidth( rParam.nDiff ); 2831 rParam.aShareFmts.SetSize( *pNewBox, aNew ); 2832 2833 // Sonderfall: kein Platz in den anderen Boxen 2834 // aber in der Zelle 2835 if( rParam.bSplittBox ) 2836 { 2837 // die akt. Box auf 2838 SwFmtFrmSize aNewSize( rSz ); 2839 aNewSize.SetWidth( nWidth - rParam.nDiff ); 2840 rParam.aShareFmts.SetSize( *pBox, aNewSize ); 2841 } 2842 2843 // Sonderbehandlung fuer Umrandung die Rechte muss 2844 // entfernt werden 2845 { 2846 const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox(); 2847 if( rBoxItem.GetRight() ) 2848 { 2849 SvxBoxItem aTmp( rBoxItem ); 2850 aTmp.SetLine( 0, BOX_LINE_RIGHT ); 2851 rParam.aShareFmts.SetAttr( rParam.bLeft 2852 ? *pNewBox 2853 : *pBox, aTmp ); 2854 } 2855 } 2856 } 2857 2858 rParam.nLowerDiff = rParam.nDiff; 2859 break; 2860 } 2861 } 2862 2863 if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide ) 2864 break; 2865 2866 nDist += nWidth; 2867 } 2868 return sal_True; 2869 } 2870 2871 sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, 2872 SwTwips nDist, sal_Bool bCheck ) 2873 { 2874 // Sonderfall: kein Platz in den anderen Boxen aber in der Zelle 2875 if( rParam.bSplittBox ) 2876 return sal_True; 2877 2878 SwTableBoxes& rBoxes = pLine->GetTabBoxes(); 2879 sal_uInt16 n; 2880 2881 // Tabelle fix, proport. 2882 if( !rParam.nRemainWidth && TBLFIX_CHGPROP == rParam.nMode ) 2883 { 2884 // dann die richtige Breite suchen, auf die sich die relative 2885 // Breitenanpassung bezieht. 2886 SwTwips nTmpDist = nDist; 2887 for( n = 0; n < rBoxes.Count(); ++n ) 2888 { 2889 SwTwips nWidth = rBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth(); 2890 if( (nTmpDist + nWidth / 2 ) > rParam.nSide ) 2891 { 2892 rParam.nRemainWidth = rParam.bLeft 2893 ? sal_uInt16(nTmpDist) 2894 : sal_uInt16(rParam.nTblWidth - nTmpDist); 2895 break; 2896 } 2897 nTmpDist += nWidth; 2898 } 2899 } 2900 2901 for( n = 0; n < rBoxes.Count(); ++n ) 2902 { 2903 SwTableBox* pBox = rBoxes[ n ]; 2904 SwFrmFmt* pFmt = pBox->GetFrmFmt(); 2905 const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); 2906 SwTwips nWidth = rSz.GetWidth(); 2907 2908 if( bCheck ) 2909 { 2910 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 2911 if( !::lcl_InsOtherBox( pBox->GetTabLines()[ i ], 2912 rParam, nDist, sal_True )) 2913 return sal_False; 2914 2915 if( 2916 rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide && 2917 (TBLFIX_CHGABS != rParam.nMode || 2918 (n < rBoxes.Count() && 2919 (nDist + nWidth + rBoxes[ n+1 ]-> 2920 GetFrmFmt()->GetFrmSize().GetWidth() / 2) 2921 > rParam.nSide) )) 2922 : (nDist + nWidth / 2 ) > rParam.nSide 2923 ) 2924 { 2925 rParam.bAnyBoxFnd = sal_True; 2926 SwTwips nDiff; 2927 if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport. 2928 { 2929 // relativ berechnen 2930 nDiff = nWidth; 2931 nDiff *= rParam.nDiff; 2932 nDiff /= rParam.nRemainWidth; 2933 2934 if( nWidth < nDiff || nWidth - nDiff < MINLAY ) 2935 return sal_False; 2936 } 2937 else 2938 { 2939 nDiff = rParam.nDiff; 2940 2941 // teste ob die linke oder rechte Box gross genug 2942 // ist, um den Platz abzugeben! 2943 // es wird davor oder dahinter eine Box eingefuegt! 2944 SwTwips nTmpWidth = nWidth; 2945 if( rParam.bLeft && pBox->GetUpper()->GetUpper() ) 2946 { 2947 const SwTableBox* pTmpBox = pBox; 2948 sal_uInt16 nBoxPos = n; 2949 while( !nBoxPos && pTmpBox->GetUpper()->GetUpper() ) 2950 { 2951 pTmpBox = pTmpBox->GetUpper()->GetUpper(); 2952 nBoxPos = pTmpBox->GetUpper()->GetTabBoxes().GetPos( pTmpBox ); 2953 } 2954 // if( nBoxPos ) 2955 nTmpWidth = pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth(); 2956 // else 2957 // nTmpWidth = 0; 2958 } 2959 2960 if( nTmpWidth < nDiff || nTmpWidth - nDiff < MINLAY ) 2961 return sal_False; 2962 break; 2963 } 2964 } 2965 } 2966 else 2967 { 2968 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff; 2969 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 2970 { 2971 rParam.nLowerDiff = 0; 2972 lcl_InsOtherBox( pBox->GetTabLines()[ i ], rParam, 2973 nDist, sal_False ); 2974 2975 if( nLowerDiff < rParam.nLowerDiff ) 2976 nLowerDiff = rParam.nLowerDiff; 2977 } 2978 rParam.nLowerDiff = nOldLower; 2979 2980 if( nLowerDiff || 2981 (rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide && 2982 (TBLFIX_CHGABS != rParam.nMode || 2983 (n < rBoxes.Count() && 2984 (nDist + nWidth + rBoxes[ n+1 ]-> 2985 GetFrmFmt()->GetFrmSize().GetWidth() / 2) 2986 > rParam.nSide) )) 2987 : (nDist + nWidth / 2 ) > rParam.nSide )) 2988 { 2989 if( !nLowerDiff ) 2990 { 2991 if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport. 2992 { 2993 // relativ berechnen 2994 nLowerDiff = nWidth; 2995 nLowerDiff *= rParam.nDiff; 2996 nLowerDiff /= rParam.nRemainWidth; 2997 } 2998 else 2999 nLowerDiff = rParam.nDiff; 3000 } 3001 3002 SwFmtFrmSize aNew( rSz ); 3003 rParam.nLowerDiff += nLowerDiff; 3004 3005 if( rParam.bBigger ) 3006 aNew.SetWidth( nWidth - nLowerDiff ); 3007 else 3008 aNew.SetWidth( nWidth + nLowerDiff ); 3009 rParam.aShareFmts.SetSize( *pBox, aNew ); 3010 3011 if( TBLFIX_CHGABS == rParam.nMode ) 3012 break; 3013 } 3014 } 3015 3016 nDist += nWidth; 3017 } 3018 return sal_True; 3019 } 3020 3021 3022 // das Ergebnis des Positions Vergleiches 3023 // POS_BEFORE, // Box liegt davor 3024 // POS_BEHIND, // Box liegt dahinter 3025 // POS_INSIDE, // Box liegt vollstaendig in Start/End 3026 // POS_OUTSIDE, // Box ueberlappt Start/End vollstaendig 3027 // POS_EQUAL, // Box und Start/End sind gleich 3028 // POS_OVERLAP_BEFORE, // Box ueberlappt den Start 3029 // POS_OVERLAP_BEHIND // Box ueberlappt das Ende 3030 3031 SwComparePosition _CheckBoxInRange( sal_uInt16 nStt, sal_uInt16 nEnd, 3032 sal_uInt16 nBoxStt, sal_uInt16 nBoxEnd ) 3033 { 3034 // COLFUZZY noch beachten!! 3035 SwComparePosition nRet; 3036 if( nBoxStt + COLFUZZY < nStt ) 3037 { 3038 if( nBoxEnd > nStt + COLFUZZY ) 3039 { 3040 if( nBoxEnd >= nEnd + COLFUZZY ) 3041 nRet = POS_OUTSIDE; 3042 else 3043 nRet = POS_OVERLAP_BEFORE; 3044 } 3045 else 3046 nRet = POS_BEFORE; 3047 } 3048 else if( nEnd > nBoxStt + COLFUZZY ) 3049 { 3050 if( nEnd + COLFUZZY >= nBoxEnd ) 3051 { 3052 if( COLFUZZY > Abs( long(nEnd) - long(nBoxEnd) ) && 3053 COLFUZZY > Abs( long(nStt) - long(nBoxStt) ) ) 3054 nRet = POS_EQUAL; 3055 else 3056 nRet = POS_INSIDE; 3057 } 3058 else 3059 nRet = POS_OVERLAP_BEHIND; 3060 } 3061 else 3062 nRet = POS_BEHIND; 3063 3064 return nRet; 3065 } 3066 3067 void lcl_DelSelBox_CorrLowers( SwTableLine& rLine, CR_SetBoxWidth& rParam, 3068 SwTwips nWidth ) 3069 { 3070 // 1. Schritt die eigene Breite feststellen 3071 SwTableBoxes& rBoxes = rLine.GetTabBoxes(); 3072 SwTwips nBoxWidth = 0; 3073 sal_uInt16 n; 3074 3075 for( n = rBoxes.Count(); n; ) 3076 nBoxWidth += rBoxes[ --n ]->GetFrmFmt()->GetFrmSize().GetWidth(); 3077 3078 if( COLFUZZY < Abs( nWidth - nBoxWidth )) 3079 { 3080 // sie muessen also angepasst werden 3081 for( n = rBoxes.Count(); n; ) 3082 { 3083 SwTableBox* pBox = rBoxes[ --n ]; 3084 SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() ); 3085 long nDiff = aNew.GetWidth(); 3086 nDiff *= nWidth; 3087 nDiff /= nBoxWidth; 3088 aNew.SetWidth( nDiff ); 3089 3090 rParam.aShareFmts.SetSize( *pBox, aNew ); 3091 3092 if( !pBox->GetSttNd() ) 3093 { 3094 // hat selbst auch Lower, also auch die anpassen 3095 for( sal_uInt16 i = pBox->GetTabLines().Count(); i; ) 3096 ::lcl_DelSelBox_CorrLowers( *pBox->GetTabLines()[ --i ], 3097 rParam, nDiff ); 3098 } 3099 } 3100 } 3101 } 3102 3103 void lcl_ChgBoxSize( SwTableBox& rBox, CR_SetBoxWidth& rParam, 3104 const SwFmtFrmSize& rOldSz, 3105 sal_uInt16& rDelWidth, SwTwips nDist ) 3106 { 3107 long nDiff = 0; 3108 sal_Bool bSetSize = sal_False; 3109 3110 switch( rParam.nMode ) 3111 { 3112 case TBLFIX_CHGABS: // Tabelle feste Breite, den Nachbar andern 3113 nDiff = rDelWidth + rParam.nLowerDiff; 3114 bSetSize = sal_True; 3115 break; 3116 3117 case TBLFIX_CHGPROP: // Tabelle feste Breite, alle Nachbarn aendern 3118 if( !rParam.nRemainWidth ) 3119 { 3120 // dann kurz berechnen: 3121 if( rParam.bLeft ) 3122 rParam.nRemainWidth = sal_uInt16(nDist); 3123 else 3124 rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist); 3125 } 3126 3127 // relativ berechnen 3128 nDiff = rOldSz.GetWidth(); 3129 nDiff *= rDelWidth + rParam.nLowerDiff; 3130 nDiff /= rParam.nRemainWidth; 3131 3132 bSetSize = sal_True; 3133 break; 3134 3135 case TBLVAR_CHGABS: // Tabelle variable, alle Nachbarn aendern 3136 if( COLFUZZY < Abs( rParam.nBoxWidth - 3137 ( rDelWidth + rParam.nLowerDiff ))) 3138 { 3139 nDiff = rDelWidth + rParam.nLowerDiff - rParam.nBoxWidth; 3140 if( 0 < nDiff ) 3141 rDelWidth = rDelWidth - sal_uInt16(nDiff); 3142 else 3143 rDelWidth = rDelWidth + sal_uInt16(-nDiff); 3144 bSetSize = sal_True; 3145 } 3146 break; 3147 } 3148 3149 if( bSetSize ) 3150 { 3151 SwFmtFrmSize aNew( rOldSz ); 3152 aNew.SetWidth( aNew.GetWidth() + nDiff ); 3153 rParam.aShareFmts.SetSize( rBox, aNew ); 3154 3155 // dann leider nochmals die Lower anpassen 3156 for( sal_uInt16 i = rBox.GetTabLines().Count(); i; ) 3157 ::lcl_DelSelBox_CorrLowers( *rBox.GetTabLines()[ --i ], rParam, 3158 aNew.GetWidth() ); 3159 } 3160 } 3161 3162 sal_Bool lcl_DeleteBox_Rekursiv( CR_SetBoxWidth& rParam, SwTableBox& rBox, 3163 sal_Bool bCheck ) 3164 { 3165 sal_Bool bRet = sal_True; 3166 if( rBox.GetSttNd() ) 3167 { 3168 if( bCheck ) 3169 { 3170 rParam.bAnyBoxFnd = sal_True; 3171 if( rBox.GetFrmFmt()->GetProtect().IsCntntProtected() ) 3172 bRet = sal_False; 3173 else 3174 { 3175 SwTableBox* pBox = &rBox; 3176 rParam.aBoxes.Insert( pBox ); 3177 } 3178 } 3179 else 3180 ::_DeleteBox( rParam.pTblNd->GetTable(), &rBox, 3181 rParam.pUndo, sal_False, sal_True, &rParam.aShareFmts ); 3182 } 3183 else 3184 { 3185 // die muessen leider alle sequentiel ueber die 3186 // Contentboxen geloescht werden 3187 for( sal_uInt16 i = rBox.GetTabLines().Count(); i; ) 3188 { 3189 SwTableLine& rLine = *rBox.GetTabLines()[ --i ]; 3190 for( sal_uInt16 n = rLine.GetTabBoxes().Count(); n; ) 3191 if( !::lcl_DeleteBox_Rekursiv( rParam, 3192 *rLine.GetTabBoxes()[ --n ], bCheck )) 3193 return sal_False; 3194 } 3195 } 3196 return bRet; 3197 } 3198 3199 sal_Bool lcl_DelSelBox( SwTableLine* pTabLine, CR_SetBoxWidth& rParam, 3200 SwTwips nDist, sal_Bool bCheck ) 3201 { 3202 SwTableBoxes& rBoxes = pTabLine->GetTabBoxes(); 3203 sal_uInt16 n, nCntEnd, nBoxChkStt, nBoxChkEnd, nDelWidth = 0; 3204 if( rParam.bLeft ) 3205 { 3206 n = rBoxes.Count(); 3207 nCntEnd = 0; 3208 nBoxChkStt = (sal_uInt16)rParam.nSide; 3209 nBoxChkEnd = static_cast<sal_uInt16>(rParam.nSide + rParam.nBoxWidth); 3210 } 3211 else 3212 { 3213 n = 0; 3214 nCntEnd = rBoxes.Count(); 3215 nBoxChkStt = static_cast<sal_uInt16>(rParam.nSide - rParam.nBoxWidth); 3216 nBoxChkEnd = (sal_uInt16)rParam.nSide; 3217 } 3218 3219 3220 while( n != nCntEnd ) 3221 { 3222 SwTableBox* pBox; 3223 if( rParam.bLeft ) 3224 pBox = rBoxes[ --n ]; 3225 else 3226 pBox = rBoxes[ n++ ]; 3227 3228 SwFrmFmt* pFmt = pBox->GetFrmFmt(); 3229 const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); 3230 long nWidth = rSz.GetWidth(); 3231 sal_Bool bDelBox = sal_False, bChgLowers = sal_False; 3232 3233 // die Boxenbreite testen und entpsrechend reagieren 3234 SwComparePosition ePosType = ::_CheckBoxInRange( 3235 nBoxChkStt, nBoxChkEnd, 3236 sal_uInt16(rParam.bLeft ? nDist - nWidth : nDist), 3237 sal_uInt16(rParam.bLeft ? nDist : nDist + nWidth)); 3238 3239 switch( ePosType ) 3240 { 3241 case POS_BEFORE: 3242 if( bCheck ) 3243 { 3244 if( rParam.bLeft ) 3245 return sal_True; 3246 } 3247 else if( rParam.bLeft ) 3248 { 3249 ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist ); 3250 if( TBLFIX_CHGABS == rParam.nMode ) 3251 n = nCntEnd; 3252 } 3253 break; 3254 3255 case POS_BEHIND: 3256 if( bCheck ) 3257 { 3258 if( !rParam.bLeft ) 3259 return sal_True; 3260 } 3261 else if( !rParam.bLeft ) 3262 { 3263 ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist ); 3264 if( TBLFIX_CHGABS == rParam.nMode ) 3265 n = nCntEnd; 3266 } 3267 break; 3268 3269 case POS_OUTSIDE: // Box ueberlappt Start/End vollstaendig 3270 case POS_INSIDE: // Box liegt vollstaendig in Start/End 3271 case POS_EQUAL: // Box und Start/End sind gleich 3272 bDelBox = sal_True; 3273 break; 3274 3275 case POS_OVERLAP_BEFORE: // Box ueberlappt den Start 3276 if( nBoxChkStt <= ( nDist + (rParam.bLeft ? - nWidth / 2 3277 : nWidth / 2 ))) 3278 { 3279 if( !pBox->GetSttNd() ) 3280 bChgLowers = sal_True; 3281 else 3282 bDelBox = sal_True; 3283 } 3284 else if( !bCheck && rParam.bLeft ) 3285 { 3286 if( !pBox->GetSttNd() ) 3287 bChgLowers = sal_True; 3288 else 3289 { 3290 ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist ); 3291 if( TBLFIX_CHGABS == rParam.nMode ) 3292 n = nCntEnd; 3293 } 3294 } 3295 break; 3296 3297 case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende 3298 // JP 10.02.99: 3299 // generell loeschen oder wie beim OVERLAP_Before nur die, die 3300 // bis zur Haelfte in die "Loesch-"Box reicht ??? 3301 if( !pBox->GetSttNd() ) 3302 bChgLowers = sal_True; 3303 else 3304 bDelBox = sal_True; 3305 break; 3306 default: break; 3307 } 3308 3309 if( bDelBox ) 3310 { 3311 nDelWidth = nDelWidth + sal_uInt16(nWidth); 3312 if( bCheck ) 3313 { 3314 // die letzte/erste Box kann nur bei Tbl-Var geloescht werden, 3315 // wenn diese so gross ist, wie die Aenderung an der Tabelle 3316 if( (( TBLVAR_CHGABS != rParam.nMode || 3317 nDelWidth != rParam.nBoxWidth ) && 3318 COLFUZZY > Abs( rParam.bLeft 3319 ? nWidth - nDist 3320 : (nDist + nWidth - rParam.nTblWidth ))) 3321 || !::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck ) ) 3322 return sal_False; 3323 3324 if( pFmt->GetProtect().IsCntntProtected() ) 3325 return sal_False; 3326 } 3327 else 3328 { 3329 ::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck ); 3330 3331 if( !rParam.bLeft ) 3332 --n, --nCntEnd; 3333 } 3334 } 3335 else if( bChgLowers ) 3336 { 3337 sal_Bool bFirst = sal_True, bCorrLowers = sal_False; 3338 long nLowerDiff = 0; 3339 long nOldLower = rParam.nLowerDiff; 3340 sal_uInt16 nOldRemain = rParam.nRemainWidth; 3341 sal_uInt16 i; 3342 3343 for( i = pBox->GetTabLines().Count(); i; ) 3344 { 3345 rParam.nLowerDiff = nDelWidth + nOldLower; 3346 rParam.nRemainWidth = nOldRemain; 3347 SwTableLine* pLine = pBox->GetTabLines()[ --i ]; 3348 if( !::lcl_DelSelBox( pLine, rParam, nDist, bCheck )) 3349 return sal_False; 3350 3351 // gibt es die Box und die darin enthaltenen Lines noch?? 3352 if( n < rBoxes.Count() && 3353 pBox == rBoxes[ rParam.bLeft ? n : n-1 ] && 3354 i < pBox->GetTabLines().Count() && 3355 pLine == pBox->GetTabLines()[ i ] ) 3356 { 3357 if( !bFirst && !bCorrLowers && 3358 COLFUZZY < Abs( nLowerDiff - rParam.nLowerDiff ) ) 3359 bCorrLowers = sal_True; 3360 3361 // die groesste "loesch" Breite entscheidet, aber nur wenn 3362 // nicht die gesamte Line geloescht wurde 3363 if( nLowerDiff < rParam.nLowerDiff ) 3364 nLowerDiff = rParam.nLowerDiff; 3365 3366 bFirst = sal_False; 3367 } 3368 } 3369 rParam.nLowerDiff = nOldLower; 3370 rParam.nRemainWidth = nOldRemain; 3371 3372 // wurden alle Boxen geloescht? Dann ist die DelBreite natuerlich 3373 // die Boxenbreite 3374 if( !nLowerDiff ) 3375 nLowerDiff = nWidth; 3376 3377 // DelBreite anpassen!! 3378 nDelWidth = nDelWidth + sal_uInt16(nLowerDiff); 3379 3380 if( !bCheck ) 3381 { 3382 // wurde die Box schon entfernt? 3383 if( n > rBoxes.Count() || 3384 pBox != rBoxes[ ( rParam.bLeft ? n : n-1 ) ] ) 3385 { 3386 // dann beim Loeschen nach rechts die Laufvar. anpassen 3387 if( !rParam.bLeft ) 3388 --n, --nCntEnd; 3389 } 3390 else 3391 { 3392 // sonst muss die Groesse der Box angepasst werden 3393 SwFmtFrmSize aNew( rSz ); 3394 sal_Bool bCorrRel = sal_False; 3395 3396 if( TBLVAR_CHGABS != rParam.nMode ) 3397 { 3398 switch( ePosType ) 3399 { 3400 case POS_OVERLAP_BEFORE: // Box ueberlappt den Start 3401 if( TBLFIX_CHGPROP == rParam.nMode ) 3402 bCorrRel = rParam.bLeft; 3403 else if( rParam.bLeft ) // TBLFIX_CHGABS 3404 { 3405 nLowerDiff = nLowerDiff - nDelWidth; 3406 bCorrLowers = sal_True; 3407 n = nCntEnd; 3408 } 3409 break; 3410 3411 case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende 3412 if( TBLFIX_CHGPROP == rParam.nMode ) 3413 bCorrRel = !rParam.bLeft; 3414 else if( !rParam.bLeft ) // TBLFIX_CHGABS 3415 { 3416 nLowerDiff = nLowerDiff - nDelWidth; 3417 bCorrLowers = sal_True; 3418 n = nCntEnd; 3419 } 3420 break; 3421 3422 default: 3423 ASSERT( !pBox, "hier sollte man nie hinkommen" ); 3424 break; 3425 } 3426 } 3427 3428 if( bCorrRel ) 3429 { 3430 if( !rParam.nRemainWidth ) 3431 { 3432 // dann kurz berechnen: 3433 if( rParam.bLeft ) 3434 rParam.nRemainWidth = sal_uInt16(nDist - nLowerDiff); 3435 else 3436 rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist 3437 - nLowerDiff ); 3438 } 3439 3440 long nDiff = aNew.GetWidth() - nLowerDiff; 3441 nDiff *= nDelWidth + rParam.nLowerDiff; 3442 nDiff /= rParam.nRemainWidth; 3443 3444 aNew.SetWidth( aNew.GetWidth() - nLowerDiff + nDiff ); 3445 } 3446 else 3447 aNew.SetWidth( aNew.GetWidth() - nLowerDiff ); 3448 rParam.aShareFmts.SetSize( *pBox, aNew ); 3449 3450 if( bCorrLowers ) 3451 { 3452 // dann leider nochmals die Lower anpassen 3453 for( i = pBox->GetTabLines().Count(); i; ) 3454 ::lcl_DelSelBox_CorrLowers( *pBox-> 3455 GetTabLines()[ --i ], rParam, aNew.GetWidth() ); 3456 } 3457 } 3458 } 3459 } 3460 3461 if( rParam.bLeft ) 3462 nDist -= nWidth; 3463 else 3464 nDist += nWidth; 3465 } 3466 rParam.nLowerDiff = nDelWidth; 3467 return sal_True; 3468 } 3469 3470 // Dummy Funktion fuer die Methode SetColWidth 3471 sal_Bool lcl_DelOtherBox( SwTableLine* , CR_SetBoxWidth& , SwTwips , sal_Bool ) 3472 { 3473 return sal_True; 3474 } 3475 3476 /**/ 3477 3478 void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam ) 3479 { 3480 SwTableBoxes& rBoxes = pLine->GetTabBoxes(); 3481 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 3482 { 3483 SwTableBox* pBox = rBoxes[ n ]; 3484 3485 SwFmtFrmSize aSz( pBox->GetFrmFmt()->GetFrmSize() ); 3486 SwTwips nWidth = aSz.GetWidth(); 3487 nWidth *= rParam.nDiff; 3488 nWidth /= rParam.nMaxSize; 3489 aSz.SetWidth( nWidth ); 3490 rParam.aShareFmts.SetSize( *pBox, aSz ); 3491 3492 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 3493 ::lcl_AjustLines( pBox->GetTabLines()[ i ], rParam ); 3494 } 3495 } 3496 3497 #if defined(DBG_UTIL) || defined( JP_DEBUG ) 3498 3499 void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize ) 3500 { 3501 const SwTableBoxes& rBoxes = rLine.GetTabBoxes(); 3502 3503 SwTwips nAktSize = 0; 3504 // checke doch mal ob die Tabellen korrekte Breiten haben 3505 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 3506 { 3507 const SwTableBox* pBox = rBoxes[ n ]; 3508 const SwTwips nBoxW = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); 3509 nAktSize += nBoxW; 3510 3511 for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) 3512 _CheckBoxWidth( *pBox->GetTabLines()[ i ], nBoxW ); 3513 } 3514 3515 if( Abs( nAktSize - nSize ) > ( COLFUZZY * rBoxes.Count() ) ) 3516 { 3517 DBG_ERROR( "Boxen der Line zu klein/gross" ); 3518 #if defined( WNT ) && defined( JP_DEBUG ) 3519 __asm int 3; 3520 #endif 3521 } 3522 } 3523 3524 #endif 3525 3526 _FndBox* lcl_SaveInsDelData( CR_SetBoxWidth& rParam, SwUndo** ppUndo, 3527 SwTableSortBoxes& rTmpLst, SwTwips nDistStt ) 3528 { 3529 // suche alle Boxen / Lines 3530 SwTable& rTbl = rParam.pTblNd->GetTable(); 3531 3532 if( !rParam.aBoxes.Count() ) 3533 { 3534 // erstmal die Boxen besorgen ! 3535 if( rParam.bBigger ) 3536 for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n ) 3537 ::lcl_DelSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True ); 3538 else 3539 for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n ) 3540 ::lcl_InsSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True ); 3541 } 3542 3543 // loeschen der gesamten Tabelle verhindern 3544 if( rParam.bBigger && rParam.aBoxes.Count() == 3545 rTbl.GetTabSortBoxes().Count() ) 3546 return 0; 3547 3548 _FndBox* pFndBox = new _FndBox( 0, 0 ); 3549 if( rParam.bBigger ) 3550 pFndBox->SetTableLines( rParam.aBoxes, rTbl ); 3551 else 3552 { 3553 _FndPara aPara( rParam.aBoxes, pFndBox ); 3554 rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); 3555 ASSERT( pFndBox->GetLines().Count(), "Wo sind die Boxen" ); 3556 pFndBox->SetTableLines( rTbl ); 3557 3558 if( ppUndo ) 3559 rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); 3560 } 3561 3562 //Lines fuer das Layout-Update herausuchen. 3563 pFndBox->DelFrms( rTbl ); 3564 3565 // TL_CHART2: this function gest called from SetColWidth exclusively, 3566 // thus it is currently speculated that nothing needs to be done here. 3567 // Note: that SetColWidth is currently not completely understood though :-( 3568 3569 return pFndBox; 3570 } 3571 3572 sal_Bool SwTable::SetColWidth( SwTableBox& rAktBox, sal_uInt16 eType, 3573 SwTwips nAbsDiff, SwTwips nRelDiff, SwUndo** ppUndo ) 3574 { 3575 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 3576 3577 const SwFmtFrmSize& rSz = GetFrmFmt()->GetFrmSize(); 3578 const SvxLRSpaceItem& rLR = GetFrmFmt()->GetLRSpace(); 3579 3580 _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen 3581 SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo 3582 sal_Bool bBigger, 3583 bRet = sal_False, 3584 bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) || 3585 nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ), 3586 bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL ); 3587 sal_uInt16 n; 3588 sal_uLong nBoxIdx = rAktBox.GetSttIdx(); 3589 3590 // bestimme die akt. Kante der Box 3591 // wird nur fuer die Breitenmanipulation benoetigt! 3592 const SwTwips nDist = ::lcl_GetDistance( &rAktBox, bLeft ); 3593 SwTwips nDistStt = 0; 3594 CR_SetBoxWidth aParam( eType, nRelDiff, nDist, rSz.GetWidth(), 3595 bLeft ? nDist : rSz.GetWidth() - nDist, 3596 (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() ); 3597 bBigger = aParam.bBigger; 3598 3599 FN_lcl_SetBoxWidth fnSelBox, fnOtherBox; 3600 if( bInsDel ) 3601 { 3602 if( bBigger ) 3603 { 3604 fnSelBox = lcl_DelSelBox; 3605 fnOtherBox = lcl_DelOtherBox; 3606 aParam.nBoxWidth = (sal_uInt16)rAktBox.GetFrmFmt()->GetFrmSize().GetWidth(); 3607 if( bLeft ) 3608 nDistStt = rSz.GetWidth(); 3609 } 3610 else 3611 { 3612 fnSelBox = lcl_InsSelBox; 3613 fnOtherBox = lcl_InsOtherBox; 3614 } 3615 } 3616 else 3617 { 3618 fnSelBox = lcl_SetSelBoxWidth; 3619 fnOtherBox = lcl_SetOtherBoxWidth; 3620 } 3621 3622 3623 switch( eType & 0xff ) 3624 { 3625 case nsTblChgWidthHeightType::WH_COL_RIGHT: 3626 case nsTblChgWidthHeightType::WH_COL_LEFT: 3627 if( TBLVAR_CHGABS == eTblChgMode ) 3628 { 3629 if( bInsDel ) 3630 bBigger = !bBigger; 3631 3632 // erstmal testen, ob ueberhaupt Platz ist 3633 sal_Bool bChgLRSpace = sal_True; 3634 if( bBigger ) 3635 { 3636 if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) && 3637 !rSz.GetWidthPercent() ) 3638 { 3639 bRet = rSz.GetWidth() < USHRT_MAX - nRelDiff; 3640 bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff 3641 : rLR.GetRight() >= nAbsDiff; 3642 } 3643 else 3644 bRet = bLeft ? rLR.GetLeft() >= nAbsDiff 3645 : rLR.GetRight() >= nAbsDiff; 3646 3647 if( !bRet && bInsDel && 3648 // auf der anderen Seite Platz? 3649 ( bLeft ? rLR.GetRight() >= nAbsDiff 3650 : rLR.GetLeft() >= nAbsDiff )) 3651 { 3652 bRet = sal_True; bLeft = !bLeft; 3653 } 3654 3655 if( !bRet ) 3656 { 3657 // dann sich selbst rekursiv aufrufen; nur mit 3658 // einem anderen Mode -> proprotional 3659 TblChgMode eOld = eTblChgMode; 3660 eTblChgMode = TBLFIX_CHGPROP; 3661 3662 bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff, 3663 ppUndo ); 3664 eTblChgMode = eOld; 3665 return bRet; 3666 } 3667 } 3668 else 3669 { 3670 bRet = sal_True; 3671 for( n = 0; n < aLines.Count(); ++n ) 3672 { 3673 aParam.LoopClear(); 3674 if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True )) 3675 { 3676 bRet = sal_False; 3677 break; 3678 } 3679 } 3680 } 3681 3682 if( bRet ) 3683 { 3684 if( bInsDel ) 3685 { 3686 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, 3687 aTmpLst, nDistStt ); 3688 if( aParam.bBigger && aParam.aBoxes.Count() == 3689 aSortCntBoxes.Count() ) 3690 { 3691 // dies gesamte Tabelle soll geloescht werden!! 3692 GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes ); 3693 return sal_False; 3694 } 3695 3696 if( ppUndo ) 3697 *ppUndo = aParam.CreateUndo( 3698 aParam.bBigger ? UNDO_COL_DELETE 3699 : UNDO_TABLE_INSCOL ); 3700 } 3701 else if( ppUndo ) 3702 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); 3703 3704 long nFrmWidth = LONG_MAX; 3705 LockModify(); 3706 SwFmtFrmSize aSz( rSz ); 3707 SvxLRSpaceItem aLR( rLR ); 3708 if( bBigger ) 3709 { 3710 // falls die Tabelle keinen Platz zum Wachsen hat, dann 3711 // muessen wir welchen schaffen! 3712 if( aSz.GetWidth() + nRelDiff > USHRT_MAX ) 3713 { 3714 // dann mal herunterbrechen auf USHRT_MAX / 2 3715 CR_SetBoxWidth aTmpPara( 0, aSz.GetWidth() / 2, 3716 0, aSz.GetWidth(), aSz.GetWidth(), aParam.pTblNd ); 3717 for( sal_uInt16 nLn = 0; nLn < aLines.Count(); ++nLn ) 3718 ::lcl_AjustLines( aLines[ nLn ], aTmpPara ); 3719 aSz.SetWidth( aSz.GetWidth() / 2 ); 3720 aParam.nDiff = nRelDiff /= 2; 3721 aParam.nSide /= 2; 3722 aParam.nMaxSize /= 2; 3723 } 3724 3725 if( bLeft ) 3726 aLR.SetLeft( sal_uInt16( aLR.GetLeft() - nAbsDiff ) ); 3727 else 3728 aLR.SetRight( sal_uInt16( aLR.GetRight() - nAbsDiff ) ); 3729 } 3730 else if( bLeft ) 3731 aLR.SetLeft( sal_uInt16( aLR.GetLeft() + nAbsDiff ) ); 3732 else 3733 aLR.SetRight( sal_uInt16( aLR.GetRight() + nAbsDiff ) ); 3734 3735 if( bChgLRSpace ) 3736 GetFrmFmt()->SetFmtAttr( aLR ); 3737 const SwFmtHoriOrient& rHOri = GetFrmFmt()->GetHoriOrient(); 3738 if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() || 3739 (text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) || 3740 (text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight())) 3741 { 3742 SwFmtHoriOrient aHOri( rHOri ); 3743 aHOri.SetHoriOrient( text::HoriOrientation::NONE ); 3744 GetFrmFmt()->SetFmtAttr( aHOri ); 3745 3746 // sollte die Tabelle noch auf relativen Werten 3747 // (USHRT_MAX) stehen dann muss es jetzt auf absolute 3748 // umgerechnet werden. Bug 61494 3749 if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) && 3750 !rSz.GetWidthPercent() ) 3751 { 3752 SwTabFrm* pTabFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() ); 3753 if( pTabFrm && 3754 pTabFrm->Prt().Width() != rSz.GetWidth() ) 3755 { 3756 nFrmWidth = pTabFrm->Prt().Width(); 3757 if( bBigger ) 3758 nFrmWidth += nAbsDiff; 3759 else 3760 nFrmWidth -= nAbsDiff; 3761 } 3762 } 3763 } 3764 3765 if( bBigger ) 3766 aSz.SetWidth( aSz.GetWidth() + nRelDiff ); 3767 else 3768 aSz.SetWidth( aSz.GetWidth() - nRelDiff ); 3769 3770 if( rSz.GetWidthPercent() ) 3771 aSz.SetWidthPercent( static_cast<sal_uInt8>(( aSz.GetWidth() * 100 ) / 3772 ( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft()))); 3773 3774 GetFrmFmt()->SetFmtAttr( aSz ); 3775 aParam.nTblWidth = sal_uInt16( aSz.GetWidth() ); 3776 3777 UnlockModify(); 3778 3779 for( n = aLines.Count(); n; ) 3780 { 3781 --n; 3782 aParam.LoopClear(); 3783 (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False ); 3784 } 3785 3786 // sollte die Tabelle noch auf relativen Werten 3787 // (USHRT_MAX) stehen dann muss es jetzt auf absolute 3788 // umgerechnet werden. Bug 61494 3789 if( LONG_MAX != nFrmWidth ) 3790 { 3791 SwFmtFrmSize aAbsSz( aSz ); 3792 aAbsSz.SetWidth( nFrmWidth ); 3793 GetFrmFmt()->SetFmtAttr( aAbsSz ); 3794 } 3795 } 3796 } 3797 else if( bInsDel || 3798 ( bLeft ? nDist : Abs( rSz.GetWidth() - nDist ) > COLFUZZY ) ) 3799 { 3800 bRet = sal_True; 3801 if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel ) 3802 aParam.bBigger = !bBigger; 3803 3804 // erstmal testen, ob ueberhaupt Platz ist 3805 if( bInsDel ) 3806 { 3807 if( aParam.bBigger ) 3808 { 3809 for( n = 0; n < aLines.Count(); ++n ) 3810 { 3811 aParam.LoopClear(); 3812 if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True )) 3813 { 3814 bRet = sal_False; 3815 break; 3816 } 3817 } 3818 } 3819 else 3820 { 3821 if( 0 != ( bRet = bLeft ? nDist != 0 3822 : ( rSz.GetWidth() - nDist ) > COLFUZZY ) ) 3823 { 3824 for( n = 0; n < aLines.Count(); ++n ) 3825 { 3826 aParam.LoopClear(); 3827 if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True )) 3828 { 3829 bRet = sal_False; 3830 break; 3831 } 3832 } 3833 if( bRet && !aParam.bAnyBoxFnd ) 3834 bRet = sal_False; 3835 } 3836 3837 if( !bRet && rAktBox.GetFrmFmt()->GetFrmSize().GetWidth() 3838 - nRelDiff > COLFUZZY + 3839 ( 567 / 2 /* min. 0,5 cm Platz lassen*/) ) 3840 { 3841 // dann den Platz von der akt. Zelle nehmen 3842 aParam.bSplittBox = sal_True; 3843 // aber das muss auch mal getestet werden! 3844 bRet = sal_True; 3845 3846 for( n = 0; n < aLines.Count(); ++n ) 3847 { 3848 aParam.LoopClear(); 3849 if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True )) 3850 { 3851 bRet = sal_False; 3852 break; 3853 } 3854 } 3855 } 3856 } 3857 } 3858 else if( aParam.bBigger ) 3859 { 3860 for( n = 0; n < aLines.Count(); ++n ) 3861 { 3862 aParam.LoopClear(); 3863 if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True )) 3864 { 3865 bRet = sal_False; 3866 break; 3867 } 3868 } 3869 } 3870 else 3871 { 3872 for( n = 0; n < aLines.Count(); ++n ) 3873 { 3874 aParam.LoopClear(); 3875 if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True )) 3876 { 3877 bRet = sal_False; 3878 break; 3879 } 3880 } 3881 } 3882 3883 // wenn ja, dann setzen 3884 if( bRet ) 3885 { 3886 CR_SetBoxWidth aParam1( aParam ); 3887 if( bInsDel ) 3888 { 3889 aParam1.bBigger = !aParam.bBigger; 3890 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, 3891 aTmpLst, nDistStt ); 3892 if( ppUndo ) 3893 *ppUndo = aParam.CreateUndo( 3894 aParam.bBigger ? UNDO_TABLE_DELBOX 3895 : UNDO_TABLE_INSCOL ); 3896 } 3897 else if( ppUndo ) 3898 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); 3899 3900 if( bInsDel 3901 ? ( TBLFIX_CHGABS == eTblChgMode ? bLeft : bLeft ) 3902 : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) ) 3903 { 3904 for( n = aLines.Count(); n; ) 3905 { 3906 --n; 3907 aParam.LoopClear(); 3908 aParam1.LoopClear(); 3909 (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False ); 3910 (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False ); 3911 } 3912 } 3913 else 3914 for( n = aLines.Count(); n; ) 3915 { 3916 --n; 3917 aParam.LoopClear(); 3918 aParam1.LoopClear(); 3919 (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False ); 3920 (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False ); 3921 } 3922 } 3923 } 3924 break; 3925 3926 case nsTblChgWidthHeightType::WH_CELL_RIGHT: 3927 case nsTblChgWidthHeightType::WH_CELL_LEFT: 3928 if( TBLVAR_CHGABS == eTblChgMode ) 3929 { 3930 // dann sich selbst rekursiv aufrufen; nur mit 3931 // einem anderen Mode -> Nachbarn 3932 TblChgMode eOld = eTblChgMode; 3933 eTblChgMode = TBLFIX_CHGABS; 3934 3935 bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff, 3936 ppUndo ); 3937 eTblChgMode = eOld; 3938 return bRet; 3939 } 3940 else if( bInsDel || ( bLeft ? nDist 3941 : (rSz.GetWidth() - nDist) > COLFUZZY )) 3942 { 3943 if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel ) 3944 aParam.bBigger = !bBigger; 3945 3946 // erstmal testen, ob ueberhaupt Platz ist 3947 SwTableBox* pBox = &rAktBox; 3948 SwTableLine* pLine = rAktBox.GetUpper(); 3949 while( pLine->GetUpper() ) 3950 { 3951 sal_uInt16 nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox ); 3952 if( bLeft ? nPos : nPos + 1 != pLine->GetTabBoxes().Count() ) 3953 break; 3954 3955 pBox = pLine->GetUpper(); 3956 pLine = pBox->GetUpper(); 3957 } 3958 3959 if( pLine->GetUpper() ) 3960 { 3961 // dann muss die Distanz wieder korriegiert werden! 3962 aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), sal_True ); 3963 3964 if( bLeft ) 3965 aParam.nMaxSize = aParam.nSide; 3966 else 3967 aParam.nMaxSize = pLine->GetUpper()->GetFrmFmt()-> 3968 GetFrmSize().GetWidth() - aParam.nSide; 3969 } 3970 3971 // erstmal testen, ob ueberhaupt Platz ist 3972 if( bInsDel ) 3973 { 3974 if( 0 != ( bRet = bLeft ? nDist != 0 3975 : ( rSz.GetWidth() - nDist ) > COLFUZZY ) && 3976 !aParam.bBigger ) 3977 { 3978 bRet = (*fnOtherBox)( pLine, aParam, 0, sal_True ); 3979 if( bRet && !aParam.bAnyBoxFnd ) 3980 bRet = sal_False; 3981 } 3982 3983 if( !bRet && !aParam.bBigger && rAktBox.GetFrmFmt()-> 3984 GetFrmSize().GetWidth() - nRelDiff > COLFUZZY + 3985 ( 567 / 2 /* min. 0,5 cm Platz lassen*/) ) 3986 { 3987 // dann den Platz von der akt. Zelle nehmen 3988 aParam.bSplittBox = sal_True; 3989 bRet = sal_True; 3990 } 3991 } 3992 else 3993 { 3994 FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox; 3995 bRet = (*fnTmp)( pLine, aParam, nDistStt, sal_True ); 3996 } 3997 3998 // wenn ja, dann setzen 3999 if( bRet ) 4000 { 4001 CR_SetBoxWidth aParam1( aParam ); 4002 if( bInsDel ) 4003 { 4004 aParam1.bBigger = !aParam.bBigger; 4005 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst, nDistStt ); 4006 if( ppUndo ) 4007 *ppUndo = aParam.CreateUndo( 4008 aParam.bBigger ? UNDO_TABLE_DELBOX 4009 : UNDO_TABLE_INSCOL ); 4010 } 4011 else if( ppUndo ) 4012 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); 4013 4014 if( bInsDel 4015 ? ( TBLFIX_CHGABS == eTblChgMode ? (bBigger && bLeft) : bLeft ) 4016 : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) ) 4017 { 4018 (*fnSelBox)( pLine, aParam, nDistStt, sal_False ); 4019 (*fnOtherBox)( pLine, aParam1, nDistStt, sal_False ); 4020 } 4021 else 4022 { 4023 (*fnOtherBox)( pLine, aParam1, nDistStt, sal_False ); 4024 (*fnSelBox)( pLine, aParam, nDistStt, sal_False ); 4025 } 4026 } 4027 } 4028 break; 4029 4030 } 4031 4032 if( pFndBox ) 4033 { 4034 // dann raeume die Struktur aller Lines auf 4035 GCLines(); 4036 4037 //Layout updaten 4038 if( !bBigger || pFndBox->AreLinesToRestore( *this ) ) 4039 pFndBox->MakeFrms( *this ); 4040 4041 // TL_CHART2: it is currently unclear if sth has to be done here. 4042 // The function name hints that nothing needs to be done, on the other 4043 // hand there is a case where sth gets deleted. :-( 4044 4045 delete pFndBox; 4046 4047 if( ppUndo && *ppUndo ) 4048 { 4049 aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType, 4050 nAbsDiff, nRelDiff ); 4051 if( !aParam.bBigger ) 4052 aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst ); 4053 } 4054 } 4055 4056 if( bRet ) 4057 { 4058 CHECKBOXWIDTH 4059 CHECKTABLELAYOUT 4060 } 4061 4062 return bRet; 4063 } 4064 /* */ 4065 4066 _FndBox* lcl_SaveInsDelData( CR_SetLineHeight& rParam, SwUndo** ppUndo, 4067 SwTableSortBoxes& rTmpLst ) 4068 { 4069 // suche alle Boxen / Lines 4070 SwTable& rTbl = rParam.pTblNd->GetTable(); 4071 4072 ASSERT( rParam.aBoxes.Count(), "ohne Boxen ist nichts zu machen!" ); 4073 4074 // loeschen der gesamten Tabelle verhindern 4075 if( !rParam.bBigger && rParam.aBoxes.Count() == 4076 rTbl.GetTabSortBoxes().Count() ) 4077 return 0; 4078 4079 _FndBox* pFndBox = new _FndBox( 0, 0 ); 4080 if( !rParam.bBigger ) 4081 pFndBox->SetTableLines( rParam.aBoxes, rTbl ); 4082 else 4083 { 4084 _FndPara aPara( rParam.aBoxes, pFndBox ); 4085 rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); 4086 ASSERT( pFndBox->GetLines().Count(), "Wo sind die Boxen" ); 4087 pFndBox->SetTableLines( rTbl ); 4088 4089 if( ppUndo ) 4090 rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); 4091 } 4092 4093 //Lines fuer das Layout-Update heraussuchen. 4094 pFndBox->DelFrms( rTbl ); 4095 4096 // TL_CHART2: it is currently unclear if sth has to be done here. 4097 4098 return pFndBox; 4099 } 4100 4101 void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight, 4102 sal_Bool bMinSize ) 4103 { 4104 SwLayoutFrm* pLineFrm = GetRowFrm( rLine ); 4105 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); 4106 4107 SwFrmFmt* pFmt = rLine.ClaimFrmFmt(); 4108 4109 SwTwips nMyNewH, nMyOldH = pLineFrm->Frm().Height(); 4110 if( !nOldHeight ) // die BaseLine und absolut 4111 nMyNewH = nMyOldH + nNewHeight; 4112 else 4113 { 4114 // moeglichst genau rechnen 4115 Fraction aTmp( nMyOldH ); 4116 aTmp *= Fraction( nNewHeight, nOldHeight ); 4117 aTmp += Fraction( 1, 2 ); // ggfs. aufrunden 4118 nMyNewH = aTmp; 4119 } 4120 4121 SwFrmSize eSize = ATT_MIN_SIZE; 4122 if( !bMinSize && 4123 ( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrm ) + ROWFUZZY )) 4124 eSize = ATT_FIX_SIZE; 4125 4126 pFmt->SetFmtAttr( SwFmtFrmSize( eSize, 0, nMyNewH ) ); 4127 4128 // erst alle inneren anpassen 4129 SwTableBoxes& rBoxes = rLine.GetTabBoxes(); 4130 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 4131 { 4132 SwTableBox& rBox = *rBoxes[ n ]; 4133 for( sal_uInt16 i = 0; i < rBox.GetTabLines().Count(); ++i ) 4134 SetLineHeight( *rBox.GetTabLines()[ i ], nMyOldH, nMyNewH, bMinSize ); 4135 } 4136 } 4137 4138 sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam, 4139 SwTwips nDist, sal_Bool bCheck ) 4140 { 4141 sal_Bool bRet = sal_True; 4142 if( !bCheck ) 4143 { 4144 // Zeilenhoehe einstellen 4145 SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist, 4146 rParam.bBigger ); 4147 } 4148 else if( !rParam.bBigger ) 4149 { 4150 // anhand der alten Size die neue relative errechnen 4151 SwLayoutFrm* pLineFrm = GetRowFrm( *pLine ); 4152 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); 4153 SwTwips nRstHeight = CalcRowRstHeight( pLineFrm ); 4154 if( (nRstHeight + ROWFUZZY) < nDist ) 4155 bRet = sal_False; 4156 } 4157 return bRet; 4158 } 4159 4160 sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam, 4161 SwTwips nDist, sal_Bool bCheck ) 4162 { 4163 sal_Bool bRet = sal_True; 4164 if( bCheck ) 4165 { 4166 if( rParam.bBigger ) 4167 { 4168 // anhand der alten Size die neue relative errechnen 4169 SwLayoutFrm* pLineFrm = GetRowFrm( *pLine ); 4170 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); 4171 4172 if( TBLFIX_CHGPROP == rParam.nMode ) 4173 { 4174 nDist *= pLineFrm->Frm().Height(); 4175 nDist /= rParam.nMaxHeight; 4176 } 4177 bRet = nDist <= CalcRowRstHeight( pLineFrm ); 4178 } 4179 } 4180 else 4181 { 4182 // Zeilenhoehe einstellen 4183 // pLine ist die nachfolgende / vorhergehende -> also anpassen 4184 if( TBLFIX_CHGPROP == rParam.nMode ) 4185 { 4186 SwLayoutFrm* pLineFrm = GetRowFrm( *pLine ); 4187 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); 4188 4189 // aus der alten Size die neue relative errechnen 4190 // Wird die selektierte Box groesser ueber den MaxSpace anpassen, 4191 // sonst ueber die MaxHeight 4192 if( 1 /*!rParam.bBigger*/ ) 4193 { 4194 nDist *= pLineFrm->Frm().Height(); 4195 nDist /= rParam.nMaxHeight; 4196 } 4197 else 4198 { 4199 // aus der alten Size die neue relative errechnen 4200 nDist *= CalcRowRstHeight( pLineFrm ); 4201 nDist /= rParam.nMaxSpace; 4202 } 4203 } 4204 SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist, 4205 !rParam.bBigger ); 4206 } 4207 return bRet; 4208 } 4209 4210 sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam, 4211 SwTwips nDist, sal_Bool bCheck ) 4212 { 4213 sal_Bool bRet = sal_True; 4214 if( !bCheck ) 4215 { 4216 SwTableBoxes& rBoxes = pLine->GetTabBoxes(); 4217 SwDoc* pDoc = pLine->GetFrmFmt()->GetDoc(); 4218 if( !rParam.bBigger ) 4219 { 4220 sal_uInt16 n; 4221 4222 for( n = rBoxes.Count(); n; ) 4223 ::lcl_SaveUpperLowerBorder( rParam.pTblNd->GetTable(), 4224 *rBoxes[ --n ], 4225 rParam.aShareFmts ); 4226 for( n = rBoxes.Count(); n; ) 4227 ::_DeleteBox( rParam.pTblNd->GetTable(), 4228 rBoxes[ --n ], rParam.pUndo, sal_False, 4229 sal_False, &rParam.aShareFmts ); 4230 } 4231 else 4232 { 4233 // Zeile einfuegen 4234 SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)pLine->GetFrmFmt(), 4235 rBoxes.Count(), pLine->GetUpper() ); 4236 SwTableLines* pLines; 4237 if( pLine->GetUpper() ) 4238 pLines = &pLine->GetUpper()->GetTabLines(); 4239 else 4240 pLines = &rParam.pTblNd->GetTable().GetTabLines(); 4241 sal_uInt16 nPos = pLines->C40_GETPOS( SwTableLine, pLine ); 4242 if( !rParam.bTop ) 4243 ++nPos; 4244 pLines->C40_INSERT( SwTableLine, pNewLine, nPos ); 4245 4246 SwFrmFmt* pNewFmt = pNewLine->ClaimFrmFmt(); 4247 pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE, 0, nDist ) ); 4248 4249 // und noch mal die Anzahl Boxen erzeugen 4250 SwTableBoxes& rNewBoxes = pNewLine->GetTabBoxes(); 4251 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 4252 { 4253 SwTwips nWidth = 0; 4254 SwTableBox* pOld = rBoxes[ n ]; 4255 if( !pOld->GetSttNd() ) 4256 { 4257 // keine normale "Content"-Box also auf die 1. naechste 4258 // Box zurueckfallen 4259 nWidth = pOld->GetFrmFmt()->GetFrmSize().GetWidth(); 4260 while( !pOld->GetSttNd() ) 4261 pOld = pOld->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ]; 4262 } 4263 ::_InsTblBox( pDoc, rParam.pTblNd, pNewLine, 4264 (SwTableBoxFmt*)pOld->GetFrmFmt(), pOld, n ); 4265 4266 // Sonderbehandlung fuer Umrandung die Obere muss 4267 // entfernt werden 4268 const SvxBoxItem& rBoxItem = pOld->GetFrmFmt()->GetBox(); 4269 if( rBoxItem.GetTop() ) 4270 { 4271 SvxBoxItem aTmp( rBoxItem ); 4272 aTmp.SetLine( 0, BOX_LINE_TOP ); 4273 rParam.aShareFmts.SetAttr( rParam.bTop 4274 ? *pOld 4275 : *rNewBoxes[ n ], aTmp ); 4276 } 4277 4278 if( nWidth ) 4279 rParam.aShareFmts.SetAttr( *rNewBoxes[ n ], 4280 SwFmtFrmSize( ATT_FIX_SIZE, nWidth, 0 ) ); 4281 } 4282 } 4283 } 4284 else 4285 { 4286 // Boxen einsammeln! 4287 SwTableBoxes& rBoxes = pLine->GetTabBoxes(); 4288 for( sal_uInt16 n = rBoxes.Count(); n; ) 4289 { 4290 SwTableBox* pBox = rBoxes[ --n ]; 4291 if( pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) 4292 return sal_False; 4293 4294 if( pBox->GetSttNd() ) 4295 rParam.aBoxes.Insert( pBox ); 4296 else 4297 { 4298 for( sal_uInt16 i = pBox->GetTabLines().Count(); i; ) 4299 lcl_InsDelSelLine( pBox->GetTabLines()[ --i ], 4300 rParam, 0, sal_True ); 4301 } 4302 } 4303 } 4304 return bRet; 4305 } 4306 4307 sal_Bool SwTable::SetRowHeight( SwTableBox& rAktBox, sal_uInt16 eType, 4308 SwTwips nAbsDiff, SwTwips nRelDiff,SwUndo** ppUndo ) 4309 { 4310 SwTableLine* pLine = rAktBox.GetUpper(); 4311 4312 SwTableLine* pBaseLine = pLine; 4313 while( pBaseLine->GetUpper() ) 4314 pBaseLine = pBaseLine->GetUpper()->GetUpper(); 4315 4316 _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen 4317 SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo 4318 sal_Bool bBigger, 4319 bRet = sal_False, 4320 bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || 4321 nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ), 4322 bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL ); 4323 sal_uInt16 n, nBaseLinePos = GetTabLines().C40_GETPOS( SwTableLine, pBaseLine ); 4324 sal_uLong nBoxIdx = rAktBox.GetSttIdx(); 4325 4326 CR_SetLineHeight aParam( eType, 4327 (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() ); 4328 bBigger = aParam.bBigger; 4329 4330 FN_lcl_SetLineHeight fnSelLine, fnOtherLine = lcl_SetOtherLineHeight; 4331 if( bInsDel ) 4332 fnSelLine = lcl_InsDelSelLine; 4333 else 4334 fnSelLine = lcl_SetSelLineHeight; 4335 4336 SwTableLines* pLines = &aLines; 4337 4338 // wie kommt man an die Hoehen heran? 4339 switch( eType & 0xff ) 4340 { 4341 case nsTblChgWidthHeightType::WH_CELL_TOP: 4342 case nsTblChgWidthHeightType::WH_CELL_BOTTOM: 4343 if( pLine == pBaseLine ) 4344 break; // dann geht es nicht! 4345 4346 // ist eine verschachtelte Line (Box!) 4347 pLines = &pLine->GetUpper()->GetTabLines(); 4348 nBaseLinePos = pLines->C40_GETPOS( SwTableLine, pLine ); 4349 pBaseLine = pLine; 4350 // kein break! 4351 4352 case nsTblChgWidthHeightType::WH_ROW_TOP: 4353 case nsTblChgWidthHeightType::WH_ROW_BOTTOM: 4354 { 4355 if( bInsDel && !bBigger ) // um wieviel wird es Hoeher? 4356 { 4357 nAbsDiff = GetRowFrm( *pBaseLine )->Frm().Height(); 4358 } 4359 4360 if( TBLVAR_CHGABS == eTblChgMode ) 4361 { 4362 // erstmal testen, ob ueberhaupt Platz ist 4363 if( bBigger ) 4364 { 4365 bRet = sal_True; 4366 // was ist mit Top, was ist mit Tabelle im Rahmen oder in Kopf-/Fusszeile 4367 // mit fester Hoehe ?? 4368 if( !bRet ) 4369 { 4370 // dann sich selbst rekursiv aufrufen; nur mit 4371 // einem anderen Mode -> proprotional 4372 TblChgMode eOld = eTblChgMode; 4373 eTblChgMode = TBLFIX_CHGPROP; 4374 4375 bRet = SetRowHeight( rAktBox, eType, nAbsDiff, 4376 nRelDiff, ppUndo ); 4377 4378 eTblChgMode = eOld; 4379 return bRet; 4380 } 4381 } 4382 else 4383 bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, 4384 nAbsDiff, sal_True ); 4385 4386 if( bRet ) 4387 { 4388 if( bInsDel ) 4389 { 4390 if( !aParam.aBoxes.Count() ) 4391 ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ], 4392 aParam, 0, sal_True ); 4393 4394 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst ); 4395 4396 // #110525# delete complete table when last row is 4397 // deleted 4398 if( !bBigger && 4399 aParam.aBoxes.Count() == aSortCntBoxes.Count() ) 4400 { 4401 GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes ); 4402 return sal_False; 4403 } 4404 4405 4406 if( ppUndo ) 4407 *ppUndo = aParam.CreateUndo( 4408 bBigger ? UNDO_TABLE_INSROW 4409 : UNDO_ROW_DELETE ); 4410 } 4411 else if( ppUndo ) 4412 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); 4413 4414 (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, 4415 nAbsDiff, sal_False ); 4416 } 4417 } 4418 else 4419 { 4420 bRet = sal_True; 4421 sal_uInt16 nStt, nEnd; 4422 if( bTop ) 4423 nStt = 0, nEnd = nBaseLinePos; 4424 else 4425 nStt = nBaseLinePos + 1, nEnd = pLines->Count(); 4426 4427 // die akt. Hoehe der Lines besorgen 4428 if( TBLFIX_CHGPROP == eTblChgMode ) 4429 { 4430 for( n = nStt; n < nEnd; ++n ) 4431 { 4432 SwLayoutFrm* pLineFrm = GetRowFrm( *(*pLines)[ n ] ); 4433 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); 4434 aParam.nMaxSpace += CalcRowRstHeight( pLineFrm ); 4435 aParam.nMaxHeight += pLineFrm->Frm().Height(); 4436 } 4437 if( bBigger && aParam.nMaxSpace < nAbsDiff ) 4438 bRet = sal_False; 4439 } 4440 else 4441 { 4442 if( bTop ? nEnd : nStt < nEnd ) 4443 { 4444 if( bTop ) 4445 nStt = nEnd - 1; 4446 else 4447 nEnd = nStt + 1; 4448 } 4449 else 4450 bRet = sal_False; 4451 } 4452 4453 if( bRet ) 4454 { 4455 if( bBigger ) 4456 { 4457 for( n = nStt; n < nEnd; ++n ) 4458 { 4459 if( !(*fnOtherLine)( (*pLines)[ n ], aParam, 4460 nAbsDiff, sal_True )) 4461 { 4462 bRet = sal_False; 4463 break; 4464 } 4465 } 4466 } 4467 else 4468 bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, 4469 nAbsDiff, sal_True ); 4470 } 4471 4472 if( bRet ) 4473 { 4474 // dann mal anpassen 4475 if( bInsDel ) 4476 { 4477 if( !aParam.aBoxes.Count() ) 4478 ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ], 4479 aParam, 0, sal_True ); 4480 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst ); 4481 if( ppUndo ) 4482 *ppUndo = aParam.CreateUndo( 4483 bBigger ? UNDO_TABLE_INSROW 4484 : UNDO_ROW_DELETE ); 4485 } 4486 else if( ppUndo ) 4487 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); 4488 4489 CR_SetLineHeight aParam1( aParam ); 4490 if( TBLFIX_CHGPROP == eTblChgMode && !bBigger && 4491 !aParam.nMaxSpace ) 4492 { 4493 // dann muss der gesamte Platz auf alle Lines 4494 // gleichmaessig verteilt werden. Dafuer wird die 4495 // Anzahl benoetigt 4496 aParam1.nLines = nEnd - nStt; 4497 } 4498 4499 if( bTop ) 4500 { 4501 (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, 4502 nAbsDiff, sal_False ); 4503 for( n = nStt; n < nEnd; ++n ) 4504 (*fnOtherLine)( (*pLines)[ n ], aParam1, 4505 nAbsDiff, sal_False ); 4506 } 4507 else 4508 { 4509 for( n = nStt; n < nEnd; ++n ) 4510 (*fnOtherLine)( (*pLines)[ n ], aParam1, 4511 nAbsDiff, sal_False ); 4512 (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, 4513 nAbsDiff, sal_False ); 4514 } 4515 } 4516 else 4517 { 4518 // dann sich selbst rekursiv aufrufen; nur mit 4519 // einem anderen Mode -> proprotional 4520 TblChgMode eOld = eTblChgMode; 4521 eTblChgMode = TBLVAR_CHGABS; 4522 4523 bRet = SetRowHeight( rAktBox, eType, nAbsDiff, 4524 nRelDiff, ppUndo ); 4525 4526 eTblChgMode = eOld; 4527 pFndBox = 0; 4528 } 4529 } 4530 } 4531 break; 4532 } 4533 4534 if( pFndBox ) 4535 { 4536 // dann raeume die Struktur aller Lines auf 4537 GCLines(); 4538 4539 //Layout updaten 4540 if( bBigger || pFndBox->AreLinesToRestore( *this ) ) 4541 pFndBox->MakeFrms( *this ); 4542 4543 // TL_CHART2: it is currently unclear if sth has to be done here. 4544 4545 delete pFndBox; 4546 4547 if( ppUndo && *ppUndo ) 4548 { 4549 aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType, 4550 nAbsDiff, nRelDiff ); 4551 if( bBigger ) 4552 aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst ); 4553 } 4554 } 4555 4556 CHECKTABLELAYOUT 4557 4558 return bRet; 4559 } 4560 4561 /* */ 4562 4563 SwFrmFmt* SwShareBoxFmt::GetFormat( long nWidth ) const 4564 { 4565 SwFrmFmt *pRet = 0, *pTmp; 4566 for( sal_uInt16 n = aNewFmts.Count(); n; ) 4567 if( ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->GetFrmSize().GetWidth() 4568 == nWidth ) 4569 { 4570 pRet = pTmp; 4571 break; 4572 } 4573 return pRet; 4574 } 4575 4576 SwFrmFmt* SwShareBoxFmt::GetFormat( const SfxPoolItem& rItem ) const 4577 { 4578 const SfxPoolItem* pItem; 4579 sal_uInt16 nWhich = rItem.Which(); 4580 SwFrmFmt *pRet = 0, *pTmp; 4581 const SfxPoolItem& rFrmSz = pOldFmt->GetFmtAttr( RES_FRM_SIZE, sal_False ); 4582 for( sal_uInt16 n = aNewFmts.Count(); n; ) 4583 if( SFX_ITEM_SET == ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])-> 4584 GetItemState( nWhich, sal_False, &pItem ) && *pItem == rItem && 4585 pTmp->GetFmtAttr( RES_FRM_SIZE, sal_False ) == rFrmSz ) 4586 { 4587 pRet = pTmp; 4588 break; 4589 } 4590 return pRet; 4591 } 4592 4593 void SwShareBoxFmt::AddFormat( const SwFrmFmt& rNew ) 4594 { 4595 void* pFmt = (void*)&rNew; 4596 aNewFmts.Insert( pFmt, aNewFmts.Count() ); 4597 } 4598 4599 sal_Bool SwShareBoxFmt::RemoveFormat( const SwFrmFmt& rFmt ) 4600 { 4601 // returnt sal_True, wenn geloescht werden kann 4602 if( pOldFmt == &rFmt ) 4603 return sal_True; 4604 4605 void* p = (void*)&rFmt; 4606 sal_uInt16 nFnd = aNewFmts.GetPos( p ); 4607 if( USHRT_MAX != nFnd ) 4608 aNewFmts.Remove( nFnd ); 4609 return 0 == aNewFmts.Count(); 4610 } 4611 4612 SwShareBoxFmts::~SwShareBoxFmts() 4613 { 4614 } 4615 4616 SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt, long nWidth ) const 4617 { 4618 sal_uInt16 nPos; 4619 return Seek_Entry( rFmt, &nPos ) 4620 ? aShareArr[ nPos ]->GetFormat( nWidth ) 4621 : 0; 4622 } 4623 SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt, 4624 const SfxPoolItem& rItem ) const 4625 { 4626 sal_uInt16 nPos; 4627 return Seek_Entry( rFmt, &nPos ) 4628 ? aShareArr[ nPos ]->GetFormat( rItem ) 4629 : 0; 4630 } 4631 4632 void SwShareBoxFmts::AddFormat( const SwFrmFmt& rOld, const SwFrmFmt& rNew ) 4633 { 4634 // wenn das Format nicht geshared ist, braucht es auch nicht in die 4635 // Liste aufgenommen werden. Denn es gibt keinen 2. der es sucht. 4636 //leider werden auch die CellFrms gefunden 4637 // if( !rOld.IsLastDepend() ) 4638 { 4639 sal_uInt16 nPos; 4640 SwShareBoxFmt* pEntry; 4641 if( !Seek_Entry( rOld, &nPos )) 4642 { 4643 pEntry = new SwShareBoxFmt( rOld ); 4644 aShareArr.C40_INSERT( SwShareBoxFmt, pEntry, nPos ); 4645 } 4646 else 4647 pEntry = aShareArr[ nPos ]; 4648 4649 pEntry->AddFormat( rNew ); 4650 } 4651 } 4652 void SwShareBoxFmts::ChangeFrmFmt( SwTableBox* pBox, SwTableLine* pLn, 4653 SwFrmFmt& rFmt ) 4654 { 4655 SwClient aCl; 4656 SwFrmFmt* pOld = 0; 4657 if( pBox ) 4658 { 4659 pOld = pBox->GetFrmFmt(); 4660 pOld->Add( &aCl ); 4661 pBox->ChgFrmFmt( (SwTableBoxFmt*)&rFmt ); 4662 } 4663 else if( pLn ) 4664 { 4665 pOld = pLn->GetFrmFmt(); 4666 pOld->Add( &aCl ); 4667 pLn->ChgFrmFmt( (SwTableLineFmt*)&rFmt ); 4668 } 4669 if( pOld && pOld->IsLastDepend() ) 4670 { 4671 RemoveFormat( *pOld ); 4672 delete pOld; 4673 } 4674 } 4675 4676 void SwShareBoxFmts::SetSize( SwTableBox& rBox, const SwFmtFrmSize& rSz ) 4677 { 4678 SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(), 4679 *pRet = GetFormat( *pBoxFmt, rSz.GetWidth() ); 4680 if( pRet ) 4681 ChangeFrmFmt( &rBox, 0, *pRet ); 4682 else 4683 { 4684 pRet = rBox.ClaimFrmFmt(); 4685 pRet->SetFmtAttr( rSz ); 4686 AddFormat( *pBoxFmt, *pRet ); 4687 } 4688 } 4689 4690 void SwShareBoxFmts::SetAttr( SwTableBox& rBox, const SfxPoolItem& rItem ) 4691 { 4692 SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(), 4693 *pRet = GetFormat( *pBoxFmt, rItem ); 4694 if( pRet ) 4695 ChangeFrmFmt( &rBox, 0, *pRet ); 4696 else 4697 { 4698 pRet = rBox.ClaimFrmFmt(); 4699 pRet->SetFmtAttr( rItem ); 4700 AddFormat( *pBoxFmt, *pRet ); 4701 } 4702 } 4703 4704 void SwShareBoxFmts::SetAttr( SwTableLine& rLine, const SfxPoolItem& rItem ) 4705 { 4706 SwFrmFmt *pLineFmt = rLine.GetFrmFmt(), 4707 *pRet = GetFormat( *pLineFmt, rItem ); 4708 if( pRet ) 4709 ChangeFrmFmt( 0, &rLine, *pRet ); 4710 else 4711 { 4712 pRet = rLine.ClaimFrmFmt(); 4713 pRet->SetFmtAttr( rItem ); 4714 AddFormat( *pLineFmt, *pRet ); 4715 } 4716 } 4717 4718 void SwShareBoxFmts::RemoveFormat( const SwFrmFmt& rFmt ) 4719 { 4720 for( sal_uInt16 i = aShareArr.Count(); i; ) 4721 if( aShareArr[ --i ]->RemoveFormat( rFmt )) 4722 aShareArr.DeleteAndDestroy( i ); 4723 } 4724 4725 sal_Bool SwShareBoxFmts::Seek_Entry( const SwFrmFmt& rFmt, sal_uInt16* pPos ) const 4726 { 4727 sal_uLong nIdx = (sal_uLong)&rFmt; 4728 sal_uInt16 nO = aShareArr.Count(), nM, nU = 0; 4729 if( nO > 0 ) 4730 { 4731 nO--; 4732 while( nU <= nO ) 4733 { 4734 nM = nU + ( nO - nU ) / 2; 4735 sal_uLong nFmt = (sal_uLong)&aShareArr[ nM ]->GetOldFormat(); 4736 if( nFmt == nIdx ) 4737 { 4738 if( pPos ) 4739 *pPos = nM; 4740 return sal_True; 4741 } 4742 else if( nFmt < nIdx ) 4743 nU = nM + 1; 4744 else if( nM == 0 ) 4745 { 4746 if( pPos ) 4747 *pPos = nU; 4748 return sal_False; 4749 } 4750 else 4751 nO = nM - 1; 4752 } 4753 } 4754 if( pPos ) 4755 *pPos = nU; 4756 return sal_False; 4757 } 4758 4759 4760