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