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 <ctype.h> 28 #include <float.h> 29 #include <hintids.hxx> 30 #include <hints.hxx> // fuer SwAttrSetChg 31 #include <editeng/lrspitem.hxx> 32 #include <editeng/shaditem.hxx> 33 #include <editeng/adjitem.hxx> 34 #include <editeng/colritem.hxx> 35 #include <sfx2/linkmgr.hxx> 36 #include <editeng/boxitem.hxx> 37 #include <fmtfsize.hxx> 38 #include <fmtornt.hxx> 39 #include <fmtpdsc.hxx> 40 #include <fldbas.hxx> 41 #include <fmtfld.hxx> 42 #include <frmatr.hxx> 43 #include <doc.hxx> 44 #include <docary.hxx> // fuer RedlineTbl() 45 #include <frame.hxx> 46 #include <swtable.hxx> 47 #include <ndtxt.hxx> 48 #include <tabcol.hxx> 49 #include <tabfrm.hxx> 50 #include <cellfrm.hxx> 51 #include <rowfrm.hxx> 52 #include <swserv.hxx> 53 #include <expfld.hxx> 54 #include <mdiexp.hxx> 55 #include <cellatr.hxx> 56 #include <txatbase.hxx> 57 #include <htmltbl.hxx> 58 #include <swtblfmt.hxx> 59 #include <ndindex.hxx> 60 #include <tblrwcl.hxx> 61 #include <shellres.hxx> 62 #include <viewsh.hxx> 63 #include <redline.hxx> 64 #include <list> 65 #include <switerator.hxx> 66 67 #ifndef DBG_UTIL 68 #define CHECK_TABLE(t) 69 #else 70 #ifdef DEBUG 71 #define CHECK_TABLE(t) (t).CheckConsistency(); 72 #else 73 #define CHECK_TABLE(t) 74 #endif 75 #endif 76 77 using namespace com::sun::star; 78 79 TYPEINIT1( SwTable, SwClient ); 80 TYPEINIT1( SwTableBox, SwClient ); 81 TYPEINIT1( SwTableLine, SwClient ); 82 83 //UUUU 84 TYPEINIT1( SwTableFmt, SwFrmFmt ); 85 86 SwTableFmt::SwTableFmt(SwAttrPool& rPool,const sal_Char* pFmtNm, SwFrmFmt *pDrvdFrm) 87 : SwFrmFmt(rPool,pFmtNm,pDrvdFrm,RES_FRMFMT,aTableSetRange) 88 { 89 } 90 91 SwTableFmt::SwTableFmt(SwAttrPool& rPool,const String &rFmtNm, SwFrmFmt *pDrvdFrm) 92 : SwFrmFmt(rPool,rFmtNm,pDrvdFrm,RES_FRMFMT,aTableSetRange) 93 { 94 } 95 96 SwTableFmt::~SwTableFmt() 97 { 98 } 99 100 //UUUU Do not support for table frames - may change later if support will be added 101 bool SwTableFmt::supportsFullDrawingLayerFillAttributeSet() const 102 { 103 return false; 104 } 105 106 //UUUU 107 TYPEINIT1( SwTableBoxFmt, SwFrmFmt ); 108 109 SwTableBoxFmt::SwTableBoxFmt(SwAttrPool& rPool,const sal_Char* pFmtNm, SwFrmFmt *pDrvdFrm) 110 : SwFrmFmt(rPool,pFmtNm,pDrvdFrm,RES_FRMFMT,aTableBoxSetRange) 111 { 112 } 113 114 SwTableBoxFmt::SwTableBoxFmt(SwAttrPool& rPool,const String &rFmtNm, SwFrmFmt *pDrvdFrm) 115 : SwFrmFmt(rPool,rFmtNm,pDrvdFrm,RES_FRMFMT,aTableBoxSetRange) 116 { 117 } 118 119 SwTableBoxFmt::~SwTableBoxFmt() 120 { 121 } 122 123 //UUUU Do not support for table frames - may change later if support will be added 124 bool SwTableBoxFmt::supportsFullDrawingLayerFillAttributeSet() const 125 { 126 return false; 127 } 128 129 //UUUU 130 TYPEINIT1( SwTableLineFmt, SwFrmFmt ); 131 132 SwTableLineFmt::SwTableLineFmt(SwAttrPool& rPool,const sal_Char* pFmtNm, SwFrmFmt *pDrvdFrm) 133 : SwFrmFmt(rPool,pFmtNm,pDrvdFrm,RES_FRMFMT,aTableLineSetRange) 134 { 135 } 136 137 SwTableLineFmt::SwTableLineFmt(SwAttrPool& rPool,const String &rFmtNm, SwFrmFmt *pDrvdFrm) 138 : SwFrmFmt(rPool,rFmtNm,pDrvdFrm,RES_FRMFMT,aTableLineSetRange) 139 { 140 } 141 142 SwTableLineFmt::~SwTableLineFmt() 143 { 144 } 145 146 //UUUU Do not support for table frames - may change later if support will be added 147 bool SwTableLineFmt::supportsFullDrawingLayerFillAttributeSet() const 148 { 149 return false; 150 } 151 152 SV_IMPL_PTRARR(SwTableLines,SwTableLine*); 153 SV_IMPL_PTRARR(SwTableBoxes,SwTableBox*); 154 SV_IMPL_PTRARR_SORT(SwTableSortBoxes,SwTableBoxPtr); 155 156 SV_IMPL_REF( SwServerObject ) 157 158 #define COLFUZZY 20 159 160 void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol, 161 sal_Bool bChgAlign,sal_uLong nNdPos ); 162 //---------------------------------- 163 164 class SwTableBox_Impl 165 { 166 Color *mpUserColor, *mpNumFmtColor; 167 long mnRowSpan; 168 bool mbDummyFlag; 169 170 void SetNewCol( Color** ppCol, const Color* pNewCol ); 171 public: 172 SwTableBox_Impl() : mpUserColor(0), mpNumFmtColor(0), mnRowSpan(1), 173 mbDummyFlag( false ) {} 174 ~SwTableBox_Impl() { delete mpUserColor; delete mpNumFmtColor; } 175 176 const Color* GetSaveUserColor() const { return mpUserColor; } 177 const Color* GetSaveNumFmtColor() const { return mpNumFmtColor; } 178 void SetSaveUserColor(const Color* p ) { SetNewCol( &mpUserColor, p ); } 179 void SetSaveNumFmtColor( const Color* p ) { SetNewCol( &mpNumFmtColor, p ); } 180 long getRowSpan() const { return mnRowSpan; } 181 void setRowSpan( long nNewRowSpan ) { mnRowSpan = nNewRowSpan; } 182 bool getDummyFlag() const { return mbDummyFlag; } 183 void setDummyFlag( bool bDummy ) { mbDummyFlag = bDummy; } 184 }; 185 186 // ----------- Inlines ----------------------------- 187 188 inline const Color* SwTableBox::GetSaveUserColor() const 189 { 190 return pImpl ? pImpl->GetSaveUserColor() : 0; 191 } 192 193 inline const Color* SwTableBox::GetSaveNumFmtColor() const 194 { 195 return pImpl ? pImpl->GetSaveNumFmtColor() : 0; 196 } 197 198 inline void SwTableBox::SetSaveUserColor(const Color* p ) 199 { 200 if( pImpl ) 201 pImpl->SetSaveUserColor( p ); 202 else if( p ) 203 ( pImpl = new SwTableBox_Impl ) ->SetSaveUserColor( p ); 204 } 205 206 inline void SwTableBox::SetSaveNumFmtColor( const Color* p ) 207 { 208 if( pImpl ) 209 pImpl->SetSaveNumFmtColor( p ); 210 else if( p ) 211 ( pImpl = new SwTableBox_Impl )->SetSaveNumFmtColor( p ); 212 } 213 214 long SwTableBox::getRowSpan() const 215 { 216 return pImpl ? pImpl->getRowSpan() : 1; 217 } 218 219 void SwTableBox::setRowSpan( long nNewRowSpan ) 220 { 221 if( !pImpl ) 222 { 223 if( nNewRowSpan == 1 ) 224 return; 225 pImpl = new SwTableBox_Impl(); 226 } 227 pImpl->setRowSpan( nNewRowSpan ); 228 } 229 230 bool SwTableBox::getDummyFlag() const 231 { 232 return pImpl ? pImpl->getDummyFlag() : false; 233 } 234 235 void SwTableBox::setDummyFlag( bool bDummy ) 236 { 237 if( !pImpl ) 238 { 239 if( !bDummy ) 240 return; 241 pImpl = new SwTableBox_Impl(); 242 } 243 pImpl->setDummyFlag( bDummy ); 244 } 245 246 //JP 15.09.98: Bug 55741 - Tabs beibehalten (vorne und hinten) 247 String& lcl_TabToBlankAtSttEnd( String& rTxt ) 248 { 249 sal_Unicode c; 250 xub_StrLen n; 251 252 for( n = 0; n < rTxt.Len() && ' ' >= ( c = rTxt.GetChar( n )); ++n ) 253 if( '\x9' == c ) 254 rTxt.SetChar( n, ' ' ); 255 for( n = rTxt.Len(); n && ' ' >= ( c = rTxt.GetChar( --n )); ) 256 if( '\x9' == c ) 257 rTxt.SetChar( n, ' ' ); 258 return rTxt; 259 } 260 261 String& lcl_DelTabsAtSttEnd( String& rTxt ) 262 { 263 sal_Unicode c; 264 xub_StrLen n; 265 266 for( n = 0; n < rTxt.Len() && ' ' >= ( c = rTxt.GetChar( n )); ++n ) 267 if( '\x9' == c ) 268 rTxt.Erase( n--, 1 ); 269 for( n = rTxt.Len(); n && ' ' >= ( c = rTxt.GetChar( --n )); ) 270 if( '\x9' == c ) 271 rTxt.Erase( n, 1 ); 272 return rTxt; 273 } 274 275 void _InsTblBox( SwDoc* pDoc, SwTableNode* pTblNd, 276 SwTableLine* pLine, SwTableBoxFmt* pBoxFrmFmt, 277 SwTableBox* pBox, 278 sal_uInt16 nInsPos, sal_uInt16 nCnt ) 279 { 280 ASSERT( pBox->GetSttNd(), "Box ohne Start-Node" ); 281 SwNodeIndex aIdx( *pBox->GetSttNd(), +1 ); 282 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); 283 if( !pCNd ) 284 pCNd = pDoc->GetNodes().GoNext( &aIdx ); 285 ASSERT( pCNd, "Box ohne ContentNode" ); 286 287 if( pCNd->IsTxtNode() ) 288 { 289 if( pBox->GetSaveNumFmtColor() && pCNd->GetpSwAttrSet() ) 290 { 291 SwAttrSet aAttrSet( *pCNd->GetpSwAttrSet() ); 292 if( pBox->GetSaveUserColor() ) 293 aAttrSet.Put( SvxColorItem( *pBox->GetSaveUserColor(), RES_CHRATR_COLOR )); 294 else 295 aAttrSet.ClearItem( RES_CHRATR_COLOR ); 296 pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt, 297 ((SwTxtNode*)pCNd)->GetTxtColl(), 298 &aAttrSet, nInsPos, nCnt ); 299 } 300 else 301 pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt, 302 ((SwTxtNode*)pCNd)->GetTxtColl(), 303 pCNd->GetpSwAttrSet(), 304 nInsPos, nCnt ); 305 } 306 else 307 pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt, 308 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl(), 0, 309 nInsPos, nCnt ); 310 311 long nRowSpan = pBox->getRowSpan(); 312 if( nRowSpan != 1 ) 313 { 314 SwTableBoxes& rTblBoxes = pLine->GetTabBoxes(); 315 for( sal_uInt16 i = 0; i < nCnt; ++i ) 316 { 317 pBox = rTblBoxes[ i + nInsPos ]; 318 pBox->setRowSpan( nRowSpan ); 319 } 320 } 321 } 322 323 /************************************************************************* 324 |* 325 |* SwTable::SwTable() 326 |* 327 |*************************************************************************/ 328 SwTable::SwTable( SwTableFmt* pFmt ) 329 : SwClient( pFmt ), 330 pHTMLLayout( 0 ), 331 pTableNode( 0 ), 332 nGrfsThatResize( 0 ), 333 nRowsToRepeat( 1 ), 334 bModifyLocked( sal_False ), 335 bNewModel( sal_True ) 336 { 337 // default Wert aus den Optionen setzen 338 eTblChgMode = (TblChgMode)GetTblChgDefaultMode(); 339 } 340 341 SwTable::SwTable( const SwTable& rTable ) 342 : SwClient( rTable.GetFrmFmt() ), 343 pHTMLLayout( 0 ), 344 pTableNode( 0 ), 345 eTblChgMode( rTable.eTblChgMode ), 346 nGrfsThatResize( 0 ), 347 nRowsToRepeat( rTable.GetRowsToRepeat() ), 348 bModifyLocked( sal_False ), 349 bNewModel( rTable.bNewModel ) 350 { 351 } 352 353 void DelBoxNode( SwTableSortBoxes& rSortCntBoxes ) 354 { 355 for( sal_uInt16 n = 0; n < rSortCntBoxes.Count(); ++n ) 356 rSortCntBoxes[ n ]->pSttNd = 0; 357 } 358 359 SwTable::~SwTable() 360 { 361 if( refObj.Is() ) 362 { 363 SwDoc* pDoc = GetFrmFmt()->GetDoc(); 364 if( !pDoc->IsInDtor() ) // dann aus der Liste entfernen 365 pDoc->GetLinkManager().RemoveServer( &refObj ); 366 367 refObj->Closed(); 368 } 369 370 // ist die Tabelle der letzte Client im FrameFormat, kann dieses 371 // geloescht werden 372 SwTableFmt* pFmt = (SwTableFmt*)GetFrmFmt(); 373 pFmt->Remove( this ); // austragen, 374 375 if( !pFmt->GetDepends() ) 376 pFmt->GetDoc()->DelTblFrmFmt( pFmt ); // und loeschen 377 378 // Loesche die Pointer aus dem SortArray der Boxen, die 379 // Objecte bleiben erhalten und werden vom DTOR der Lines/Boxes 380 // Arrays geloescht. 381 //JP: reicht leider nicht, es muessen die Pointer auf den StartNode 382 // der Section geloescht werden 383 DelBoxNode( aSortCntBoxes ); 384 aSortCntBoxes.Remove( (sal_uInt16)0, aSortCntBoxes.Count() ); 385 delete pHTMLLayout; 386 } 387 388 /************************************************************************* 389 |* 390 |* SwTable::Modify() 391 |* 392 |*************************************************************************/ 393 inline void FmtInArr( SvPtrarr& rFmtArr, SwFmt* pBoxFmt ) 394 { 395 sal_Bool bRet = USHRT_MAX != rFmtArr.GetPos( (VoidPtr)pBoxFmt ); 396 if( !bRet ) 397 rFmtArr.Insert( (VoidPtr)pBoxFmt, rFmtArr.Count() ); 398 } 399 400 void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld, 401 const long nNew, SvPtrarr& rFmtArr ); 402 403 void lcl_ModifyLines( SwTableLines &rLines, const long nOld, 404 const long nNew, SvPtrarr& rFmtArr, const bool bCheckSum ) 405 { 406 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 407 ::lcl_ModifyBoxes( rLines[i]->GetTabBoxes(), nOld, nNew, rFmtArr ); 408 if( bCheckSum ) 409 { 410 for( sal_uInt16 i = 0; i < rFmtArr.Count(); ++i ) 411 { 412 SwFmt* pFmt = (SwFmt*)rFmtArr[i]; 413 sal_uInt64 nBox = pFmt->GetFrmSize().GetWidth(); 414 nBox *= nNew; 415 nBox /= nOld; 416 SwFmtFrmSize aNewBox( ATT_VAR_SIZE, SwTwips(nBox), 0 ); 417 pFmt->LockModify(); 418 pFmt->SetFmtAttr( aNewBox ); 419 pFmt->UnlockModify(); 420 } 421 } 422 } 423 424 void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld, 425 const long nNew, SvPtrarr& rFmtArr ) 426 { 427 sal_uInt64 nSum = 0; // To avoid rounding errors we summarize all box widths 428 sal_uInt64 nOriginalSum = 0; // Sum of original widths 429 for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i ) 430 { 431 SwTableBox &rBox = *rBoxes[i]; 432 if ( rBox.GetTabLines().Count() ) 433 { 434 // For SubTables the rounding problem will not be solved :-( 435 ::lcl_ModifyLines( rBox.GetTabLines(), nOld, nNew, rFmtArr, false ); 436 } 437 //Die Box anpassen 438 SwFrmFmt *pFmt = rBox.GetFrmFmt(); 439 sal_uInt64 nBox = pFmt->GetFrmSize().GetWidth(); 440 nOriginalSum += nBox; 441 nBox *= nNew; 442 nBox /= nOld; 443 sal_uInt64 nWishedSum = nOriginalSum; 444 nWishedSum *= nNew; 445 nWishedSum /= nOld; 446 nWishedSum -= nSum; 447 if( nWishedSum > 0 ) 448 { 449 if( nBox == nWishedSum ) 450 FmtInArr( rFmtArr, pFmt ); 451 else 452 { 453 nBox = nWishedSum; 454 pFmt = rBox.ClaimFrmFmt(); 455 SwFmtFrmSize aNewBox( ATT_VAR_SIZE, static_cast< SwTwips >(nBox), 0 ); 456 pFmt->LockModify(); 457 pFmt->SetFmtAttr( aNewBox ); 458 pFmt->UnlockModify(); 459 } 460 } 461 else { 462 ASSERT( false, "Rounding error" ); 463 } 464 nSum += nBox; 465 } 466 } 467 468 void SwTable::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew ) 469 { 470 // fange SSize Aenderungen ab, um die Lines/Boxen anzupassen 471 sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ; 472 const SwFmtFrmSize* pNewSize = 0, *pOldSize = 0; 473 474 if( RES_ATTRSET_CHG == nWhich ) 475 { 476 if( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( 477 RES_FRM_SIZE, sal_False, (const SfxPoolItem**)&pNewSize )) 478 pOldSize = &((SwAttrSetChg*)pOld)->GetChgSet()->GetFrmSize(); 479 } 480 else if( RES_FRM_SIZE == nWhich ) 481 { 482 pOldSize = (const SwFmtFrmSize*)pOld; 483 pNewSize = (const SwFmtFrmSize*)pNew; 484 } 485 else 486 CheckRegistration( pOld, pNew ); 487 488 if( pOldSize || pNewSize ) 489 { 490 if ( !IsModifyLocked() ) 491 { 492 ASSERT( pOldSize && pOldSize->Which() == RES_FRM_SIZE && 493 pNewSize && pNewSize->Which() == RES_FRM_SIZE, 494 "Kein Old oder New fuer FmtFrmSize-Modify der SwTable." ); 495 AdjustWidths( pOldSize->GetWidth(), pNewSize->GetWidth() ); 496 } 497 } 498 } 499 500 void SwTable::AdjustWidths( const long nOld, const long nNew ) 501 { 502 SvPtrarr aFmtArr( (sal_uInt8)aLines[0]->GetTabBoxes().Count(), 1 ); 503 ::lcl_ModifyLines( aLines, nOld, nNew, aFmtArr, true ); 504 } 505 506 /************************************************************************* 507 |* 508 |* SwTable::GetTabCols() 509 |* 510 |*************************************************************************/ 511 void lcl_RefreshHidden( SwTabCols &rToFill, sal_uInt16 nPos ) 512 { 513 for ( sal_uInt16 i = 0; i < rToFill.Count(); ++i ) 514 { 515 if ( Abs((long)(nPos - rToFill[i])) <= COLFUZZY ) 516 { 517 rToFill.SetHidden( i, sal_False ); 518 break; 519 } 520 } 521 } 522 523 void lcl_SortedTabColInsert( SwTabCols &rToFill, const SwTableBox *pBox, 524 const SwFrmFmt *pTabFmt, const sal_Bool bHidden, 525 const FASTBOOL bRefreshHidden ) 526 { 527 const long nWish = pTabFmt->GetFrmSize().GetWidth(); 528 const long nAct = rToFill.GetRight() - rToFill.GetLeft(); // +1 why? 529 530 //Der Wert fuer die linke Kante der Box errechnet sich aus den 531 //Breiten der vorhergehenden Boxen. 532 sal_uInt16 nPos = 0; 533 sal_uInt16 nSum = 0; 534 sal_uInt16 nLeftMin = 0; 535 sal_uInt16 nRightMax = 0; 536 const SwTableBox *pCur = pBox; 537 const SwTableLine *pLine = pBox->GetUpper(); 538 while ( pLine ) 539 { const SwTableBoxes &rBoxes = pLine->GetTabBoxes(); 540 for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i ) 541 { 542 SwTwips nWidth = rBoxes[i]->GetFrmFmt()->GetFrmSize().GetWidth(); 543 nSum = (sal_uInt16)(nSum + nWidth); 544 sal_uInt64 nTmp = nSum; 545 nTmp *= nAct; 546 nTmp /= nWish; 547 if (rBoxes[i] != pCur) 548 { 549 if ( pLine == pBox->GetUpper() || 0 == nLeftMin ) 550 nLeftMin = (sal_uInt16)(nTmp - nPos); 551 nPos = (sal_uInt16)nTmp; 552 } 553 else 554 { 555 nSum = (sal_uInt16)(nSum - nWidth); 556 if ( 0 == nRightMax ) 557 nRightMax = (sal_uInt16)(nTmp - nPos); 558 break; 559 } 560 } 561 pCur = pLine->GetUpper(); 562 pLine = pCur ? pCur->GetUpper() : 0; 563 } 564 565 sal_Bool bInsert = !bRefreshHidden; 566 for ( sal_uInt16 j = 0; bInsert && (j < rToFill.Count()); ++j ) 567 { 568 long nCmp = rToFill[j]; 569 if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) && 570 (nPos <= (nCmp + COLFUZZY)) ) 571 { 572 bInsert = sal_False; //Hat ihn schon. 573 } 574 else if ( nPos < nCmp ) 575 { 576 bInsert = sal_False; 577 rToFill.Insert( nPos, bHidden, j ); 578 } 579 } 580 if ( bInsert ) 581 rToFill.Insert( nPos, bHidden, rToFill.Count() ); 582 else if ( bRefreshHidden ) 583 ::lcl_RefreshHidden( rToFill, nPos ); 584 585 if ( bHidden && !bRefreshHidden ) 586 { 587 // calculate minimum/maximum values for the existing entries: 588 nLeftMin = nPos - nLeftMin; 589 nRightMax = nPos + nRightMax; 590 591 // check if nPos is entry: 592 bool bFoundPos = false; 593 bool bFoundMax = false; 594 for ( sal_uInt16 j = 0; !(bFoundPos && bFoundMax ) && j < rToFill.Count(); ++j ) 595 { 596 SwTabColsEntry& rEntry = rToFill.GetEntry( j ); 597 long nCmp = rToFill[j]; 598 599 if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) && 600 (nPos <= (nCmp + COLFUZZY)) ) 601 { 602 // check if nLeftMin is > old minimum for entry nPos: 603 const long nOldMin = rEntry.nMin; 604 if ( nLeftMin > nOldMin ) 605 rEntry.nMin = nLeftMin; 606 // check if nRightMin is < old maximum for entry nPos: 607 const long nOldMax = rEntry.nMax; 608 if ( nRightMax < nOldMax ) 609 rEntry.nMax = nRightMax; 610 611 bFoundPos = true; 612 } 613 else if ( (nRightMax >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) && 614 (nRightMax <= (nCmp + COLFUZZY)) ) 615 { 616 // check if nPos is > old minimum for entry nRightMax: 617 const long nOldMin = rEntry.nMin; 618 if ( nPos > nOldMin ) 619 rEntry.nMin = nPos; 620 621 bFoundMax = true; 622 } 623 } 624 } 625 } 626 627 void lcl_ProcessBoxGet( const SwTableBox *pBox, SwTabCols &rToFill, 628 const SwFrmFmt *pTabFmt, FASTBOOL bRefreshHidden ) 629 { 630 if ( pBox->GetTabLines().Count() ) 631 { 632 const SwTableLines &rLines = pBox->GetTabLines(); 633 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 634 { const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes(); 635 for ( sal_uInt16 j = 0; j < rBoxes.Count(); ++j ) 636 ::lcl_ProcessBoxGet( rBoxes[j], rToFill, pTabFmt, bRefreshHidden); 637 } 638 } 639 else 640 ::lcl_SortedTabColInsert( rToFill, pBox, pTabFmt, sal_False, bRefreshHidden ); 641 } 642 643 void lcl_ProcessLineGet( const SwTableLine *pLine, SwTabCols &rToFill, 644 const SwFrmFmt *pTabFmt ) 645 { 646 for ( sal_uInt16 i = 0; i < pLine->GetTabBoxes().Count(); ++i ) 647 { 648 const SwTableBox *pBox = pLine->GetTabBoxes()[i]; 649 if ( pBox->GetSttNd() ) 650 ::lcl_SortedTabColInsert( rToFill, pBox, pTabFmt, sal_True, sal_False ); 651 else 652 for ( sal_uInt16 j = 0; j < pBox->GetTabLines().Count(); ++j ) 653 ::lcl_ProcessLineGet( pBox->GetTabLines()[j], rToFill, pTabFmt ); 654 } 655 } 656 657 // MS: Sonst Absturz auf der DEC-Kiste 658 // 659 #if defined(ALPHA) && defined(WNT) 660 #pragma optimize("", off) 661 #endif 662 663 void SwTable::GetTabCols( SwTabCols &rToFill, const SwTableBox *pStart, 664 sal_Bool bRefreshHidden, sal_Bool bCurRowOnly ) const 665 { 666 //MA 30. Nov. 95: Opt: wenn bHidden gesetzt ist, wird nur das Hidden 667 //Array aktualisiert. 668 if ( bRefreshHidden ) 669 { 670 //Korrekturen entfernen 671 sal_uInt16 i; 672 for ( i = 0; i < rToFill.Count(); ++i ) 673 { 674 SwTabColsEntry& rEntry = rToFill.GetEntry( i ); 675 rEntry.nPos -= rToFill.GetLeft(); 676 rEntry.nMin -= rToFill.GetLeft(); 677 rEntry.nMax -= rToFill.GetLeft(); 678 } 679 680 //Alle sind hidden, dann die sichtbaren eintragen. 681 for ( i = 0; i < rToFill.Count(); ++i ) 682 rToFill.SetHidden( i, sal_True ); 683 } 684 else 685 { 686 rToFill.Remove( 0, rToFill.Count() ); 687 } 688 689 //Eingetragen werden: 690 //1. Alle Boxen unterhalb der dem Start uebergeordneten Line sowie 691 // deren untergeordnete Boxen falls vorhanden. 692 //2. Ausgehend von der Line die uebergeordnete Box sowie deren Nachbarn; 693 // nicht aber deren untergeordnete. 694 //3. Mit der der Boxenkette uebergeordneten Line wieder wie 2. bis einer 695 // Line keine Box (sondern die Table) uebergeordnet ist. 696 //Es werden nur diejenigen Boxen eingetragen, die keine weiteren Zeilen 697 //enhalten. Die eintragende Funktion sorgt dafuer, dass keine doppelten 698 //eingetragen werden. Um dies zu gewaehrleisten wird mit einer gewissen 699 //Unschaerfe gearbeitet (um Rundungsfehler auszuschalten). 700 //Es werden nur die linken Kanten der Boxen eingetragen. 701 //Am Schluss wird der Erste wieder ausgetragen denn er ist bereits vom 702 //Rand abgedeckt. 703 704 //4. Nochmalige abscannen der Tabelle und eintragen _aller_ Boxen, 705 // jetzt aber als Hidden. 706 707 const SwFrmFmt *pTabFmt = GetFrmFmt(); 708 709 //1. 710 const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes(); 711 712 sal_uInt16 i; 713 for ( i = 0; i < rBoxes.Count(); ++i ) 714 ::lcl_ProcessBoxGet( rBoxes[i], rToFill, pTabFmt, bRefreshHidden ); 715 716 //2. und 3. 717 const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ? 718 pStart->GetUpper()->GetUpper()->GetUpper() : 0; 719 while ( pLine ) 720 { 721 const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes(); 722 for ( sal_uInt16 k = 0; k < rBoxes2.Count(); ++k ) 723 ::lcl_SortedTabColInsert( rToFill, rBoxes2[k], 724 pTabFmt, sal_False, bRefreshHidden ); 725 pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0; 726 } 727 728 if ( !bRefreshHidden ) 729 { 730 //4. 731 if ( !bCurRowOnly ) 732 { 733 for ( i = 0; i < aLines.Count(); ++i ) 734 ::lcl_ProcessLineGet( aLines[i], rToFill, pTabFmt ); 735 } 736 737 rToFill.Remove( 0, 1 ); 738 } 739 740 //Die Koordinaten sind jetzt relativ zum linken Rand der Tabelle - also 741 //relativ zum nLeft vom SwTabCols. Die Werte werden aber relativ zum 742 //linken Rand - also nLeftMin vom SwTabCols - erwartet. 743 //Alle Werte muessen also um nLeft erweitert werden. 744 for ( i = 0; i < rToFill.Count(); ++i ) 745 { 746 SwTabColsEntry& rEntry = rToFill.GetEntry( i ); 747 rEntry.nPos += rToFill.GetLeft(); 748 rEntry.nMin += rToFill.GetLeft(); 749 rEntry.nMax += rToFill.GetLeft(); 750 } 751 } 752 753 #if defined(ALPHA) && defined(WNT) 754 #pragma optimize("", on) 755 #endif 756 757 /************************************************************************* 758 |* 759 |* SwTable::SetTabCols() 760 |* 761 |*************************************************************************/ 762 //Struktur zur Parameteruebergabe 763 struct Parm 764 { 765 const SwTabCols &rNew; 766 const SwTabCols &rOld; 767 long nNewWish, 768 nOldWish; 769 SvPtrarr aBoxArr; 770 SwShareBoxFmts aShareFmts; 771 772 Parm( const SwTabCols &rN, const SwTabCols &rO ) : 773 rNew( rN ), rOld( rO ), aBoxArr( 10, 1 ) {} 774 }; 775 inline sal_Bool BoxInArr( SvPtrarr& rArr, SwTableBox* pBox ) 776 { 777 sal_Bool bRet = USHRT_MAX != rArr.GetPos( (VoidPtr)pBox ); 778 if( !bRet ) 779 rArr.Insert( (VoidPtr)pBox, rArr.Count() ); 780 return bRet; 781 } 782 783 void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm ); 784 785 void lcl_ProcessLine( SwTableLine *pLine, Parm &rParm ) 786 { 787 SwTableBoxes &rBoxes = pLine->GetTabBoxes(); 788 for ( int i = rBoxes.Count()-1; i >= 0; --i ) 789 ::lcl_ProcessBoxSet( rBoxes[ static_cast< sal_uInt16 >(i) ], rParm ); 790 } 791 792 void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm ) 793 { 794 if ( pBox->GetTabLines().Count() ) 795 { SwTableLines &rLines = pBox->GetTabLines(); 796 for ( int i = rLines.Count()-1; i >= 0; --i ) 797 lcl_ProcessLine( rLines[ static_cast< sal_uInt16 >(i) ], rParm ); 798 } 799 else 800 { 801 //Aktuelle Position (linke und rechte Kante berechnen) und im 802 //alten TabCols suchen. Im neuen TabCols die Werte vergleichen und 803 //wenn es Unterschiede gibt die Box entsprechend anpassen. 804 //Wenn an der veraenderten Kante kein Nachbar existiert werden auch 805 //alle uebergeordneten Boxen angepasst. 806 807 const long nOldAct = rParm.rOld.GetRight() - 808 rParm.rOld.GetLeft(); // +1 why? 809 810 //Der Wert fuer die linke Kante der Box errechnet sich aus den 811 //Breiten der vorhergehenden Boxen plus dem linken Rand 812 long nLeft = rParm.rOld.GetLeft(); 813 const SwTableBox *pCur = pBox; 814 const SwTableLine *pLine = pBox->GetUpper(); 815 816 while ( pLine ) 817 { const SwTableBoxes &rBoxes = pLine->GetTabBoxes(); 818 for ( sal_uInt16 i = 0; (i < rBoxes.Count()) && (rBoxes[i] != pCur); ++i) 819 { 820 sal_uInt64 nWidth = rBoxes[i]->GetFrmFmt()-> 821 GetFrmSize().GetWidth(); 822 nWidth *= nOldAct; 823 nWidth /= rParm.nOldWish; 824 nLeft += (sal_uInt16)nWidth; 825 } 826 pCur = pLine->GetUpper(); 827 pLine = pCur ? pCur->GetUpper() : 0; 828 } 829 long nLeftDiff; 830 long nRightDiff = 0; 831 if ( nLeft != rParm.rOld.GetLeft() ) //Es gibt noch Boxen davor. 832 { 833 //Rechte Kante ist linke Kante plus Breite. 834 sal_uInt64 nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); 835 nWidth *= nOldAct; 836 nWidth /= rParm.nOldWish; 837 long nRight = nLeft + (long)nWidth; 838 sal_uInt16 nLeftPos = USHRT_MAX, 839 nRightPos = USHRT_MAX; 840 for ( sal_uInt16 i = 0; i < rParm.rOld.Count(); ++i ) 841 { 842 if ( nLeft >= (rParm.rOld[i] - COLFUZZY) && 843 nLeft <= (rParm.rOld[i] + COLFUZZY) ) 844 nLeftPos = i; 845 else if ( nRight >= (rParm.rOld[i] - COLFUZZY) && 846 nRight <= (rParm.rOld[i] + COLFUZZY) ) 847 nRightPos = i; 848 } 849 nLeftDiff = nLeftPos != USHRT_MAX ? 850 (int)rParm.rOld[nLeftPos] - (int)rParm.rNew[nLeftPos] : 0; 851 nRightDiff= nRightPos!= USHRT_MAX ? 852 (int)rParm.rNew[nRightPos] - (int)rParm.rOld[nRightPos] : 0; 853 } 854 else //Die erste Box. 855 { 856 nLeftDiff = (long)rParm.rOld.GetLeft() - (long)rParm.rNew.GetLeft(); 857 if ( rParm.rOld.Count() ) 858 { 859 //Differnz zu der Kante berechnen, von der die erste Box 860 //beruehrt wird. 861 sal_uInt64 nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); 862 nWidth *= nOldAct; 863 nWidth /= rParm.nOldWish; 864 long nTmp = (long)nWidth; 865 nTmp += rParm.rOld.GetLeft(); 866 sal_uInt16 nLeftPos = USHRT_MAX; 867 for ( sal_uInt16 i = 0; i < rParm.rOld.Count() && 868 nLeftPos == USHRT_MAX; ++i ) 869 { 870 if ( nTmp >= (rParm.rOld[i] - COLFUZZY) && 871 nTmp <= (rParm.rOld[i] + COLFUZZY) ) 872 nLeftPos = i; 873 } 874 if ( nLeftPos != USHRT_MAX ) 875 nRightDiff = (long)rParm.rNew[nLeftPos] - 876 (long)rParm.rOld[nLeftPos]; 877 } 878 //MA 11. Feb. 99: #61577# 0 sollte doch gerade richtig sein, weil die 879 //Kante doch schon in SetTabCols() korrigiert wurde. 880 // else 881 // nRightDiff = (long)rParm.rNew.GetRight() - 882 // (long)rParm.rOld.GetRight(); 883 } 884 885 if( pBox->getRowSpan() == 1 ) 886 { 887 SwTableBoxes& rTblBoxes = pBox->GetUpper()->GetTabBoxes(); 888 sal_uInt16 nPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox ); 889 if( nPos && rTblBoxes[ nPos - 1 ]->getRowSpan() != 1 ) 890 nLeftDiff = 0; 891 if( nPos + 1 < rTblBoxes.Count() && 892 rTblBoxes[ nPos + 1 ]->getRowSpan() != 1 ) 893 nRightDiff = 0; 894 } 895 else 896 nLeftDiff = nRightDiff = 0; 897 898 if ( nLeftDiff || nRightDiff ) 899 { 900 //Die Differenz ist der tatsaechliche Differenzbetrag; die 901 //Attribute der Boxen um diesen Betrag anzupassen macht keinen 902 //Sinn wenn die Tabelle gestrecht ist. Der Differenzbetrag muss 903 //entsprechend umgerechnet werden. 904 long nTmp = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); // +1 why? 905 nLeftDiff *= rParm.nNewWish; 906 nLeftDiff /= nTmp; 907 nRightDiff *= rParm.nNewWish; 908 nRightDiff /= nTmp; 909 long nDiff = nLeftDiff + nRightDiff; 910 911 //Box und alle uebergeordneten um den Differenzbetrag anpassen. 912 while ( pBox ) 913 { 914 SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() ); 915 aFmtFrmSize.SetWidth( aFmtFrmSize.GetWidth() + nDiff ); 916 if ( aFmtFrmSize.GetWidth() < 0 ) 917 aFmtFrmSize.SetWidth( -aFmtFrmSize.GetWidth() ); 918 rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize ); 919 920 // The outer cells of the last row are responsible to adjust a surrounding cell. 921 // Last line check: 922 if ( pBox->GetUpper()->GetUpper() && 923 pBox->GetUpper() != pBox->GetUpper()->GetUpper()->GetTabLines() 924 [pBox->GetUpper()->GetUpper()->GetTabLines().Count()-1]) 925 { 926 pBox = 0; 927 } 928 else 929 { 930 // Middle cell check: 931 if ( pBox != pBox->GetUpper()->GetTabBoxes()[0] ) 932 nDiff = nRightDiff; 933 934 if ( pBox != pBox->GetUpper()->GetTabBoxes() 935 [pBox->GetUpper()->GetTabBoxes().Count()-1] ) 936 nDiff -= nRightDiff; 937 938 pBox = nDiff ? pBox->GetUpper()->GetUpper() : 0; 939 } 940 } 941 } 942 } 943 } 944 945 void lcl_ProcessBoxPtr( SwTableBox *pBox, SvPtrarr &rBoxArr, 946 sal_Bool bBefore ) 947 { 948 if ( pBox->GetTabLines().Count() ) 949 { 950 const SwTableLines &rLines = pBox->GetTabLines(); 951 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 952 { 953 const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes(); 954 for ( sal_uInt16 j = 0; j < rBoxes.Count(); ++j ) 955 ::lcl_ProcessBoxPtr( rBoxes[j], rBoxArr, bBefore ); 956 } 957 } 958 else if ( bBefore ) 959 rBoxArr.Insert( (VoidPtr)pBox, 0 ); 960 else 961 rBoxArr.Insert( (VoidPtr)pBox, rBoxArr.Count() ); 962 } 963 964 void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm ); 965 966 void lcl_AdjustLines( SwTableLines &rLines, const long nDiff, Parm &rParm ) 967 { 968 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 969 { 970 SwTableBox *pBox = rLines[i]->GetTabBoxes() 971 [rLines[i]->GetTabBoxes().Count()-1]; 972 lcl_AdjustBox( pBox, nDiff, rParm ); 973 } 974 } 975 976 void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm ) 977 { 978 if ( pBox->GetTabLines().Count() ) 979 ::lcl_AdjustLines( pBox->GetTabLines(), nDiff, rParm ); 980 981 //Groesse der Box anpassen. 982 SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() ); 983 aFmtFrmSize.SetWidth( aFmtFrmSize.GetWidth() + nDiff ); 984 //#30009# if ( aFmtFrmSize.GetWidth() < 0 ) 985 // aFmtFrmSize.SetWidth( -aFmtFrmSize.GetWidth() ); 986 987 rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize ); 988 } 989 990 void SwTable::SetTabCols( const SwTabCols &rNew, const SwTabCols &rOld, 991 const SwTableBox *pStart, sal_Bool bCurRowOnly ) 992 { 993 CHECK_TABLE( *this ) 994 995 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen 996 997 // FME: Made rOld const. The caller is responsible for passing correct 998 // values of rOld. Therefore we do not have to call GetTabCols anymore: 999 //GetTabCols( rOld, pStart ); 1000 1001 Parm aParm( rNew, rOld ); 1002 1003 ASSERT( rOld.Count() == rNew.Count(), "Columnanzahl veraendert."); 1004 1005 //Raender verarbeiten. Groesse der Tabelle und ein paar Boxen mussen 1006 //angepasst werden. Bei der Groesseneinstellung darf allerdings das 1007 //Modify nicht verarbeitet werden - dieses wuerde alle Boxen anpassen 1008 //und das koennen wir ueberhaupt nicht gebrauchen. 1009 SwFrmFmt *pFmt = GetFrmFmt(); 1010 aParm.nOldWish = aParm.nNewWish = pFmt->GetFrmSize().GetWidth(); 1011 if ( (rOld.GetLeft() != rNew.GetLeft()) || 1012 (rOld.GetRight()!= rNew.GetRight()) ) 1013 { 1014 LockModify(); 1015 { 1016 SvxLRSpaceItem aLR( pFmt->GetLRSpace() ); 1017 SvxShadowItem aSh( pFmt->GetShadow() ); 1018 1019 SwTwips nShRight = aSh.CalcShadowSpace( SHADOW_RIGHT ); 1020 SwTwips nShLeft = aSh.CalcShadowSpace( SHADOW_LEFT ); 1021 1022 aLR.SetLeft ( rNew.GetLeft() - nShLeft ); 1023 aLR.SetRight( rNew.GetRightMax() - rNew.GetRight() - nShRight ); 1024 pFmt->SetFmtAttr( aLR ); 1025 1026 //Die Ausrichtung der Tabelle muss entsprechend angepasst werden, 1027 //das geschieht so, dass die Tabelle genauso stehenbleibt wie der 1028 //Anwender sie gerade hingezuppelt hat. 1029 SwFmtHoriOrient aOri( pFmt->GetHoriOrient() ); 1030 if(text::HoriOrientation::NONE != aOri.GetHoriOrient()) 1031 { 1032 const sal_Bool bLeftDist = rNew.GetLeft() != nShLeft; 1033 const sal_Bool bRightDist = rNew.GetRight() + nShRight != rNew.GetRightMax(); 1034 if(!bLeftDist && !bRightDist) 1035 aOri.SetHoriOrient( text::HoriOrientation::FULL ); 1036 else if(!bRightDist && rNew.GetLeft() > nShLeft ) 1037 aOri.SetHoriOrient( text::HoriOrientation::RIGHT ); 1038 else if(!bLeftDist && rNew.GetRight() + nShRight < rNew.GetRightMax()) 1039 aOri.SetHoriOrient( text::HoriOrientation::LEFT ); 1040 else 1041 aOri.SetHoriOrient( text::HoriOrientation::NONE ); 1042 } 1043 pFmt->SetFmtAttr( aOri ); 1044 } 1045 const long nAct = rOld.GetRight() - rOld.GetLeft(); // +1 why? 1046 long nTabDiff = 0; 1047 1048 if ( rOld.GetLeft() != rNew.GetLeft() ) 1049 { 1050 nTabDiff = rOld.GetLeft() - rNew.GetLeft(); 1051 nTabDiff *= aParm.nOldWish; 1052 nTabDiff /= nAct; 1053 } 1054 if ( rOld.GetRight() != rNew.GetRight() ) 1055 { 1056 long nDiff = rNew.GetRight() - rOld.GetRight(); 1057 nDiff *= aParm.nOldWish; 1058 nDiff /= nAct; 1059 nTabDiff += nDiff; 1060 if( !IsNewModel() ) 1061 ::lcl_AdjustLines( GetTabLines(), nDiff, aParm ); 1062 } 1063 1064 //Groesse der Tabelle anpassen. Es muss beachtet werden, das die 1065 //Tabelle gestrecht sein kann. 1066 if ( nTabDiff ) 1067 { 1068 aParm.nNewWish += nTabDiff; 1069 if ( aParm.nNewWish < 0 ) 1070 aParm.nNewWish = USHRT_MAX; //Uuups! Eine Rolle rueckwaerts. 1071 SwFmtFrmSize aSz( pFmt->GetFrmSize() ); 1072 if ( aSz.GetWidth() != aParm.nNewWish ) 1073 { 1074 aSz.SetWidth( aParm.nNewWish ); 1075 aSz.SetWidthPercent( 0 ); 1076 pFmt->SetFmtAttr( aSz ); 1077 } 1078 } 1079 UnlockModify(); 1080 } 1081 1082 if( IsNewModel() ) 1083 NewSetTabCols( aParm, rNew, rOld, pStart, bCurRowOnly ); 1084 else 1085 { 1086 if ( bCurRowOnly ) 1087 { 1088 //Um die aktuelle Zeile anzupassen muessen wir analog zu dem 1089 //Verfahren zum fuellen der TabCols (siehe GetTabCols()) die 1090 //Boxen der aktuellen Zeile abklappern. 1091 //Leider muessen wir auch hier dafuer sorgen, dass die Boxen von 1092 //hinten nach vorne bzw. von innen nach aussen veraendert werden. 1093 //Der beste Weg hierzu scheint mir darin zu liegen die 1094 //entsprechenden Boxen in einem PtrArray vorzumerken. 1095 1096 const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes(); 1097 for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i ) 1098 ::lcl_ProcessBoxPtr( rBoxes[i], aParm.aBoxArr, sal_False ); 1099 1100 const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ? 1101 pStart->GetUpper()->GetUpper()->GetUpper() : 0; 1102 const SwTableBox *pExcl = pStart->GetUpper()->GetUpper(); 1103 while ( pLine ) 1104 { 1105 const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes(); 1106 sal_Bool bBefore = sal_True; 1107 for ( sal_uInt16 i = 0; i < rBoxes2.Count(); ++i ) 1108 { 1109 if ( rBoxes2[i] != pExcl ) 1110 ::lcl_ProcessBoxPtr( rBoxes2[i], aParm.aBoxArr, bBefore ); 1111 else 1112 bBefore = sal_False; 1113 } 1114 pExcl = pLine->GetUpper(); 1115 pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0; 1116 } 1117 //Nachdem wir haufenweise Boxen (hoffentlich alle und in der richtigen 1118 //Reihenfolge) eingetragen haben, brauchen diese nur noch rueckwaerts 1119 //verarbeitet zu werden. 1120 for ( int j = aParm.aBoxArr.Count()-1; j >= 0; --j ) 1121 { 1122 SwTableBox *pBox = (SwTableBox*)aParm.aBoxArr[ static_cast< sal_uInt16 >(j)]; 1123 ::lcl_ProcessBoxSet( pBox, aParm ); 1124 } 1125 } 1126 else 1127 { //Die gesamte Tabelle anzupassen ist 'einfach'. 1128 //Es werden alle Boxen, die keine Lines mehr enthalten angepasst. 1129 //Diese Boxen passen alle uebergeordneten Boxen entsprechend mit an. 1130 //Um uns nicht selbst hereinzulegen muss natuerlich rueckwaerst 1131 //gearbeitet werden! 1132 SwTableLines &rLines = GetTabLines(); 1133 for ( int i = rLines.Count()-1; i >= 0; --i ) 1134 ::lcl_ProcessLine( rLines[ static_cast< sal_uInt16 >(i) ], aParm ); 1135 } 1136 } 1137 1138 #ifdef DBG_UTIL 1139 { 1140 // steht im tblrwcl.cxx 1141 extern void _CheckBoxWidth( const SwTableLine&, SwTwips ); 1142 // checke doch mal ob die Tabellen korrekte Breiten haben 1143 SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth(); 1144 for( sal_uInt16 n = 0; n < aLines.Count(); ++n ) 1145 _CheckBoxWidth( *aLines[ n ], nSize ); 1146 } 1147 #endif 1148 } 1149 1150 typedef std::pair<sal_uInt16, sal_uInt16> ColChange; 1151 typedef std::list< ColChange > ChangeList; 1152 1153 static void lcl_AdjustWidthsInLine( SwTableLine* pLine, ChangeList& rOldNew, 1154 Parm& rParm, sal_uInt16 nColFuzzy ) 1155 { 1156 ChangeList::iterator pCurr = rOldNew.begin(); 1157 if( pCurr == rOldNew.end() ) 1158 return; 1159 sal_uInt16 nCount = pLine->GetTabBoxes().Count(); 1160 sal_uInt16 i = 0; 1161 SwTwips nBorder = 0; 1162 SwTwips nRest = 0; 1163 while( i < nCount ) 1164 { 1165 SwTableBox* pBox = pLine->GetTabBoxes()[i++]; 1166 SwTwips nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); 1167 SwTwips nNewWidth = nWidth - nRest; 1168 nRest = 0; 1169 nBorder += nWidth; 1170 if( pCurr != rOldNew.end() && nBorder + nColFuzzy >= pCurr->first ) 1171 { 1172 nBorder -= nColFuzzy; 1173 while( pCurr != rOldNew.end() && nBorder > pCurr->first ) 1174 ++pCurr; 1175 if( pCurr != rOldNew.end() ) 1176 { 1177 nBorder += nColFuzzy; 1178 if( nBorder + nColFuzzy >= pCurr->first ) 1179 { 1180 if( pCurr->second == pCurr->first ) 1181 nRest = 0; 1182 else 1183 nRest = pCurr->second - nBorder; 1184 nNewWidth += nRest; 1185 ++pCurr; 1186 } 1187 } 1188 } 1189 if( nNewWidth != nWidth ) 1190 { 1191 if( nNewWidth < 0 ) 1192 { 1193 nRest += 1 - nNewWidth; 1194 nNewWidth = 1; 1195 } 1196 SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() ); 1197 aFmtFrmSize.SetWidth( nNewWidth ); 1198 rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize ); 1199 } 1200 } 1201 } 1202 1203 static void lcl_CalcNewWidths( std::list<sal_uInt16> &rSpanPos, ChangeList& rChanges, 1204 SwTableLine* pLine, long nWish, long nWidth, bool bTop ) 1205 { 1206 if( !rChanges.size() ) 1207 { 1208 rSpanPos.clear(); 1209 return; 1210 } 1211 if( !rSpanPos.size() ) 1212 { 1213 rChanges.clear(); 1214 return; 1215 } 1216 std::list<sal_uInt16> aNewSpanPos; 1217 ChangeList aNewChanges; 1218 ChangeList::iterator pCurr = rChanges.begin(); 1219 aNewChanges.push_back( *pCurr ); // Nullposition 1220 std::list<sal_uInt16>::iterator pSpan = rSpanPos.begin(); 1221 sal_uInt16 nCurr = 0; 1222 sal_uInt16 nOrgSum = 0; 1223 bool bRowSpan = false; 1224 sal_uInt16 nRowSpanCount = 0; 1225 sal_uInt16 nCount = pLine->GetTabBoxes().Count(); 1226 for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox ) 1227 { 1228 SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox]; 1229 SwTwips nCurrWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); 1230 const long nRowSpan = pBox->getRowSpan(); 1231 const bool bCurrRowSpan = bTop ? nRowSpan < 0 : 1232 ( nRowSpan > 1 || nRowSpan < -1 ); 1233 if( bRowSpan || bCurrRowSpan ) 1234 aNewSpanPos.push_back( nRowSpanCount ); 1235 bRowSpan = bCurrRowSpan; 1236 nOrgSum = (sal_uInt16)(nOrgSum + nCurrWidth); 1237 sal_uInt64 nSum = nOrgSum; 1238 nSum *= nWidth; 1239 nSum /= nWish; 1240 nSum *= nWish; 1241 nSum /= nWidth; 1242 sal_uInt16 nPos = (sal_uInt16)nSum; 1243 while( pCurr != rChanges.end() && pCurr->first < nPos ) 1244 { 1245 #ifdef DBG_UTIL 1246 sal_uInt16 nTemp = pCurr->first; 1247 nTemp = pCurr->second; 1248 #endif 1249 ++nCurr; 1250 ++pCurr; 1251 } 1252 bool bNew = true; 1253 if( pCurr != rChanges.end() && pCurr->first <= nPos && 1254 pCurr->first != pCurr->second ) 1255 { 1256 while( pSpan != rSpanPos.end() && *pSpan < nCurr ) 1257 ++pSpan; 1258 if( pSpan != rSpanPos.end() && *pSpan == nCurr ) 1259 { 1260 aNewChanges.push_back( *pCurr ); 1261 ++nRowSpanCount; 1262 bNew = false; 1263 } 1264 } 1265 if( bNew ) 1266 { 1267 ColChange aTmp( nPos, nPos ); 1268 aNewChanges.push_back( aTmp ); 1269 ++nRowSpanCount; 1270 } 1271 } 1272 1273 pCurr = aNewChanges.begin(); 1274 ChangeList::iterator pLast = pCurr; 1275 ChangeList::iterator pLeftMove = pCurr; 1276 while( pCurr != aNewChanges.end() ) 1277 { 1278 if( pLeftMove == pCurr ) 1279 { 1280 while( ++pLeftMove != aNewChanges.end() && pLeftMove->first <= pLeftMove->second ) 1281 ; 1282 } 1283 if( pCurr->second == pCurr->first ) 1284 { 1285 if( pLeftMove != aNewChanges.end() && pCurr->second > pLeftMove->second ) 1286 { 1287 if( pLeftMove->first == pLast->first ) 1288 pCurr->second = pLeftMove->second; 1289 else 1290 { 1291 sal_uInt64 nTmp = pCurr->first - pLast->first; 1292 nTmp *= pLeftMove->second - pLast->second; 1293 nTmp /= pLeftMove->first - pLast->first; 1294 nTmp += pLast->second; 1295 pCurr->second = (sal_uInt16)nTmp; 1296 } 1297 } 1298 pLast = pCurr; 1299 ++pCurr; 1300 } 1301 else if( pCurr->second > pCurr->first ) 1302 { 1303 pLast = pCurr; 1304 ++pCurr; 1305 ChangeList::iterator pNext = pCurr; 1306 while( pNext != pLeftMove && pNext->second == pNext->first && 1307 pNext->second < pLast->second ) 1308 ++pNext; 1309 while( pCurr != pNext ) 1310 { 1311 if( pNext == aNewChanges.end() || pNext->first == pLast->first ) 1312 pCurr->second = pLast->second; 1313 else 1314 { 1315 sal_uInt64 nTmp = pCurr->first - pLast->first; 1316 nTmp *= pNext->second - pLast->second; 1317 nTmp /= pNext->first - pLast->first; 1318 nTmp += pLast->second; 1319 pCurr->second = (sal_uInt16)nTmp; 1320 } 1321 ++pCurr; 1322 } 1323 pLast = pCurr; 1324 } 1325 else 1326 { 1327 pLast = pCurr; 1328 ++pCurr; 1329 } 1330 } 1331 1332 rChanges.clear(); 1333 ChangeList::iterator pCopy = aNewChanges.begin(); 1334 while( pCopy != aNewChanges.end() ) 1335 rChanges.push_back( *pCopy++ ); 1336 rSpanPos.clear(); 1337 std::list<sal_uInt16>::iterator pSpCopy = aNewSpanPos.begin(); 1338 while( pSpCopy != aNewSpanPos.end() ) 1339 rSpanPos.push_back( *pSpCopy++ ); 1340 } 1341 1342 void SwTable::NewSetTabCols( Parm &rParm, const SwTabCols &rNew, 1343 const SwTabCols &rOld, const SwTableBox *pStart, sal_Bool bCurRowOnly ) 1344 { 1345 #ifdef DBG_UTIL 1346 static int nCallCount = 0; 1347 ++nCallCount; 1348 #endif 1349 // First step: evaluate which lines have been moved/which widths changed 1350 ChangeList aOldNew; 1351 const long nNewWidth = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); 1352 const long nOldWidth = rParm.rOld.GetRight() - rParm.rOld.GetLeft(); 1353 if( nNewWidth < 1 || nOldWidth < 1 ) 1354 return; 1355 for( sal_uInt16 i = 0; i <= rOld.Count(); ++i ) 1356 { 1357 sal_uInt64 nNewPos; 1358 sal_uInt64 nOldPos; 1359 if( i == rOld.Count() ) 1360 { 1361 nOldPos = rParm.rOld.GetRight() - rParm.rOld.GetLeft(); 1362 nNewPos = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); 1363 } 1364 else 1365 { 1366 nOldPos = rOld[i] - rParm.rOld.GetLeft(); 1367 nNewPos = rNew[i] - rParm.rNew.GetLeft(); 1368 } 1369 nNewPos *= rParm.nNewWish; 1370 nNewPos /= nNewWidth; 1371 nOldPos *= rParm.nOldWish; 1372 nOldPos /= nOldWidth; 1373 if( nOldPos != nNewPos && nNewPos > 0 && nOldPos > 0 ) 1374 { 1375 ColChange aChg( (sal_uInt16)nOldPos, (sal_uInt16)nNewPos ); 1376 aOldNew.push_back( aChg ); 1377 } 1378 } 1379 // Finished first step 1380 int nCount = aOldNew.size(); 1381 if( !nCount ) 1382 return; // no change, nothing to do 1383 SwTableLines &rLines = GetTabLines(); 1384 if( bCurRowOnly ) 1385 { 1386 const SwTableLine* pCurrLine = pStart->GetUpper(); 1387 sal_uInt16 nCurr = rLines.C40_GETPOS( SwTableLine, pCurrLine ); 1388 if( nCurr >= USHRT_MAX ) 1389 return; 1390 1391 ColChange aChg( 0, 0 ); 1392 aOldNew.push_front( aChg ); 1393 std::list<sal_uInt16> aRowSpanPos; 1394 if( nCurr ) 1395 { 1396 ChangeList aCopy; 1397 ChangeList::iterator pCop = aOldNew.begin(); 1398 sal_uInt16 nPos = 0; 1399 while( pCop != aOldNew.end() ) 1400 { 1401 aCopy.push_back( *pCop ); 1402 ++pCop; 1403 aRowSpanPos.push_back( nPos++ ); 1404 } 1405 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr], 1406 rParm.nOldWish, nOldWidth, true ); 1407 bool bGoOn = aRowSpanPos.size() > 0; 1408 sal_uInt16 j = nCurr; 1409 while( bGoOn ) 1410 { 1411 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[--j], 1412 rParm.nOldWish, nOldWidth, true ); 1413 lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 ); 1414 bGoOn = aRowSpanPos.size() > 0 && j > 0; 1415 }; 1416 aRowSpanPos.clear(); 1417 } 1418 if( nCurr+1 < rLines.Count() ) 1419 { 1420 ChangeList aCopy; 1421 ChangeList::iterator pCop = aOldNew.begin(); 1422 sal_uInt16 nPos = 0; 1423 while( pCop != aOldNew.end() ) 1424 { 1425 aCopy.push_back( *pCop ); 1426 ++pCop; 1427 aRowSpanPos.push_back( nPos++ ); 1428 } 1429 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr], 1430 rParm.nOldWish, nOldWidth, false ); 1431 bool bGoOn = aRowSpanPos.size() > 0; 1432 sal_uInt16 j = nCurr; 1433 while( bGoOn ) 1434 { 1435 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[++j], 1436 rParm.nOldWish, nOldWidth, false ); 1437 lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 ); 1438 bGoOn = aRowSpanPos.size() > 0 && j+1 < rLines.Count(); 1439 }; 1440 } 1441 ::lcl_AdjustWidthsInLine( rLines[nCurr], aOldNew, rParm, 1 ); 1442 } 1443 else for( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 1444 ::lcl_AdjustWidthsInLine( rLines[i], aOldNew, rParm, COLFUZZY ); 1445 CHECK_TABLE( *this ) 1446 } 1447 1448 1449 /************************************************************************* 1450 |* 1451 |* const SwTableBox* SwTable::GetTblBox( const Strn?ng& rName ) const 1452 |* gebe den Pointer auf die benannte Box zurueck. 1453 |* 1454 |*************************************************************************/ 1455 1456 sal_Bool IsValidRowName( const String& rStr ) 1457 { 1458 sal_Bool bIsValid = sal_True; 1459 xub_StrLen nLen = rStr.Len(); 1460 for (xub_StrLen i = 0; i < nLen && bIsValid; ++i) 1461 { 1462 const sal_Unicode cChar = rStr.GetChar(i); 1463 if (cChar < '0' || cChar > '9') 1464 bIsValid = sal_False; 1465 } 1466 return bIsValid; 1467 } 1468 1469 // --> OD 2007-08-03 #i80314# 1470 // add 3rd parameter and its handling 1471 sal_uInt16 SwTable::_GetBoxNum( String& rStr, sal_Bool bFirstPart, 1472 const bool bPerformValidCheck ) 1473 { 1474 sal_uInt16 nRet = 0; 1475 xub_StrLen nPos = 0; 1476 if( bFirstPart ) // sal_True == column; sal_False == row 1477 { 1478 // die 1. ist mit Buchstaben addressiert! 1479 sal_Unicode cChar; 1480 sal_Bool bFirst = sal_True; 1481 while( 0 != ( cChar = rStr.GetChar( nPos )) && 1482 ( (cChar >= 'A' && cChar <= 'Z') || 1483 (cChar >= 'a' && cChar <= 'z') ) ) 1484 { 1485 if( (cChar -= 'A') >= 26 ) 1486 cChar -= 'a' - '['; 1487 if( bFirst ) 1488 bFirst = sal_False; 1489 else 1490 ++nRet; 1491 nRet = nRet * 52 + cChar; 1492 ++nPos; 1493 } 1494 rStr.Erase( 0, nPos ); // Zeichen aus dem String loeschen 1495 } 1496 else if( STRING_NOTFOUND == ( nPos = rStr.Search( aDotStr ) )) 1497 { 1498 nRet = 0; 1499 if ( !bPerformValidCheck || IsValidRowName( rStr ) ) 1500 { 1501 nRet = static_cast<sal_uInt16>(rStr.ToInt32()); 1502 } 1503 rStr.Erase(); 1504 } 1505 else 1506 { 1507 nRet = 0; 1508 String aTxt( rStr.Copy( 0, nPos ) ); 1509 if ( !bPerformValidCheck || IsValidRowName( aTxt ) ) 1510 { 1511 nRet = static_cast<sal_uInt16>(aTxt.ToInt32()); 1512 } 1513 rStr.Erase( 0, nPos+1 ); 1514 } 1515 return nRet; 1516 } 1517 // <-- 1518 1519 // --> OD 2007-08-03 #i80314# 1520 // add 2nd parameter and its handling 1521 const SwTableBox* SwTable::GetTblBox( const String& rName, 1522 const bool bPerformValidCheck ) const 1523 { 1524 const SwTableBox* pBox = 0; 1525 const SwTableLine* pLine; 1526 const SwTableLines* pLines; 1527 const SwTableBoxes* pBoxes; 1528 1529 sal_uInt16 nLine, nBox; 1530 String aNm( rName ); 1531 while( aNm.Len() ) 1532 { 1533 nBox = SwTable::_GetBoxNum( aNm, 0 == pBox, bPerformValidCheck ); 1534 // erste Box ? 1535 if( !pBox ) 1536 pLines = &GetTabLines(); 1537 else 1538 { 1539 pLines = &pBox->GetTabLines(); 1540 if( nBox ) 1541 --nBox; 1542 } 1543 1544 nLine = SwTable::_GetBoxNum( aNm, sal_False, bPerformValidCheck ); 1545 1546 // bestimme die Line 1547 if( !nLine || nLine > pLines->Count() ) 1548 return 0; 1549 pLine = (*pLines)[ nLine-1 ]; 1550 1551 // bestimme die Box 1552 pBoxes = &pLine->GetTabBoxes(); 1553 if( nBox >= pBoxes->Count() ) 1554 return 0; 1555 pBox = (*pBoxes)[ nBox ]; 1556 } 1557 1558 // abpruefen, ob die gefundene Box auch wirklich eine Inhaltstragende 1559 // Box ist ?? 1560 if( pBox && !pBox->GetSttNd() ) 1561 { 1562 ASSERT( sal_False, "Box ohne Inhalt, suche die naechste !!" ); 1563 // "herunterfallen lassen" bis zur ersten Box 1564 while( pBox->GetTabLines().Count() ) 1565 pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0]; 1566 } 1567 return pBox; 1568 } 1569 1570 SwTableBox* SwTable::GetTblBox( sal_uLong nSttIdx ) 1571 { 1572 //MA: Zur Optimierung nicht immer umstaendlich das ganze SortArray abhuenern. 1573 //OS: #102675# converting text to table tries und certain conditions 1574 // to ask for a table box of a table that is not yet having a format 1575 if(!GetFrmFmt()) 1576 return 0; 1577 SwTableBox* pRet = 0; 1578 SwNodes& rNds = GetFrmFmt()->GetDoc()->GetNodes(); 1579 sal_uLong nIndex = nSttIdx + 1; 1580 SwCntntNode* pCNd = 0; 1581 SwTableNode* pTblNd = 0; 1582 1583 while ( nIndex < rNds.Count() ) 1584 { 1585 pTblNd = rNds[ nIndex ]->GetTableNode(); 1586 if ( pTblNd ) 1587 break; 1588 1589 pCNd = rNds[ nIndex ]->GetCntntNode(); 1590 if ( pCNd ) 1591 break; 1592 1593 ++nIndex; 1594 } 1595 1596 if ( pCNd || pTblNd ) 1597 { 1598 SwModify* pModify = pCNd; 1599 // --> FME 2007-3-26 #144862# Better handling of table in table: 1600 if ( pTblNd && pTblNd->GetTable().GetFrmFmt() ) 1601 pModify = pTblNd->GetTable().GetFrmFmt(); 1602 // <-- 1603 1604 SwFrm* pFrm = SwIterator<SwFrm,SwModify>::FirstElement( *pModify ); 1605 while ( pFrm && !pFrm->IsCellFrm() ) 1606 pFrm = pFrm->GetUpper(); 1607 if ( pFrm ) 1608 pRet = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); 1609 } 1610 1611 //Falls es das Layout noch nicht gibt oder sonstwie etwas schieft geht. 1612 if ( !pRet ) 1613 { 1614 for( sal_uInt16 n = aSortCntBoxes.Count(); n; ) 1615 if( aSortCntBoxes[ --n ]->GetSttIdx() == nSttIdx ) 1616 return aSortCntBoxes[ n ]; 1617 } 1618 return pRet; 1619 } 1620 1621 sal_Bool SwTable::IsTblComplex() const 1622 { 1623 // returnt sal_True wenn sich in der Tabelle Verschachtelungen befinden 1624 // steht eine Box nicht in der obersten Line, da wurde gesplittet/ 1625 // gemergt und die Struktur ist komplexer. 1626 for( sal_uInt16 n = 0; n < aSortCntBoxes.Count(); ++n ) 1627 if( aSortCntBoxes[ n ]->GetUpper()->GetUpper() ) 1628 return sal_True; 1629 return sal_False; 1630 } 1631 1632 1633 1634 /************************************************************************* 1635 |* 1636 |* SwTableLine::SwTableLine() 1637 |* 1638 |*************************************************************************/ 1639 SwTableLine::SwTableLine( SwTableLineFmt *pFmt, sal_uInt16 nBoxes, 1640 SwTableBox *pUp ) 1641 : SwClient( pFmt ), 1642 aBoxes( (sal_uInt8)nBoxes, 1 ), 1643 pUpper( pUp ) 1644 { 1645 } 1646 1647 SwTableLine::~SwTableLine() 1648 { 1649 // ist die TabelleLine der letzte Client im FrameFormat, kann dieses 1650 // geloescht werden 1651 SwModify* pMod = GetFrmFmt(); 1652 pMod->Remove( this ); // austragen, 1653 if( !pMod->GetDepends() ) 1654 delete pMod; // und loeschen 1655 } 1656 1657 /************************************************************************* 1658 |* 1659 |* SwTableLine::ClaimFrmFmt(), ChgFrmFmt() 1660 |* 1661 |*************************************************************************/ 1662 SwFrmFmt* SwTableLine::ClaimFrmFmt() 1663 { 1664 // This method makes sure that this object is an exclusive SwTableLine client 1665 // of an SwTableLineFmt object 1666 // If other SwTableLine objects currently listen to the same SwTableLineFmt as 1667 // this one, something needs to be done 1668 SwTableLineFmt *pRet = (SwTableLineFmt*)GetFrmFmt(); 1669 SwIterator<SwTableLine,SwFmt> aIter( *pRet ); 1670 for( SwTableLine* pLast = aIter.First(); pLast; pLast = aIter.Next() ) 1671 { 1672 if ( pLast != this ) 1673 { 1674 // found another SwTableLine that is a client of the current Fmt 1675 // create a new Fmt as a copy and use it for this object 1676 SwTableLineFmt *pNewFmt = pRet->GetDoc()->MakeTableLineFmt(); 1677 *pNewFmt = *pRet; 1678 1679 // register SwRowFrms that know me as clients at the new Fmt 1680 SwIterator<SwRowFrm,SwFmt> aFrmIter( *pRet ); 1681 for( SwRowFrm* pFrm = aFrmIter.First(); pFrm; pFrm = aFrmIter.Next() ) 1682 if( pFrm->GetTabLine() == this ) 1683 pFrm->RegisterToFormat( *pNewFmt ); 1684 1685 // register myself 1686 pNewFmt->Add( this ); 1687 pRet = pNewFmt; 1688 break; 1689 } 1690 } 1691 1692 return pRet; 1693 } 1694 1695 void SwTableLine::ChgFrmFmt( SwTableLineFmt *pNewFmt ) 1696 { 1697 SwFrmFmt *pOld = GetFrmFmt(); 1698 SwIterator<SwRowFrm,SwFmt> aIter( *pOld ); 1699 1700 //Erstmal die Frms ummelden. 1701 for( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() ) 1702 { 1703 if( pRow->GetTabLine() == this ) 1704 { 1705 pRow->RegisterToFormat( *pNewFmt ); 1706 1707 pRow->InvalidateSize(); 1708 pRow->_InvalidatePrt(); 1709 pRow->SetCompletePaint(); 1710 pRow->ReinitializeFrmSizeAttrFlags(); 1711 1712 // --> FME 2004-10-27 #i35063# 1713 // consider 'split row allowed' attribute 1714 SwTabFrm* pTab = pRow->FindTabFrm(); 1715 bool bInFollowFlowRow = false; 1716 const bool bInFirstNonHeadlineRow = pTab->IsFollow() && 1717 pRow == pTab->GetFirstNonHeadlineRow(); 1718 if ( bInFirstNonHeadlineRow || 1719 !pRow->GetNext() || 1720 0 != ( bInFollowFlowRow = pRow->IsInFollowFlowRow() ) || 1721 0 != pRow->IsInSplitTableRow() ) 1722 { 1723 if ( bInFirstNonHeadlineRow || bInFollowFlowRow ) 1724 pTab = pTab->FindMaster(); 1725 1726 pTab->SetRemoveFollowFlowLinePending( sal_True ); 1727 pTab->InvalidatePos(); 1728 } 1729 // <-- 1730 } 1731 } 1732 1733 //Jetzt noch mich selbst ummelden. 1734 pNewFmt->Add( this ); 1735 1736 if ( !pOld->GetDepends() ) 1737 delete pOld; 1738 } 1739 1740 SwTwips SwTableLine::GetTableLineHeight( bool& bLayoutAvailable ) const 1741 { 1742 SwTwips nRet = 0; 1743 bLayoutAvailable = false; 1744 SwIterator<SwRowFrm,SwFmt> aIter( *GetFrmFmt() ); 1745 // A row could appear several times in headers/footers so only one chain of master/follow tables 1746 // will be accepted... 1747 const SwTabFrm* pChain = NULL; // My chain 1748 for( SwRowFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() ) 1749 { 1750 if( pLast->GetTabLine() == this ) 1751 { 1752 const SwTabFrm* pTab = pLast->FindTabFrm(); 1753 bLayoutAvailable = ( pTab && pTab->IsVertical() ) ? 1754 ( 0 < pTab->Frm().Height() ) : 1755 ( 0 < pTab->Frm().Width() ); 1756 1757 // The first one defines the chain, if a chain is defined, only members of the chain 1758 // will be added. 1759 if( !pChain || pChain->IsAnFollow( pTab ) || pTab->IsAnFollow( pChain ) ) 1760 { 1761 pChain = pTab; // defines my chain (even it is already) 1762 if( pTab->IsVertical() ) 1763 nRet += pLast->Frm().Width(); 1764 else 1765 nRet += pLast->Frm().Height(); 1766 // Optimization, if there are no master/follows in my chain, nothing more to add 1767 if( !pTab->HasFollow() && !pTab->IsFollow() ) 1768 break; 1769 // This is not an optimization, this is necessary to avoid double additions of 1770 // repeating rows 1771 if( pTab->IsInHeadline(*pLast) ) 1772 break; 1773 } 1774 } 1775 } 1776 return nRet; 1777 } 1778 1779 /************************************************************************* 1780 |* 1781 |* SwTableBox::SwTableBox() 1782 |* 1783 |*************************************************************************/ 1784 SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, sal_uInt16 nLines, SwTableLine *pUp ) 1785 : SwClient( 0 ), 1786 aLines( (sal_uInt8)nLines, 1 ), 1787 pSttNd( 0 ), 1788 pUpper( pUp ), 1789 pImpl( 0 ) 1790 { 1791 CheckBoxFmt( pFmt )->Add( this ); 1792 } 1793 1794 SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, const SwNodeIndex &rIdx, 1795 SwTableLine *pUp ) 1796 : SwClient( 0 ), 1797 aLines( 0, 0 ), 1798 pUpper( pUp ), 1799 pImpl( 0 ) 1800 { 1801 CheckBoxFmt( pFmt )->Add( this ); 1802 1803 pSttNd = rIdx.GetNode().GetStartNode(); 1804 1805 // an der Table eintragen 1806 const SwTableNode* pTblNd = pSttNd->FindTableNode(); 1807 ASSERT( pTblNd, "in welcher Tabelle steht denn die Box?" ); 1808 SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable(). 1809 GetTabSortBoxes(); 1810 SwTableBox* p = this; // error: &this 1811 rSrtArr.Insert( p ); // eintragen 1812 } 1813 1814 SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, const SwStartNode& rSttNd, SwTableLine *pUp ) : 1815 SwClient( 0 ), 1816 aLines( 0, 0 ), 1817 pSttNd( &rSttNd ), 1818 pUpper( pUp ), 1819 pImpl( 0 ) 1820 { 1821 CheckBoxFmt( pFmt )->Add( this ); 1822 1823 // an der Table eintragen 1824 const SwTableNode* pTblNd = pSttNd->FindTableNode(); 1825 ASSERT( pTblNd, "in welcher Tabelle steht denn die Box?" ); 1826 SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable(). 1827 GetTabSortBoxes(); 1828 SwTableBox* p = this; // error: &this 1829 rSrtArr.Insert( p ); // eintragen 1830 } 1831 1832 SwTableBox::~SwTableBox() 1833 { 1834 // Inhaltstragende Box ? 1835 if( !GetFrmFmt()->GetDoc()->IsInDtor() && pSttNd ) 1836 { 1837 // an der Table austragen 1838 const SwTableNode* pTblNd = pSttNd->FindTableNode(); 1839 ASSERT( pTblNd, "in welcher Tabelle steht denn die Box?" ); 1840 SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable(). 1841 GetTabSortBoxes(); 1842 SwTableBox *p = this; // error: &this 1843 rSrtArr.Remove( p ); // austragen 1844 } 1845 1846 // ist die TabelleBox der letzte Client im FrameFormat, kann dieses 1847 // geloescht werden 1848 SwModify* pMod = GetFrmFmt(); 1849 pMod->Remove( this ); // austragen, 1850 if( !pMod->GetDepends() ) 1851 delete pMod; // und loeschen 1852 1853 delete pImpl; 1854 } 1855 1856 SwTableBoxFmt* SwTableBox::CheckBoxFmt( SwTableBoxFmt* pFmt ) 1857 { 1858 // sollte das Format eine Formel oder einen Value tragen, dann muss die 1859 // Box alleine am Format haengen. Ggfs. muss ein neues angelegt werden. 1860 if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) || 1861 SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA, sal_False ) ) 1862 { 1863 SwTableBox* pOther = SwIterator<SwTableBox,SwFmt>::FirstElement( *pFmt ); 1864 if( pOther ) 1865 { 1866 SwTableBoxFmt* pNewFmt = pFmt->GetDoc()->MakeTableBoxFmt(); 1867 pNewFmt->LockModify(); 1868 *pNewFmt = *pFmt; 1869 1870 // Values und Formeln entfernen 1871 pNewFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE ); 1872 pNewFmt->UnlockModify(); 1873 1874 pFmt = pNewFmt; 1875 } 1876 } 1877 return pFmt; 1878 } 1879 1880 /************************************************************************* 1881 |* 1882 |* SwTableBox::ClaimFrmFmt(), ChgFrmFmt() 1883 |* 1884 |*************************************************************************/ 1885 SwFrmFmt* SwTableBox::ClaimFrmFmt() 1886 { 1887 // This method makes sure that this object is an exclusive SwTableBox client 1888 // of an SwTableBoxFmt object 1889 // If other SwTableBox objects currently listen to the same SwTableBoxFmt as 1890 // this one, something needs to be done 1891 SwTableBoxFmt *pRet = (SwTableBoxFmt*)GetFrmFmt(); 1892 SwIterator<SwTableBox,SwFmt> aIter( *pRet ); 1893 for( SwTableBox* pLast = aIter.First(); pLast; pLast = aIter.Next() ) 1894 { 1895 if ( pLast != this ) 1896 { 1897 // Found another SwTableBox object 1898 // create a new Fmt as a copy and assign me to it 1899 // don't copy values and formulas 1900 SwTableBoxFmt* pNewFmt = pRet->GetDoc()->MakeTableBoxFmt(); 1901 pNewFmt->LockModify(); 1902 *pNewFmt = *pRet; 1903 pNewFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE ); 1904 pNewFmt->UnlockModify(); 1905 1906 // re-register SwCellFrm objects that know me 1907 SwIterator<SwCellFrm,SwFmt> aFrmIter( *pRet ); 1908 for( SwCellFrm* pCell = aFrmIter.First(); pCell; pCell = aFrmIter.Next() ) 1909 if( pCell->GetTabBox() == this ) 1910 pCell->RegisterToFormat( *pNewFmt ); 1911 1912 // re-register myself 1913 pNewFmt->Add( this ); 1914 pRet = pNewFmt; 1915 break; 1916 } 1917 } 1918 return pRet; 1919 } 1920 1921 void SwTableBox::ChgFrmFmt( SwTableBoxFmt* pNewFmt ) 1922 { 1923 SwFrmFmt *pOld = GetFrmFmt(); 1924 SwIterator<SwCellFrm,SwFmt> aIter( *pOld ); 1925 1926 //Erstmal die Frms ummelden. 1927 for( SwCellFrm* pCell = aIter.First(); pCell; pCell = aIter.Next() ) 1928 { 1929 if( pCell->GetTabBox() == this ) 1930 { 1931 pCell->RegisterToFormat( *pNewFmt ); 1932 pCell->InvalidateSize(); 1933 pCell->_InvalidatePrt(); 1934 pCell->SetCompletePaint(); 1935 pCell->SetDerivedVert( sal_False ); 1936 pCell->CheckDirChange(); 1937 1938 // --> FME 2005-04-15 #i47489# 1939 // make sure that the row will be formatted, in order 1940 // to have the correct Get(Top|Bottom)MarginForLowers values 1941 // set at the row. 1942 const SwTabFrm* pTab = pCell->FindTabFrm(); 1943 if ( pTab && pTab->IsCollapsingBorders() ) 1944 { 1945 SwFrm* pRow = pCell->GetUpper(); 1946 pRow->_InvalidateSize(); 1947 pRow->_InvalidatePrt(); 1948 } 1949 // <-- 1950 } 1951 } 1952 1953 //Jetzt noch mich selbst ummelden. 1954 pNewFmt->Add( this ); 1955 1956 if( !pOld->GetDepends() ) 1957 delete pOld; 1958 } 1959 1960 /************************************************************************* 1961 |* 1962 |* String SwTableBox::GetName() const 1963 |* gebe den Namen dieser Box zurueck. Dieser wird dynamisch bestimmt 1964 |* und ergibt sich aus der Position in den Lines/Boxen/Tabelle 1965 |* 1966 |*************************************************************************/ 1967 void lcl_GetTblBoxColStr( sal_uInt16 nCol, String& rNm ) 1968 { 1969 const sal_uInt16 coDiff = 52; // 'A'-'Z' 'a' - 'z' 1970 sal_uInt16 nCalc; 1971 1972 do { 1973 nCalc = nCol % coDiff; 1974 if( nCalc >= 26 ) 1975 rNm.Insert( sal_Unicode('a' - 26 + nCalc ), 0 ); 1976 else 1977 rNm.Insert( sal_Unicode('A' + nCalc ), 0 ); 1978 1979 if( 0 == (nCol = nCol - nCalc) ) 1980 break; 1981 nCol /= coDiff; 1982 --nCol; 1983 } while( 1 ); 1984 } 1985 1986 String SwTableBox::GetName() const 1987 { 1988 if( !pSttNd ) // keine Content Box ?? 1989 { 1990 // die naechste erste Box suchen ?? 1991 return aEmptyStr; 1992 } 1993 1994 const SwTable& rTbl = pSttNd->FindTableNode()->GetTable(); 1995 sal_uInt16 nPos; 1996 String sNm, sTmp; 1997 const SwTableBox* pBox = this; 1998 do { 1999 const SwTableBoxes* pBoxes = &pBox->GetUpper()->GetTabBoxes(); 2000 const SwTableLine* pLine = pBox->GetUpper(); 2001 // auf oberstere Ebene ? 2002 const SwTableLines* pLines = pLine->GetUpper() 2003 ? &pLine->GetUpper()->GetTabLines() : &rTbl.GetTabLines(); 2004 2005 sTmp = String::CreateFromInt32( nPos = pLines->GetPos( pLine ) + 1 ); 2006 if( sNm.Len() ) 2007 sNm.Insert( aDotStr, 0 ).Insert( sTmp, 0 ); 2008 else 2009 sNm = sTmp; 2010 2011 sTmp = String::CreateFromInt32(( nPos = pBoxes->GetPos( pBox )) + 1 ); 2012 if( 0 != ( pBox = pLine->GetUpper()) ) 2013 sNm.Insert( aDotStr, 0 ).Insert( sTmp, 0 ); 2014 else 2015 ::lcl_GetTblBoxColStr( nPos, sNm ); 2016 2017 } while( pBox ); 2018 return sNm; 2019 } 2020 2021 sal_Bool SwTableBox::IsInHeadline( const SwTable* pTbl ) const 2022 { 2023 if( !GetUpper() ) // sollte nur beim Merge vorkommen. 2024 return sal_False; 2025 2026 if( !pTbl ) 2027 pTbl = &pSttNd->FindTableNode()->GetTable(); 2028 2029 const SwTableLine* pLine = GetUpper(); 2030 while( pLine->GetUpper() ) 2031 pLine = pLine->GetUpper()->GetUpper(); 2032 2033 // Headerline? 2034 return pTbl->GetTabLines()[ 0 ] == pLine; 2035 } 2036 2037 #ifdef DBG_UTIL 2038 2039 sal_uLong SwTableBox::GetSttIdx() const 2040 { 2041 return pSttNd ? pSttNd->GetIndex() : 0; 2042 } 2043 #endif 2044 2045 // erfrage vom Client Informationen 2046 sal_Bool SwTable::GetInfo( SfxPoolItem& rInfo ) const 2047 { 2048 switch( rInfo.Which() ) 2049 { 2050 case RES_AUTOFMT_DOCNODE: 2051 { 2052 const SwTableNode* pTblNode = GetTableNode(); 2053 if( pTblNode && &pTblNode->GetNodes() == ((SwAutoFmtGetDocNode&)rInfo).pNodes ) 2054 { 2055 if ( aSortCntBoxes.Count() ) 2056 { 2057 SwNodeIndex aIdx( *aSortCntBoxes[ 0 ]->GetSttNd() ); 2058 ((SwAutoFmtGetDocNode&)rInfo).pCntntNode = 2059 GetFrmFmt()->GetDoc()->GetNodes().GoNext( &aIdx ); 2060 } 2061 return sal_False; 2062 } 2063 break; 2064 } 2065 case RES_FINDNEARESTNODE: 2066 if( GetFrmFmt() && ((SwFmtPageDesc&)GetFrmFmt()->GetFmtAttr( 2067 RES_PAGEDESC )).GetPageDesc() && 2068 aSortCntBoxes.Count() && 2069 aSortCntBoxes[ 0 ]->GetSttNd()->GetNodes().IsDocNodes() ) 2070 ((SwFindNearestNode&)rInfo).CheckNode( * 2071 aSortCntBoxes[ 0 ]->GetSttNd()->FindTableNode() ); 2072 break; 2073 2074 case RES_CONTENT_VISIBLE: 2075 { 2076 ((SwPtrMsgPoolItem&)rInfo).pObject = SwIterator<SwFrm,SwFmt>::FirstElement( *GetFrmFmt() ); 2077 } 2078 return sal_False; 2079 } 2080 return sal_True; 2081 } 2082 2083 SwTable * SwTable::FindTable( SwFrmFmt const*const pFmt ) 2084 { 2085 return (pFmt) 2086 ? SwIterator<SwTable,SwFmt>::FirstElement(*pFmt) 2087 : 0; 2088 } 2089 2090 SwTableNode* SwTable::GetTableNode() const 2091 { 2092 return GetTabSortBoxes().Count() ? 2093 (SwTableNode*)GetTabSortBoxes()[ 0 ]->GetSttNd()->FindTableNode() : 2094 pTableNode; 2095 } 2096 2097 void SwTable::SetRefObject( SwServerObject* pObj ) 2098 { 2099 if( refObj.Is() ) 2100 refObj->Closed(); 2101 2102 refObj = pObj; 2103 } 2104 2105 2106 void SwTable::SetHTMLTableLayout( SwHTMLTableLayout *p ) 2107 { 2108 delete pHTMLLayout; 2109 pHTMLLayout = p; 2110 } 2111 2112 void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol, 2113 sal_Bool bChgAlign ) 2114 { 2115 sal_uLong nNdPos = rBox.IsValidNumTxtNd( sal_True ); 2116 ChgTextToNum( rBox,rTxt,pCol,bChgAlign,nNdPos); 2117 } 2118 void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol, 2119 sal_Bool bChgAlign,sal_uLong nNdPos ) 2120 { 2121 2122 if( ULONG_MAX != nNdPos ) 2123 { 2124 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc(); 2125 SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode(); 2126 const SfxPoolItem* pItem; 2127 2128 // Ausrichtung umsetzen 2129 if( bChgAlign ) 2130 { 2131 pItem = &pTNd->SwCntntNode::GetAttr( RES_PARATR_ADJUST ); 2132 SvxAdjust eAdjust = ((SvxAdjustItem*)pItem)->GetAdjust(); 2133 if( SVX_ADJUST_LEFT == eAdjust || SVX_ADJUST_BLOCK == eAdjust ) 2134 { 2135 SvxAdjustItem aAdjust( *(SvxAdjustItem*)pItem ); 2136 aAdjust.SetAdjust( SVX_ADJUST_RIGHT ); 2137 pTNd->SetAttr( aAdjust ); 2138 } 2139 } 2140 2141 // Farbe umsetzen oder "Benutzer Farbe" sichern 2142 if( !pTNd->GetpSwAttrSet() || SFX_ITEM_SET != pTNd->GetpSwAttrSet()-> 2143 GetItemState( RES_CHRATR_COLOR, sal_False, &pItem )) 2144 pItem = 0; 2145 2146 const Color* pOldNumFmtColor = rBox.GetSaveNumFmtColor(); 2147 const Color* pNewUserColor = pItem ? &((SvxColorItem*)pItem)->GetValue() : 0; 2148 2149 if( ( pNewUserColor && pOldNumFmtColor && 2150 *pNewUserColor == *pOldNumFmtColor ) || 2151 ( !pNewUserColor && !pOldNumFmtColor )) 2152 { 2153 // User Color nicht veraendern aktuellen Werte setzen 2154 // ggfs. die alte NumFmtColor loeschen 2155 if( pCol ) 2156 // ggfs. die Farbe setzen 2157 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR )); 2158 else if( pItem ) 2159 { 2160 pNewUserColor = rBox.GetSaveUserColor(); 2161 if( pNewUserColor ) 2162 pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR )); 2163 else 2164 pTNd->ResetAttr( RES_CHRATR_COLOR ); 2165 } 2166 } 2167 else 2168 { 2169 // User Color merken, ggfs. die NumFormat Color setzen, aber 2170 // nie die Farbe zurueck setzen 2171 rBox.SetSaveUserColor( pNewUserColor ); 2172 2173 if( pCol ) 2174 // ggfs. die Farbe setzen 2175 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR )); 2176 2177 } 2178 rBox.SetSaveNumFmtColor( pCol ); 2179 2180 if( pTNd->GetTxt() != rTxt ) 2181 { 2182 // Text austauschen 2183 //JP 15.09.98: Bug 55741 - Tabs beibehalten (vorne und hinten!) 2184 const String& rOrig = pTNd->GetTxt(); 2185 xub_StrLen n; 2186 2187 for( n = 0; n < rOrig.Len() && '\x9' == rOrig.GetChar( n ); ++n ) 2188 ; 2189 for( ; n < rOrig.Len() && '\x01' == rOrig.GetChar( n ); ++n ) 2190 ; 2191 SwIndex aIdx( pTNd, n ); 2192 for( n = rOrig.Len(); n && '\x9' == rOrig.GetChar( --n ); ) 2193 ; 2194 n -= aIdx.GetIndex() - 1; 2195 2196 //JP 06.04.99: Bug 64321 - DontExpand-Flags vorm Austauschen 2197 // zuruecksetzen, damit sie wieder aufgespannt werden 2198 { 2199 SwIndex aResetIdx( aIdx, n ); 2200 pTNd->DontExpandFmt( aResetIdx, sal_False, sal_False ); 2201 } 2202 2203 if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() ) 2204 { 2205 SwPaM aTemp(*pTNd, 0, *pTNd, rOrig.Len()); 2206 pDoc->DeleteRedline(aTemp, true, USHRT_MAX); 2207 } 2208 2209 pTNd->EraseText( aIdx, n, 2210 IDocumentContentOperations::INS_EMPTYEXPAND ); 2211 pTNd->InsertText( rTxt, aIdx, 2212 IDocumentContentOperations::INS_EMPTYEXPAND ); 2213 2214 if( pDoc->IsRedlineOn() ) 2215 { 2216 SwPaM aTemp(*pTNd, 0, *pTNd, rTxt.Len()); 2217 pDoc->AppendRedline(new SwRedline(nsRedlineType_t::REDLINE_INSERT, aTemp), true); 2218 } 2219 } 2220 2221 // vertikale Ausrichtung umsetzen 2222 if( bChgAlign && 2223 ( SFX_ITEM_SET != rBox.GetFrmFmt()->GetItemState( 2224 RES_VERT_ORIENT, sal_True, &pItem ) || 2225 text::VertOrientation::TOP == ((SwFmtVertOrient*)pItem)->GetVertOrient() )) 2226 { 2227 rBox.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::BOTTOM )); 2228 } 2229 } 2230 } 2231 2232 void ChgNumToText( SwTableBox& rBox, sal_uLong nFmt ) 2233 { 2234 sal_uLong nNdPos = rBox.IsValidNumTxtNd( sal_False ); 2235 if( ULONG_MAX != nNdPos ) 2236 { 2237 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc(); 2238 SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode(); 2239 sal_Bool bChgAlign = pDoc->IsInsTblAlignNum(); 2240 const SfxPoolItem* pItem; 2241 2242 Color* pCol = 0; 2243 if( NUMBERFORMAT_TEXT != nFmt ) 2244 { 2245 // speziellen Textformat: 2246 String sTmp, sTxt( pTNd->GetTxt() ); 2247 pDoc->GetNumberFormatter()->GetOutputString( sTxt, nFmt, sTmp, &pCol ); 2248 if( sTxt != sTmp ) 2249 { 2250 // Text austauschen 2251 SwIndex aIdx( pTNd, sTxt.Len() ); 2252 //JP 06.04.99: Bug 64321 - DontExpand-Flags vorm Austauschen 2253 // zuruecksetzen, damit sie wieder aufgespannt werden 2254 pTNd->DontExpandFmt( aIdx, sal_False, sal_False ); 2255 aIdx = 0; 2256 pTNd->EraseText( aIdx, STRING_LEN, 2257 IDocumentContentOperations::INS_EMPTYEXPAND ); 2258 pTNd->InsertText( sTmp, aIdx, 2259 IDocumentContentOperations::INS_EMPTYEXPAND ); 2260 } 2261 } 2262 2263 const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet(); 2264 2265 // Ausrichtung umsetzen 2266 if( bChgAlign && pAttrSet && SFX_ITEM_SET == pAttrSet->GetItemState( 2267 RES_PARATR_ADJUST, sal_False, &pItem ) && 2268 SVX_ADJUST_RIGHT == ((SvxAdjustItem*)pItem)->GetAdjust() ) 2269 { 2270 pTNd->SetAttr( SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ) ); 2271 } 2272 2273 // Farbe umsetzen oder "Benutzer Farbe" sichern 2274 if( !pAttrSet || SFX_ITEM_SET != pAttrSet-> 2275 GetItemState( RES_CHRATR_COLOR, sal_False, &pItem )) 2276 pItem = 0; 2277 2278 const Color* pOldNumFmtColor = rBox.GetSaveNumFmtColor(); 2279 const Color* pNewUserColor = pItem ? &((SvxColorItem*)pItem)->GetValue() : 0; 2280 2281 if( ( pNewUserColor && pOldNumFmtColor && 2282 *pNewUserColor == *pOldNumFmtColor ) || 2283 ( !pNewUserColor && !pOldNumFmtColor )) 2284 { 2285 // User Color nicht veraendern aktuellen Werte setzen 2286 // ggfs. die alte NumFmtColor loeschen 2287 if( pCol ) 2288 // ggfs. die Farbe setzen 2289 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR )); 2290 else if( pItem ) 2291 { 2292 pNewUserColor = rBox.GetSaveUserColor(); 2293 if( pNewUserColor ) 2294 pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR )); 2295 else 2296 pTNd->ResetAttr( RES_CHRATR_COLOR ); 2297 } 2298 } 2299 else 2300 { 2301 // User Color merken, ggfs. die NumFormat Color setzen, aber 2302 // nie die Farbe zurueck setzen 2303 rBox.SetSaveUserColor( pNewUserColor ); 2304 2305 if( pCol ) 2306 // ggfs. die Farbe setzen 2307 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR )); 2308 2309 } 2310 rBox.SetSaveNumFmtColor( pCol ); 2311 2312 2313 // vertikale Ausrichtung umsetzen 2314 if( bChgAlign && 2315 SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState( 2316 RES_VERT_ORIENT, sal_False, &pItem ) && 2317 text::VertOrientation::BOTTOM == ((SwFmtVertOrient*)pItem)->GetVertOrient() ) 2318 { 2319 rBox.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::TOP )); 2320 } 2321 } 2322 } 2323 2324 // zum Erkennen von Veraenderungen (haupts. TableBoxAttribute) 2325 void SwTableBoxFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 2326 { 2327 if( !IsModifyLocked() && !IsInDocDTOR() ) 2328 { 2329 const SwTblBoxNumFormat *pNewFmt = 0; 2330 const SwTblBoxFormula *pNewFml = 0; 2331 const SwTblBoxValue *pNewVal = 0; 2332 double aOldValue = 0; 2333 sal_uLong nOldFmt = NUMBERFORMAT_TEXT; 2334 2335 switch( pNew ? pNew->Which() : 0 ) 2336 { 2337 case RES_ATTRSET_CHG: 2338 { 2339 const SfxItemSet& rSet = *((SwAttrSetChg*)pNew)->GetChgSet(); 2340 if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT, 2341 sal_False, (const SfxPoolItem**)&pNewFmt ) ) 2342 nOldFmt = ((SwTblBoxNumFormat&)((SwAttrSetChg*)pOld)-> 2343 GetChgSet()->Get( RES_BOXATR_FORMAT )).GetValue(); 2344 rSet.GetItemState( RES_BOXATR_FORMULA, sal_False, 2345 (const SfxPoolItem**)&pNewFml ); 2346 if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE, 2347 sal_False, (const SfxPoolItem**)&pNewVal ) ) 2348 aOldValue = ((SwTblBoxValue&)((SwAttrSetChg*)pOld)-> 2349 GetChgSet()->Get( RES_BOXATR_VALUE )).GetValue(); 2350 } 2351 break; 2352 2353 case RES_BOXATR_FORMAT: 2354 pNewFmt = (SwTblBoxNumFormat*)pNew; 2355 nOldFmt = ((SwTblBoxNumFormat*)pOld)->GetValue(); 2356 break; 2357 case RES_BOXATR_FORMULA: 2358 pNewFml = (SwTblBoxFormula*)pNew; 2359 break; 2360 case RES_BOXATR_VALUE: 2361 pNewVal = (SwTblBoxValue*)pNew; 2362 aOldValue = ((SwTblBoxValue*)pOld)->GetValue(); 2363 break; 2364 } 2365 2366 // es hat sich etwas getan und im Set ist noch irgendein BoxAttribut 2367 // vorhanden! 2368 if( pNewFmt || pNewFml || pNewVal ) 2369 { 2370 GetDoc()->SetFieldsDirty(true, NULL, 0); 2371 2372 if( SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMAT, sal_False ) || 2373 SFX_ITEM_SET == GetItemState( RES_BOXATR_VALUE, sal_False ) || 2374 SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMULA, sal_False ) ) 2375 { 2376 // die Box holen 2377 SwIterator<SwTableBox,SwFmt> aIter( *this ); 2378 SwTableBox* pBox = aIter.First(); 2379 if( pBox ) 2380 { 2381 ASSERT( !aIter.Next(), "keine Box oder mehrere am Format" ); 2382 2383 sal_uLong nNewFmt; 2384 if( pNewFmt ) 2385 { 2386 nNewFmt = pNewFmt->GetValue(); 2387 // neu Formatieren 2388 // ist es neuer oder wurde der akt. entfernt? 2389 if( SFX_ITEM_SET != GetItemState( RES_BOXATR_VALUE, sal_False )) 2390 pNewFmt = 0; 2391 } 2392 else 2393 { 2394 // das akt. Item besorgen 2395 GetItemState( RES_BOXATR_FORMAT, sal_False, 2396 (const SfxPoolItem**)&pNewFmt ); 2397 nOldFmt = GetTblBoxNumFmt().GetValue(); 2398 nNewFmt = pNewFmt ? pNewFmt->GetValue() : nOldFmt; 2399 } 2400 2401 // ist es neuer oder wurde der akt. entfernt? 2402 if( pNewVal ) 2403 { 2404 if( NUMBERFORMAT_TEXT != nNewFmt ) 2405 { 2406 if( SFX_ITEM_SET == GetItemState( 2407 RES_BOXATR_VALUE, sal_False )) 2408 nOldFmt = NUMBERFORMAT_TEXT; 2409 else 2410 nNewFmt = NUMBERFORMAT_TEXT; 2411 } 2412 else if( NUMBERFORMAT_TEXT == nNewFmt ) 2413 nOldFmt = 0; 2414 } 2415 2416 // Logik: 2417 // ValueAenderung: -> "simuliere" eine FormatAenderung! 2418 // FormatAenderung: 2419 // Text -> !Text oder FormatAenderung: 2420 // - Ausrichtung auf RECHTS, wenn LINKS oder Blocksatz 2421 // - vertikale Ausrichtung auf UNTEN wenn OBEN oder nicht 2422 // gesetzt ist. 2423 // - Text ersetzen (Farbe?? neg. Zahlen ROT??) 2424 // !Text -> Text: 2425 // - Ausrichtung auf LINKS, wenn RECHTS 2426 // - vertikale Ausrichtung auf OEBN, wenn UNTEN gesetzt ist 2427 2428 SvNumberFormatter* pNumFmtr = GetDoc()->GetNumberFormatter(); 2429 sal_Bool bNewIsTxtFmt = pNumFmtr->IsTextFormat( nNewFmt ) || 2430 NUMBERFORMAT_TEXT == nNewFmt; 2431 2432 if( (!bNewIsTxtFmt && nOldFmt != nNewFmt) || pNewFml ) 2433 { 2434 sal_Bool bChgTxt = sal_True; 2435 double fVal = 0; 2436 if( !pNewVal && SFX_ITEM_SET != GetItemState( 2437 RES_BOXATR_VALUE, sal_False, (const SfxPoolItem**)&pNewVal )) 2438 { 2439 // es wurde noch nie ein Wert gesetzt, dann versuche 2440 // doch mal den Inhalt auszuwerten 2441 sal_uLong nNdPos = pBox->IsValidNumTxtNd( sal_True ); 2442 if( ULONG_MAX != nNdPos ) 2443 { 2444 sal_uInt32 nTmpFmtIdx = nNewFmt; 2445 String aTxt( GetDoc()->GetNodes()[ nNdPos ] 2446 ->GetTxtNode()->GetRedlineTxt()); 2447 if( !aTxt.Len() ) 2448 bChgTxt = sal_False; 2449 else 2450 { 2451 //JP 15.09.98: Bug 55741 - Tabs beibehalten 2452 lcl_TabToBlankAtSttEnd( aTxt ); 2453 2454 // JP 22.04.98: Bug 49659 - 2455 // Sonderbehandlung fuer Prozent 2456 sal_Bool bIsNumFmt = sal_False; 2457 if( NUMBERFORMAT_PERCENT == 2458 pNumFmtr->GetType( nNewFmt )) 2459 { 2460 sal_uInt32 nTmpFmt = 0; 2461 if( pNumFmtr->IsNumberFormat( 2462 aTxt, nTmpFmt, fVal )) 2463 { 2464 if( NUMBERFORMAT_NUMBER == 2465 pNumFmtr->GetType( nTmpFmt )) 2466 aTxt += '%'; 2467 2468 bIsNumFmt = pNumFmtr->IsNumberFormat( 2469 aTxt, nTmpFmtIdx, fVal ); 2470 } 2471 } 2472 else 2473 bIsNumFmt = pNumFmtr->IsNumberFormat( 2474 aTxt, nTmpFmtIdx, fVal ); 2475 2476 if( bIsNumFmt ) 2477 { 2478 // dann setze den Value direkt in den Set - 2479 // ohne Modify 2480 int bIsLockMod = IsModifyLocked(); 2481 LockModify(); 2482 SetFmtAttr( SwTblBoxValue( fVal )); 2483 if( !bIsLockMod ) 2484 UnlockModify(); 2485 } 2486 } 2487 } 2488 } 2489 else 2490 fVal = pNewVal->GetValue(); 2491 2492 // den Inhalt mit dem neuen Wert Formtieren und in den Absatz 2493 // schbreiben 2494 Color* pCol = 0; 2495 String sNewTxt; 2496 if( DBL_MAX == fVal ) 2497 sNewTxt = ViewShell::GetShellRes()->aCalc_Error; 2498 else 2499 { 2500 pNumFmtr->GetOutputString( fVal, nNewFmt, sNewTxt, &pCol ); 2501 2502 if( !bChgTxt ) 2503 sNewTxt.Erase(); 2504 } 2505 2506 // ueber alle Boxen 2507 ChgTextToNum( *pBox, sNewTxt, pCol, 2508 GetDoc()->IsInsTblAlignNum() ); 2509 2510 } 2511 else if( bNewIsTxtFmt && nOldFmt != nNewFmt ) 2512 { 2513 // auf jedenfall muessen jetzt die Formeln/Values 2514 // geloescht werden! 2515 // LockModify(); 2516 // ResetAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE ); 2517 // UnlockModify(); 2518 2519 2520 ChgNumToText( *pBox, nNewFmt ); 2521 } 2522 } 2523 } 2524 } 2525 } 2526 // Und die Basis-Klasse rufen 2527 SwFrmFmt::Modify( pOld, pNew ); 2528 } 2529 2530 sal_Bool SwTableBox::HasNumCntnt( double& rNum, sal_uInt32& rFmtIndex, 2531 sal_Bool& rIsEmptyTxtNd ) const 2532 { 2533 sal_Bool bRet = sal_False; 2534 sal_uLong nNdPos = IsValidNumTxtNd( sal_True ); 2535 if( ULONG_MAX != nNdPos ) 2536 { 2537 String aTxt( pSttNd->GetNodes()[ nNdPos ]->GetTxtNode()-> 2538 GetRedlineTxt() ); 2539 //JP 15.09.98: Bug 55741 - Tabs beibehalten 2540 lcl_TabToBlankAtSttEnd( aTxt ); 2541 rIsEmptyTxtNd = 0 == aTxt.Len(); 2542 SvNumberFormatter* pNumFmtr = GetFrmFmt()->GetDoc()->GetNumberFormatter(); 2543 2544 const SfxPoolItem* pItem; 2545 if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT, 2546 sal_False, &pItem )) 2547 { 2548 rFmtIndex = ((SwTblBoxNumFormat*)pItem)->GetValue(); 2549 // JP 22.04.98: Bug 49659 - Sonderbehandlung fuer Prozent 2550 if( !rIsEmptyTxtNd && 2551 NUMBERFORMAT_PERCENT == pNumFmtr->GetType( rFmtIndex )) 2552 { 2553 sal_uInt32 nTmpFmt = 0; 2554 if( pNumFmtr->IsNumberFormat( aTxt, nTmpFmt, rNum ) && 2555 NUMBERFORMAT_NUMBER == pNumFmtr->GetType( nTmpFmt )) 2556 aTxt += '%'; 2557 } 2558 } 2559 else 2560 rFmtIndex = 0; 2561 2562 bRet = pNumFmtr->IsNumberFormat( aTxt, rFmtIndex, rNum ); 2563 } 2564 else 2565 rIsEmptyTxtNd = sal_False; 2566 return bRet; 2567 } 2568 2569 sal_Bool SwTableBox::IsNumberChanged() const 2570 { 2571 sal_Bool bRet = sal_True; 2572 2573 if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA, sal_False )) 2574 { 2575 const SwTblBoxNumFormat *pNumFmt; 2576 const SwTblBoxValue *pValue; 2577 2578 if( SFX_ITEM_SET != GetFrmFmt()->GetItemState( RES_BOXATR_VALUE, sal_False, 2579 (const SfxPoolItem**)&pValue )) 2580 pValue = 0; 2581 if( SFX_ITEM_SET != GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT, sal_False, 2582 (const SfxPoolItem**)&pNumFmt )) 2583 pNumFmt = 0; 2584 2585 sal_uLong nNdPos; 2586 if( pNumFmt && pValue && 2587 ULONG_MAX != ( nNdPos = IsValidNumTxtNd( sal_True ) ) ) 2588 { 2589 String sNewTxt, sOldTxt( pSttNd->GetNodes()[ nNdPos ]-> 2590 GetTxtNode()->GetRedlineTxt() ); 2591 lcl_DelTabsAtSttEnd( sOldTxt ); 2592 2593 Color* pCol = 0; 2594 GetFrmFmt()->GetDoc()->GetNumberFormatter()->GetOutputString( 2595 pValue->GetValue(), pNumFmt->GetValue(), sNewTxt, &pCol ); 2596 2597 bRet = sNewTxt != sOldTxt || 2598 !( ( !pCol && !GetSaveNumFmtColor() ) || 2599 ( pCol && GetSaveNumFmtColor() && 2600 *pCol == *GetSaveNumFmtColor() )); 2601 } 2602 } 2603 return bRet; 2604 } 2605 2606 sal_uLong SwTableBox::IsValidNumTxtNd( sal_Bool bCheckAttr ) const 2607 { 2608 sal_uLong nPos = ULONG_MAX; 2609 if( pSttNd ) 2610 { 2611 SwNodeIndex aIdx( *pSttNd ); 2612 sal_uLong nIndex = aIdx.GetIndex(); 2613 const sal_uLong nIndexEnd = pSttNd->GetNodes()[ nIndex ]->EndOfSectionIndex(); 2614 const SwTxtNode *pTextNode = 0; 2615 while( ++nIndex < nIndexEnd ) 2616 { 2617 const SwNode* pNode = pSttNd->GetNodes()[nIndex]; 2618 if( pNode->IsTableNode() ) 2619 { /*return ULONG_MAX if the cell contains a table(in table)*/ 2620 pTextNode = 0; 2621 break; 2622 } 2623 if( pNode->IsTxtNode() ) 2624 { 2625 if( pTextNode ) 2626 { /*return ULONG_MAX if the cell contains complex paragraphs*/ 2627 pTextNode = 0; 2628 break; 2629 } 2630 else 2631 { 2632 pTextNode = pNode->GetTxtNode(); 2633 nPos = nIndex; 2634 } 2635 } 2636 } 2637 if( pTextNode ) 2638 { 2639 if( bCheckAttr ) 2640 { 2641 const SwpHints* pHts = pTextNode->GetpSwpHints(); 2642 const String& rTxt = pTextNode->GetTxt(); 2643 // dann teste doch mal, ob das wirklich nur Text im Node steht! 2644 // Flys/Felder/.. 2645 if( pHts ) 2646 { 2647 xub_StrLen nNextSetField = 0; 2648 for( sal_uInt16 n = 0; n < pHts->Count(); ++n ) 2649 { 2650 const SwTxtAttr* pAttr = (*pHts)[ n ]; 2651 if( RES_TXTATR_NOEND_BEGIN <= pAttr->Which() || 2652 *pAttr->GetStart() || 2653 *pAttr->GetAnyEnd() < rTxt.Len() ) 2654 { 2655 if ( (*pAttr->GetStart() == nNextSetField) 2656 && (pAttr->Which() == RES_TXTATR_FIELD)) 2657 { 2658 // #i104949# hideous hack for report builder: 2659 // it inserts hidden variable-set fields at 2660 // the beginning of para in cell, but they 2661 // should not turn cell into text cell 2662 const SwField* pField = pAttr->GetFmtFld().GetField(); 2663 if (pField && 2664 (pField->GetTypeId() == TYP_SETFLD) && 2665 (0 != (static_cast<SwSetExpField const*> 2666 (pField)->GetSubType() & 2667 nsSwExtendedSubType::SUB_INVISIBLE))) 2668 { 2669 nNextSetField = *pAttr->GetStart() + 1; 2670 continue; 2671 } 2672 } 2673 nPos = ULONG_MAX; 2674 break; 2675 } 2676 } 2677 } 2678 } 2679 } 2680 else 2681 nPos = ULONG_MAX; 2682 } 2683 return nPos; 2684 } 2685 2686 // ist das eine FormelBox oder eine Box mit numerischen Inhalt (AutoSum) 2687 sal_uInt16 SwTableBox::IsFormulaOrValueBox() const 2688 { 2689 sal_uInt16 nWhich = 0; 2690 const SwTxtNode* pTNd; 2691 SwFrmFmt* pFmt = GetFrmFmt(); 2692 if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA, sal_False )) 2693 nWhich = RES_BOXATR_FORMULA; 2694 else if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) && 2695 !pFmt->GetDoc()->GetNumberFormatter()->IsTextFormat( 2696 pFmt->GetTblBoxNumFmt().GetValue() )) 2697 nWhich = RES_BOXATR_VALUE; 2698 else if( pSttNd && pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex() 2699 && 0 != ( pTNd = pSttNd->GetNodes()[ pSttNd->GetIndex() + 1 ] 2700 ->GetTxtNode() ) && !pTNd->GetTxt().Len() ) 2701 nWhich = USHRT_MAX; 2702 2703 return nWhich; 2704 } 2705 2706 void SwTableBox::ActualiseValueBox() 2707 { 2708 const SfxPoolItem *pFmtItem, *pValItem; 2709 SwFrmFmt* pFmt = GetFrmFmt(); 2710 if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMAT, sal_True, &pFmtItem ) 2711 && SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_True, &pValItem )) 2712 { 2713 const sal_uLong nFmtId = ((SwTblBoxNumFormat*)pFmtItem)->GetValue(); 2714 sal_uLong nNdPos = ULONG_MAX; 2715 SvNumberFormatter* pNumFmtr = pFmt->GetDoc()->GetNumberFormatter(); 2716 2717 if( !pNumFmtr->IsTextFormat( nFmtId ) && 2718 ULONG_MAX != (nNdPos = IsValidNumTxtNd( sal_True )) ) 2719 { 2720 double fVal = ((SwTblBoxValue*)pValItem)->GetValue(); 2721 Color* pCol = 0; 2722 String sNewTxt; 2723 pNumFmtr->GetOutputString( fVal, nFmtId, sNewTxt, &pCol ); 2724 2725 const String& rTxt = pSttNd->GetNodes()[ nNdPos ]->GetTxtNode()->GetTxt(); 2726 if( rTxt != sNewTxt ) 2727 ChgTextToNum( *this, sNewTxt, pCol, sal_False ,nNdPos); 2728 } 2729 } 2730 } 2731 2732 void SwTableBox_Impl::SetNewCol( Color** ppCol, const Color* pNewCol ) 2733 { 2734 if( *ppCol != pNewCol ) 2735 { 2736 delete *ppCol; 2737 if( pNewCol ) 2738 *ppCol = new Color( *pNewCol ); 2739 else 2740 *ppCol = 0; 2741 } 2742 } 2743 2744 struct SwTableCellInfo::Impl 2745 { 2746 const SwTable * m_pTable; 2747 const SwCellFrm * m_pCellFrm; 2748 const SwTabFrm * m_pTabFrm; 2749 typedef ::std::set<const SwTableBox *> TableBoxes_t; 2750 TableBoxes_t m_HandledTableBoxes; 2751 2752 public: 2753 Impl() 2754 : m_pTable(NULL), m_pCellFrm(NULL), m_pTabFrm(NULL) 2755 { 2756 } 2757 2758 ~Impl() {} 2759 2760 void setTable(const SwTable * pTable) { 2761 m_pTable = pTable; 2762 SwFrmFmt * pFrmFmt = m_pTable->GetFrmFmt(); 2763 m_pTabFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement(*pFrmFmt); 2764 if (m_pTabFrm->IsFollow()) 2765 m_pTabFrm = m_pTabFrm->FindMaster(true); 2766 } 2767 const SwTable * getTable() const { return m_pTable; } 2768 2769 const SwCellFrm * getCellFrm() const { return m_pCellFrm; } 2770 2771 const SwFrm * getNextFrmInTable(const SwFrm * pFrm); 2772 const SwCellFrm * getNextCellFrm(const SwFrm * pFrm); 2773 const SwCellFrm * getNextTableBoxsCellFrm(const SwFrm * pFrm); 2774 bool getNext(); 2775 }; 2776 2777 const SwFrm * SwTableCellInfo::Impl::getNextFrmInTable(const SwFrm * pFrm) 2778 { 2779 const SwFrm * pResult = NULL; 2780 2781 if (((! pFrm->IsTabFrm()) || pFrm == m_pTabFrm) && pFrm->GetLower()) 2782 pResult = pFrm->GetLower(); 2783 else if (pFrm->GetNext()) 2784 pResult = pFrm->GetNext(); 2785 else 2786 { 2787 while (pFrm->GetUpper() != NULL) 2788 { 2789 pFrm = pFrm->GetUpper(); 2790 2791 if (pFrm->IsTabFrm()) 2792 { 2793 m_pTabFrm = static_cast<const SwTabFrm *>(pFrm)->GetFollow(); 2794 pResult = m_pTabFrm; 2795 break; 2796 } 2797 else if (pFrm->GetNext()) 2798 { 2799 pResult = pFrm->GetNext(); 2800 break; 2801 } 2802 } 2803 } 2804 2805 return pResult; 2806 } 2807 2808 const SwCellFrm * SwTableCellInfo::Impl::getNextCellFrm(const SwFrm * pFrm) 2809 { 2810 const SwCellFrm * pResult = NULL; 2811 2812 while ((pFrm = getNextFrmInTable(pFrm)) != NULL) 2813 { 2814 if (pFrm->IsCellFrm()) 2815 { 2816 pResult = static_cast<const SwCellFrm *>(pFrm); 2817 break; 2818 } 2819 } 2820 2821 return pResult; 2822 } 2823 2824 const SwCellFrm * SwTableCellInfo::Impl::getNextTableBoxsCellFrm(const SwFrm * pFrm) 2825 { 2826 const SwCellFrm * pResult = NULL; 2827 2828 while ((pFrm = getNextCellFrm(pFrm)) != NULL) 2829 { 2830 const SwCellFrm * pCellFrm = static_cast<const SwCellFrm *>(pFrm); 2831 const SwTableBox * pTabBox = pCellFrm->GetTabBox(); 2832 TableBoxes_t::const_iterator aIt = m_HandledTableBoxes.find(pTabBox); 2833 2834 if (aIt == m_HandledTableBoxes.end()) 2835 { 2836 pResult = pCellFrm; 2837 m_HandledTableBoxes.insert(pTabBox); 2838 break; 2839 } 2840 } 2841 2842 return pResult; 2843 } 2844 2845 const SwCellFrm * SwTableCellInfo::getCellFrm() const 2846 { 2847 return m_pImpl->getCellFrm(); 2848 } 2849 2850 bool SwTableCellInfo::Impl::getNext() 2851 { 2852 if (m_pCellFrm == NULL) 2853 { 2854 if (m_pTabFrm != NULL) 2855 m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pTabFrm); 2856 } 2857 else 2858 m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pCellFrm); 2859 2860 return m_pCellFrm != NULL; 2861 } 2862 2863 SwTableCellInfo::SwTableCellInfo(const SwTable * pTable) 2864 { 2865 m_pImpl.reset(new Impl()); 2866 m_pImpl->setTable(pTable); 2867 } 2868 2869 SwTableCellInfo::~SwTableCellInfo() 2870 { 2871 } 2872 2873 bool SwTableCellInfo::getNext() 2874 { 2875 return m_pImpl->getNext(); 2876 } 2877 2878 SwRect SwTableCellInfo::getRect() const 2879 { 2880 SwRect aRet; 2881 2882 if (getCellFrm() != NULL) 2883 aRet = getCellFrm()->Frm(); 2884 2885 return aRet; 2886 } 2887 2888 const SwTableBox * SwTableCellInfo::getTableBox() const 2889 { 2890 const SwTableBox * pRet = NULL; 2891 2892 if (getCellFrm() != NULL) 2893 pRet = getCellFrm()->GetTabBox(); 2894 2895 return pRet; 2896 } 2897 2898 void SwTable::RegisterToFormat( SwFmt& rFmt ) 2899 { 2900 rFmt.Add( this ); 2901 } 2902 2903 void SwTableLine::RegisterToFormat( SwFmt& rFmt ) 2904 { 2905 rFmt.Add( this ); 2906 } 2907 2908 void SwTableBox::RegisterToFormat( SwFmt& rFmt ) 2909 { 2910 rFmt.Add( this ); 2911 } 2912 2913 void SwTableBox::ForgetFrmFmt() 2914 { 2915 if ( GetRegisteredIn() ) 2916 GetRegisteredInNonConst()->Remove(this); 2917 } 2918