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