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 #include "pagefrm.hxx" 27 #include "rootfrm.hxx" 28 #include "cntfrm.hxx" 29 #include "viewsh.hxx" 30 #include "doc.hxx" 31 #include "docsh.hxx" 32 #include "viewimp.hxx" 33 #include "swtable.hxx" 34 #include "dflyobj.hxx" 35 #include "flyfrm.hxx" 36 #include "frmtool.hxx" 37 #include "frmfmt.hxx" 38 #include "dcontact.hxx" 39 #include <anchoreddrawobject.hxx> 40 #include <fmtanchr.hxx> 41 #include "viewopt.hxx" 42 #include "hints.hxx" 43 #include "dbg_lay.hxx" 44 #include <ftnidx.hxx> 45 #include <svl/itemiter.hxx> 46 #include <docary.hxx> 47 #include <editeng/keepitem.hxx> 48 #include <editeng/ulspitem.hxx> 49 #include <editeng/lrspitem.hxx> 50 #include <editeng/brshitem.hxx> 51 #include <editeng/boxitem.hxx> 52 #include <vcl/outdev.hxx> 53 #include <fmtlsplt.hxx> 54 #include <fmtrowsplt.hxx> 55 #include <fmtsrnd.hxx> 56 #include <fmtornt.hxx> 57 #include <fmtpdsc.hxx> 58 #include <fmtfsize.hxx> 59 #include <swtblfmt.hxx> 60 #include <ndtxt.hxx> 61 #include "tabfrm.hxx" 62 #include "rowfrm.hxx" 63 #include "cellfrm.hxx" 64 #include "flyfrms.hxx" 65 #include "txtfrm.hxx" //HasFtn() 66 #include "htmltbl.hxx" 67 #include "sectfrm.hxx" //SwSectionFrm 68 #include <fmtfollowtextflow.hxx> 69 #include <sortedobjs.hxx> 70 #include <objectformatter.hxx> 71 #include <layouter.hxx> 72 #include <switerator.hxx> 73 74 extern void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex, 75 SwFrm *pFrm, SwPageFrm *pPage ); 76 77 using namespace ::com::sun::star; 78 79 80 /************************************************************************* 81 |* 82 |* SwTabFrm::SwTabFrm(), ~SwTabFrm() 83 |* 84 |* Ersterstellung MA 09. Mar. 93 85 |* Letzte Aenderung MA 30. May. 96 86 |* 87 |*************************************************************************/ 88 SwTabFrm::SwTabFrm( SwTable &rTab, SwFrm* pSib ): 89 SwLayoutFrm( rTab.GetFrmFmt(), pSib ), 90 SwFlowFrm( (SwFrm&)*this ), 91 pTable( &rTab ) 92 { 93 bComplete = bCalcLowers = bONECalcLowers = bLowersFormatted = bLockBackMove = 94 bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine = 95 bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False; 96 // --> OD 2004-10-04 #i26945# 97 bConsiderObjsForMinCellHeight = sal_True; 98 bObjsDoesFit = sal_True; 99 // <-- 100 bFixSize = sal_False; //Nicht nochmal auf die Importfilter hereinfallen. 101 nType = FRMC_TAB; 102 103 //Gleich die Zeilen erzeugen und einfuegen. 104 const SwTableLines &rLines = rTab.GetTabLines(); 105 SwFrm *pTmpPrev = 0; 106 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 107 { 108 SwRowFrm *pNew = new SwRowFrm( *rLines[i], this ); 109 if( pNew->Lower() ) 110 { 111 pNew->InsertBehind( this, pTmpPrev ); 112 pTmpPrev = pNew; 113 } 114 else 115 delete pNew; 116 } 117 ASSERT( Lower() && Lower()->IsRowFrm(), "SwTabFrm::SwTabFrm: No rows." ); 118 } 119 120 SwTabFrm::SwTabFrm( SwTabFrm &rTab ) : 121 SwLayoutFrm( rTab.GetFmt(), &rTab ), 122 SwFlowFrm( (SwFrm&)*this ), 123 pTable( rTab.GetTable() ) 124 { 125 bIsFollow = sal_True; 126 bLockJoin = bComplete = bONECalcLowers = bCalcLowers = bLowersFormatted = bLockBackMove = 127 bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine = 128 bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False; 129 // --> OD 2004-10-04 #i26945# 130 bConsiderObjsForMinCellHeight = sal_True; 131 bObjsDoesFit = sal_True; 132 // <-- 133 bFixSize = sal_False; //Nicht nochmal auf die Importfilter hereinfallen. 134 nType = FRMC_TAB; 135 136 SetFollow( rTab.GetFollow() ); 137 rTab.SetFollow( this ); 138 } 139 140 extern const SwTable *pColumnCacheLastTable; 141 extern const SwTabFrm *pColumnCacheLastTabFrm; 142 extern const SwFrm *pColumnCacheLastCellFrm; 143 extern const SwTable *pRowCacheLastTable; 144 extern const SwTabFrm *pRowCacheLastTabFrm; 145 extern const SwFrm *pRowCacheLastCellFrm; 146 147 SwTabFrm::~SwTabFrm() 148 { 149 // There is some terrible code in fetab.cxx, that 150 // makes use of these global pointers. Obviously 151 // this code did not consider that a TabFrm can be 152 // deleted. 153 if ( this == pColumnCacheLastTabFrm ) 154 { 155 pColumnCacheLastTable = NULL; 156 pColumnCacheLastTabFrm = NULL; 157 pColumnCacheLastCellFrm= NULL; 158 pRowCacheLastTable = NULL; 159 pRowCacheLastTabFrm = NULL; 160 pRowCacheLastCellFrm= NULL; 161 } 162 } 163 164 /************************************************************************* 165 |* 166 |* SwTabFrm::JoinAndDelFollows() 167 |* 168 |* Ersterstellung MA 30. May. 96 169 |* Letzte Aenderung MA 30. May. 96 170 |* 171 |*************************************************************************/ 172 void SwTabFrm::JoinAndDelFollows() 173 { 174 SwTabFrm *pFoll = GetFollow(); 175 if ( pFoll->HasFollow() ) 176 pFoll->JoinAndDelFollows(); 177 pFoll->Cut(); 178 SetFollow( pFoll->GetFollow() ); 179 delete pFoll; 180 } 181 182 /************************************************************************* 183 |* 184 |* SwTabFrm::RegistFlys() 185 |* 186 |* Ersterstellung MA 08. Jul. 93 187 |* Letzte Aenderung MA 27. Jan. 99 188 |* 189 |*************************************************************************/ 190 void SwTabFrm::RegistFlys() 191 { 192 ASSERT( Lower() && Lower()->IsRowFrm(), "Keine Zeilen." ); 193 194 SwPageFrm *pPage = FindPageFrm(); 195 if ( pPage ) 196 { 197 SwRowFrm *pRow = (SwRowFrm*)Lower(); 198 do 199 { 200 pRow->RegistFlys( pPage ); 201 pRow = (SwRowFrm*)pRow->GetNext(); 202 } while ( pRow ); 203 } 204 } 205 206 /************************************************************************* 207 |* Some prototypes 208 |*************************************************************************/ 209 void MA_FASTCALL SwInvalidateAll( SwFrm *pFrm, long nBottom ); 210 void MA_FASTCALL lcl_RecalcRow( SwRowFrm& rRow, long nBottom ); 211 sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva ); 212 // --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control 213 // that only row and cell frames are formatted. 214 sal_Bool MA_FASTCALL lcl_InnerCalcLayout( SwFrm *pFrm, 215 long nBottom, 216 bool _bOnlyRowsAndCells = false ); 217 // <-- 218 // OD 2004-02-18 #106629# - correct type of 1st parameter 219 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to 220 // control, if floating screen objects have to be considered for the minimal 221 // cell height. 222 SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm *pRow, 223 const sal_Bool _bConsiderObjs ); 224 // <-- 225 SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm&, const SwBorderAttrs& ); 226 227 /************************************************************************* 228 |* START: local helper functions for repeated headlines 229 |*************************************************************************/ 230 231 SwTwips lcl_GetHeightOfRows( const SwFrm* pStart, long nCount ) 232 { 233 if ( !nCount || !pStart) 234 return 0; 235 236 SwTwips nRet = 0; 237 SWRECTFN( pStart ) 238 while ( pStart && nCount > 0 ) 239 { 240 nRet += (pStart->Frm().*fnRect->fnGetHeight)(); 241 pStart = pStart->GetNext(); 242 --nCount; 243 } 244 245 return nRet; 246 } 247 248 /************************************************************************* 249 |* END: local helper functions for repeated headlines 250 |*************************************************************************/ 251 252 /************************************************************************* 253 |* START: local helper functions for splitting row frames 254 |*************************************************************************/ 255 256 // 257 // Local helper function to insert a new follow flow line 258 // 259 SwRowFrm* lcl_InsertNewFollowFlowLine( SwTabFrm& rTab, const SwFrm& rTmpRow, bool bRowSpanLine ) 260 { 261 ASSERT( rTmpRow.IsRowFrm(), "No row frame to copy for FollowFlowLine" ) 262 const SwRowFrm& rRow = (SwRowFrm&)rTmpRow; 263 264 rTab.SetFollowFlowLine( sal_True ); 265 SwRowFrm *pFollowFlowLine = new SwRowFrm(*rRow.GetTabLine(), &rTab, false ); 266 pFollowFlowLine->SetRowSpanLine( bRowSpanLine ); 267 SwFrm* pFirstRow = rTab.GetFollow()->GetFirstNonHeadlineRow(); 268 pFollowFlowLine->InsertBefore( rTab.GetFollow(), pFirstRow ); 269 return pFollowFlowLine; 270 } 271 272 // --> OD 2004-11-05 #i26945# - local helper function to invalidate all lower 273 // objects. By parameter <_bMoveObjsOutOfRange> it can be controlled, if 274 // additionally the objects are moved 'out of range'. 275 void lcl_InvalidateLowerObjs( SwLayoutFrm& _rLayoutFrm, 276 const bool _bMoveObjsOutOfRange = false, 277 SwPageFrm* _pPageFrm = 0L ) 278 { 279 // determine page frame, if needed 280 if ( !_pPageFrm ) 281 { 282 _pPageFrm = _rLayoutFrm.FindPageFrm(); 283 ASSERT( _pPageFrm, 284 "<lcl_InvalidateLowerObjs(..)> - missing page frame -> no move of lower objects out of range" ); 285 if ( !_pPageFrm ) 286 { 287 return; 288 } 289 } 290 291 // loop on lower frames 292 SwFrm* pLowerFrm = _rLayoutFrm.Lower(); 293 while ( pLowerFrm ) 294 { 295 if ( pLowerFrm->IsLayoutFrm() ) 296 { 297 ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pLowerFrm)), 298 _bMoveObjsOutOfRange, _pPageFrm ); 299 } 300 if ( pLowerFrm->GetDrawObjs() ) 301 { 302 for ( sal_uInt16 i = 0; i < pLowerFrm->GetDrawObjs()->Count(); ++i ) 303 { 304 SwAnchoredObject* pAnchoredObj = (*pLowerFrm->GetDrawObjs())[i]; 305 306 // invalidate position of anchored object 307 pAnchoredObj->SetTmpConsiderWrapInfluence( false ); 308 pAnchoredObj->SetConsiderForTextWrap( false ); 309 pAnchoredObj->UnlockPosition(); 310 pAnchoredObj->InvalidateObjPos(); 311 312 // move anchored object 'out of range' 313 if ( _bMoveObjsOutOfRange ) 314 { 315 // indicate, that positioning is progress to avoid 316 // modification of the anchored object resp. its attributes 317 // due to the movement 318 SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj ); 319 pAnchoredObj->SetObjLeft( _pPageFrm->Frm().Right() ); 320 // --> OD 2004-11-24 #115759# - reset character rectangle, 321 // top of line and relative position in order to assure, 322 // that anchored object is correctly positioned. 323 pAnchoredObj->ClearCharRectAndTopOfLine(); 324 pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) ); 325 if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId() 326 == FLY_AS_CHAR ) 327 { 328 pAnchoredObj->AnchorFrm() 329 ->Prepare( PREP_FLY_ATTR_CHG, 330 &(pAnchoredObj->GetFrmFmt()) ); 331 } 332 // <-- 333 if ( pAnchoredObj->ISA(SwFlyFrm) ) 334 { 335 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 336 pFly->GetVirtDrawObj()->SetRectsDirty(); 337 pFly->GetVirtDrawObj()->SetChanged(); 338 } 339 } 340 341 // If anchored object is a fly frame, invalidate its lower objects 342 if ( pAnchoredObj->ISA(SwFlyFrm) ) 343 { 344 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 345 ::lcl_InvalidateLowerObjs( *pFly, _bMoveObjsOutOfRange, _pPageFrm ); 346 } 347 } 348 } 349 pLowerFrm = pLowerFrm->GetNext(); 350 } 351 } 352 // <-- 353 // 354 // Local helper function to shrink all lowers of rRow to 0 height 355 // 356 void lcl_ShrinkCellsAndAllContent( SwRowFrm& rRow ) 357 { 358 SwCellFrm* pCurrMasterCell = static_cast<SwCellFrm*>(rRow.Lower()); 359 SWRECTFN( pCurrMasterCell ) 360 361 while ( pCurrMasterCell ) 362 { 363 // NEW TABLES 364 SwCellFrm& rToAdjust = pCurrMasterCell->GetTabBox()->getRowSpan() < 1 ? 365 const_cast<SwCellFrm&>(pCurrMasterCell->FindStartEndOfRowSpanCell( true, true )) : 366 *pCurrMasterCell; 367 368 // --> OD 2004-10-04 #i26945# 369 // all lowers should have the correct position 370 lcl_ArrangeLowers( &rToAdjust, 371 (rToAdjust.*fnRect->fnGetPrtTop)(), 372 sal_False ); 373 // <-- 374 // TODO: Optimize number of frames which are set to 0 height 375 // we have to start with the last lower frame, otherwise 376 // the shrink will not shrink the current cell 377 SwFrm* pTmp = rToAdjust.GetLastLower(); 378 379 if ( pTmp && pTmp->IsRowFrm() ) 380 { 381 SwRowFrm* pTmpRow = (SwRowFrm*)pTmp; 382 lcl_ShrinkCellsAndAllContent( *pTmpRow ); 383 } 384 else 385 { 386 // TODO: Optimize number of frames which are set to 0 height 387 while ( pTmp ) 388 { 389 // the frames have to be shrunk 390 if ( pTmp && pTmp->IsTabFrm() ) 391 { 392 SwRowFrm* pTmpRow = (SwRowFrm*)((SwTabFrm*)pTmp)->Lower(); 393 while ( pTmpRow ) 394 { 395 lcl_ShrinkCellsAndAllContent( *pTmpRow ); 396 pTmpRow = (SwRowFrm*)pTmpRow->GetNext(); 397 } 398 } 399 else 400 { 401 pTmp->Shrink( (pTmp->Frm().*fnRect->fnGetHeight)() ); 402 (pTmp->Prt().*fnRect->fnSetTop)( 0 ); 403 (pTmp->Prt().*fnRect->fnSetHeight)( 0 ); 404 } 405 406 pTmp = pTmp->GetPrev(); 407 } 408 409 // all lowers should have the correct position 410 lcl_ArrangeLowers( &rToAdjust, 411 (rToAdjust.*fnRect->fnGetPrtTop)(), 412 sal_False ); 413 } 414 415 pCurrMasterCell = static_cast<SwCellFrm*>(pCurrMasterCell->GetNext()); 416 } 417 } 418 419 // 420 // Local helper function to move the content from rSourceLine to rDestLine 421 // The content is inserted behind the last content in the corresponding 422 // cell in rDestLine. 423 // 424 void lcl_MoveRowContent( SwRowFrm& rSourceLine, SwRowFrm& rDestLine ) 425 { 426 SwCellFrm* pCurrDestCell = (SwCellFrm*)rDestLine.Lower(); 427 SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower(); 428 429 // Move content of follow cells into master cells 430 while ( pCurrSourceCell ) 431 { 432 if ( pCurrSourceCell->Lower() && pCurrSourceCell->Lower()->IsRowFrm() ) 433 { 434 SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower(); 435 while ( pTmpSourceRow ) 436 { 437 // --> FME 2006-01-10 #125926# Achtung! It is possible, 438 // that pTmpSourceRow->IsFollowFlowRow() but pTmpDestRow 439 // cannot be found. In this case, we have to move the complete 440 // row. 441 SwRowFrm* pTmpDestRow = (SwRowFrm*)pCurrDestCell->Lower(); 442 // <-- 443 444 if ( pTmpSourceRow->IsFollowFlowRow() && pTmpDestRow ) 445 { 446 // move content from follow flow row to pTmpDestRow: 447 while ( pTmpDestRow->GetNext() ) 448 pTmpDestRow = (SwRowFrm*)pTmpDestRow->GetNext(); 449 450 ASSERT( pTmpDestRow->GetFollowRow() == pTmpSourceRow, "Knoten in der Tabelle" ) 451 452 lcl_MoveRowContent( *pTmpSourceRow, *pTmpDestRow ); 453 pTmpDestRow->SetFollowRow( pTmpSourceRow->GetFollowRow() ); 454 pTmpSourceRow->Remove(); 455 delete pTmpSourceRow; 456 } 457 else 458 { 459 // move complete row: 460 pTmpSourceRow->Remove(); 461 pTmpSourceRow->InsertBefore( pCurrDestCell, 0 ); 462 } 463 464 pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower(); 465 } 466 } 467 else 468 { 469 SwFrm *pTmp = ::SaveCntnt( (SwCellFrm*)pCurrSourceCell ); 470 if ( pTmp ) 471 { 472 // NEW TABLES 473 SwCellFrm* pDestCell = static_cast<SwCellFrm*>(pCurrDestCell); 474 if ( pDestCell->GetTabBox()->getRowSpan() < 1 ) 475 pDestCell = & const_cast<SwCellFrm&>(pDestCell->FindStartEndOfRowSpanCell( true, true )); 476 477 // Find last content 478 SwFrm* pFrm = pDestCell->GetLastLower(); 479 ::RestoreCntnt( pTmp, pDestCell, pFrm, true ); 480 } 481 } 482 pCurrDestCell = (SwCellFrm*)pCurrDestCell->GetNext(); 483 pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext(); 484 } 485 } 486 487 // 488 // Local helper function to move all footnotes in rRowFrm from 489 // the footnote boss of rSource to the footnote boss of rDest. 490 // 491 void lcl_MoveFootnotes( SwTabFrm& rSource, SwTabFrm& rDest, SwLayoutFrm& rRowFrm ) 492 { 493 if ( 0 != rSource.GetFmt()->GetDoc()->GetFtnIdxs().Count() ) 494 { 495 SwFtnBossFrm* pOldBoss = rSource.FindFtnBossFrm( sal_True ); 496 SwFtnBossFrm* pNewBoss = rDest.FindFtnBossFrm( sal_True ); 497 rRowFrm.MoveLowerFtns( 0, pOldBoss, pNewBoss, sal_True ); 498 } 499 } 500 501 // 502 // Local helper function to handle nested table cells before the split process 503 // 504 void lcl_PreprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine, 505 SwRowFrm& rFollowFlowLine, SwTwips nRemain ) 506 { 507 SwCellFrm* pCurrLastLineCell = (SwCellFrm*)rLastLine.Lower(); 508 SwCellFrm* pCurrFollowFlowLineCell = (SwCellFrm*)rFollowFlowLine.Lower(); 509 510 SWRECTFN( pCurrLastLineCell ) 511 512 // 513 // Move content of follow cells into master cells 514 // 515 while ( pCurrLastLineCell ) 516 { 517 if ( pCurrLastLineCell->Lower() && pCurrLastLineCell->Lower()->IsRowFrm() ) 518 { 519 SwTwips nTmpCut = nRemain; 520 SwRowFrm* pTmpLastLineRow = (SwRowFrm*)pCurrLastLineCell->Lower(); 521 522 // --> OD 2004-10-04 #i26945# 523 SwTwips nCurrentHeight = 524 lcl_CalcMinRowHeight( pTmpLastLineRow, 525 rTab.IsConsiderObjsForMinCellHeight() ); 526 // <-- 527 while ( pTmpLastLineRow && pTmpLastLineRow->GetNext() && nTmpCut > nCurrentHeight ) 528 { 529 nTmpCut -= nCurrentHeight; 530 pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext(); 531 // --> OD 2004-10-04 #i26945# 532 nCurrentHeight = 533 lcl_CalcMinRowHeight( pTmpLastLineRow, 534 rTab.IsConsiderObjsForMinCellHeight() ); 535 // <-- 536 } 537 538 // 539 // pTmpLastLineRow does not fit to the line or it is the last line 540 // 541 if ( pTmpLastLineRow ) 542 { 543 // 544 // Check if we can move pTmpLastLineRow to the follow table, 545 // or if we have to split the line: 546 // 547 SwFrm* pCell = pTmpLastLineRow->Lower(); 548 bool bTableLayoutToComplex = false; 549 long nMinHeight = 0; 550 551 // 552 // We have to take into account: 553 // 1. The fixed height of the row 554 // 2. The borders of the cells inside the row 555 // 3. The minimum height of the row 556 // 557 if ( pTmpLastLineRow->HasFixSize() ) 558 nMinHeight = (pTmpLastLineRow->Frm().*fnRect->fnGetHeight)(); 559 else 560 { 561 while ( pCell ) 562 { 563 if ( ((SwCellFrm*)pCell)->Lower() && 564 ((SwCellFrm*)pCell)->Lower()->IsRowFrm() ) 565 { 566 bTableLayoutToComplex = true; 567 break; 568 } 569 570 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell ); 571 const SwBorderAttrs &rAttrs = *aAccess.Get(); 572 nMinHeight = Max( nMinHeight, lcl_CalcTopAndBottomMargin( *(SwLayoutFrm*)pCell, rAttrs ) ); 573 pCell = pCell->GetNext(); 574 } 575 576 const SwFmtFrmSize &rSz = pTmpLastLineRow->GetFmt()->GetFrmSize(); 577 if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE ) 578 nMinHeight = Max( nMinHeight, rSz.GetHeight() ); 579 } 580 581 // 582 // 1. Case: 583 // The line completely fits into the master table. 584 // Nevertheless, we build a follow (otherwise painting problems 585 // with empty cell). 586 // 587 // 2. Case: 588 // The line has to be split, the minimum height still fits into 589 // the master table, and the table structure is not to complex. 590 // 591 if ( nTmpCut > nCurrentHeight || 592 ( pTmpLastLineRow->IsRowSplitAllowed() && 593 !bTableLayoutToComplex && nMinHeight < nTmpCut ) ) 594 { 595 // The line has to be split: 596 SwRowFrm* pNewRow = new SwRowFrm( *pTmpLastLineRow->GetTabLine(), &rTab, false ); 597 pNewRow->SetFollowFlowRow( true ); 598 pNewRow->SetFollowRow( pTmpLastLineRow->GetFollowRow() ); 599 pTmpLastLineRow->SetFollowRow( pNewRow ); 600 pNewRow->InsertBehind( pCurrFollowFlowLineCell, 0 ); 601 pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext(); 602 } 603 604 // 605 // The following lines have to be moved: 606 // 607 while ( pTmpLastLineRow ) 608 { 609 SwRowFrm* pTmp = (SwRowFrm*)pTmpLastLineRow->GetNext(); 610 lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pTmpLastLineRow ); 611 pTmpLastLineRow->Remove(); 612 pTmpLastLineRow->InsertBefore( pCurrFollowFlowLineCell, 0 ); 613 pTmpLastLineRow->Shrink( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() ); 614 pCurrFollowFlowLineCell->Grow( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() ); 615 pTmpLastLineRow = pTmp; 616 } 617 } 618 } 619 620 pCurrLastLineCell = (SwCellFrm*)pCurrLastLineCell->GetNext(); 621 pCurrFollowFlowLineCell = (SwCellFrm*)pCurrFollowFlowLineCell->GetNext(); 622 } 623 } 624 625 // 626 // Local helper function to handle nested table cells after the split process 627 // 628 void lcl_PostprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine ) 629 { 630 SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower(); 631 while ( pCurrMasterCell ) 632 { 633 if ( pCurrMasterCell->Lower() && 634 pCurrMasterCell->Lower()->IsRowFrm() ) 635 { 636 SwRowFrm* pRowFrm = static_cast<SwRowFrm*>(pCurrMasterCell->GetLastLower()); 637 638 if ( NULL != pRowFrm->GetPrev() && !pRowFrm->ContainsCntnt() ) 639 { 640 ASSERT( pRowFrm->GetFollowRow(), "Deleting row frame without follow" ) 641 642 // The footnotes have to be moved: 643 lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pRowFrm ); 644 pRowFrm->Cut(); 645 SwRowFrm* pFollowRow = pRowFrm->GetFollowRow(); 646 pRowFrm->Paste( pFollowRow->GetUpper(), pFollowRow ); 647 pRowFrm->SetFollowRow( pFollowRow->GetFollowRow() ); 648 lcl_MoveRowContent( *pFollowRow, *pRowFrm ); 649 pFollowRow->Cut(); 650 delete pFollowRow; 651 ::SwInvalidateAll( pCurrMasterCell, LONG_MAX ); 652 } 653 } 654 655 pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext(); 656 } 657 } 658 659 // 660 // Local helper function to re-calculate the split line. 661 // 662 inline void TableSplitRecalcLock( SwFlowFrm *pTab ) { pTab->LockJoin(); } 663 inline void TableSplitRecalcUnlock( SwFlowFrm *pTab ) { pTab->UnlockJoin(); } 664 665 bool lcl_RecalcSplitLine( SwRowFrm& rLastLine, SwRowFrm& rFollowLine, 666 SwTwips nRemainingSpaceForLastRow ) 667 { 668 bool bRet = true; 669 670 SwTabFrm& rTab = (SwTabFrm&)*rLastLine.GetUpper(); 671 672 // 673 // If there are nested cells in rLastLine, the recalculation of the last 674 // line needs some preprocessing. 675 // 676 lcl_PreprocessRowsInCells( rTab, rLastLine, rFollowLine, nRemainingSpaceForLastRow ); 677 678 // 679 // Here the recalculation process starts: 680 // 681 rTab.SetRebuildLastLine( sal_True ); 682 // --> OD 2004-10-15 #i26945# 683 rTab.SetDoesObjsFit( sal_True ); 684 // <-- 685 SWRECTFN( rTab.GetUpper() ) 686 687 // --> OD 2004-11-05 #i26945# - invalidate and move floating screen 688 // objects 'out of range' 689 ::lcl_InvalidateLowerObjs( rLastLine, true ); 690 // <-- 691 // 692 // manipulate row and cell sizes 693 // 694 // --> OD 2004-10-04 #i26945# - Do *not* consider floating screen objects 695 // for the minimal cell height. 696 rTab.SetConsiderObjsForMinCellHeight( sal_False ); 697 ::lcl_ShrinkCellsAndAllContent( rLastLine ); 698 rTab.SetConsiderObjsForMinCellHeight( sal_True ); 699 // <-- 700 701 // 702 // invalidate last line 703 // 704 ::SwInvalidateAll( &rLastLine, LONG_MAX ); 705 706 // 707 // Lock this tab frame and its follow 708 // 709 bool bUnlockMaster = false; 710 bool bUnlockFollow = false; 711 SwTabFrm* pMaster = rTab.IsFollow() ? (SwTabFrm*)rTab.FindMaster() : 0; 712 if ( pMaster && !pMaster->IsJoinLocked() ) 713 { 714 bUnlockMaster = true; 715 ::TableSplitRecalcLock( pMaster ); 716 } 717 if ( !rTab.GetFollow()->IsJoinLocked() ) 718 { 719 bUnlockFollow = true; 720 ::TableSplitRecalcLock( rTab.GetFollow() ); 721 } 722 723 // 724 // TODO: e.g., for i71806: What shall we do if the table already 725 // exceeds its upper? I think we have to adjust the heights of the 726 // table, rLastRow and all cells in rLastRow 727 // 728 /*SwTwips nDistanceToUpperPrtBottom = 729 (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)()); 730 731 if ( nDistanceToUpperPrtBottom < 0 ) 732 { 733 (rTab.Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom ); 734 (rTab.Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom ); 735 736 (rLastLine.Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom ); 737 (rLastLine.Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom ); 738 739 SwFrm* pTmpCell = rLastLine.Lower(); 740 while ( pTmpCell ) 741 { 742 (pTmpCell->Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom ); 743 (pTmpCell->Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom ); 744 745 pTmpCell = pTmpCell->GetNext(); 746 } 747 }*/ 748 749 // 750 // Do the recalculation 751 // 752 lcl_RecalcRow( rLastLine, LONG_MAX ); 753 // --> OD 2004-11-23 #115759# - force a format of the last line in order to 754 // get the correct height. 755 rLastLine.InvalidateSize(); 756 rLastLine.Calc(); 757 // <-- 758 759 // 760 // Unlock this tab frame and its follow 761 // 762 if ( bUnlockFollow ) 763 ::TableSplitRecalcUnlock( rTab.GetFollow() ); 764 if ( bUnlockMaster ) 765 ::TableSplitRecalcUnlock( pMaster ); 766 767 // 768 // If there are nested cells in rLastLine, the recalculation of the last 769 // line needs some postprocessing. 770 // 771 lcl_PostprocessRowsInCells( rTab, rLastLine ); 772 773 // 774 // Do a couple of checks on the current situation. 775 // 776 // If we are not happy with the current situation we return false. 777 // This will start a new try to split the table, this time we do not 778 // try to split the table rows. 779 // 780 781 // 782 // 1. Check if table fits to its upper. 783 // --> OD 2004-10-15 #i26945# - include check, if objects fit 784 // 785 const SwTwips nDistanceToUpperPrtBottom = 786 (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)()); 787 if ( nDistanceToUpperPrtBottom < 0 || !rTab.DoesObjsFit() ) 788 bRet = false; 789 // <-- 790 791 // 792 // 2. Check if each cell in the last line has at least one content frame. 793 // 794 // Note: a FollowFlowRow may contains empty cells! 795 // 796 if ( bRet ) 797 { 798 if ( !rLastLine.IsInFollowFlowRow() ) 799 { 800 SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower(); 801 while ( pCurrMasterCell ) 802 { 803 if ( !pCurrMasterCell->ContainsCntnt() && pCurrMasterCell->GetTabBox()->getRowSpan() >= 1 ) 804 { 805 bRet = false; 806 break; 807 } 808 pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext(); 809 } 810 } 811 } 812 813 // 814 // 3. Check if last line does not contain any content: 815 // 816 if ( bRet ) 817 { 818 if ( !rLastLine.ContainsCntnt() ) 819 { 820 bRet = false; 821 } 822 } 823 824 825 // 826 // 4. Check if follow flow line does not contain content: 827 // 828 if ( bRet ) 829 { 830 if ( !rFollowLine.IsRowSpanLine() && !rFollowLine.ContainsCntnt() ) 831 { 832 bRet = false; 833 } 834 } 835 836 if ( bRet ) 837 { 838 // 839 // Everything looks fine. Splitting seems to be successful. We invalidate 840 // rFollowLine to force a new formatting. 841 // 842 ::SwInvalidateAll( &rFollowLine, LONG_MAX ); 843 } 844 else 845 { 846 // 847 // Splitting the table row gave us an unexpected result. 848 // Everything has to be prepared for a second try to split 849 // the table, this time without splitting the row. 850 // 851 ::SwInvalidateAll( &rLastLine, LONG_MAX ); 852 } 853 854 rTab.SetRebuildLastLine( sal_False ); 855 // --> OD 2004-10-15 #i26945# 856 rTab.SetDoesObjsFit( sal_True ); 857 // <-- 858 859 return bRet; 860 } 861 862 // 863 // Sets the correct height for all spanned cells 864 // 865 void lcl_AdjustRowSpanCells( SwRowFrm* pRow ) 866 { 867 SWRECTFN( pRow ) 868 SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pRow->GetLower()); 869 while ( pCellFrm ) 870 { 871 const long nLayoutRowSpan = pCellFrm->GetLayoutRowSpan(); 872 if ( nLayoutRowSpan > 1 ) 873 { 874 // calculate height of cell: 875 const long nNewCellHeight = lcl_GetHeightOfRows( pRow, nLayoutRowSpan ); 876 const long nDiff = nNewCellHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)(); 877 if ( nDiff ) 878 (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff ); 879 } 880 881 pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext()); 882 } 883 } 884 885 // 886 // Returns the maximum layout row span of the row 887 // Looking for the next row that contains no covered cells: 888 long lcl_GetMaximumLayoutRowSpan( const SwRowFrm& rRow ) 889 { 890 long nRet = 1; 891 892 const SwRowFrm* pCurrentRowFrm = static_cast<const SwRowFrm*>(rRow.GetNext()); 893 bool bNextRow = false; 894 895 while ( pCurrentRowFrm ) 896 { 897 // if there is any covered cell, we proceed to the next row frame 898 const SwCellFrm* pLower = static_cast<const SwCellFrm*>( pCurrentRowFrm->Lower()); 899 while ( pLower ) 900 { 901 if ( pLower->GetTabBox()->getRowSpan() < 0 ) 902 { 903 ++nRet; 904 bNextRow = true; 905 break; 906 } 907 pLower = static_cast<const SwCellFrm*>(pLower->GetNext()); 908 } 909 pCurrentRowFrm = bNextRow ? 910 static_cast<const SwRowFrm*>(pCurrentRowFrm->GetNext() ) : 911 0; 912 } 913 914 return nRet; 915 } 916 917 /************************************************************************* 918 |* END: local helper functions for splitting row frames 919 |*************************************************************************/ 920 921 // 922 // Function to remove the FollowFlowLine of rTab. 923 // The content of the FollowFlowLine is moved to the associated line in the 924 // master table. 925 // 926 bool SwTabFrm::RemoveFollowFlowLine() 927 { 928 // find FollowFlowLine 929 SwRowFrm* pFollowFlowLine = static_cast<SwRowFrm*>(GetFollow()->GetFirstNonHeadlineRow()); 930 931 // find last row in master 932 SwFrm* pLastLine = GetLastLower(); 933 934 ASSERT( HasFollowFlowLine() && 935 pFollowFlowLine && 936 pLastLine, "There should be a flowline in the follow" ) 937 938 // We have to reset the flag here, because lcl_MoveRowContent 939 // calls a GrowFrm(), which has a different bahavior if 940 // this flag is set. 941 SetFollowFlowLine( sal_False ); 942 943 // --> FME 2007-07-19 #140081# Make code robust. 944 if ( !pFollowFlowLine || !pLastLine ) 945 return true; 946 947 // Move content 948 lcl_MoveRowContent( *pFollowFlowLine, *(SwRowFrm*)pLastLine ); 949 950 // NEW TABLES 951 // If a row span follow flow line is removed, we want to move the whole span 952 // to the master: 953 SwTwips nGrow = 0; 954 long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pFollowFlowLine ); 955 956 if ( nRowsToMove > 1 ) 957 { 958 SWRECTFN( this ) 959 SwFrm* pRow = pFollowFlowLine->GetNext(); 960 SwFrm* pInsertBehind = GetLastLower(); 961 962 while ( pRow && nRowsToMove-- > 1 ) 963 { 964 SwFrm* pNxt = pRow->GetNext(); 965 nGrow += (pRow->Frm().*fnRect->fnGetHeight)(); 966 967 // The footnotes have to be moved: 968 lcl_MoveFootnotes( *GetFollow(), *this, (SwRowFrm&)*pRow ); 969 970 pRow->Remove(); 971 pRow->InsertBehind( this, pInsertBehind ); 972 pRow->_InvalidateAll(); 973 pRow->CheckDirChange(); 974 pInsertBehind = pRow; 975 pRow = pNxt; 976 } 977 978 SwFrm* pFirstRow = Lower(); 979 while ( pFirstRow ) 980 { 981 lcl_AdjustRowSpanCells( static_cast<SwRowFrm*>(pFirstRow) ); 982 pFirstRow = pFirstRow->GetNext(); 983 } 984 985 Grow( nGrow ); 986 GetFollow()->Shrink( nGrow ); 987 } 988 989 bool bJoin = !pFollowFlowLine->GetNext(); 990 pFollowFlowLine->Cut(); 991 delete pFollowFlowLine; 992 993 return bJoin; 994 } 995 996 // --> OD 2004-10-04 #i26945# - Floating screen objects are no longer searched. 997 bool lcl_FindSectionsInRow( const SwRowFrm& rRow ) 998 { 999 bool bRet = false; 1000 SwCellFrm* pLower = (SwCellFrm*)rRow.Lower(); 1001 while ( pLower ) 1002 { 1003 if ( pLower->IsVertical() != rRow.IsVertical() ) 1004 return true; 1005 1006 SwFrm* pTmpFrm = pLower->Lower(); 1007 while ( pTmpFrm ) 1008 { 1009 if ( pTmpFrm->IsRowFrm() ) 1010 { 1011 bRet = lcl_FindSectionsInRow( *(SwRowFrm*)pTmpFrm ); 1012 } 1013 else 1014 { 1015 // --> OD 2004-10-04 #i26945# - search only for sections 1016 bRet = pTmpFrm->IsSctFrm(); 1017 // <-- 1018 } 1019 1020 if ( bRet ) 1021 return true; 1022 pTmpFrm = pTmpFrm->GetNext(); 1023 } 1024 1025 pLower = (SwCellFrm*)pLower->GetNext(); 1026 } 1027 return bRet; 1028 } 1029 1030 /************************************************************************* 1031 |* 1032 |* SwTabFrm::Split(), Join() 1033 |* 1034 |* Ersterstellung MA 03. Jun. 93 1035 |* Letzte Aenderung MA 03. Sep. 96 1036 |* 1037 |*************************************************************************/ 1038 bool SwTabFrm::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep ) 1039 { 1040 bool bRet = true; 1041 1042 SWRECTFN( this ) 1043 //ASSERT( bVert ? nCutPos >= Frm().Left() && 1044 // nCutPos <= Frm().Left() + Frm().Width() : 1045 // nCutPos >= Frm().Top() && nCutPos <= Frm().Bottom(), "SplitLine out of table." ); 1046 1047 // --> OD 2004-10-14 #i26745# - format row and cell frames of table 1048 { 1049 this->Lower()->_InvalidatePos(); 1050 // --> OD 2005-03-30 #i43913# - correction: 1051 // call method <lcl_InnerCalcLayout> with first lower. 1052 lcl_InnerCalcLayout( this->Lower(), LONG_MAX, true ); 1053 // <-- 1054 } 1055 // <-- 1056 1057 //Um die Positionen der Zellen mit der CutPos zu vergleichen muessen sie 1058 //ausgehend von der Tabelle nacheinander berechnet werden. Sie koennen 1059 //wg. Positionsaenderungen der Tabelle durchaus ungueltig sein. 1060 SwRowFrm *pRow = static_cast<SwRowFrm*>(Lower()); 1061 if( !pRow ) 1062 return bRet; 1063 1064 const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat(); 1065 sal_uInt16 nRowCount = 0; // pRow currently points to the first row 1066 1067 SwTwips nRemainingSpaceForLastRow = 1068 (*fnRect->fnYDiff)( nCutPos, (Frm().*fnRect->fnGetTop)() ); 1069 nRemainingSpaceForLastRow -= (this->*fnRect->fnGetTopMargin)(); 1070 1071 // 1072 // Make pRow point to the line that does not fit anymore: 1073 // 1074 while( pRow->GetNext() && 1075 nRemainingSpaceForLastRow >= ( (pRow->Frm().*fnRect->fnGetHeight)() + 1076 (IsCollapsingBorders() ? 1077 pRow->GetBottomLineSize() : 1078 0 ) ) ) 1079 { 1080 if( bTryToSplit || !pRow->IsRowSpanLine() || 1081 0 != (pRow->Frm().*fnRect->fnGetHeight)() ) 1082 ++nRowCount; 1083 nRemainingSpaceForLastRow -= (pRow->Frm().*fnRect->fnGetHeight)(); 1084 pRow = static_cast<SwRowFrm*>(pRow->GetNext()); 1085 } 1086 1087 // 1088 // bSplitRowAllowed: Row may be split according to its attributes. 1089 // bTryToSplit: Row will never be split if bTryToSplit = false. 1090 // This can either be passed as a parameter, indicating 1091 // that we are currently doing the second try to split the 1092 // table, or it will be set to falseunder certain 1093 // conditions that are not suitable for splitting 1094 // the row. 1095 // 1096 bool bSplitRowAllowed = pRow->IsRowSplitAllowed(); 1097 1098 // --> FME 2004-06-03 #i29438# 1099 // --> OD 2004-10-04 #i26945# - Floating screen objects no longer forbid 1100 // a splitting of the table row. 1101 // Special DoNotSplit case 1: 1102 // Search for sections inside pRow: 1103 // 1104 if ( lcl_FindSectionsInRow( *pRow ) ) 1105 { 1106 bTryToSplit = false; 1107 } 1108 // <-- 1109 1110 // --> FME 2004-06-07 #i29771# 1111 // To avoid loops, we do some checks before actually trying to split 1112 // the row. Maybe we should keep the next row in this table. 1113 // Note: This is only done if we are at the beginning of our upper 1114 bool bKeepNextRow = false; 1115 if ( nRowCount < nRepeat ) 1116 { 1117 // 1118 // First case: One of the repeated headline does not fit to the page anymore. 1119 // At least one more non-heading row has to stay in this table in 1120 // order to avoid loops: 1121 // 1122 ASSERT( !GetIndPrev(), "Table is supposed to be at beginning" ) 1123 bKeepNextRow = true; 1124 } 1125 else if ( !GetIndPrev() && nRepeat == nRowCount ) 1126 { 1127 // 1128 // Second case: The first non-headline row does not fit to the page. 1129 // If it is not allowed to be split, or it contains a sub-row that 1130 // is not allowed to be split, we keep the row in this table: 1131 // 1132 if ( bTryToSplit && bSplitRowAllowed ) 1133 { 1134 // Check if there are (first) rows inside this row, 1135 // which are not allowed to be split. 1136 SwCellFrm* pLowerCell = pRow ? (SwCellFrm*)pRow->Lower() : 0; 1137 while ( pLowerCell ) 1138 { 1139 if ( pLowerCell->Lower() && pLowerCell->Lower()->IsRowFrm() ) 1140 { 1141 const SwRowFrm* pLowerRow = (SwRowFrm*)pLowerCell->Lower(); 1142 if ( !pLowerRow->IsRowSplitAllowed() && 1143 (pLowerRow->Frm().*fnRect->fnGetHeight)() > 1144 nRemainingSpaceForLastRow ) 1145 { 1146 bKeepNextRow = true; 1147 break; 1148 } 1149 } 1150 pLowerCell = (SwCellFrm*)pLowerCell->GetNext(); 1151 } 1152 } 1153 else 1154 bKeepNextRow = true; 1155 } 1156 1157 // 1158 // Better keep the next row in this table: 1159 // 1160 if ( bKeepNextRow ) 1161 { 1162 pRow = GetFirstNonHeadlineRow(); 1163 if( pRow && pRow->IsRowSpanLine() && 0 == (pRow->Frm().*fnRect->fnGetHeight)() ) 1164 pRow = static_cast<SwRowFrm*>(pRow->GetNext()); 1165 if ( pRow ) 1166 { 1167 pRow = static_cast<SwRowFrm*>(pRow->GetNext()); 1168 ++nRowCount; 1169 } 1170 } 1171 1172 // 1173 // No more row to split or to move to follow table: 1174 // 1175 if ( !pRow ) 1176 return bRet; 1177 1178 // 1179 // We try to split the row if 1180 // - the attributes of the row are set accordingly and 1181 // - we are allowed to do so 1182 // - the it should not keep with the next row 1183 // 1184 bSplitRowAllowed = bSplitRowAllowed && bTryToSplit && 1185 ( !bTableRowKeep || 1186 !pRow->ShouldRowKeepWithNext() ); 1187 1188 // Adjust pRow according to the keep-with-next attribute: 1189 if ( !bSplitRowAllowed && bTableRowKeep ) 1190 { 1191 SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pRow->GetPrev()); 1192 SwRowFrm* pOldRow = pRow; 1193 while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() && 1194 nRowCount > nRepeat ) 1195 { 1196 pRow = pTmpRow; 1197 --nRowCount; 1198 pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetPrev()); 1199 } 1200 1201 // loop prevention 1202 if ( nRowCount == nRepeat && !GetIndPrev()) 1203 { 1204 pRow = pOldRow; 1205 } 1206 } 1207 1208 // 1209 // If we do not indent to split pRow, we check if we are 1210 // allowed to move pRow to a follow. Otherwise we return 1211 // false, indicating an error 1212 // 1213 if ( !bSplitRowAllowed ) 1214 { 1215 SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow(); 1216 if ( pRow == pFirstNonHeadlineRow ) 1217 return false; 1218 1219 // --> OD 2008-10-21 #i91764# 1220 // Ignore row span lines 1221 SwRowFrm* pTmpRow = pFirstNonHeadlineRow; 1222 while ( pTmpRow && pTmpRow->IsRowSpanLine() ) 1223 { 1224 pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetNext()); 1225 } 1226 if ( !pTmpRow || pRow == pTmpRow ) 1227 { 1228 return false; 1229 } 1230 // <-- 1231 } 1232 1233 // 1234 // Build follow table if not already done: 1235 // 1236 sal_Bool bNewFollow; 1237 SwTabFrm *pFoll; 1238 if ( GetFollow() ) 1239 { 1240 pFoll = GetFollow(); 1241 bNewFollow = sal_False; 1242 } 1243 else 1244 { 1245 bNewFollow = sal_True; 1246 pFoll = new SwTabFrm( *this ); 1247 1248 // 1249 // We give the follow table an initial width. 1250 // 1251 (pFoll->Frm().*fnRect->fnAddWidth)( (Frm().*fnRect->fnGetWidth)() ); 1252 (pFoll->Prt().*fnRect->fnAddWidth)( (Prt().*fnRect->fnGetWidth)() ); 1253 (pFoll->Frm().*fnRect->fnSetLeft)( (Frm().*fnRect->fnGetLeft)() ); 1254 1255 // 1256 // Insert the new follow table 1257 // 1258 pFoll->InsertBehind( GetUpper(), this ); 1259 1260 // 1261 // Repeat the headlines. 1262 // 1263 for ( nRowCount = 0; nRowCount < nRepeat; ++nRowCount ) 1264 { 1265 // Insert new headlines: 1266 bDontCreateObjects = sal_True; //frmtool 1267 SwRowFrm* pHeadline = new SwRowFrm( 1268 *GetTable()->GetTabLines()[ nRowCount ], this ); 1269 pHeadline->SetRepeatedHeadline( true ); 1270 bDontCreateObjects = sal_False; 1271 pHeadline->InsertBefore( pFoll, 0 ); 1272 1273 SwPageFrm *pPage = pHeadline->FindPageFrm(); 1274 const SwSpzFrmFmts *pTbl = GetFmt()->GetDoc()->GetSpzFrmFmts(); 1275 if( pTbl->Count() ) 1276 { 1277 sal_uLong nIndex; 1278 SwCntntFrm* pFrm = pHeadline->ContainsCntnt(); 1279 while( pFrm ) 1280 { 1281 nIndex = pFrm->GetNode()->GetIndex(); 1282 AppendObjs( pTbl, nIndex, pFrm, pPage ); 1283 pFrm = pFrm->GetNextCntntFrm(); 1284 if( !pHeadline->IsAnLower( pFrm ) ) 1285 break; 1286 } 1287 } 1288 } 1289 } 1290 1291 SwRowFrm* pLastRow = 0; // will point to the last remaining line in master 1292 SwRowFrm* pFollowRow = 0; // points to either the follow flow line of the 1293 // first regular line in the follow 1294 1295 if ( bSplitRowAllowed ) 1296 { 1297 // If the row that does not fit anymore is allowed 1298 // to be split, the next row has to be moved to the follow table. 1299 pLastRow = pRow; 1300 pRow = static_cast<SwRowFrm*>(pRow->GetNext()); 1301 1302 // new follow flow line for last row of master table 1303 pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, false ); 1304 } 1305 else 1306 { 1307 pFollowRow = pRow; 1308 1309 // NEW TABLES 1310 // check if we will break a row span by moving pFollowRow to the follow: 1311 // In this case we want to reformat the last line. 1312 const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>(pFollowRow->GetLower()); 1313 while ( pCellFrm ) 1314 { 1315 if ( pCellFrm->GetTabBox()->getRowSpan() < 1 ) 1316 { 1317 pLastRow = static_cast<SwRowFrm*>(pRow->GetPrev()); 1318 break; 1319 } 1320 1321 pCellFrm = static_cast<const SwCellFrm*>(pCellFrm->GetNext()); 1322 } 1323 1324 // new follow flow line for last row of master table 1325 if ( pLastRow ) 1326 pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, true ); 1327 } 1328 1329 SwTwips nRet = 0; 1330 1331 //Optimierung beim neuen Follow braucht's kein Paste und dann kann 1332 //das Optimierte Insert verwendet werden (nur dann treten gluecklicher weise 1333 //auch groessere Mengen von Rows auf). 1334 if ( bNewFollow ) 1335 { 1336 SwFrm* pNxt = 0; 1337 SwFrm* pInsertBehind = pFoll->GetLastLower(); 1338 1339 while ( pRow ) 1340 { 1341 pNxt = pRow->GetNext(); 1342 nRet += (pRow->Frm().*fnRect->fnGetHeight)(); 1343 // The footnotes do not have to be moved, this is done in the 1344 // MoveFwd of the follow table!!! 1345 pRow->Remove(); 1346 pRow->InsertBehind( pFoll, pInsertBehind ); 1347 pRow->_InvalidateAll(); 1348 pInsertBehind = pRow; 1349 pRow = static_cast<SwRowFrm*>(pNxt); 1350 } 1351 } 1352 else 1353 { 1354 SwFrm* pNxt = 0; 1355 SwFrm* pPasteBefore = HasFollowFlowLine() ? 1356 pFollowRow->GetNext() : 1357 pFoll->GetFirstNonHeadlineRow(); 1358 1359 while ( pRow ) 1360 { 1361 pNxt = pRow->GetNext(); 1362 nRet += (pRow->Frm().*fnRect->fnGetHeight)(); 1363 1364 // The footnotes have to be moved: 1365 lcl_MoveFootnotes( *this, *GetFollow(), *pRow ); 1366 1367 pRow->Remove(); 1368 pRow->Paste( pFoll, pPasteBefore ); 1369 1370 pRow->CheckDirChange(); 1371 pRow = static_cast<SwRowFrm*>(pNxt); 1372 } 1373 } 1374 1375 Shrink( nRet ); 1376 1377 // we rebuild the last line to assure that it will be fully formatted 1378 if ( pLastRow ) 1379 { 1380 // recalculate the split line 1381 bRet = lcl_RecalcSplitLine( *pLastRow, *pFollowRow, nRemainingSpaceForLastRow ); 1382 1383 // NEW TABLES 1384 // check if each cell in the row span line has a good height 1385 if ( bRet && pFollowRow->IsRowSpanLine() ) 1386 lcl_AdjustRowSpanCells( pFollowRow ); 1387 1388 // We The RowSplitLine stuff did not work. In this case we conceal the split error: 1389 if ( !bRet && !bSplitRowAllowed ) 1390 { 1391 bRet = true; 1392 } 1393 } 1394 1395 return bRet; 1396 } 1397 1398 bool SwTabFrm::Join() 1399 { 1400 ASSERT( !HasFollowFlowLine(), "Joining follow flow line" ) 1401 1402 SwTabFrm *pFoll = GetFollow(); 1403 SwTwips nHeight = 0; //Gesamthoehe der eingefuegten Zeilen als Return. 1404 1405 if ( !pFoll->IsJoinLocked() ) 1406 { 1407 SWRECTFN( this ) 1408 pFoll->Cut(); //Erst ausschneiden um unuetze Benachrichtigungen zu 1409 //minimieren. 1410 1411 SwFrm *pRow = pFoll->GetFirstNonHeadlineRow(), 1412 *pNxt; 1413 1414 SwFrm* pPrv = GetLastLower(); 1415 1416 while ( pRow ) 1417 { 1418 pNxt = pRow->GetNext(); 1419 nHeight += (pRow->Frm().*fnRect->fnGetHeight)(); 1420 pRow->Remove(); 1421 pRow->_InvalidateAll(); 1422 pRow->InsertBehind( this, pPrv ); 1423 pRow->CheckDirChange(); 1424 pPrv = pRow; 1425 pRow = pNxt; 1426 } 1427 1428 SetFollow( pFoll->GetFollow() ); 1429 SetFollowFlowLine( pFoll->HasFollowFlowLine() ); 1430 delete pFoll; 1431 1432 Grow( nHeight ); 1433 } 1434 1435 return true; 1436 } 1437 1438 /************************************************************************* 1439 |* 1440 |* SwTabFrm::MakeAll() 1441 |* 1442 |* Ersterstellung MA 09. Mar. 93 1443 |* Letzte Aenderung MA 10. Apr. 97 1444 |* 1445 |*************************************************************************/ 1446 void MA_FASTCALL SwInvalidatePositions( SwFrm *pFrm, long nBottom ) 1447 { 1448 // LONG_MAX == nBottom means we have to calculate all 1449 sal_Bool bAll = LONG_MAX == nBottom; 1450 SWRECTFN( pFrm ) 1451 do 1452 { pFrm->_InvalidatePos(); 1453 pFrm->_InvalidateSize(); 1454 if( pFrm->IsLayoutFrm() ) 1455 { 1456 if ( ((SwLayoutFrm*)pFrm)->Lower() ) 1457 { 1458 ::SwInvalidatePositions( ((SwLayoutFrm*)pFrm)->Lower(), nBottom); 1459 // --> OD 2004-11-05 #i26945# 1460 ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pFrm)) ); 1461 // <-- 1462 } 1463 } 1464 else 1465 pFrm->Prepare( PREP_ADJUST_FRM ); 1466 pFrm = pFrm->GetNext(); 1467 } while ( pFrm && 1468 ( bAll || 1469 (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) ); 1470 } 1471 1472 void MA_FASTCALL SwInvalidateAll( SwFrm *pFrm, long nBottom ) 1473 { 1474 // LONG_MAX == nBottom means we have to calculate all 1475 sal_Bool bAll = LONG_MAX == nBottom; 1476 SWRECTFN( pFrm ) 1477 do 1478 { 1479 pFrm->_InvalidatePos(); 1480 pFrm->_InvalidateSize(); 1481 pFrm->_InvalidatePrt(); 1482 if( pFrm->IsLayoutFrm() ) 1483 { 1484 // NEW TABLES 1485 SwLayoutFrm* pToInvalidate = static_cast<SwLayoutFrm*>(pFrm); 1486 SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm); 1487 if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 ) 1488 { 1489 pToInvalidate = & const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true )); 1490 pToInvalidate->_InvalidatePos(); 1491 pToInvalidate->_InvalidateSize(); 1492 pToInvalidate->_InvalidatePrt(); 1493 } 1494 1495 if ( pToInvalidate->Lower() ) 1496 ::SwInvalidateAll( pToInvalidate->Lower(), nBottom); 1497 } 1498 else 1499 pFrm->Prepare( PREP_CLEAR ); 1500 1501 pFrm = pFrm->GetNext(); 1502 } while ( pFrm && 1503 ( bAll || 1504 (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) ); 1505 } 1506 1507 // --> collapsing borders FME 2005-05-27 #i29550# 1508 void lcl_InvalidateAllLowersPrt( SwLayoutFrm* pLayFrm ) 1509 { 1510 pLayFrm->_InvalidatePrt(); 1511 pLayFrm->_InvalidateSize(); 1512 pLayFrm->SetCompletePaint(); 1513 1514 SwFrm* pFrm = pLayFrm->Lower(); 1515 1516 while ( pFrm ) 1517 { 1518 if ( pFrm->IsLayoutFrm() ) 1519 lcl_InvalidateAllLowersPrt( (SwLayoutFrm*)pFrm ); 1520 else 1521 { 1522 pFrm->_InvalidatePrt(); 1523 pFrm->_InvalidateSize(); 1524 pFrm->SetCompletePaint(); 1525 } 1526 1527 pFrm = pFrm->GetNext(); 1528 } 1529 } 1530 // <-- collapsing 1531 1532 bool SwCntntFrm::CalcLowers( SwLayoutFrm* pLay, const SwLayoutFrm* pDontLeave, 1533 long nBottom, bool bSkipRowSpanCells ) 1534 { 1535 if ( !pLay ) 1536 return sal_True; 1537 1538 // LONG_MAX == nBottom means we have to calculate all 1539 bool bAll = LONG_MAX == nBottom; 1540 bool bRet = sal_False; 1541 SwCntntFrm *pCnt = pLay->ContainsCntnt(); 1542 SWRECTFN( pLay ) 1543 1544 // FME 2007-08-30 #i81146# new loop control 1545 sal_uInt16 nLoopControlRuns = 0; 1546 const sal_uInt16 nLoopControlMax = 10; 1547 const SwModify* pLoopControlCond = 0; 1548 1549 while ( pCnt && pDontLeave->IsAnLower( pCnt ) ) 1550 { 1551 // --> OD 2004-11-23 #115759# - check, if a format of content frame is 1552 // possible. Thus, 'copy' conditions, found at the beginning of 1553 // <SwCntntFrm::MakeAll(..)>, and check these. 1554 const bool bFormatPossible = !pCnt->IsJoinLocked() && 1555 ( !pCnt->IsTxtFrm() || 1556 !static_cast<SwTxtFrm*>(pCnt)->IsLocked() ) && 1557 ( pCnt->IsFollow() || !StackHack::IsLocked() ); 1558 1559 // NEW TABLES 1560 bool bSkipContent = false; 1561 if ( bSkipRowSpanCells && pCnt->IsInTab() ) 1562 { 1563 const SwFrm* pCell = pCnt->GetUpper(); 1564 while ( pCell && !pCell->IsCellFrm() ) 1565 pCell = pCell->GetUpper(); 1566 if ( pCell && 1 != static_cast<const SwCellFrm*>( pCell )->GetLayoutRowSpan() ) 1567 bSkipContent = true; 1568 } 1569 1570 if ( bFormatPossible && !bSkipContent ) 1571 { 1572 bRet |= !pCnt->IsValid(); 1573 // --> OD 2004-10-06 #i26945# - no extra invalidation of floating 1574 // screen objects needed. 1575 // Thus, delete call of method <SwFrm::InvalidateObjs( true )> 1576 // <-- 1577 pCnt->Calc(); 1578 // OD 2004-05-11 #i28701# - usage of new method <::FormatObjsAtFrm(..)> 1579 // to format the floating screen objects 1580 // --> OD 2005-05-03 #i46941# - frame has to be valid 1581 // Note: frame could be invalid after calling its format, if it's locked. 1582 ASSERT( !pCnt->IsTxtFrm() || 1583 pCnt->IsValid() || 1584 static_cast<SwTxtFrm*>(pCnt)->IsJoinLocked(), 1585 "<SwCntntFrm::CalcLowers(..)> - text frame invalid and not locked." ); 1586 if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) 1587 { 1588 // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame to 1589 // the object formatter 1590 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, 1591 *(pCnt->FindPageFrm()) ) ) 1592 // <-- 1593 { 1594 if ( pCnt->GetRegisteredIn() == pLoopControlCond ) 1595 ++nLoopControlRuns; 1596 else 1597 { 1598 nLoopControlRuns = 0; 1599 pLoopControlCond = pCnt->GetRegisteredIn(); 1600 } 1601 1602 if ( nLoopControlRuns < nLoopControlMax ) 1603 { 1604 // restart format with first content 1605 pCnt = pLay->ContainsCntnt(); 1606 continue; 1607 } 1608 1609 #if OSL_DEBUG_LEVEL > 1 1610 ASSERT( false, "LoopControl in SwCntntFrm::CalcLowers" ) 1611 #endif 1612 } 1613 } 1614 pCnt->GetUpper()->Calc(); 1615 } 1616 // <-- 1617 if( ! bAll && (*fnRect->fnYDiff)((pCnt->Frm().*fnRect->fnGetTop)(), nBottom) > 0 ) 1618 break; 1619 pCnt = pCnt->GetNextCntntFrm(); 1620 } 1621 return bRet; 1622 } 1623 1624 // --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control 1625 // that only row and cell frames are formatted. 1626 sal_Bool MA_FASTCALL lcl_InnerCalcLayout( SwFrm *pFrm, 1627 long nBottom, 1628 bool _bOnlyRowsAndCells ) 1629 { 1630 // LONG_MAX == nBottom means we have to calculate all 1631 sal_Bool bAll = LONG_MAX == nBottom; 1632 sal_Bool bRet = sal_False; 1633 const SwFrm* pOldUp = pFrm->GetUpper(); 1634 SWRECTFN( pFrm ) 1635 do 1636 { 1637 // --> OD 2004-10-15 #i26945# - parameter <_bOnlyRowsAndCells> controls, 1638 // if only row and cell frames are formatted. 1639 if ( pFrm->IsLayoutFrm() && 1640 ( !_bOnlyRowsAndCells || pFrm->IsRowFrm() || pFrm->IsCellFrm() ) ) 1641 // <-- 1642 { 1643 // --> FME 2006-02-23 #130744# An invalid locked table frame will 1644 // not be calculated => It will not become valid => 1645 // Loop in lcl_RecalcRow(). Therefore we do not consider them for bRet. 1646 bRet |= !pFrm->IsValid() && ( !pFrm->IsTabFrm() || !static_cast<SwTabFrm*>(pFrm)->IsJoinLocked() ); 1647 // <-- 1648 pFrm->Calc(); 1649 if( static_cast<SwLayoutFrm*>(pFrm)->Lower() ) 1650 bRet |= lcl_InnerCalcLayout( static_cast<SwLayoutFrm*>(pFrm)->Lower(), nBottom); 1651 1652 // NEW TABLES 1653 SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm); 1654 if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 ) 1655 { 1656 SwCellFrm& rToCalc = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true )); 1657 bRet |= !rToCalc.IsValid(); 1658 rToCalc.Calc(); 1659 if ( rToCalc.Lower() ) 1660 bRet |= lcl_InnerCalcLayout( rToCalc.Lower(), nBottom); 1661 } 1662 } 1663 pFrm = pFrm->GetNext(); 1664 } while( pFrm && 1665 ( bAll || 1666 (*fnRect->fnYDiff)((pFrm->Frm().*fnRect->fnGetTop)(), nBottom) < 0 ) 1667 && pFrm->GetUpper() == pOldUp ); 1668 return bRet; 1669 } 1670 1671 void MA_FASTCALL lcl_RecalcRow( SwRowFrm& rRow, long nBottom ) 1672 { 1673 // --> OD 2004-10-05 #i26945# - For correct appliance of the 'straightforward 1674 // object positioning process, it's needed to notify that the page frame, 1675 // on which the given layout frame is in, is in its layout process. 1676 SwPageFrm* pPageFrm = rRow.FindPageFrm(); 1677 if ( pPageFrm && !pPageFrm->IsLayoutInProgress() ) 1678 pPageFrm->SetLayoutInProgress( true ); 1679 else 1680 pPageFrm = 0L; 1681 // <-- 1682 1683 // FME 2007-08-30 #i81146# new loop control 1684 sal_uInt16 nLoopControlRuns_1 = 0; 1685 sal_uInt16 nLoopControlStage_1 = 0; 1686 const sal_uInt16 nLoopControlMax = 10; 1687 1688 bool bCheck = true; 1689 do 1690 { 1691 // FME 2007-08-30 #i81146# new loop control 1692 sal_uInt16 nLoopControlRuns_2 = 0; 1693 sal_uInt16 nLoopControlStage_2 = 0; 1694 1695 while( lcl_InnerCalcLayout( &rRow, nBottom ) ) 1696 { 1697 if ( ++nLoopControlRuns_2 > nLoopControlMax ) 1698 { 1699 #if OSL_DEBUG_LEVEL > 1 1700 ASSERT( 0 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 1!" ); 1701 ASSERT( 1 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 2!!" ); 1702 ASSERT( 2 > nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 3!!!" ); 1703 #endif 1704 rRow.ValidateThisAndAllLowers( nLoopControlStage_2++ ); 1705 nLoopControlRuns_2 = 0; 1706 if( nLoopControlStage_2 > 2 ) 1707 break; 1708 } 1709 1710 bCheck = true; 1711 } 1712 1713 if( bCheck ) 1714 { 1715 // --> OD 2004-11-23 #115759# - force another format of the 1716 // lowers, if at least one of it was invalid. 1717 bCheck = SwCntntFrm::CalcLowers( &rRow, rRow.GetUpper(), nBottom, true ); 1718 // <-- 1719 1720 // NEW TABLES 1721 // First we calculate the cells with row span of < 1, afterwards 1722 // all cells with row span of > 1: 1723 for ( int i = 0; i < 2; ++i ) 1724 { 1725 SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(rRow.Lower()); 1726 while ( pCellFrm ) 1727 { 1728 const bool bCalc = 0 == i ? 1729 pCellFrm->GetLayoutRowSpan() < 1 : 1730 pCellFrm->GetLayoutRowSpan() > 1; 1731 1732 if ( bCalc ) 1733 { 1734 SwCellFrm& rToRecalc = 0 == i ? 1735 const_cast<SwCellFrm&>(pCellFrm->FindStartEndOfRowSpanCell( true, true )) : 1736 *pCellFrm; 1737 bCheck |= SwCntntFrm::CalcLowers( &rToRecalc, &rToRecalc, nBottom, false ); 1738 } 1739 1740 pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext()); 1741 } 1742 } 1743 1744 if ( bCheck ) 1745 { 1746 if ( ++nLoopControlRuns_1 > nLoopControlMax ) 1747 { 1748 #if OSL_DEBUG_LEVEL > 1 1749 ASSERT( 0 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 1!" ); 1750 ASSERT( 1 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 2!!" ); 1751 ASSERT( 2 > nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 3!!!" ); 1752 #endif 1753 rRow.ValidateThisAndAllLowers( nLoopControlStage_1++ ); 1754 nLoopControlRuns_1 = 0; 1755 if( nLoopControlStage_1 > 2 ) 1756 break; 1757 } 1758 1759 continue; 1760 } 1761 } 1762 break; 1763 } while( true ); 1764 1765 // --> OD 2004-10-05 #i26945# 1766 if ( pPageFrm ) 1767 pPageFrm->SetLayoutInProgress( false ); 1768 // <-- 1769 } 1770 1771 void MA_FASTCALL lcl_RecalcTable( SwTabFrm& rTab, 1772 SwLayoutFrm *pFirstRow, 1773 SwLayNotify &rNotify ) 1774 { 1775 if ( rTab.Lower() ) 1776 { 1777 if ( !pFirstRow ) 1778 { 1779 pFirstRow = (SwLayoutFrm*)rTab.Lower(); 1780 rNotify.SetLowersComplete( sal_True ); 1781 } 1782 ::SwInvalidatePositions( pFirstRow, LONG_MAX ); 1783 lcl_RecalcRow( static_cast<SwRowFrm&>(*pFirstRow), LONG_MAX ); 1784 } 1785 } 1786 1787 // This is a new function to check the first condition whether 1788 // a tab frame may move backward. It replaces the formerly used 1789 // GetIndPrev(), which did not work correctly for #i5947# 1790 bool lcl_NoPrev( const SwFrm& rFrm ) 1791 { 1792 // --> OD 2007-09-04 #i79774#, #b6596954# 1793 // skip empty sections on investigation of direct previous frame. 1794 // use information, that at least one empty section is skipped in the following code. 1795 bool bSkippedDirectPrevEmptySection( false ); 1796 if ( rFrm.GetPrev() ) 1797 { 1798 const SwFrm* pPrev( rFrm.GetPrev() ); 1799 while ( pPrev && 1800 pPrev->IsSctFrm() && 1801 !dynamic_cast<const SwSectionFrm*>(pPrev)->GetSection() ) 1802 { 1803 pPrev = pPrev->GetPrev(); 1804 bSkippedDirectPrevEmptySection = true; 1805 } 1806 if ( pPrev ) 1807 { 1808 return false; 1809 } 1810 } 1811 1812 if ( ( !bSkippedDirectPrevEmptySection && !rFrm.GetIndPrev() ) || 1813 ( bSkippedDirectPrevEmptySection && 1814 ( !rFrm.IsInSct() || !rFrm._GetIndPrev() ) ) ) 1815 { 1816 return true; 1817 } 1818 // <-- 1819 1820 // I do not have a direct prev, but I have an indirect prev. 1821 // In section frames I have to check if I'm located inside 1822 // the first column: 1823 if ( rFrm.IsInSct() ) 1824 { 1825 const SwFrm* pSct = rFrm.GetUpper(); 1826 if ( pSct && pSct->IsColBodyFrm() && 1827 (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() ) 1828 { 1829 const SwFrm* pPrevCol = rFrm.GetUpper()->GetUpper()->GetPrev(); 1830 if ( pPrevCol ) 1831 // I'm not inside the first column and do not have a direct 1832 // prev. I can try to go backward. 1833 return true; 1834 } 1835 } 1836 1837 return false; 1838 } 1839 1840 #define KEEPTAB ( !GetFollow() && !IsFollow() ) 1841 1842 // --> OD 2005-09-28 #b6329202# - helper method to find next content frame of 1843 // a table frame and format it to assure keep attribute. 1844 // method return true, if a next content frame is formatted. 1845 // Precondition: The given table frame hasn't a follow and isn't a follow. 1846 SwFrm* lcl_FormatNextCntntForKeep( SwTabFrm* pTabFrm ) 1847 { 1848 // find next content, table or section 1849 SwFrm* pNxt = pTabFrm->FindNext(); 1850 1851 // skip empty sections 1852 while ( pNxt && pNxt->IsSctFrm() && 1853 !static_cast<SwSectionFrm*>(pNxt)->GetSection() ) 1854 { 1855 pNxt = pNxt->FindNext(); 1856 } 1857 1858 // if found next frame is a section, get its first content. 1859 if ( pNxt && pNxt->IsSctFrm() ) 1860 { 1861 pNxt = static_cast<SwSectionFrm*>(pNxt)->ContainsAny(); 1862 } 1863 1864 // format found next frame. 1865 // if table frame is inside another table, method <SwFrm::MakeAll()> is 1866 // called to avoid that the superior table frame is formatted. 1867 if ( pNxt ) 1868 { 1869 if ( pTabFrm->GetUpper()->IsInTab() ) 1870 pNxt->MakeAll(); 1871 else 1872 pNxt->Calc(); 1873 } 1874 1875 return pNxt; 1876 } 1877 1878 namespace { 1879 bool AreAllRowsKeepWithNext( const SwRowFrm* pFirstRowFrm ) 1880 { 1881 bool bRet = pFirstRowFrm != 0 && 1882 pFirstRowFrm->ShouldRowKeepWithNext(); 1883 1884 while ( bRet && pFirstRowFrm->GetNext() != 0 ) 1885 { 1886 pFirstRowFrm = dynamic_cast<const SwRowFrm*>(pFirstRowFrm->GetNext()); 1887 bRet = pFirstRowFrm != 0 && 1888 pFirstRowFrm->ShouldRowKeepWithNext(); 1889 } 1890 1891 return bRet; 1892 } 1893 } 1894 void SwTabFrm::MakeAll() 1895 { 1896 if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 ) 1897 return; 1898 1899 if ( HasFollow() ) 1900 { 1901 SwTabFrm* pFollowFrm = (SwTabFrm*)GetFollow(); 1902 ASSERT( !pFollowFrm->IsJoinLocked() || !pFollowFrm->IsRebuildLastLine(), 1903 "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" ) 1904 if ( pFollowFrm->IsJoinLocked() && pFollowFrm->IsRebuildLastLine() ) 1905 return; 1906 } 1907 1908 PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 ) 1909 1910 LockJoin(); //Ich lass mich nicht unterwegs vernichten. 1911 SwLayNotify aNotify( this ); //uebernimmt im DTor die Benachrichtigung 1912 // If pos is invalid, we have to call a SetInvaKeep at aNotify. 1913 // Otherwise the keep atribute would not work in front of a table. 1914 const sal_Bool bOldValidPos = GetValidPosFlag(); 1915 1916 //Wenn mein direkter Nachbar gleichzeitig mein Follow ist 1917 //verleibe ich mir das Teil ein. 1918 // OD 09.04.2003 #108698# - join all follows, which are placed on the 1919 // same page/column. 1920 // OD 29.04.2003 #109213# - join follow, only if join for the follow 1921 // is not locked. Otherwise, join will not be performed and this loop 1922 // will be endless. 1923 while ( GetNext() && GetNext() == GetFollow() && 1924 !GetFollow()->IsJoinLocked() 1925 ) 1926 { 1927 if ( HasFollowFlowLine() ) 1928 RemoveFollowFlowLine(); 1929 Join(); 1930 } 1931 1932 // The bRemoveFollowFlowLinePending is set if the split attribute of the 1933 // last line is set: 1934 if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() ) 1935 { 1936 if ( RemoveFollowFlowLine() ) 1937 Join(); 1938 SetRemoveFollowFlowLinePending( sal_False ); 1939 } 1940 1941 if ( bResizeHTMLTable ) //Optimiertes Zusammenspiel mit Grow/Shrink des Inhaltes 1942 { 1943 bResizeHTMLTable = sal_False; 1944 SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout(); 1945 if ( pLayout ) 1946 bCalcLowers = pLayout->Resize( 1947 pLayout->GetBrowseWidthByTabFrm( *this ), sal_False ); 1948 } 1949 1950 1951 sal_Bool bMakePage = sal_True; //solange sal_True kann eine neue Seite 1952 //angelegt werden (genau einmal) 1953 sal_Bool bMovedBwd = sal_False; //Wird sal_True wenn der Frame zurueckfliesst 1954 sal_Bool bMovedFwd = sal_False; //solange sal_False kann der Frm zurueck- 1955 //fliessen (solange, bis er einmal 1956 //vorwaerts ge'moved wurde). 1957 sal_Bool bSplit = sal_False; //Wird sal_True wenn der Frm gesplittet wurde. 1958 const sal_Bool bFtnsInDoc = 0 != GetFmt()->GetDoc()->GetFtnIdxs().Count(); 1959 sal_Bool bMoveable; 1960 const sal_Bool bFly = IsInFly(); 1961 1962 SwBorderAttrAccess *pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this ); 1963 const SwBorderAttrs *pAttrs = pAccess->Get(); 1964 1965 // The beloved keep attribute 1966 const bool bKeep = IsKeep( pAttrs->GetAttrSet() ); 1967 1968 // All rows should keep together 1969 // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next 1970 const bool bDontSplit = !IsFollow() && 1971 ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep ); 1972 1973 // The number of repeated headlines 1974 const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat(); 1975 1976 // This flag indicates that we are allowed to try to split the 1977 // table rows. 1978 bool bTryToSplit = true; 1979 1980 // --> FME 2006-02-16 #131283# 1981 // Indicates that two individual rows may keep together, based on the keep 1982 // attribute set at the first paragraph in the first cell. 1983 const bool bTableRowKeep = !bDontSplit && GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP); 1984 1985 // The Magic Move: Used for the table row keep feature. 1986 // If only the last row of the table wants to keep (implicitely by setting 1987 // keep for the first paragraph in the first cell), and this table does 1988 // not have a next, the last line will be cut. Loop prevention: Only 1989 // one try. 1990 bool bLastRowHasToMoveToFollow = false; 1991 bool bLastRowMoveNoMoreTries = false; 1992 1993 // Join follow table, if this table is not allowed to split: 1994 if ( bDontSplit ) 1995 { 1996 while ( GetFollow() && !GetFollow()->IsJoinLocked() ) 1997 { 1998 if ( HasFollowFlowLine() ) 1999 RemoveFollowFlowLine(); 2000 Join(); 2001 } 2002 } 2003 2004 // Join follow table, if this does not have enough (repeated) lines: 2005 if ( nRepeat ) 2006 { 2007 if( GetFollow() && !GetFollow()->IsJoinLocked() && 2008 0 == GetFirstNonHeadlineRow() ) 2009 { 2010 if ( HasFollowFlowLine() ) 2011 RemoveFollowFlowLine(); 2012 Join(); 2013 } 2014 } 2015 2016 // Join follow table, if last row of this table should keep: 2017 if ( bTableRowKeep && GetFollow() && !GetFollow()->IsJoinLocked() ) 2018 { 2019 const SwRowFrm* pTmpRow = static_cast<const SwRowFrm*>(GetLastLower()); 2020 if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() ) 2021 { 2022 if ( HasFollowFlowLine() ) 2023 RemoveFollowFlowLine(); 2024 Join(); 2025 } 2026 } 2027 2028 //Einen Frischling moven wir gleich schon einmal vorwaerts... 2029 if ( !Frm().Top() && IsFollow() ) 2030 { 2031 SwFrm *pPre = GetPrev(); 2032 if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this) 2033 { 2034 if ( !MoveFwd( bMakePage, sal_False ) ) 2035 bMakePage = sal_False; 2036 bMovedFwd = sal_True; 2037 } 2038 } 2039 2040 int nUnSplitted = 5; // Just another loop control :-( 2041 SWRECTFN( this ) 2042 while ( !bValidPos || !bValidSize || !bValidPrtArea ) 2043 { 2044 if ( sal_True == (bMoveable = IsMoveable()) ) 2045 if ( CheckMoveFwd( bMakePage, bKeep && KEEPTAB, bMovedBwd ) ) 2046 { 2047 bMovedFwd = sal_True; 2048 bCalcLowers = sal_True; 2049 // --> OD 2009-08-12 #i99267# 2050 // reset <bSplit> after forward move to assure that follows 2051 // can be joined, if further space is available. 2052 bSplit = sal_False; 2053 // <-- 2054 } 2055 2056 Point aOldPos( (Frm().*fnRect->fnGetPos)() ); 2057 MakePos(); 2058 2059 if ( aOldPos != (Frm().*fnRect->fnGetPos)() ) 2060 { 2061 if ( aOldPos.Y() != (Frm().*fnRect->fnGetTop)() ) 2062 { 2063 SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout(); 2064 if( pLayout ) 2065 { 2066 delete pAccess; 2067 bCalcLowers |= pLayout->Resize( 2068 pLayout->GetBrowseWidthByTabFrm( *this ), sal_False ); 2069 pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this ); 2070 pAttrs = pAccess->Get(); 2071 } 2072 2073 bValidPrtArea = sal_False; 2074 aNotify.SetLowersComplete( sal_False ); 2075 } 2076 SwFrm *pPre; 2077 if ( bKeep || (0 != (pPre = FindPrev()) && 2078 pPre->GetAttrSet()->GetKeep().GetValue()) ) 2079 { 2080 bCalcLowers = sal_True; 2081 } 2082 } 2083 2084 //Wir muessen die Hoehe der ersten Zeile kennen, denn nur wenn diese 2085 //kleiner wird muss ggf. der Master angestossen werden um noetigenfalls 2086 //die Zeile aufzunehmen. 2087 long n1StLineHeight = 0; 2088 if ( IsFollow() ) 2089 { 2090 SwFrm* pFrm = GetFirstNonHeadlineRow(); 2091 if ( pFrm ) 2092 n1StLineHeight = (pFrm->Frm().*fnRect->fnGetHeight)(); 2093 } 2094 2095 if ( !bValidSize || !bValidPrtArea ) 2096 { 2097 const long nOldPrtWidth = (Prt().*fnRect->fnGetWidth)(); 2098 const long nOldFrmWidth = (Frm().*fnRect->fnGetWidth)(); 2099 const Point aOldPrtPos = (Prt().*fnRect->fnGetPos)(); 2100 Format( pAttrs ); 2101 2102 SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout(); 2103 if ( pLayout && 2104 ((Prt().*fnRect->fnGetWidth)() != nOldPrtWidth || 2105 (Frm().*fnRect->fnGetWidth)() != nOldFrmWidth) ) 2106 { 2107 delete pAccess; 2108 bCalcLowers |= pLayout->Resize( 2109 pLayout->GetBrowseWidthByTabFrm( *this ), sal_False ); 2110 // GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() ? sal_False : sal_True ); 2111 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this ); 2112 pAttrs = pAccess->Get(); 2113 } 2114 if ( aOldPrtPos != (Prt().*fnRect->fnGetPos)() ) 2115 aNotify.SetLowersComplete( sal_False ); 2116 } 2117 2118 //Wenn ich der erste einer Kette bin koennte ich mal sehen ob 2119 //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll). 2120 //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts 2121 //geflosssen sein. 2122 if ( !bMovedFwd && (bMoveable || bFly) && lcl_NoPrev( *this ) ) 2123 { 2124 //Bei Follows muss der Master benachrichtigt 2125 //werden. Der Follow muss nur dann Moven, wenn er leere Blaetter 2126 //ueberspringen muss. 2127 if ( IsFollow() ) 2128 { 2129 //Nur wenn die Hoehe der ersten Zeile kleiner geworder ist. 2130 SwFrm *pFrm = GetFirstNonHeadlineRow(); 2131 if( pFrm && n1StLineHeight >(pFrm->Frm().*fnRect->fnGetHeight )() ) 2132 { 2133 SwTabFrm *pMaster = (SwTabFrm*)FindMaster(); 2134 sal_Bool bDummy; 2135 if ( ShouldBwdMoved( pMaster->GetUpper(), sal_False, bDummy ) ) 2136 pMaster->InvalidatePos(); 2137 } 2138 } 2139 SwFtnBossFrm *pOldBoss = bFtnsInDoc ? FindFtnBossFrm( sal_True ) : 0; 2140 sal_Bool bReformat; 2141 if ( MoveBwd( bReformat ) ) 2142 { 2143 SWREFRESHFN( this ) 2144 bMovedBwd = sal_True; 2145 aNotify.SetLowersComplete( sal_False ); 2146 if ( bFtnsInDoc ) 2147 MoveLowerFtns( 0, pOldBoss, 0, sal_True ); 2148 if ( bReformat || bKeep ) 2149 { 2150 long nOldTop = (Frm().*fnRect->fnGetTop)(); 2151 MakePos(); 2152 if( nOldTop != (Frm().*fnRect->fnGetTop)() ) 2153 { 2154 SwHTMLTableLayout *pHTMLLayout = 2155 GetTable()->GetHTMLTableLayout(); 2156 if( pHTMLLayout ) 2157 { 2158 delete pAccess; 2159 bCalcLowers |= pHTMLLayout->Resize( 2160 pHTMLLayout->GetBrowseWidthByTabFrm( *this ), 2161 sal_False ); 2162 2163 pAccess= new SwBorderAttrAccess( 2164 SwFrm::GetCache(), this ); 2165 pAttrs = pAccess->Get(); 2166 } 2167 2168 bValidPrtArea = sal_False; 2169 Format( pAttrs ); 2170 } 2171 lcl_RecalcTable( *this, 0, aNotify ); 2172 bLowersFormatted = sal_True; 2173 if ( bKeep && KEEPTAB ) 2174 { 2175 // --> OD 2005-09-28 #b6329202# 2176 // Consider case that table is inside another table, 2177 // because it has to be avoided, that superior table 2178 // is formatted. 2179 // Thus, find next content, table or section 2180 // and, if a section is found, get its first 2181 // content. 2182 // SwFrm *pNxt = FindNextCnt(); 2183 // if( pNxt && pNxt->IsInTab() ) 2184 // pNxt = pNxt->FindTabFrm(); 2185 // if ( pNxt ) 2186 // { 2187 // pNxt->Calc(); 2188 // if ( !GetNext() ) 2189 // bValidPos = sal_False; 2190 // } 2191 if ( 0 != lcl_FormatNextCntntForKeep( this ) && !GetNext() ) 2192 { 2193 bValidPos = sal_False; 2194 } 2195 // <-- 2196 } 2197 } 2198 } 2199 } 2200 2201 //Wieder ein Wert ungueltig? - dann nochmal das ganze... 2202 if ( !bValidPos || !bValidSize || !bValidPrtArea ) 2203 continue; 2204 2205 // check, if calculation of table frame is ready. 2206 2207 /// OD 23.10.2002 #103517# - Local variable <nDistanceToUpperPrtBottom> 2208 /// Introduce local variable and init it with the distance from the 2209 /// table frame bottom to the bottom of the upper printing area. 2210 /// Note: negative values denotes the situation that table frame doesn't 2211 /// fit in its upper. 2212 2213 SwTwips nDistanceToUpperPrtBottom = 2214 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)()); 2215 2216 /// OD 23.10.2002 #103517# - In online layout try to grow upper of table 2217 /// frame, if table frame doesn't fit in its upper. 2218 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 2219 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode(); 2220 if ( nDistanceToUpperPrtBottom < 0 && bBrowseMode ) 2221 { 2222 if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom ) ) 2223 { 2224 // upper is grown --> recalculate <nDistanceToUpperPrtBottom> 2225 nDistanceToUpperPrtBottom = 2226 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)()); 2227 } 2228 } 2229 2230 // If there is still some space left in the upper, we check if we 2231 // can join some rows of the follow. 2232 // Setting bLastRowHasToMoveToFollow to true means we want to force 2233 // the table to be split! Only skip this if condition once. 2234 if( nDistanceToUpperPrtBottom >= 0 && !bLastRowHasToMoveToFollow ) 2235 { 2236 // OD 23.10.2002 - translate german commentary 2237 // If there is space left in the upper printing area, join as for trial 2238 // at least one further row of an existing follow. 2239 if ( !bSplit && GetFollow() ) 2240 { 2241 sal_Bool bDummy; 2242 if ( GetFollow()->ShouldBwdMoved( GetUpper(), sal_False, bDummy ) ) 2243 { 2244 SwFrm *pTmp = GetUpper(); 2245 SwTwips nDeadLine = (pTmp->*fnRect->fnGetPrtBottom)(); 2246 if ( bBrowseMode ) 2247 nDeadLine += pTmp->Grow( LONG_MAX, sal_True ); 2248 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 ) 2249 { 2250 // 2251 // First, we remove an existing follow flow line. 2252 // 2253 if ( HasFollowFlowLine() ) 2254 { 2255 SwFrm* pLastLine = const_cast<SwFrm*>(GetLastLower()); 2256 RemoveFollowFlowLine(); 2257 // invalidate and rebuild last row 2258 if ( pLastLine ) 2259 { 2260 ::SwInvalidateAll( pLastLine, LONG_MAX ); 2261 SetRebuildLastLine( sal_True ); 2262 lcl_RecalcRow( static_cast<SwRowFrm&>(*pLastLine), LONG_MAX ); 2263 SetRebuildLastLine( sal_False ); 2264 } 2265 2266 SwFrm* pRow = GetFollow()->GetFirstNonHeadlineRow(); 2267 2268 if ( !pRow || !pRow->GetNext() ) 2269 //Der Follow wird leer und damit ueberfluessig. 2270 Join(); 2271 2272 continue; 2273 } 2274 2275 // 2276 // If there is no follow flow line, we move the first 2277 // row in the follow table to the master table. 2278 // 2279 SwRowFrm *pRow = GetFollow()->GetFirstNonHeadlineRow(); 2280 2281 //Der Follow wird leer und damit ueberfluessig. 2282 if ( !pRow ) 2283 { 2284 Join(); 2285 continue; 2286 } 2287 2288 const SwTwips nOld = (Frm().*fnRect->fnGetHeight)(); 2289 long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pRow ); 2290 SwFrm* pRowToMove = pRow; 2291 2292 while ( pRowToMove && nRowsToMove-- > 0 ) 2293 { 2294 const sal_Bool bMoveFtns = bFtnsInDoc && !GetFollow()->IsJoinLocked(); 2295 2296 SwFtnBossFrm *pOldBoss = 0; 2297 if ( bMoveFtns ) 2298 pOldBoss = pRowToMove->FindFtnBossFrm( sal_True ); 2299 2300 SwFrm* pNextRow = pRowToMove->GetNext(); 2301 2302 if ( !pNextRow ) 2303 //Der Follow wird leer und damit ueberfluessig. 2304 Join(); 2305 else 2306 { 2307 pRowToMove->Cut(); 2308 pRowToMove->Paste( this ); 2309 } 2310 2311 //Die Fussnoten verschieben! 2312 if ( bMoveFtns ) 2313 if ( ((SwLayoutFrm*)pRowToMove)->MoveLowerFtns( 2314 0, pOldBoss, FindFtnBossFrm( sal_True ), sal_True ) ) 2315 GetUpper()->Calc(); 2316 2317 pRowToMove = pNextRow; 2318 } 2319 2320 if ( nOld != (Frm().*fnRect->fnGetHeight)() ) 2321 lcl_RecalcTable( *this, (SwLayoutFrm*)pRow, aNotify ); 2322 2323 continue; 2324 } 2325 } 2326 } 2327 else if ( KEEPTAB ) 2328 { 2329 bool bFormat = false; 2330 if ( bKeep ) 2331 bFormat = true; 2332 else if ( bTableRowKeep && !bLastRowMoveNoMoreTries ) 2333 { 2334 // We only want to give the last row one chance to move 2335 // to the follow table. Set the flag as early as possible: 2336 bLastRowMoveNoMoreTries = true; 2337 2338 // The last line of the table has to be cut off if: 2339 // 1. The table does not want to keep with its next 2340 // 2. The compatibility option is set and the table is allowed to split 2341 // 3. We did not already cut off the last row 2342 // 4. There is not break after attribute set at the table 2343 // 5. There is no break before attribute set behind the table 2344 // 6. There is no section change behind the table (see IsKeep) 2345 // 7. The last table row wants to keep with its next. 2346 const SwRowFrm* pLastRow = static_cast<const SwRowFrm*>(GetLastLower()); 2347 if ( pLastRow && IsKeep( pAttrs->GetAttrSet(), true ) && 2348 pLastRow->ShouldRowKeepWithNext() ) 2349 bFormat = true; 2350 } 2351 2352 if ( bFormat ) 2353 { 2354 delete pAccess; 2355 2356 // --> OD 2005-09-28 #b6329202# 2357 // Consider case that table is inside another table, because 2358 // it has to be avoided, that superior table is formatted. 2359 // Thus, find next content, table or section and, if a section 2360 // is found, get its first content. 2361 const SwFrm* pTmpNxt = lcl_FormatNextCntntForKeep( this ); 2362 // <-- 2363 2364 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this ); 2365 pAttrs = pAccess->Get(); 2366 2367 // The last row wants to keep with the frame behind the table. 2368 // Check if the next frame is on a different page and valid. 2369 // In this case we do a magic trick: 2370 if ( !bKeep && !GetNext() && pTmpNxt && pTmpNxt->IsValid() ) 2371 { 2372 bValidPos = sal_False; 2373 bLastRowHasToMoveToFollow = true; 2374 } 2375 } 2376 } 2377 2378 if ( IsValid() ) 2379 { 2380 if ( bCalcLowers ) 2381 { 2382 lcl_RecalcTable( *this, 0, aNotify ); 2383 bLowersFormatted = sal_True; 2384 bCalcLowers = sal_False; 2385 } 2386 else if ( bONECalcLowers ) 2387 { 2388 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX ); 2389 bONECalcLowers = sal_False; 2390 } 2391 } 2392 continue; 2393 } 2394 2395 //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt 2396 //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen 2397 2398 //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe 2399 //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man 2400 //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und 2401 //zwar mit aller Kraft. 2402 if ( !bMoveable ) 2403 { 2404 if ( bCalcLowers && IsValid() ) 2405 { 2406 lcl_RecalcTable( *this, 0, aNotify ); 2407 bLowersFormatted = sal_True; 2408 bCalcLowers = sal_False; 2409 } 2410 else if ( bONECalcLowers ) 2411 { 2412 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX ); 2413 bONECalcLowers = sal_False; 2414 } 2415 2416 // It does not make sense to cut off the last line if we are 2417 // not moveable: 2418 bLastRowHasToMoveToFollow = false; 2419 2420 continue; 2421 } 2422 2423 if ( bCalcLowers && IsValid() ) 2424 { 2425 lcl_RecalcTable( *this, 0, aNotify ); 2426 bLowersFormatted = sal_True; 2427 bCalcLowers = sal_False; 2428 if( !IsValid() ) 2429 continue; 2430 } 2431 2432 // 2433 // First try to split the table. Condition: 2434 // 1. We have at least one non headline row 2435 // 2. If this row wants to keep, we need an additional row 2436 // 3. The table is allowed to split or we do not have an pIndPrev: 2437 // 2438 SwFrm* pIndPrev = GetIndPrev(); 2439 const SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow(); 2440 // #120016# if this row wants to keep, allow split in case that all rows want to keep with next, 2441 // the table can not move forward as it is the first one and a split is in general allowed. 2442 const bool bAllowSplitOfRow = ( bTableRowKeep && 2443 AreAllRowsKeepWithNext( pFirstNonHeadlineRow ) ) && 2444 !pIndPrev && 2445 !bDontSplit; 2446 2447 if ( pFirstNonHeadlineRow && nUnSplitted > 0 && 2448 ( !bTableRowKeep || pFirstNonHeadlineRow->GetNext() || !pFirstNonHeadlineRow->ShouldRowKeepWithNext() || bAllowSplitOfRow ) && 2449 ( !bDontSplit || !pIndPrev ) ) 2450 { 2451 // --> FME 2004-06-03 #i29438# 2452 // Special DoNotSplit case: 2453 // We better avoid splitting of a row frame if we are inside a columned 2454 // section which has a height of 0, because this is not growable and thus 2455 // all kinds of unexpected things could happen. 2456 const SwSectionFrm* pTmpSct = 0; 2457 if ( IsInSct() && 2458 (pTmpSct = FindSctFrm())->Lower()->IsColumnFrm() && 2459 0 == (GetUpper()->Frm().*fnRect->fnGetHeight)() ) 2460 { 2461 bTryToSplit = false; 2462 } 2463 // <-- 2464 2465 // 1. Try: bTryToSplit = true => Try to split the row. 2466 // 2. Try: bTryToSplit = false => Split the table between the rows. 2467 if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit ) 2468 { 2469 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)(); 2470 if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE) 2471 nDeadLine = (*fnRect->fnYInc)( nDeadLine, 2472 GetUpper()->Grow( LONG_MAX, sal_True ) ); 2473 2474 ::lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), nDeadLine ); 2475 bLowersFormatted = sal_True; 2476 aNotify.SetLowersComplete( sal_True ); 2477 2478 // One more check if its really necessary to split the table. 2479 // 1. The table either has to exceed the deadline or 2480 // 2. We explicitly want to cut off the last row. 2481 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 && !bLastRowHasToMoveToFollow ) 2482 { 2483 continue; 2484 } 2485 2486 // Set to false again as early as possible. 2487 bLastRowHasToMoveToFollow = false; 2488 2489 // --> FME 2005-08-03 #i52781# 2490 // YaSC - Yet another special case: 2491 // If our upper is inside a table cell which is not allowed 2492 // to split, we do not try to split: 2493 if ( GetUpper()->IsInTab() ) 2494 { 2495 const SwFrm* pTmpRow = GetUpper(); 2496 while ( pTmpRow && !pTmpRow->IsRowFrm() ) 2497 pTmpRow = pTmpRow->GetUpper(); 2498 if ( pTmpRow && !static_cast<const SwRowFrm*>(pTmpRow)->IsRowSplitAllowed() ) 2499 continue; 2500 } 2501 // <-- 2502 2503 sal_uInt16 nMinNumOfLines = nRepeat; 2504 2505 if ( bTableRowKeep ) 2506 { 2507 const SwRowFrm* pTmpRow = pFirstNonHeadlineRow; 2508 while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() ) 2509 { 2510 ++nMinNumOfLines; 2511 pTmpRow = static_cast<const SwRowFrm*>(pTmpRow->GetNext()); 2512 } 2513 // Check if all lines want to keep together and we 2514 // have a pIndPrev. In this case we set nDeadLine 2515 // to 0, forcing the table to move forward. 2516 if ( !pTmpRow && pIndPrev ) 2517 nDeadLine = 0; 2518 } 2519 2520 if ( !bTryToSplit ) 2521 ++nMinNumOfLines; 2522 2523 const SwTwips nBreakLine = (*fnRect->fnYInc)( 2524 (Frm().*fnRect->fnGetTop)(), 2525 (this->*fnRect->fnGetTopMargin)() + 2526 lcl_GetHeightOfRows( GetLower(), nMinNumOfLines ) ); 2527 2528 // Some more checks if we want to call the split algorithm or not: 2529 // The repeating lines / keeping lines still fit into the upper or 2530 // if we do not have an (in)direkt Prev, we split anyway. 2531 if( (*fnRect->fnYDiff)(nDeadLine, nBreakLine) >=0 || !pIndPrev ) 2532 { 2533 aNotify.SetLowersComplete( sal_False ); 2534 bSplit = sal_True; 2535 2536 // 2537 // An existing follow flow line has to be removed. 2538 // 2539 if ( HasFollowFlowLine() ) 2540 { 2541 RemoveFollowFlowLine(); 2542 } 2543 2544 const bool bSplitError = !Split( nDeadLine, bTryToSplit, ( bTableRowKeep && !bAllowSplitOfRow ) ); 2545 if( !bTryToSplit && !bSplitError && nUnSplitted > 0 ) 2546 { 2547 --nUnSplitted; 2548 } 2549 2550 // --> FME 2004-06-09 #i29771# Two tries to split the table: 2551 // If an error occured during splitting. We start a second 2552 // try, this time without splitting of table rows. 2553 if ( bSplitError ) 2554 { 2555 if ( HasFollowFlowLine() ) 2556 RemoveFollowFlowLine(); 2557 } 2558 2559 // --> FME 2005-02-10 #119477# 2560 // If splitting the table was successfull or not, 2561 // we do not want to have 'empty' follow tables. 2562 if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() ) 2563 Join(); 2564 // <-- 2565 2566 2567 // We want to restore the situation before the failed 2568 // split operation as good as possible. Therefore we 2569 // do some more calculations. Note: Restricting this 2570 // to nDeadLine may not be enough. 2571 if ( bSplitError && bTryToSplit ) // no restart if we did not try to split: i72847, i79426 2572 { 2573 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX ); 2574 bValidPos = sal_False; 2575 bTryToSplit = false; 2576 continue; 2577 } 2578 // <-- 2579 2580 bTryToSplit = !bSplitError; 2581 2582 //Damit es nicht zu Oszillationen kommt, muss der 2583 //Follow gleich gueltig gemacht werden. 2584 if ( GetFollow() ) 2585 { 2586 // --> OD 2007-11-30 #i80924# 2587 // After a successful split assure that the first row 2588 // is invalid. When graphics are present, this isn't hold. 2589 // Note: defect i80924 could also be fixed, if it is 2590 // assured, that <SwLayNotify::bLowersComplete> is only 2591 // set, if all lower are valid *and* are correct laid out. 2592 if ( !bSplitError && GetFollow()->GetLower() ) 2593 { 2594 GetFollow()->GetLower()->InvalidatePos(); 2595 } 2596 // <-- 2597 SWRECTFNX( GetFollow() ) 2598 2599 static sal_uInt8 nStack = 0; 2600 if ( !StackHack::IsLocked() && nStack < 4 ) 2601 { 2602 ++nStack; 2603 StackHack aHack; 2604 delete pAccess; 2605 2606 GetFollow()->MakeAll(); 2607 2608 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this ); 2609 pAttrs = pAccess->Get(); 2610 2611 ((SwTabFrm*)GetFollow())->SetLowersFormatted(sal_False); 2612 // --> OD 2005-03-30 #i43913# - lock follow table 2613 // to avoid its formatting during the format of 2614 // its content. 2615 const bool bOldJoinLock = GetFollow()->IsJoinLocked(); 2616 GetFollow()->LockJoin(); 2617 // <-- 2618 ::lcl_RecalcRow( static_cast<SwRowFrm&>(*GetFollow()->Lower()), 2619 (GetFollow()->GetUpper()->Frm().*fnRectX->fnGetBottom)() ); 2620 // --> OD 2005-03-30 #i43913# 2621 // --> FME 2006-04-05 #i63632# Do not unlock the 2622 // follow if it wasn't locked before. 2623 if ( !bOldJoinLock ) 2624 GetFollow()->UnlockJoin(); 2625 // <-- 2626 2627 if ( !GetFollow()->GetFollow() ) 2628 { 2629 SwFrm* pNxt = ((SwFrm*)GetFollow())->FindNext(); 2630 if ( pNxt ) 2631 { 2632 // OD 26.08.2003 #i18103# - no formatting 2633 // of found next frame, if its a follow 2634 // section of the 'ColLocked' section, 2635 // the follow table is in. 2636 bool bCalcNxt = true; 2637 if ( GetFollow()->IsInSct() && pNxt->IsSctFrm() ) 2638 { 2639 SwSectionFrm* pSct = GetFollow()->FindSctFrm(); 2640 if ( pSct->IsColLocked() && 2641 pSct->GetFollow() == pNxt ) 2642 { 2643 bCalcNxt = false; 2644 } 2645 } 2646 if ( bCalcNxt ) 2647 { 2648 pNxt->Calc(); 2649 } 2650 } 2651 } 2652 --nStack; 2653 } 2654 else if ( GetFollow() == GetNext() ) 2655 ((SwTabFrm*)GetFollow())->MoveFwd( sal_True, sal_False ); 2656 } 2657 continue; 2658 } 2659 } 2660 } 2661 2662 // Set to false again as early as possible. 2663 bLastRowHasToMoveToFollow = false; 2664 2665 if( IsInSct() && bMovedFwd && bMakePage && GetUpper()->IsColBodyFrm() && 2666 GetUpper()->GetUpper()->GetUpper()->IsSctFrm() && 2667 ( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) && 2668 ((SwSectionFrm*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) ) 2669 { 2670 bMovedFwd = sal_False; 2671 } 2672 2673 // --> FME 2004-06-09 #i29771# Reset bTryToSplit flag on change of upper 2674 const SwFrm* pOldUpper = GetUpper(); 2675 // <-- 2676 2677 //Mal sehen ob ich irgenwo Platz finde... 2678 if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) ) 2679 bMakePage = sal_False; 2680 2681 // --> FME 2004-06-09 #i29771# Reset bSplitError flag on change of upper 2682 if ( GetUpper() != pOldUpper ) 2683 { 2684 bTryToSplit = true; 2685 nUnSplitted = 5; 2686 } 2687 // <-- 2688 2689 SWREFRESHFN( this ) 2690 bMovedFwd = bCalcLowers = sal_True; 2691 aNotify.SetLowersComplete( sal_False ); 2692 if ( IsFollow() ) 2693 { //Um Oszillationen zu vermeiden sollte kein ungueltiger Master 2694 //zurueckbleiben. 2695 SwTabFrm *pTab = FindMaster(); 2696 if ( pTab->GetUpper() ) 2697 pTab->GetUpper()->Calc(); 2698 pTab->Calc(); 2699 pTab->SetLowersFormatted( sal_False ); 2700 } 2701 2702 //Wenn mein direkter Nachbar jetzt gleichzeitig mein Follow ist 2703 //verleibe ich mir das Teil ein. 2704 if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() ) 2705 { 2706 if ( HasFollowFlowLine() ) 2707 RemoveFollowFlowLine(); 2708 if ( GetFollow() ) 2709 Join(); 2710 } 2711 2712 if ( bMovedBwd && GetUpper() ) 2713 //Beim zurueckfliessen wurde der Upper angeregt sich vollstaendig 2714 //zu Painten, dass koennen wir uns jetzt nach dem hin und her 2715 //fliessen sparen. 2716 GetUpper()->ResetCompletePaint(); 2717 2718 if ( bCalcLowers && IsValid() ) 2719 { 2720 // --> OD 2005-05-11 #i44910# - format of lower frames unnecessary 2721 // and can cause layout loops, if table doesn't fit and isn't 2722 // allowed to split. 2723 SwTwips nDistToUpperPrtBottom = 2724 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)()); 2725 if ( nDistToUpperPrtBottom >= 0 || bTryToSplit ) 2726 { 2727 lcl_RecalcTable( *this, 0, aNotify ); 2728 bLowersFormatted = sal_True; 2729 bCalcLowers = sal_False; 2730 } 2731 #if OSL_DEBUG_LEVEL > 1 2732 else 2733 { 2734 ASSERT( false, "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" ); 2735 } 2736 #endif 2737 // <-- 2738 } 2739 2740 } //while ( !bValidPos || !bValidSize || !bValidPrtArea ) 2741 2742 //Wenn mein direkter Vorgaenger jetzt mein Master ist, so kann er mich 2743 //bei der nachstbesten Gelegenheit vernichten. 2744 if ( IsFollow() ) 2745 { 2746 SwFrm *pPre = GetPrev(); 2747 if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this) 2748 pPre->InvalidatePos(); 2749 } 2750 2751 bCalcLowers = bONECalcLowers = sal_False; 2752 delete pAccess; 2753 UnlockJoin(); 2754 if ( bMovedFwd || bMovedBwd || !bOldValidPos ) 2755 aNotify.SetInvaKeep(); 2756 } 2757 2758 /************************************************************************* 2759 |* 2760 |* SwTabFrm::CalcFlyOffsets() 2761 |* 2762 |* Beschreibung: Berechnet die Offsets, die durch FlyFrames 2763 |* entstehen. 2764 |* Ersterstellung MA/MIB 14. Apr. 99 2765 |* Letzte Aenderung 2766 |* 2767 |*************************************************************************/ 2768 sal_Bool SwTabFrm::CalcFlyOffsets( SwTwips& rUpper, 2769 long& rLeftOffset, 2770 long& rRightOffset ) const 2771 { 2772 sal_Bool bInvalidatePrtArea = sal_False; 2773 const SwPageFrm *pPage = FindPageFrm(); 2774 const SwFlyFrm* pMyFly = FindFlyFrm(); 2775 2776 // --> #108724# Page header/footer content doesn't have to wrap around 2777 // floating screen objects 2778 2779 const IDocumentSettingAccess* pIDSA = GetFmt()->getIDocumentSettingAccess(); 2780 const bool bWrapAllowed = pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) || 2781 ( !IsInFtn() && 0 == FindFooterOrHeader() ); 2782 // <-- 2783 2784 if ( pPage->GetSortedObjs() && bWrapAllowed ) 2785 { 2786 SWRECTFN( this ) 2787 const bool bConsiderWrapOnObjPos = pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION); 2788 long nPrtPos = (Frm().*fnRect->fnGetTop)(); 2789 nPrtPos = (*fnRect->fnYInc)( nPrtPos, rUpper ); 2790 SwRect aRect( Frm() ); 2791 long nYDiff = (*fnRect->fnYDiff)( (Prt().*fnRect->fnGetTop)(), rUpper ); 2792 if( nYDiff > 0 ) 2793 (aRect.*fnRect->fnAddBottom)( -nYDiff ); 2794 for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i ) 2795 { 2796 SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i]; 2797 if ( pAnchoredObj->ISA(SwFlyFrm) ) 2798 { 2799 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 2800 const SwRect aFlyRect = pFly->GetObjRectWithSpaces(); 2801 // --> OD 2004-10-07 #i26945# - correction of conditions, 2802 // if Writer fly frame has to be considered: 2803 // - no need to check, if top of Writer fly frame differs 2804 // from WEIT_WECH, because its also check, if the Writer 2805 // fly frame rectangle overlaps with <aRect> 2806 // - no check, if bottom of anchor frame is prior the top of 2807 // the table, because Writer fly frames can be negative positioned. 2808 // - correct check, if the Writer fly frame is an lower of the 2809 // table, because table lines/rows can split and a at-character 2810 // anchored Writer fly frame could be positioned in the follow 2811 // flow line. 2812 // - add condition, that an existing anchor character text frame 2813 // has to be on the same page as the table. 2814 // E.g., it could happen, that the fly frame is still registered 2815 // at the page frame, the table is on, but it's anchor character 2816 // text frame has already changed its page. 2817 //if ( WEIT_WECH != (pFly->Frm().*fnRect->fnGetTop)() && 2818 // pFly->IsFlyAtCntFrm() && aFlyRect.IsOver( aRect ) && 2819 // // OD 25.02.2003 #i9040# - use '<=' instead of '<' 2820 // (*fnRect->fnYDiff)( 2821 // (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetBottom)(), 2822 // (Frm().*fnRect->fnGetTop)() ) <= 0 && 2823 // !IsAnLower( pFly ) && !pFly->IsAnLower( this ) && 2824 // ( !pMyFly || pMyFly->IsAnLower( pFly ) ) && 2825 // pPage->GetPhyPageNum() >= 2826 // pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() && 2827 // // anchor should be in same page body/header/footer 2828 // ( pFly->GetAnchorFrm()->FindFooterOrHeader() == 2829 // FindFooterOrHeader() ) ) 2830 const SwTxtFrm* pAnchorCharFrm = pFly->FindAnchorCharFrm(); 2831 bool bConsiderFly = 2832 // --> OD 2005-04-06 #i46807# - do not consider invalid 2833 // Writer fly frames. 2834 pFly->IsValid() && 2835 // <-- 2836 // fly anchored at character 2837 pFly->IsFlyAtCntFrm() && 2838 // fly overlaps with corresponding table rectangle 2839 aFlyRect.IsOver( aRect ) && 2840 // fly isn't lower of table and 2841 // anchor character frame of fly isn't lower of table 2842 ( !IsAnLower( pFly ) && 2843 ( !pAnchorCharFrm || !IsAnLower( pAnchorCharFrm ) ) ) && 2844 // table isn't lower of fly 2845 !pFly->IsAnLower( this ) && 2846 // fly is lower of fly, the table is in 2847 // --> OD 2005-05-31 #123274# - correction: 2848 // assure that fly isn't a lower of a fly, the table isn't in. 2849 // E.g., a table in the body doesn't wrap around a graphic, 2850 // which is inside a frame. 2851 ( ( !pMyFly || 2852 pMyFly->IsAnLower( pFly ) ) && 2853 pMyFly == pFly->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) && 2854 // <-- 2855 // anchor frame not on following page 2856 pPage->GetPhyPageNum() >= 2857 pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() && 2858 // anchor character text frame on same page 2859 ( !pAnchorCharFrm || 2860 pAnchorCharFrm->FindPageFrm()->GetPhyPageNum() == 2861 pPage->GetPhyPageNum() ); 2862 2863 if ( bConsiderFly ) 2864 { 2865 const SwFrm* pFlyHeaderFooterFrm = pFly->GetAnchorFrm()->FindFooterOrHeader(); 2866 const SwFrm* pThisHeaderFooterFrm = FindFooterOrHeader(); 2867 2868 if ( pFlyHeaderFooterFrm != pThisHeaderFooterFrm && 2869 // --> FME 2007-07-02 #148493# If bConsiderWrapOnObjPos is set, 2870 // we want to consider the fly if it is located in the header and 2871 // the table is located in the body: 2872 ( !bConsiderWrapOnObjPos || 0 != pThisHeaderFooterFrm || !pFlyHeaderFooterFrm->IsHeaderFrm() ) ) 2873 bConsiderFly = false; 2874 // <-- 2875 } 2876 2877 if ( bConsiderFly ) 2878 // <-- 2879 { 2880 const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround(); 2881 const SwFmtHoriOrient &rHori= pFly->GetFmt()->GetHoriOrient(); 2882 if ( SURROUND_NONE == rSur.GetSurround() ) 2883 { 2884 long nBottom = (aFlyRect.*fnRect->fnGetBottom)(); 2885 if( (*fnRect->fnYDiff)( nPrtPos, nBottom ) < 0 ) 2886 nPrtPos = nBottom; 2887 bInvalidatePrtArea = sal_True; 2888 } 2889 if ( (SURROUND_RIGHT == rSur.GetSurround() || 2890 SURROUND_PARALLEL == rSur.GetSurround())&& 2891 text::HoriOrientation::LEFT == rHori.GetHoriOrient() ) 2892 { 2893 const long nWidth = (*fnRect->fnXDiff)( 2894 (aFlyRect.*fnRect->fnGetRight)(), 2895 (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetLeft)() ); 2896 rLeftOffset = Max( rLeftOffset, nWidth ); 2897 bInvalidatePrtArea = sal_True; 2898 } 2899 if ( (SURROUND_LEFT == rSur.GetSurround() || 2900 SURROUND_PARALLEL == rSur.GetSurround())&& 2901 text::HoriOrientation::RIGHT == rHori.GetHoriOrient() ) 2902 { 2903 const long nWidth = (*fnRect->fnXDiff)( 2904 (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetRight)(), 2905 (aFlyRect.*fnRect->fnGetLeft)() ); 2906 rRightOffset = Max( rRightOffset, nWidth ); 2907 bInvalidatePrtArea = sal_True; 2908 } 2909 } 2910 } 2911 } 2912 rUpper = (*fnRect->fnYDiff)( nPrtPos, (Frm().*fnRect->fnGetTop)() ); 2913 } 2914 2915 return bInvalidatePrtArea; 2916 } 2917 2918 /************************************************************************* 2919 |* 2920 |* SwTabFrm::Format() 2921 |* 2922 |* Beschreibung: "Formatiert" den Frame; Frm und PrtArea 2923 |* Die Fixsize wird hier nicht eingestellt. 2924 |* Ersterstellung MA 09. Mar. 93 2925 |* Letzte Aenderung MA 18. Jun. 97 2926 |* 2927 |*************************************************************************/ 2928 void SwTabFrm::Format( const SwBorderAttrs *pAttrs ) 2929 { 2930 ASSERT( pAttrs, "TabFrm::Format, pAttrs ist 0." ); 2931 2932 SWRECTFN( this ) 2933 if ( !bValidSize ) 2934 { 2935 long nDiff = (GetUpper()->Prt().*fnRect->fnGetWidth)() - 2936 (Frm().*fnRect->fnGetWidth)(); 2937 if( nDiff ) 2938 (aFrm.*fnRect->fnAddRight)( nDiff ); 2939 } 2940 2941 //VarSize ist immer die Hoehe. 2942 //Fuer den oberen/unteren Rand gelten die selben Regeln wie fuer 2943 //cntfrms (sie MakePrtArea() von diesen). 2944 2945 SwTwips nUpper = CalcUpperSpace( pAttrs ); 2946 2947 //Wir wollen Rahmen ausweichen. Zwei Moeglichkeiten: 2948 //1. Es gibt Rahmen mit SurroundNone, diesen wird vollsaendig ausgewichen 2949 //2. Es gibt Rahmen mit Umlauf nur rechts bzw. nur links und diese sind 2950 // rechts bzw. links ausgerichtet, diese geben ein Minimum fuer die 2951 // Raender vor. 2952 long nTmpRight = -1000000, 2953 nLeftOffset = 0; 2954 if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) ) 2955 bValidPrtArea = sal_False; 2956 long nRightOffset = Max( 0L, nTmpRight ); 2957 2958 SwTwips nLower = pAttrs->CalcBottomLine(); 2959 // --> collapsing borders FME 2005-05-27 #i29550# 2960 if ( IsCollapsingBorders() ) 2961 nLower += GetBottomLineSize(); 2962 // <-- collapsing 2963 2964 if ( !bValidPrtArea ) 2965 { bValidPrtArea = sal_True; 2966 2967 //Die Breite der PrtArea wird vom FrmFmt vorgegeben, die Raender 2968 //sind entsprechend einzustellen. 2969 //Mindestraender werden von Umrandung und Schatten vorgegeben. 2970 //Die Rander werden so eingestellt, dass die PrtArea nach dem 2971 //angegebenen Adjustment im Frm ausgerichtet wird. 2972 //Wenn das Adjustment 0 ist, so werden die Rander anhand des 2973 //Randattributes eingestellt. 2974 2975 const SwTwips nOldHeight = (Prt().*fnRect->fnGetHeight)(); 2976 const SwTwips nMax = (aFrm.*fnRect->fnGetWidth)(); 2977 2978 // OD 14.03.2003 #i9040# - adjust variable names. 2979 const SwTwips nLeftLine = pAttrs->CalcLeftLine(); 2980 const SwTwips nRightLine = pAttrs->CalcRightLine(); 2981 2982 //Die Breite ist evtl. eine Prozentangabe. Wenn die Tabelle irgendwo 2983 //'drinsteckt bezieht sie sich auf die Umgebung. Ist es der Body, so 2984 //bezieht sie sich in der BrowseView auf die Bildschirmbreite. 2985 const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize(); 2986 // OD 14.03.2003 #i9040# - adjust variable name. 2987 const SwTwips nWishedTableWidth = CalcRel( rSz, sal_True ); 2988 2989 sal_Bool bCheckBrowseWidth = sal_False; 2990 2991 // OD 14.03.2003 #i9040# - insert new variables for left/right spacing. 2992 SwTwips nLeftSpacing = 0; 2993 SwTwips nRightSpacing = 0; 2994 switch ( GetFmt()->GetHoriOrient().GetHoriOrient() ) 2995 { 2996 case text::HoriOrientation::LEFT: 2997 { 2998 // left indent: 2999 nLeftSpacing = nLeftLine + nLeftOffset; 3000 // OD 06.03.2003 #i9040# - correct calculation of right indent: 3001 // - Consider right indent given by right line attributes. 3002 // - Consider negative right indent. 3003 // wished right indent determined by wished table width and 3004 // left offset given by surround fly frames on the left: 3005 const SwTwips nWishRight = nMax - nWishedTableWidth - nLeftOffset; 3006 if ( nRightOffset > 0 ) 3007 { 3008 // surrounding fly frames on the right 3009 // -> right indent is maximun of given right offset 3010 // and wished right offset. 3011 nRightSpacing = nRightLine + Max( nRightOffset, nWishRight ); 3012 } 3013 else 3014 { 3015 // no surrounding fly frames on the right 3016 // If intrinsic right indent (intrinsic means not considering 3017 // determined left indent) is negative, 3018 // then hold this intrinsic indent, 3019 // otherwise non negative wished right indent is hold. 3020 nRightSpacing = nRightLine + 3021 ( ( (nWishRight+nLeftOffset) < 0 ) ? 3022 (nWishRight+nLeftOffset) : 3023 Max( 0L, nWishRight ) ); 3024 } 3025 } 3026 break; 3027 case text::HoriOrientation::RIGHT: 3028 { 3029 // right indent: 3030 nRightSpacing = nRightLine + nRightOffset; 3031 // OD 06.03.2003 #i9040# - correct calculation of left indent: 3032 // - Consider left indent given by left line attributes. 3033 // - Consider negative left indent. 3034 // wished left indent determined by wished table width and 3035 // right offset given by surrounding fyl frames on the right: 3036 const SwTwips nWishLeft = nMax - nWishedTableWidth - nRightOffset; 3037 if ( nLeftOffset > 0 ) 3038 { 3039 // surrounding fly frames on the left 3040 // -> right indent is maximun of given left offset 3041 // and wished left offset. 3042 nLeftSpacing = nLeftLine + Max( nLeftOffset, nWishLeft ); 3043 } 3044 else 3045 { 3046 // no surrounding fly frames on the left 3047 // If intrinsic left indent (intrinsic = not considering 3048 // determined right indent) is negative, 3049 // then hold this intrinsic indent, 3050 // otherwise non negative wished left indent is hold. 3051 nLeftSpacing = nLeftLine + 3052 ( ( (nWishLeft+nRightOffset) < 0 ) ? 3053 (nWishLeft+nRightOffset) : 3054 Max( 0L, nWishLeft ) ); 3055 } 3056 } 3057 break; 3058 case text::HoriOrientation::CENTER: 3059 { 3060 // OD 07.03.2003 #i9040# - consider left/right line attribute. 3061 // OD 10.03.2003 #i9040# - 3062 const SwTwips nCenterSpacing = ( nMax - nWishedTableWidth ) / 2; 3063 nLeftSpacing = nLeftLine + 3064 ( (nLeftOffset > 0) ? 3065 Max( nCenterSpacing, nLeftOffset ) : 3066 nCenterSpacing ); 3067 nRightSpacing = nRightLine + 3068 ( (nRightOffset > 0) ? 3069 Max( nCenterSpacing, nRightOffset ) : 3070 nCenterSpacing ); 3071 } 3072 break; 3073 case text::HoriOrientation::FULL: 3074 //Das Teil dehnt sich ueber die gesamte Breite aus. 3075 //Nur die fuer die Umrandung benoetigten Freiraeume 3076 //werden beruecksichtigt. 3077 //Die Attributwerte von LRSpace werden bewusst missachtet! 3078 bCheckBrowseWidth = sal_True; 3079 nLeftSpacing = nLeftLine + nLeftOffset; 3080 nRightSpacing = nRightLine + nRightOffset; 3081 break; 3082 case text::HoriOrientation::NONE: 3083 { 3084 //Die Raender werden vom Randattribut bestimmt. 3085 nLeftSpacing = pAttrs->CalcLeft( this ); 3086 if( nLeftOffset ) 3087 { 3088 // OD 07.03.2003 #i9040# - surround fly frames only, if 3089 // they overlap with the table. 3090 // Thus, take maximun of left spacing and left offset. 3091 // OD 10.03.2003 #i9040# - consider left line attribute. 3092 nLeftSpacing = Max( nLeftSpacing, ( nLeftOffset + nLeftLine ) ); 3093 } 3094 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)> 3095 nRightSpacing = pAttrs->CalcRight( this ); 3096 if( nRightOffset ) 3097 { 3098 // OD 07.03.2003 #i9040# - surround fly frames only, if 3099 // they overlap with the table. 3100 // Thus, take maximun of right spacing and right offset. 3101 // OD 10.03.2003 #i9040# - consider right line attribute. 3102 nRightSpacing = Max( nRightSpacing, ( nRightOffset + nRightLine ) ); 3103 } 3104 // OD 10.03.2003 #i9040# - do not hold wished table width. 3105 /* 3106 if ( !pAttrs->GetLRSpace().GetRight() ) 3107 nRight = Max( nRight, nMax - (nWish + nLeft + nRight)); 3108 */ 3109 } 3110 break; 3111 case text::HoriOrientation::LEFT_AND_WIDTH: 3112 { 3113 //Linker Rand und die Breite zaehlen (Word-Spezialitaet) 3114 // OD 10.03.2003 #i9040# - no width alignment in online mode. 3115 //bCheckBrowseWidth = sal_True; 3116 nLeftSpacing = pAttrs->CalcLeft( this ); 3117 if( nLeftOffset ) 3118 { 3119 // OD 10.03.2003 #i9040# - surround fly frames only, if 3120 // they overlap with the table. 3121 // Thus, take maximun of right spacing and right offset. 3122 // OD 10.03.2003 #i9040# - consider left line attribute. 3123 nLeftSpacing = Max( nLeftSpacing, ( pAttrs->CalcLeftLine() + nLeftOffset ) ); 3124 } 3125 // OD 10.03.2003 #i9040# - consider right and left line attribute. 3126 const SwTwips nWishRight = 3127 nMax - (nLeftSpacing-pAttrs->CalcLeftLine()) - nWishedTableWidth; 3128 nRightSpacing = nRightLine + 3129 ( (nRightOffset > 0) ? 3130 Max( nWishRight, nRightOffset ) : 3131 nWishRight ); 3132 } 3133 break; 3134 default: 3135 ASSERT( sal_False, "Ungueltige orientation fuer Table." ); 3136 } 3137 3138 // --> OD 2004-07-15 #i26250# - extend bottom printing area, if table 3139 // is last content inside a table cell. 3140 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) && 3141 GetUpper()->IsInTab() && !GetIndNext() ) 3142 { 3143 nLower += pAttrs->GetULSpace().GetLower(); 3144 } 3145 // <-- 3146 (this->*fnRect->fnSetYMargins)( nUpper, nLower ); 3147 if( (nMax - MINLAY) < (nLeftSpacing + nRightSpacing) ) 3148 (this->*fnRect->fnSetXMargins)( 0, 0 ); 3149 else 3150 (this->*fnRect->fnSetXMargins)( nLeftSpacing, nRightSpacing ); 3151 3152 ViewShell *pSh = getRootFrm()->GetCurrShell(); 3153 if ( bCheckBrowseWidth && 3154 pSh && pSh->GetViewOptions()->getBrowseMode() && 3155 GetUpper()->IsPageBodyFrm() && // nur PageBodyFrms, nicht etwa ColBodyFrms 3156 pSh->VisArea().Width() ) 3157 { 3158 //Nicht ueber die Kante des sichbaren Bereiches hinausragen. 3159 //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite" 3160 //geben kann (RootFrm::ImplCalcBrowseWidth()) 3161 long nWidth = pSh->GetBrowseWidth(); 3162 nWidth -= Prt().Left(); 3163 nWidth -= pAttrs->CalcRightLine(); 3164 Prt().Width( Min( nWidth, Prt().Width() ) ); 3165 } 3166 3167 if ( nOldHeight != (Prt().*fnRect->fnGetHeight)() ) 3168 bValidSize = sal_False; 3169 } 3170 3171 if ( !bValidSize ) 3172 { 3173 bValidSize = sal_True; 3174 3175 //Die Groesse wird durch den Inhalt plus den Raendern bestimmt. 3176 SwTwips nRemaining = 0, nDiff; 3177 SwFrm *pFrm = pLower; 3178 while ( pFrm ) 3179 { 3180 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)(); 3181 pFrm = pFrm->GetNext(); 3182 } 3183 //Jetzt noch die Raender addieren 3184 nRemaining += nUpper + nLower; 3185 3186 nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining; 3187 if ( nDiff > 0 ) 3188 Shrink( nDiff ); 3189 else if ( nDiff < 0 ) 3190 Grow( -nDiff ); 3191 } 3192 } 3193 /************************************************************************* 3194 |* 3195 |* SwTabFrm::GrowFrm() 3196 |* 3197 |* Ersterstellung MA 12. Mar. 93 3198 |* Letzte Aenderung MA 23. Sep. 96 3199 |* 3200 |*************************************************************************/ 3201 SwTwips SwTabFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo ) 3202 { 3203 SWRECTFN( this ) 3204 SwTwips nHeight =(Frm().*fnRect->fnGetHeight)(); 3205 if( nHeight > 0 && nDist > ( LONG_MAX - nHeight ) ) 3206 nDist = LONG_MAX - nHeight; 3207 3208 if ( bTst && !IsRestrictTableGrowth() ) 3209 return nDist; 3210 3211 if ( GetUpper() ) 3212 { 3213 SwRect aOldFrm( Frm() ); 3214 3215 //Der Upper wird nur soweit wie notwendig gegrowed. In nReal wird erstmal 3216 //die bereits zur Verfuegung stehende Strecke bereitgestellt. 3217 SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)(); 3218 SwFrm *pFrm = GetUpper()->Lower(); 3219 while ( pFrm && GetFollow() != pFrm ) 3220 { 3221 nReal -= (pFrm->Frm().*fnRect->fnGetHeight)(); 3222 pFrm = pFrm->GetNext(); 3223 } 3224 3225 long nTmp = 0; 3226 if ( nReal < nDist ) 3227 { 3228 nTmp = GetUpper()->Grow( nDist - ( nReal > 0 ? nReal : 0), bTst, bInfo ); 3229 3230 if ( IsRestrictTableGrowth() ) 3231 { 3232 nTmp = Min( nDist, nReal + nTmp ); 3233 nDist = nTmp < 0 ? 0 : nTmp; 3234 } 3235 } 3236 3237 if ( !bTst ) 3238 { 3239 (Frm().*fnRect->fnAddBottom)( nDist ); 3240 3241 SwRootFrm *pRootFrm = getRootFrm(); 3242 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && 3243 pRootFrm->GetCurrShell() ) 3244 { 3245 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm ); 3246 } 3247 } 3248 } 3249 3250 if ( !bTst && ( nDist || IsRestrictTableGrowth() ) ) 3251 { 3252 SwPageFrm *pPage = FindPageFrm(); 3253 if ( GetNext() ) 3254 { 3255 GetNext()->_InvalidatePos(); 3256 if ( GetNext()->IsCntntFrm() ) 3257 GetNext()->InvalidatePage( pPage ); 3258 } 3259 // --> OD 2004-07-05 #i28701# - Due to the new object positioning the 3260 // frame on the next page/column can flow backward (e.g. it was moved 3261 // forward due to the positioning of its objects ). Thus, invalivate this 3262 // next frame, if document compatibility option 'Consider wrapping style 3263 // influence on object positioning' is ON. 3264 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ) 3265 { 3266 InvalidateNextPos(); 3267 } 3268 // <-- 3269 _InvalidateAll(); 3270 InvalidatePage( pPage ); 3271 SetComplete(); 3272 3273 const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos(); 3274 if ( GPOS_NONE != ePos && GPOS_TILED != ePos ) 3275 SetCompletePaint(); 3276 } 3277 3278 return nDist; 3279 } 3280 /************************************************************************* 3281 |* 3282 |* SwTabFrm::Modify() 3283 |* 3284 |* Ersterstellung MA 14. Mar. 93 3285 |* Letzte Aenderung MA 06. Dec. 96 3286 |* 3287 |*************************************************************************/ 3288 void SwTabFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) 3289 { 3290 sal_uInt8 nInvFlags = 0; 3291 sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which(); 3292 3293 if( bAttrSetChg ) 3294 { 3295 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() ); 3296 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() ); 3297 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld ); 3298 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew ); 3299 while( sal_True ) 3300 { 3301 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(), 3302 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags, 3303 &aOldSet, &aNewSet ); 3304 if( aNIter.IsAtEnd() ) 3305 break; 3306 aNIter.NextItem(); 3307 aOIter.NextItem(); 3308 } 3309 if ( aOldSet.Count() || aNewSet.Count() ) 3310 SwLayoutFrm::Modify( &aOldSet, &aNewSet ); 3311 } 3312 else 3313 _UpdateAttr( pOld, pNew, nInvFlags ); 3314 3315 if ( nInvFlags != 0 ) 3316 { 3317 SwPageFrm *pPage = FindPageFrm(); 3318 InvalidatePage( pPage ); 3319 // if ( nInvFlags & 0x01 ) 3320 // SetCompletePaint(); 3321 if ( nInvFlags & 0x02 ) 3322 _InvalidatePrt(); 3323 if ( nInvFlags & 0x40 ) 3324 _InvalidatePos(); 3325 SwFrm *pTmp; 3326 if ( 0 != (pTmp = GetIndNext()) ) 3327 { 3328 if ( nInvFlags & 0x04 ) 3329 { 3330 pTmp->_InvalidatePrt(); 3331 if ( pTmp->IsCntntFrm() ) 3332 pTmp->InvalidatePage( pPage ); 3333 } 3334 if ( nInvFlags & 0x10 ) 3335 pTmp->SetCompletePaint(); 3336 } 3337 if ( nInvFlags & 0x08 && 0 != (pTmp = GetPrev()) ) 3338 { 3339 pTmp->_InvalidatePrt(); 3340 if ( pTmp->IsCntntFrm() ) 3341 pTmp->InvalidatePage( pPage ); 3342 } 3343 if ( nInvFlags & 0x20 ) 3344 { 3345 if ( pPage && pPage->GetUpper() && !IsFollow() ) 3346 ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth(); 3347 } 3348 if ( nInvFlags & 0x80 ) 3349 InvalidateNextPos(); 3350 } 3351 } 3352 3353 void SwTabFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew, 3354 sal_uInt8 &rInvFlags, 3355 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet ) 3356 { 3357 sal_Bool bClear = sal_True; 3358 const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0; 3359 switch( nWhich ) 3360 { 3361 case RES_TBLHEADLINECHG: 3362 if ( IsFollow() ) 3363 { 3364 // Delete remaining headlines: 3365 SwRowFrm* pLowerRow = 0; 3366 while ( 0 != ( pLowerRow = (SwRowFrm*)Lower() ) && pLowerRow->IsRepeatedHeadline() ) 3367 { 3368 pLowerRow->Cut(); 3369 delete pLowerRow; 3370 } 3371 3372 // insert new headlines 3373 const sal_uInt16 nNewRepeat = GetTable()->GetRowsToRepeat(); 3374 for ( sal_uInt16 nIdx = 0; nIdx < nNewRepeat; ++nIdx ) 3375 { 3376 bDontCreateObjects = sal_True; //frmtool 3377 SwRowFrm* pHeadline = new SwRowFrm( *GetTable()->GetTabLines()[ nIdx ], this ); 3378 pHeadline->SetRepeatedHeadline( true ); 3379 bDontCreateObjects = sal_False; 3380 pHeadline->Paste( this, pLowerRow ); 3381 } 3382 } 3383 rInvFlags |= 0x02; 3384 break; 3385 3386 case RES_FRM_SIZE: 3387 case RES_HORI_ORIENT: 3388 rInvFlags |= 0x22; 3389 break; 3390 3391 case RES_PAGEDESC: //Attributaenderung (an/aus) 3392 if ( IsInDocBody() ) 3393 { 3394 rInvFlags |= 0x40; 3395 SwPageFrm *pPage = FindPageFrm(); 3396 if ( !GetPrev() ) 3397 CheckPageDescs( pPage ); 3398 if ( pPage && GetFmt()->GetPageDesc().GetNumOffset() ) 3399 ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True ); 3400 SwDocPosUpdate aMsgHnt( pPage->Frm().Top() ); 3401 GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt ); 3402 } 3403 break; 3404 3405 case RES_BREAK: 3406 rInvFlags |= 0xC0; 3407 break; 3408 3409 case RES_LAYOUT_SPLIT: 3410 if ( !IsFollow() ) 3411 rInvFlags |= 0x40; 3412 break; 3413 case RES_FRAMEDIR : 3414 SetDerivedR2L( sal_False ); 3415 CheckDirChange(); 3416 break; 3417 case RES_COLLAPSING_BORDERS : 3418 rInvFlags |= 0x02; 3419 lcl_InvalidateAllLowersPrt( this ); 3420 break; 3421 case RES_UL_SPACE: 3422 rInvFlags |= 0x1C; 3423 /* kein Break hier */ 3424 3425 default: 3426 bClear = sal_False; 3427 } 3428 if ( bClear ) 3429 { 3430 if ( pOldSet || pNewSet ) 3431 { 3432 if ( pOldSet ) 3433 pOldSet->ClearItem( nWhich ); 3434 if ( pNewSet ) 3435 pNewSet->ClearItem( nWhich ); 3436 } 3437 else 3438 SwLayoutFrm::Modify( pOld, pNew ); 3439 } 3440 } 3441 3442 /************************************************************************* 3443 |* 3444 |* SwTabFrm::GetInfo() 3445 |* 3446 |* Ersterstellung MA 06. Dec. 96 3447 |* Letzte Aenderung MA 26. Jun. 98 3448 |* 3449 |*************************************************************************/ 3450 sal_Bool SwTabFrm::GetInfo( SfxPoolItem &rHnt ) const 3451 { 3452 if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && !IsFollow() ) 3453 { 3454 SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt; 3455 const SwPageFrm *pPage = FindPageFrm(); 3456 if ( pPage ) 3457 { 3458 if ( pPage == rInfo.GetOrigPage() && !GetPrev() ) 3459 { 3460 //Das sollte er sein (kann allenfalls temporaer anders sein, 3461 // sollte uns das beunruhigen?) 3462 rInfo.SetInfo( pPage, this ); 3463 return sal_False; 3464 } 3465 if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() && 3466 (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum())) 3467 { 3468 //Das koennte er sein. 3469 rInfo.SetInfo( pPage, this ); 3470 } 3471 } 3472 } 3473 return sal_True; 3474 } 3475 3476 /************************************************************************* 3477 |* 3478 |* SwTabFrm::FindLastCntnt() 3479 |* 3480 |* Ersterstellung MA 13. Apr. 93 3481 |* Letzte Aenderung MA 15. May. 98 3482 |* 3483 |*************************************************************************/ 3484 SwCntntFrm *SwTabFrm::FindLastCntnt() 3485 { 3486 SwFrm *pRet = pLower; 3487 3488 while ( pRet && !pRet->IsCntntFrm() ) 3489 { 3490 SwFrm *pOld = pRet; 3491 3492 SwFrm *pTmp = pRet; // To skip empty section frames 3493 while ( pRet->GetNext() ) 3494 { 3495 pRet = pRet->GetNext(); 3496 if( !pRet->IsSctFrm() || ((SwSectionFrm*)pRet)->GetSection() ) 3497 pTmp = pRet; 3498 } 3499 pRet = pTmp; 3500 3501 if ( pRet->GetLower() ) 3502 pRet = pRet->GetLower(); 3503 if ( pRet == pOld ) 3504 { 3505 // Wenn am Ende der letzten Zelle ein spaltiger Bereich steht, 3506 // der eine leere letzte Spalte hat, muessen wir noch die anderen 3507 // Spalten abklappern, dies erledigt SwSectionFrm::FindLastCntnt 3508 if( pRet->IsColBodyFrm() ) 3509 { 3510 #ifdef DBG_UTIL 3511 SwSectionFrm* pSect = pRet->FindSctFrm(); 3512 ASSERT( pSect, "Wo kommt denn die Spalte her?") 3513 ASSERT( IsAnLower( pSect ), "Gespaltene Zelle?" ); 3514 #endif 3515 return pRet->FindSctFrm()->FindLastCntnt(); 3516 } 3517 3518 // 3519 // pRet may be a cell frame without a lower (cell has been split). 3520 // We have to find the last content the hard way: 3521 // 3522 ASSERT( pRet->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" ) 3523 const SwFrm* pRow = pRet->GetUpper(); 3524 while ( pRow && !pRow->GetUpper()->IsTabFrm() ) 3525 pRow = pRow->GetUpper(); 3526 SwCntntFrm* pCntntFrm = ((SwLayoutFrm*)pRow)->ContainsCntnt(); 3527 pRet = 0; 3528 3529 while ( pCntntFrm && ((SwLayoutFrm*)pRow)->IsAnLower( pCntntFrm ) ) 3530 { 3531 pRet = pCntntFrm; 3532 pCntntFrm = pCntntFrm->GetNextCntntFrm(); 3533 } 3534 } 3535 } 3536 3537 // #112929# There actually is a situation, which results in pRet = 0: 3538 // Insert frame, insert table via text <-> table. This gives you a frame 3539 // containing a table without any other content frames. Split the table 3540 // and undo the splitting. This operation gives us a table frame without 3541 // a lower. 3542 if ( pRet ) 3543 { 3544 while ( pRet->GetNext() ) 3545 pRet = pRet->GetNext(); 3546 3547 if( pRet->IsSctFrm() ) 3548 pRet = ((SwSectionFrm*)pRet)->FindLastCntnt(); 3549 } 3550 3551 return (SwCntntFrm*)pRet; 3552 } 3553 3554 /************************************************************************* 3555 |* 3556 |* SwTabFrm::GetLeaf() 3557 |* 3558 |* Ersterstellung MA 19. Mar. 93 3559 |* Letzte Aenderung MA 25. Apr. 95 3560 |* 3561 |*************************************************************************/ 3562 SwLayoutFrm *SwTabFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd ) 3563 { 3564 SwLayoutFrm *pRet; 3565 if ( bFwd ) 3566 { 3567 pRet = GetNextLeaf( eMakePage ); 3568 while ( IsAnLower( pRet ) ) 3569 pRet = pRet->GetNextLeaf( eMakePage ); 3570 } 3571 else 3572 pRet = GetPrevLeaf(); 3573 if ( pRet ) 3574 pRet->Calc(); 3575 return pRet; 3576 } 3577 3578 /************************************************************************* 3579 |* 3580 |* SwTabFrm::ShouldBwdMoved() 3581 |* 3582 |* Beschreibung Returnwert sagt ob der Frm verschoben werden sollte 3583 |* Ersterstellung MA 10. Jul. 95 3584 |* Letzte Aenderung MA 04. Mar. 97 3585 |* 3586 |*************************************************************************/ 3587 sal_Bool SwTabFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool &rReformat ) 3588 { 3589 rReformat = sal_False; 3590 if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) ) 3591 { 3592 //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv. 3593 //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen 3594 //moechte die FixSize die gleiche ist, die der Frm selbst hat. 3595 //In diesem Fall kann einfach geprueft werden, ob der Frm genug 3596 //Platz fuer seine VarSize findet, ist dies nicht der Fall kann 3597 //gleich auf das Verschieben verzichtet werden. 3598 //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst 3599 //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise 3600 //aufspalten kann. 3601 //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind 3602 //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn 3603 //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt 3604 //etwas Platz zur Verfuegung steht). 3605 3606 //Die FixSize der Umgebungen in denen Tabellen herumlungern ist immer 3607 //Die Breite. 3608 3609 SwPageFrm *pOldPage = FindPageFrm(), 3610 *pNewPage = pNewUpper->FindPageFrm(); 3611 sal_Bool bMoveAnyway = sal_False; 3612 SwTwips nSpace = 0; 3613 3614 SWRECTFN( this ) 3615 if ( !SwFlowFrm::IsMoveBwdJump() ) 3616 { 3617 3618 long nOldWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)(); 3619 SWRECTFNX( pNewUpper ); 3620 long nNewWidth = (pNewUpper->Prt().*fnRectX->fnGetWidth)(); 3621 if( Abs( nNewWidth - nOldWidth ) < 2 ) 3622 { 3623 if( sal_False == 3624 ( bMoveAnyway = BwdMoveNecessary( pOldPage, Frm() ) > 1 ) ) 3625 { 3626 SwRect aRect( pNewUpper->Prt() ); 3627 aRect.Pos() += pNewUpper->Frm().Pos(); 3628 const SwFrm *pPrevFrm = pNewUpper->Lower(); 3629 while ( pPrevFrm && pPrevFrm != this ) 3630 { 3631 (aRect.*fnRectX->fnSetTop)( (pPrevFrm->Frm().*fnRectX-> 3632 fnGetBottom)() ); 3633 pPrevFrm = pPrevFrm->GetNext(); 3634 } 3635 bMoveAnyway = BwdMoveNecessary( pNewPage, aRect) > 1; 3636 3637 // --> FME 2006-01-20 #i54861# Due to changes made in PrepareMake, 3638 // the tabfrm may not have a correct position. Therefore 3639 // it is possible that pNewUpper->Prt().Height == 0. In this 3640 // case the above calculation of nSpace might give wrong 3641 // results and we really do not want to MoveBackwrd into a 3642 // 0 height frame. If nTmpSpace is already <= 0, we take this 3643 // value: 3644 const SwTwips nTmpSpace = (aRect.*fnRectX->fnGetHeight)(); 3645 if ( (pNewUpper->Prt().*fnRectX->fnGetHeight)() > 0 || nTmpSpace <= 0 ) 3646 nSpace = nTmpSpace; 3647 // <-- 3648 3649 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 3650 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 3651 nSpace += pNewUpper->Grow( LONG_MAX, sal_True ); 3652 } 3653 } 3654 else if( !bLockBackMove ) 3655 bMoveAnyway = sal_True; 3656 } 3657 else if( !bLockBackMove ) 3658 bMoveAnyway = sal_True; 3659 3660 if ( bMoveAnyway ) 3661 return rReformat = sal_True; 3662 else if ( !bLockBackMove && nSpace > 0 ) 3663 { 3664 // --> OD 2004-10-05 #i26945# - check, if follow flow line 3665 // contains frame, which are moved forward due to its object 3666 // positioning. 3667 SwRowFrm* pFirstRow = GetFirstNonHeadlineRow(); 3668 if ( pFirstRow && pFirstRow->IsInFollowFlowRow() && 3669 SwLayouter::DoesRowContainMovedFwdFrm( 3670 *(pFirstRow->GetFmt()->GetDoc()), 3671 *(pFirstRow) ) ) 3672 { 3673 return sal_False; 3674 } 3675 // <-- 3676 SwTwips nTmpHeight = CalcHeightOfFirstContentLine(); 3677 3678 // --> FME 2005-01-17 #118840# 3679 // For some mysterious reason, I changed the good old 3680 // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'. 3681 // This obviously results in problems with table frames in 3682 // sections. Remember: Every twip is sacred. 3683 return nTmpHeight <= nSpace; 3684 // <-- 3685 } 3686 } 3687 return sal_False; 3688 } 3689 3690 /************************************************************************* 3691 |* 3692 |* SwTabFrm::Cut() 3693 |* 3694 |* Ersterstellung MA 23. Feb. 94 3695 |* Letzte Aenderung MA 09. Sep. 98 3696 |* 3697 |*************************************************************************/ 3698 void SwTabFrm::Cut() 3699 { 3700 ASSERT( GetUpper(), "Cut ohne Upper()." ); 3701 3702 SwPageFrm *pPage = FindPageFrm(); 3703 InvalidatePage( pPage ); 3704 SwFrm *pFrm = GetNext(); 3705 if( pFrm ) 3706 { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger 3707 //berechnet der ist jetzt wo er der erste wird obsolete 3708 pFrm->_InvalidatePrt(); 3709 pFrm->_InvalidatePos(); 3710 if ( pFrm->IsCntntFrm() ) 3711 pFrm->InvalidatePage( pPage ); 3712 if( IsInSct() && !GetPrev() ) 3713 { 3714 SwSectionFrm* pSct = FindSctFrm(); 3715 if( !pSct->IsFollow() ) 3716 { 3717 pSct->_InvalidatePrt(); 3718 pSct->InvalidatePage( pPage ); 3719 } 3720 } 3721 } 3722 else 3723 { 3724 InvalidateNextPos(); 3725 //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper 3726 if ( 0 != (pFrm = GetPrev()) ) 3727 { pFrm->SetRetouche(); 3728 pFrm->Prepare( PREP_WIDOWS_ORPHANS ); 3729 pFrm->_InvalidatePos(); 3730 if ( pFrm->IsCntntFrm() ) 3731 pFrm->InvalidatePage( pPage ); 3732 } 3733 //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss 3734 //er die Retouche uebernehmen. 3735 //Ausserdem kann eine Leerseite entstanden sein. 3736 else 3737 { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper(); 3738 pRoot->SetSuperfluous(); 3739 GetUpper()->SetCompletePaint(); 3740 if( IsInSct() ) 3741 { 3742 SwSectionFrm* pSct = FindSctFrm(); 3743 if( !pSct->IsFollow() ) 3744 { 3745 pSct->_InvalidatePrt(); 3746 pSct->InvalidatePage( pPage ); 3747 } 3748 } 3749 } 3750 } 3751 3752 //Erst removen, dann Upper Shrinken. 3753 SwLayoutFrm *pUp = GetUpper(); 3754 SWRECTFN( this ) 3755 Remove(); 3756 if ( pUp ) 3757 { 3758 ASSERT( !pUp->IsFtnFrm(), "Tabelle in Fussnote." ); 3759 SwSectionFrm *pSct = 0; 3760 // --> OD 2006-01-04 #126020# - adjust check for empty section 3761 // --> OD 2006-02-01 #130797# - correct fix #126020# 3762 if ( !pUp->Lower() && pUp->IsInSct() && 3763 !(pSct = pUp->FindSctFrm())->ContainsCntnt() && 3764 !pSct->ContainsAny( true ) ) 3765 // <-- 3766 { 3767 if ( pUp->GetUpper() ) 3768 { 3769 pSct->DelEmpty( sal_False ); 3770 pSct->_InvalidateSize(); 3771 } 3772 } 3773 else if( (Frm().*fnRect->fnGetHeight)() ) 3774 { 3775 // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section - 3776 // undo changes of fix for #104992# 3777 pUp->Shrink( Frm().Height() ); 3778 } 3779 } 3780 3781 if ( pPage && !IsFollow() && pPage->GetUpper() ) 3782 ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth(); 3783 } 3784 3785 /************************************************************************* 3786 |* 3787 |* SwTabFrm::Paste() 3788 |* 3789 |* Ersterstellung MA 23. Feb. 94 3790 |* Letzte Aenderung MA 09. Sep. 98 3791 |* 3792 |*************************************************************************/ 3793 void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling ) 3794 { 3795 ASSERT( pParent, "Kein Parent fuer Paste." ); 3796 ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." ); 3797 ASSERT( pParent != this, "Bin selbst der Parent." ); 3798 ASSERT( pSibling != this, "Bin mein eigener Nachbar." ); 3799 ASSERT( !GetPrev() && !GetNext() && !GetUpper(), 3800 "Bin noch irgendwo angemeldet." ); 3801 3802 //In den Baum einhaengen. 3803 InsertBefore( (SwLayoutFrm*)pParent, pSibling ); 3804 3805 _InvalidateAll(); 3806 SwPageFrm *pPage = FindPageFrm(); 3807 InvalidatePage( pPage ); 3808 3809 if ( GetNext() ) 3810 { 3811 GetNext()->_InvalidatePos(); 3812 GetNext()->_InvalidatePrt(); 3813 if ( GetNext()->IsCntntFrm() ) 3814 GetNext()->InvalidatePage( pPage ); 3815 } 3816 3817 SWRECTFN( this ) 3818 if( (Frm().*fnRect->fnGetHeight)() ) 3819 pParent->Grow( (Frm().*fnRect->fnGetHeight)() ); 3820 3821 if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)() ) 3822 Prepare( PREP_FIXSIZE_CHG ); 3823 if ( GetPrev() ) 3824 { 3825 if ( !IsFollow() ) 3826 { 3827 GetPrev()->InvalidateSize(); 3828 if ( GetPrev()->IsCntntFrm() ) 3829 GetPrev()->InvalidatePage( pPage ); 3830 } 3831 } 3832 else if ( GetNext() ) 3833 //Bei CntntFrm's gilt es den Abstand zum Vorgaenger/Nachfolger 3834 //zu beachten. Faelle (beide treten immer gleichzeitig auf): 3835 //a) Der Cntnt wird der erste einer Kette 3836 //b) Der neue Nachfolger war vorher der erste einer Kette 3837 GetNext()->_InvalidatePrt(); 3838 3839 if ( pPage && !IsFollow() ) 3840 { 3841 if ( pPage->GetUpper() ) 3842 ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth(); 3843 3844 if ( !GetPrev() )//Mindestens fuer HTML mit Tabelle am Anfang notwendig. 3845 { 3846 const SwPageDesc *pDesc = GetFmt()->GetPageDesc().GetPageDesc(); 3847 if ( (pDesc && pDesc != pPage->GetPageDesc()) || 3848 (!pDesc && pPage->GetPageDesc() != 3849 &(const_cast<const SwDoc *>(GetFmt()->GetDoc()) 3850 ->GetPageDesc(0))) ) 3851 CheckPageDescs( pPage, sal_True ); 3852 } 3853 } 3854 } 3855 3856 /************************************************************************* 3857 |* 3858 |* SwTabFrm::Prepare() 3859 |* 3860 |* Created AMA 01/10/02 3861 |* Last Change AMA 01/10/02 3862 |* 3863 |*************************************************************************/ 3864 void SwTabFrm::Prepare( const PrepareHint eHint, const void *, sal_Bool ) 3865 { 3866 if( PREP_BOSS_CHGD == eHint ) 3867 CheckDirChange(); 3868 } 3869 3870 /************************************************************************* 3871 |* 3872 |* SwRowFrm::SwRowFrm(), ~SwRowFrm() 3873 |* 3874 |* Ersterstellung MA 09. Mar. 93 3875 |* Letzte Aenderung MA 30. May. 96 3876 |* 3877 |*************************************************************************/ 3878 SwRowFrm::SwRowFrm( const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent ): 3879 SwLayoutFrm( rLine.GetFrmFmt(), pSib ), 3880 pTabLine( &rLine ), 3881 pFollowRow( 0 ), 3882 // --> collapsing borders FME 2005-05-27 #i29550# 3883 mnTopMarginForLowers( 0 ), 3884 mnBottomMarginForLowers( 0 ), 3885 mnBottomLineSize( 0 ), 3886 // <-- collapsing 3887 // --> split table rows 3888 bIsFollowFlowRow( false ), 3889 // <-- split table rows 3890 bIsRepeatedHeadline( false ), 3891 mbIsRowSpanLine( false ) 3892 { 3893 nType = FRMC_ROW; 3894 3895 //Gleich die Boxen erzeugen und einfuegen. 3896 const SwTableBoxes &rBoxes = rLine.GetTabBoxes(); 3897 SwFrm *pTmpPrev = 0; 3898 for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i ) 3899 { 3900 SwCellFrm *pNew = new SwCellFrm( *rBoxes[i], this, bInsertContent ); 3901 pNew->InsertBehind( this, pTmpPrev ); 3902 pTmpPrev = pNew; 3903 } 3904 } 3905 3906 SwRowFrm::~SwRowFrm() 3907 { 3908 SwModify* pMod = GetFmt(); 3909 if( pMod ) 3910 { 3911 pMod->Remove( this ); // austragen, 3912 if( !pMod->GetDepends() ) 3913 delete pMod; // und loeschen 3914 } 3915 } 3916 3917 /************************************************************************* 3918 |* 3919 |* SwRowFrm::RegistFlys() 3920 |* 3921 |* Ersterstellung MA 08. Jul. 93 3922 |* Letzte Aenderung MA 08. Jul. 93 3923 |* 3924 |*************************************************************************/ 3925 void SwRowFrm::RegistFlys( SwPageFrm *pPage ) 3926 { 3927 ::RegistFlys( pPage ? pPage : FindPageFrm(), this ); 3928 } 3929 3930 /************************************************************************* 3931 |* 3932 |* SwRowFrm::Modify() 3933 |* 3934 |* Ersterstellung MA 12. Nov. 97 3935 |* Letzte Aenderung MA 12. Nov. 97 3936 |* 3937 |*************************************************************************/ 3938 void SwRowFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) 3939 { 3940 sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which(); 3941 const SfxPoolItem *pItem = 0; 3942 3943 if( bAttrSetChg ) 3944 { 3945 const SwAttrSet* pChgSet = ((SwAttrSetChg*)pNew)->GetChgSet(); 3946 pChgSet->GetItemState( RES_FRM_SIZE, sal_False, &pItem); 3947 if ( !pItem ) 3948 pChgSet->GetItemState( RES_ROW_SPLIT, sal_False, &pItem); 3949 } 3950 else if ( RES_FRM_SIZE == pNew->Which() || RES_ROW_SPLIT == pNew->Which() ) 3951 pItem = pNew; 3952 3953 if ( pItem ) 3954 { 3955 SwTabFrm *pTab = FindTabFrm(); 3956 if ( pTab ) 3957 { 3958 const bool bInFirstNonHeadlineRow = pTab->IsFollow() && 3959 this == pTab->GetFirstNonHeadlineRow(); 3960 // --> FME 2004-10-27 #i35063# 3961 // Invalidation required is pRow is last row 3962 if ( bInFirstNonHeadlineRow || !GetNext() ) 3963 // <-- 3964 { 3965 if ( bInFirstNonHeadlineRow ) 3966 pTab = pTab->FindMaster(); 3967 pTab->InvalidatePos(); 3968 } 3969 } 3970 } 3971 3972 SwLayoutFrm::Modify( pOld, pNew ); 3973 } 3974 3975 3976 3977 /************************************************************************* 3978 |* 3979 |* SwRowFrm::MakeAll() 3980 |* 3981 |* Ersterstellung MA 01. Mar. 94 3982 |* Letzte Aenderung MA 01. Mar. 94 3983 |* 3984 |*************************************************************************/ 3985 void SwRowFrm::MakeAll() 3986 { 3987 if ( !GetNext() ) 3988 bValidSize = sal_False; 3989 SwLayoutFrm::MakeAll(); 3990 } 3991 3992 /************************************************************************* 3993 |* 3994 |* SwRowFrm::Format() 3995 |* 3996 |* Ersterstellung MA 13. Mar. 93 3997 |* Letzte Aenderung MA 20. Jun. 96 3998 |* 3999 |*************************************************************************/ 4000 long MA_FASTCALL CalcHeightWidthFlys( const SwFrm *pFrm ) 4001 { 4002 SWRECTFN( pFrm ) 4003 long nHeight = 0; 4004 const SwFrm* pTmp = pFrm->IsSctFrm() ? 4005 ((SwSectionFrm*)pFrm)->ContainsCntnt() : pFrm; 4006 while( pTmp ) 4007 { 4008 // --> OD 2004-10-08 #i26945# - consider follow text frames 4009 const SwSortedObjs* pObjs( 0L ); 4010 bool bIsFollow( false ); 4011 if ( pTmp->IsTxtFrm() && static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) 4012 { 4013 const SwFrm* pMaster; 4014 // --> FME 2005-04-01 #i46450# Master does not necessarily have 4015 // to exist if this function is called from JoinFrm() -> 4016 // Cut() -> Shrink() 4017 const SwTxtFrm* pTmpFrm = static_cast<const SwTxtFrm*>(pTmp); 4018 if ( pTmpFrm->GetPrev() && pTmpFrm->GetPrev()->IsTxtFrm() && 4019 static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() && 4020 static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() != pTmp ) 4021 pMaster = 0; 4022 else 4023 pMaster = pTmpFrm->FindMaster(); 4024 4025 if ( pMaster ) 4026 { 4027 pObjs = static_cast<const SwTxtFrm*>(pTmp)->FindMaster()->GetDrawObjs(); 4028 bIsFollow = true; 4029 } 4030 } 4031 else 4032 { 4033 pObjs = pTmp->GetDrawObjs(); 4034 } 4035 if ( pObjs ) 4036 // <-- 4037 { 4038 for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i ) 4039 { 4040 const SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; 4041 // --> OD 2004-10-08 #i26945# - if <pTmp> is follow, the 4042 // anchor character frame has to be <pTmp>. 4043 if ( bIsFollow && 4044 const_cast<SwAnchoredObject*>(pAnchoredObj)->FindAnchorCharFrm() != pTmp ) 4045 { 4046 continue; 4047 } 4048 // <-- 4049 // --> OD 2004-10-04 #i26945# - consider also drawing objects 4050 { 4051 // OD 30.09.2003 #i18732# - only objects, which follow 4052 // the text flow have to be considered. 4053 const SwFrmFmt& rFrmFmt = pAnchoredObj->GetFrmFmt(); 4054 const bool bConsiderObj = 4055 (rFrmFmt.GetAnchor().GetAnchorId() != FLY_AS_CHAR) && 4056 pAnchoredObj->GetObjRect().Top() != WEIT_WECH && 4057 rFrmFmt.GetFollowTextFlow().GetValue() && 4058 pAnchoredObj->GetPageFrm() == pTmp->FindPageFrm(); 4059 if ( bConsiderObj ) 4060 { 4061 const SwFmtFrmSize &rSz = rFrmFmt.GetFrmSize(); 4062 if( !rSz.GetHeightPercent() ) 4063 { 4064 const SwTwips nDistOfFlyBottomToAnchorTop = 4065 (pAnchoredObj->GetObjRect().*fnRect->fnGetHeight)() + 4066 ( bVert ? 4067 pAnchoredObj->GetCurrRelPos().X() : 4068 pAnchoredObj->GetCurrRelPos().Y() ); 4069 4070 const SwTwips nFrmDiff = 4071 (*fnRect->fnYDiff)( 4072 (pTmp->Frm().*fnRect->fnGetTop)(), 4073 (pFrm->Frm().*fnRect->fnGetTop)() ); 4074 4075 nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop + nFrmDiff - 4076 (pFrm->Frm().*fnRect->fnGetHeight)() ); 4077 4078 // --> FME 2006-01-24 #i56115# The first height calculation 4079 // gives wrong results if pFrm->Prt().Y() > 0. We do 4080 // a second calculation based on the actual rectangles of 4081 // pFrm and pAnchoredObj, and use the maximum of the results. 4082 // I do not want to remove the first calculation because 4083 // if clipping has been applied, using the GetCurrRelPos 4084 // might be the better option to calculate nHeight. 4085 const SwTwips nDistOfFlyBottomToAnchorTop2 = (*fnRect->fnYDiff)( 4086 (pAnchoredObj->GetObjRect().*fnRect->fnGetBottom)(), 4087 (pFrm->Frm().*fnRect->fnGetBottom)() ); 4088 4089 nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop2 ); 4090 // <-- 4091 } 4092 } 4093 } 4094 // <-- 4095 } 4096 } 4097 if( !pFrm->IsSctFrm() ) 4098 break; 4099 pTmp = pTmp->FindNextCnt(); 4100 if( !((SwSectionFrm*)pFrm)->IsAnLower( pTmp ) ) 4101 break; 4102 } 4103 return nHeight; 4104 } 4105 4106 SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm& rCell, const SwBorderAttrs& rAttrs ) 4107 { 4108 const SwTabFrm* pTab = rCell.FindTabFrm(); 4109 SwTwips nTopSpace = 0; 4110 SwTwips nBottomSpace = 0; 4111 4112 // --> collapsing borders FME 2005-05-27 #i29550# 4113 if ( pTab->IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrm() ) 4114 { 4115 nTopSpace = ((SwRowFrm*)rCell.GetUpper())->GetTopMarginForLowers(); 4116 nBottomSpace = ((SwRowFrm*)rCell.GetUpper())->GetBottomMarginForLowers(); 4117 } 4118 // <-- collapsing 4119 else 4120 { 4121 if ( pTab->IsVertical() != rCell.IsVertical() ) 4122 { 4123 nTopSpace = rAttrs.CalcLeft( &rCell ); 4124 nBottomSpace = rAttrs.CalcRight( &rCell ); 4125 } 4126 else 4127 { 4128 nTopSpace = rAttrs.CalcTop(); 4129 nBottomSpace = rAttrs.CalcBottom(); 4130 } 4131 } 4132 4133 return nTopSpace + nBottomSpace; 4134 } 4135 4136 4137 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to 4138 // control, if floating screen objects have to be considered for the minimal 4139 // cell height. 4140 SwTwips MA_FASTCALL lcl_CalcMinCellHeight( const SwLayoutFrm *_pCell, 4141 const sal_Bool _bConsiderObjs, 4142 const SwBorderAttrs *pAttrs = 0 ) 4143 { 4144 SWRECTFN( _pCell ) 4145 SwTwips nHeight = 0; 4146 const SwFrm* pLow = _pCell->Lower(); 4147 if ( pLow ) 4148 { 4149 long nFlyAdd = 0; 4150 while ( pLow ) 4151 { 4152 // OD 2004-02-18 #106629# - change condition and switch then-body 4153 // and else-body 4154 if ( pLow->IsRowFrm() ) 4155 { 4156 // --> OD 2004-10-04 #i26945# 4157 nHeight += ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm*>(pLow), 4158 _bConsiderObjs ); 4159 // <-- 4160 } 4161 else 4162 { 4163 long nLowHeight = (pLow->Frm().*fnRect->fnGetHeight)(); 4164 nHeight += nLowHeight; 4165 // --> OD 2004-10-04 #i26945# 4166 if ( _bConsiderObjs ) 4167 { 4168 nFlyAdd = Max( 0L, nFlyAdd - nLowHeight ); 4169 nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) ); 4170 } 4171 // <-- 4172 } 4173 4174 pLow = pLow->GetNext(); 4175 } 4176 if ( nFlyAdd ) 4177 nHeight += nFlyAdd; 4178 } 4179 //Der Border will natuerlich auch mitspielen, er kann leider nicht 4180 //aus PrtArea und Frm errechnet werden, da diese in beliebiger 4181 //Kombination ungueltig sein koennen. 4182 if ( _pCell->Lower() ) 4183 { 4184 if ( pAttrs ) 4185 nHeight += lcl_CalcTopAndBottomMargin( *_pCell, *pAttrs ); 4186 else 4187 { 4188 SwBorderAttrAccess aAccess( SwFrm::GetCache(), _pCell ); 4189 const SwBorderAttrs &rAttrs = *aAccess.Get(); 4190 nHeight += lcl_CalcTopAndBottomMargin( *_pCell, rAttrs ); 4191 } 4192 } 4193 return nHeight; 4194 } 4195 4196 // OD 2004-02-18 #106629# - correct type of 1st parameter 4197 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to control, 4198 // if floating screen objects have to be considered for the minimal cell height 4199 SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm* _pRow, 4200 const sal_Bool _bConsiderObjs ) 4201 { 4202 SWRECTFN( _pRow ) 4203 4204 const SwFmtFrmSize &rSz = _pRow->GetFmt()->GetFrmSize(); 4205 4206 if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() ) 4207 { 4208 ASSERT( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" ) 4209 return rSz.GetHeight(); 4210 } 4211 4212 SwTwips nHeight = 0; 4213 const SwCellFrm* pLow = static_cast<const SwCellFrm*>(_pRow->Lower()); 4214 while ( pLow ) 4215 { 4216 SwTwips nTmp = 0; 4217 const long nRowSpan = pLow->GetLayoutRowSpan(); 4218 // --> NEW TABLES 4219 // Consider height of 4220 // 1. current cell if RowSpan == 1 4221 // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1 4222 // 3. master cell if RowSpan == -1 4223 if ( 1 == nRowSpan ) 4224 { 4225 nTmp = ::lcl_CalcMinCellHeight( pLow, _bConsiderObjs ); 4226 } 4227 else if ( -1 == nRowSpan ) 4228 { 4229 // Height of the last cell of a row span is height of master cell 4230 // minus the height of the other rows which are covered by the master 4231 // cell: 4232 const SwCellFrm& rMaster = pLow->FindStartEndOfRowSpanCell( true, true ); 4233 nTmp = ::lcl_CalcMinCellHeight( &rMaster, _bConsiderObjs ); 4234 const SwFrm* pMasterRow = rMaster.GetUpper(); 4235 while ( pMasterRow && pMasterRow != _pRow ) 4236 { 4237 nTmp -= (pMasterRow->Frm().*fnRect->fnGetHeight)(); 4238 pMasterRow = pMasterRow->GetNext(); 4239 } 4240 } 4241 // <-- NEW TABLES 4242 4243 // Do not consider rotated cells: 4244 if ( ( 0 != pLow->IsVertical() ) == ( 0 != bVert ) && nTmp > nHeight ) 4245 nHeight = nTmp; 4246 4247 pLow = static_cast<const SwCellFrm*>(pLow->GetNext()); 4248 } 4249 if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() ) 4250 nHeight = Max( nHeight, rSz.GetHeight() ); 4251 return nHeight; 4252 } 4253 4254 // --> collapsing borders FME 2005-05-27 #i29550# 4255 4256 // Calculate the maximum of (TopLineSize + TopLineDist) over all lowers: 4257 sal_uInt16 lcl_GetTopSpace( const SwRowFrm& rRow ) 4258 { 4259 sal_uInt16 nTopSpace = 0; 4260 for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower; 4261 pCurrLower = (SwCellFrm*)pCurrLower->GetNext() ) 4262 { 4263 sal_uInt16 nTmpTopSpace = 0; 4264 if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() ) 4265 nTmpTopSpace = lcl_GetTopSpace( *(SwRowFrm*)pCurrLower->Lower() ); 4266 else 4267 { 4268 const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet(); 4269 const SvxBoxItem& rBoxItem = rSet.GetBox(); 4270 nTmpTopSpace = rBoxItem.CalcLineSpace( BOX_LINE_TOP, sal_True ); 4271 } 4272 nTopSpace = Max( nTopSpace, nTmpTopSpace ); 4273 } 4274 return nTopSpace; 4275 } 4276 4277 // Calculate the maximum of TopLineDist over all lowers: 4278 sal_uInt16 lcl_GetTopLineDist( const SwRowFrm& rRow ) 4279 { 4280 sal_uInt16 nTopLineDist = 0; 4281 for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower; 4282 pCurrLower = (SwCellFrm*)pCurrLower->GetNext() ) 4283 { 4284 sal_uInt16 nTmpTopLineDist = 0; 4285 if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() ) 4286 nTmpTopLineDist = lcl_GetTopLineDist( *(SwRowFrm*)pCurrLower->Lower() ); 4287 else 4288 { 4289 const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet(); 4290 const SvxBoxItem& rBoxItem = rSet.GetBox(); 4291 nTmpTopLineDist = rBoxItem.GetDistance( BOX_LINE_TOP ); 4292 } 4293 nTopLineDist = Max( nTopLineDist, nTmpTopLineDist ); 4294 } 4295 return nTopLineDist; 4296 } 4297 4298 // Calculate the maximum of BottomLineSize over all lowers: 4299 sal_uInt16 lcl_GetBottomLineSize( const SwRowFrm& rRow ) 4300 { 4301 sal_uInt16 nBottomLineSize = 0; 4302 for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower; 4303 pCurrLower = (SwCellFrm*)pCurrLower->GetNext() ) 4304 { 4305 sal_uInt16 nTmpBottomLineSize = 0; 4306 if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() ) 4307 { 4308 const SwFrm* pRow = pCurrLower->GetLastLower(); 4309 nTmpBottomLineSize = lcl_GetBottomLineSize( *(SwRowFrm*)pRow ); 4310 } 4311 else 4312 { 4313 const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet(); 4314 const SvxBoxItem& rBoxItem = rSet.GetBox(); 4315 nTmpBottomLineSize = rBoxItem.CalcLineSpace( BOX_LINE_BOTTOM, sal_True ) - 4316 rBoxItem.GetDistance( BOX_LINE_BOTTOM ); 4317 } 4318 nBottomLineSize = Max( nBottomLineSize, nTmpBottomLineSize ); 4319 } 4320 return nBottomLineSize; 4321 } 4322 4323 // Calculate the maximum of BottomLineDist over all lowers: 4324 sal_uInt16 lcl_GetBottomLineDist( const SwRowFrm& rRow ) 4325 { 4326 sal_uInt16 nBottomLineDist = 0; 4327 for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower; 4328 pCurrLower = (SwCellFrm*)pCurrLower->GetNext() ) 4329 { 4330 sal_uInt16 nTmpBottomLineDist = 0; 4331 if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() ) 4332 { 4333 const SwFrm* pRow = pCurrLower->GetLastLower(); 4334 nTmpBottomLineDist = lcl_GetBottomLineDist( *(SwRowFrm*)pRow ); 4335 } 4336 else 4337 { 4338 const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet(); 4339 const SvxBoxItem& rBoxItem = rSet.GetBox(); 4340 nTmpBottomLineDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM ); 4341 } 4342 nBottomLineDist = Max( nBottomLineDist, nTmpBottomLineDist ); 4343 } 4344 return nBottomLineDist; 4345 } 4346 4347 // <-- collapsing 4348 4349 void SwRowFrm::Format( const SwBorderAttrs *pAttrs ) 4350 { 4351 SWRECTFN( this ) 4352 ASSERT( pAttrs, "SwRowFrm::Format ohne Attrs." ); 4353 4354 const sal_Bool bFix = bFixSize; 4355 4356 if ( !bValidPrtArea ) 4357 { 4358 //RowFrms haben keine Umrandung usw. also entspricht die PrtArea immer 4359 //dem Frm. 4360 bValidPrtArea = sal_True; 4361 aPrt.Left( 0 ); 4362 aPrt.Top( 0 ); 4363 aPrt.Width ( aFrm.Width() ); 4364 aPrt.Height( aFrm.Height() ); 4365 4366 // --> collapsing borders FME 2005-05-27 #i29550# 4367 // Here we calculate the top-printing area for the lower cell frames 4368 SwTabFrm* pTabFrm = FindTabFrm(); 4369 if ( pTabFrm->IsCollapsingBorders() ) 4370 { 4371 const sal_uInt16 nTopSpace = lcl_GetTopSpace( *this ); 4372 const sal_uInt16 nTopLineDist = lcl_GetTopLineDist( *this ); 4373 const sal_uInt16 nBottomLineSize = lcl_GetBottomLineSize( *this ); 4374 const sal_uInt16 nBottomLineDist = lcl_GetBottomLineDist( *this ); 4375 4376 4377 const SwRowFrm* pPreviousRow = 0; 4378 4379 // --> FME 2004-09-14 #i32456# 4380 // In order to calculate the top printing area for the lower cell 4381 // frames, we have to find the 'previous' row frame and compare 4382 // the bottom values of the 'previous' row with the 'top' values 4383 // of this row. The best way to find the 'previous' row is to 4384 // use the table structure: 4385 const SwTable* pTable = pTabFrm->GetTable(); 4386 const SwTableLine* pPrevTabLine = 0; 4387 const SwRowFrm* pTmpRow = this; 4388 4389 while ( pTmpRow && !pPrevTabLine ) 4390 { 4391 sal_uInt16 nIdx = 0; 4392 const SwTableLines& rLines = pTmpRow->GetTabLine()->GetUpper() ? 4393 pTmpRow->GetTabLine()->GetUpper()->GetTabLines() : 4394 pTable->GetTabLines(); 4395 4396 while ( rLines[ nIdx ] != pTmpRow->GetTabLine() ) 4397 ++nIdx; 4398 4399 if ( nIdx > 0 ) 4400 { 4401 // pTmpRow has a 'previous' row in the table structure: 4402 pPrevTabLine = rLines[ nIdx - 1 ]; 4403 } 4404 else 4405 { 4406 // pTmpRow is a first row in the table structue. 4407 // We go up in the table structure: 4408 pTmpRow = pTmpRow->GetUpper()->GetUpper() && 4409 pTmpRow->GetUpper()->GetUpper()->IsRowFrm() ? 4410 static_cast<const SwRowFrm*>( pTmpRow->GetUpper()->GetUpper() ) : 4411 0; 4412 } 4413 } 4414 4415 // If we found a 'previous' row, we look for the appropriate row frame: 4416 if ( pPrevTabLine ) 4417 { 4418 SwIterator<SwRowFrm,SwFmt> aIter( *pPrevTabLine->GetFrmFmt() ); 4419 for ( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() ) 4420 { 4421 // --> OD 2004-11-23 #115759# - do *not* take repeated 4422 // headlines, because during split of table it can be 4423 // invalid and thus can't provide correct border values. 4424 if ( pRow->GetTabLine() == pPrevTabLine && 4425 !pRow->IsRepeatedHeadline() ) 4426 // <-- 4427 { 4428 pPreviousRow = pRow; 4429 break; 4430 } 4431 } 4432 } 4433 // <-- 4434 4435 sal_uInt16 nTopPrtMargin = nTopSpace; 4436 if ( pPreviousRow ) 4437 { 4438 const sal_uInt16 nTmpPrtMargin = pPreviousRow->GetBottomLineSize() + nTopLineDist; 4439 if ( nTmpPrtMargin > nTopPrtMargin ) 4440 nTopPrtMargin = nTmpPrtMargin; 4441 } 4442 4443 // table has to be notified if it has to change its lower 4444 // margin due to changes of nBottomLineSize: 4445 if ( !GetNext() && nBottomLineSize != GetBottomLineSize() ) 4446 pTabFrm->_InvalidatePrt(); 4447 4448 // If there are rows nested inside this row, the nested rows 4449 // may not have been calculated yet. Therefore the 4450 // ::lcl_CalcMinRowHeight( this ) operation later in this 4451 // function cannot consider the correct border values. We 4452 // have to trigger the invalidation of the outer row frame 4453 // manually: 4454 // Note: If any further invalidations should be necessary, we 4455 // should consider moving the invalidation stuff to the 4456 // appropriate SwNotify object. 4457 if ( GetUpper()->GetUpper()->IsRowFrm() && 4458 ( nBottomLineDist != GetBottomMarginForLowers() || 4459 nTopPrtMargin != GetTopMarginForLowers() ) ) 4460 GetUpper()->GetUpper()->_InvalidateSize(); 4461 4462 SetBottomMarginForLowers( nBottomLineDist ); // 3. 4463 SetBottomLineSize( nBottomLineSize ); // 4. 4464 SetTopMarginForLowers( nTopPrtMargin ); // 5. 4465 4466 } 4467 // <-- collapsing 4468 } 4469 4470 while ( !bValidSize ) 4471 { 4472 bValidSize = sal_True; 4473 4474 #ifdef DBG_UTIL 4475 if ( HasFixSize() ) 4476 { 4477 const SwFmtFrmSize &rFrmSize = GetFmt()->GetFrmSize(); 4478 ASSERT( rFrmSize.GetSize().Height() > 0, "Hat ihn" ); 4479 } 4480 #endif 4481 const SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - 4482 ( HasFixSize() && !IsRowSpanLine() 4483 ? pAttrs->GetSize().Height() 4484 // --> OD 2004-10-04 #i26945# 4485 : ::lcl_CalcMinRowHeight( this, 4486 FindTabFrm()->IsConsiderObjsForMinCellHeight() ) ); 4487 // <-- 4488 if ( nDiff ) 4489 { 4490 bFixSize = sal_False; 4491 if ( nDiff > 0 ) 4492 Shrink( nDiff, sal_False, sal_True ); 4493 else if ( nDiff < 0 ) 4494 Grow( -nDiff ); 4495 bFixSize = bFix; 4496 } 4497 } 4498 4499 // last row will fill the space in its upper. 4500 if ( !GetNext() ) 4501 { 4502 //Der letzte fuellt den verbleibenden Raum im Upper aus. 4503 SwTwips nDiff = (GetUpper()->Prt().*fnRect->fnGetHeight)(); 4504 SwFrm *pSibling = GetUpper()->Lower(); 4505 do 4506 { nDiff -= (pSibling->Frm().*fnRect->fnGetHeight)(); 4507 pSibling = pSibling->GetNext(); 4508 } while ( pSibling ); 4509 if ( nDiff > 0 ) 4510 { 4511 bFixSize = sal_False; 4512 Grow( nDiff ); 4513 bFixSize = bFix; 4514 bValidSize = sal_True; 4515 } 4516 } 4517 } 4518 4519 /************************************************************************* 4520 |* 4521 |* SwRowFrm::AdjustCells() 4522 |* 4523 |* Ersterstellung MA 10. Aug. 93 4524 |* Letzte Aenderung MA 16. Dec. 96 4525 |* 4526 |*************************************************************************/ 4527 void SwRowFrm::AdjustCells( const SwTwips nHeight, const sal_Bool bHeight ) 4528 { 4529 SwFrm *pFrm = Lower(); 4530 if ( bHeight ) 4531 { 4532 SwRootFrm *pRootFrm = getRootFrm(); 4533 SWRECTFN( this ) 4534 SwRect aOldFrm; 4535 4536 while ( pFrm ) 4537 { 4538 SwFrm* pNotify = 0; 4539 4540 SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pFrm); 4541 4542 // NEW TABLES 4543 // Which cells need to be adjusted if the current row changes 4544 // its height? 4545 4546 // Current frame is a covered frame: 4547 // Set new height for covered cell and adjust master cell: 4548 if ( pCellFrm->GetTabBox()->getRowSpan() < 1 ) 4549 { 4550 // Set height of current (covered) cell to new line height. 4551 const long nDiff = nHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)(); 4552 if ( nDiff ) 4553 { 4554 (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff ); 4555 pCellFrm->_InvalidatePrt(); 4556 } 4557 } 4558 4559 SwCellFrm* pToAdjust = 0; 4560 SwFrm* pToAdjustRow = 0; 4561 4562 // If current frame is covered frame, we still want to adjust the 4563 // height of the cell starting the row span 4564 if ( pCellFrm->GetLayoutRowSpan() < 1 ) 4565 { 4566 pToAdjust = const_cast< SwCellFrm*>(&pCellFrm->FindStartEndOfRowSpanCell( true, true )); 4567 pToAdjustRow = pToAdjust->GetUpper(); 4568 } 4569 else 4570 { 4571 pToAdjust = pCellFrm; 4572 pToAdjustRow = this; 4573 } 4574 4575 // Set height of master cell to height of all lines spanned by this line. 4576 long nRowSpan = pToAdjust->GetLayoutRowSpan(); 4577 SwTwips nSumRowHeight = 0; 4578 while ( pToAdjustRow ) 4579 { 4580 // Use new height for the current row: 4581 nSumRowHeight += pToAdjustRow == this ? 4582 nHeight : 4583 (pToAdjustRow->Frm().*fnRect->fnGetHeight)(); 4584 4585 if ( nRowSpan-- == 1 ) 4586 break; 4587 4588 pToAdjustRow = pToAdjustRow->GetNext(); 4589 } 4590 4591 if ( pToAdjustRow && pToAdjustRow != this ) 4592 pToAdjustRow->_InvalidateSize(); 4593 4594 const long nDiff = nSumRowHeight - (pToAdjust->Frm().*fnRect->fnGetHeight)(); 4595 if ( nDiff ) 4596 { 4597 aOldFrm = pToAdjust->Frm(); 4598 (pToAdjust->Frm().*fnRect->fnAddBottom)( nDiff ); 4599 pNotify = pToAdjust; 4600 } 4601 4602 if ( pNotify ) 4603 { 4604 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && pRootFrm->GetCurrShell() ) 4605 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify, aOldFrm ); 4606 4607 pNotify->_InvalidatePrt(); 4608 } 4609 4610 pFrm = pFrm->GetNext(); 4611 } 4612 } 4613 else 4614 { while ( pFrm ) 4615 { 4616 pFrm->_InvalidateAll(); 4617 pFrm = pFrm->GetNext(); 4618 } 4619 } 4620 InvalidatePage(); 4621 } 4622 4623 /************************************************************************* 4624 |* 4625 |* SwRowFrm::Cut() 4626 |* 4627 |* Ersterstellung MA 12. Nov. 97 4628 |* Letzte Aenderung MA 12. Nov. 97 4629 |* 4630 |*************************************************************************/ 4631 void SwRowFrm::Cut() 4632 { 4633 SwTabFrm *pTab = FindTabFrm(); 4634 if ( pTab && pTab->IsFollow() && this == pTab->GetFirstNonHeadlineRow() ) 4635 { 4636 pTab->FindMaster()->InvalidatePos(); 4637 } 4638 4639 // --> OD 2010-02-17 #i103961# 4640 // notification for accessibility 4641 { 4642 SwRootFrm *pRootFrm = getRootFrm(); 4643 if( pRootFrm && pRootFrm->IsAnyShellAccessible() ) 4644 { 4645 ViewShell* pVSh = pRootFrm->GetCurrShell(); 4646 if ( pVSh && pVSh->Imp() ) 4647 { 4648 SwFrm* pCellFrm( GetLower() ); 4649 while ( pCellFrm ) 4650 { 4651 ASSERT( pCellFrm->IsCellFrm(), 4652 "<SwRowFrm::Cut()> - unexpected type of SwRowFrm lower." ); 4653 pVSh->Imp()->DisposeAccessibleFrm( pCellFrm ); 4654 4655 pCellFrm = pCellFrm->GetNext(); 4656 } 4657 } 4658 } 4659 } 4660 // <-- 4661 4662 SwLayoutFrm::Cut(); 4663 } 4664 4665 /************************************************************************* 4666 |* 4667 |* SwRowFrm::GrowFrm() 4668 |* 4669 |* Ersterstellung MA 15. Mar. 93 4670 |* Letzte Aenderung MA 05. May. 94 4671 |* 4672 |*************************************************************************/ 4673 4674 4675 SwTwips SwRowFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo ) 4676 { 4677 SwTwips nReal = 0; 4678 4679 SwTabFrm* pTab = FindTabFrm(); 4680 SWRECTFN( pTab ) 4681 4682 bool bRestrictTableGrowth; 4683 bool bHasFollowFlowLine = pTab->HasFollowFlowLine(); 4684 4685 if ( GetUpper()->IsTabFrm() ) 4686 { 4687 const SwRowFrm* pFollowFlowRow = IsInSplitTableRow(); 4688 bRestrictTableGrowth = pFollowFlowRow && !pFollowFlowRow->IsRowSpanLine(); 4689 } 4690 else 4691 { 4692 ASSERT( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" ) 4693 bRestrictTableGrowth = GetFollowRow() && bHasFollowFlowLine; 4694 ASSERT( !bRestrictTableGrowth || !GetNext(), 4695 "GetFollowRow for row frame that has a Next" ) 4696 4697 // 4698 // There may still be some space left in my direct upper: 4699 // 4700 const SwTwips nAdditionalSpace = 4701 (Frm().*fnRect->fnBottomDist)( (GetUpper()->GetUpper()->*fnRect->fnGetPrtBottom)() ); 4702 if ( bRestrictTableGrowth && nAdditionalSpace > 0 ) 4703 { 4704 nReal = Min( nAdditionalSpace, nDist ); 4705 nDist -= nReal; 4706 if ( !bTst ) 4707 (Frm().*fnRect->fnAddBottom)( nReal ); 4708 } 4709 } 4710 4711 if ( bRestrictTableGrowth ) 4712 pTab->SetRestrictTableGrowth( sal_True ); 4713 else 4714 { 4715 // Ok, this looks like a hack, indeed, it is a hack. 4716 // If the current row frame is inside another cell frame, 4717 // and the current row frame has no follow, it should not 4718 // be allowed to grow. In fact, setting bRestrictTableGrowth 4719 // to 'false' does not work, because the surrounding RowFrm 4720 // would set this to 'true'. 4721 pTab->SetFollowFlowLine( sal_False ); 4722 } 4723 4724 nReal += SwLayoutFrm::GrowFrm( nDist, bTst, bInfo); 4725 4726 pTab->SetRestrictTableGrowth( sal_False ); 4727 pTab->SetFollowFlowLine( bHasFollowFlowLine ); 4728 4729 //Hoehe der Zellen auf den neuesten Stand bringen. 4730 if ( !bTst ) 4731 { 4732 SWRECTFNX( this ) 4733 AdjustCells( (Prt().*fnRectX->fnGetHeight)() + nReal, sal_True ); 4734 if ( nReal ) 4735 SetCompletePaint(); 4736 } 4737 4738 return nReal; 4739 } 4740 4741 /************************************************************************* 4742 |* 4743 |* SwRowFrm::ShrinkFrm() 4744 |* 4745 |* Ersterstellung MA 15. Mar. 93 4746 |* Letzte Aenderung MA 20. Jun. 96 4747 |* 4748 |*************************************************************************/ 4749 SwTwips SwRowFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo ) 4750 { 4751 SWRECTFN( this ) 4752 if( HasFixSize() ) 4753 { 4754 AdjustCells( (Prt().*fnRect->fnGetHeight)(), sal_True ); 4755 return 0L; 4756 } 4757 4758 //bInfo wird ggf. vom SwRowFrm::Format auf sal_True gesetzt, hier muss dann 4759 //entsprechend reagiert werden 4760 const sal_Bool bShrinkAnyway = bInfo; 4761 4762 //Nur soweit Shrinken, wie es der Inhalt der groessten Zelle zulaesst. 4763 SwTwips nRealDist = nDist; 4764 { 4765 const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize(); 4766 SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? 4767 rSz.GetHeight() : 4768 0; 4769 4770 // Only necessary to calculate minimal row height if height 4771 // of pRow is at least nMinHeight. Otherwise nMinHeight is the 4772 // minimum height. 4773 if( nMinHeight < (Frm().*fnRect->fnGetHeight)() ) 4774 { 4775 // --> OD 2004-10-04 #i26945# 4776 ASSERT( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." ); 4777 const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() ); 4778 // <-- 4779 nMinHeight = lcl_CalcMinRowHeight( this, bConsiderObjs ); 4780 } 4781 4782 if ( ((Frm().*fnRect->fnGetHeight)() - nRealDist) < nMinHeight ) 4783 nRealDist = (Frm().*fnRect->fnGetHeight)() - nMinHeight; 4784 } 4785 if ( nRealDist < 0 ) 4786 nRealDist = 0; 4787 4788 SwTwips nReal = nRealDist; 4789 if ( nReal ) 4790 { 4791 if ( !bTst ) 4792 { 4793 SwTwips nHeight = (Frm().*fnRect->fnGetHeight)(); 4794 (Frm().*fnRect->fnSetHeight)( nHeight - nReal ); 4795 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 4796 if( IsVertical() && !IsVertLR() && !bRev ) 4797 Frm().Pos().X() += nReal; 4798 } 4799 4800 SwTwips nTmp = GetUpper()->Shrink( nReal, bTst ); 4801 if ( !bShrinkAnyway && !GetNext() && nTmp != nReal ) 4802 { 4803 //Der letzte bekommt den Rest im Upper und nimmt deshalb 4804 //ggf. Ruecksichten (sonst: Endlosschleife) 4805 if ( !bTst ) 4806 { 4807 nReal -= nTmp; 4808 SwTwips nHeight = (Frm().*fnRect->fnGetHeight)(); 4809 (Frm().*fnRect->fnSetHeight)( nHeight + nReal ); 4810 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 4811 if( IsVertical() && !IsVertLR() && !bRev ) 4812 Frm().Pos().X() -= nReal; 4813 } 4814 nReal = nTmp; 4815 } 4816 } 4817 4818 //Geeignet invalidieren und die Hoehe der Zellen auf den neuesten 4819 //Stand bringen. 4820 if ( !bTst ) 4821 { 4822 if ( nReal ) 4823 { 4824 if ( GetNext() ) 4825 GetNext()->_InvalidatePos(); 4826 _InvalidateAll(); 4827 SetCompletePaint(); 4828 4829 SwTabFrm *pTab = FindTabFrm(); 4830 if ( !pTab->IsRebuildLastLine() && pTab->IsFollow() && 4831 this == pTab->GetFirstNonHeadlineRow() ) 4832 { 4833 SwTabFrm* pMasterTab = const_cast< SwTabFrm* >( pTab->FindMaster() ); 4834 pMasterTab->InvalidatePos(); 4835 } 4836 } 4837 AdjustCells( (Prt().*fnRect->fnGetHeight)() - nReal, sal_True ); 4838 } 4839 return nReal; 4840 } 4841 4842 /************************************************************************* 4843 |* 4844 |* SwRowFrm::IsRowSplitAllowed() 4845 |* 4846 |*************************************************************************/ 4847 bool SwRowFrm::IsRowSplitAllowed() const 4848 { 4849 // Fixed size rows are never allowed to split: 4850 if ( HasFixSize() ) 4851 { 4852 ASSERT( ATT_FIX_SIZE == GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" ) 4853 return false; 4854 } 4855 4856 // Repeated headlines are never allowed to split: 4857 const SwTabFrm* pTabFrm = FindTabFrm(); 4858 if ( pTabFrm->GetTable()->GetRowsToRepeat() > 0 && 4859 pTabFrm->IsInHeadline( *this ) ) 4860 return false; 4861 4862 const SwTableLineFmt* pFrmFmt = (SwTableLineFmt*)GetTabLine()->GetFrmFmt(); 4863 const SwFmtRowSplit& rLP = pFrmFmt->GetRowSplit(); 4864 return 0 != rLP.GetValue(); 4865 } 4866 4867 /************************************************************************* 4868 |* 4869 |* SwRowFrm::ShouldRowKeepWithNext() 4870 |* 4871 |*************************************************************************/ 4872 bool SwRowFrm::ShouldRowKeepWithNext() const 4873 { 4874 bool bRet = false; 4875 4876 const SwCellFrm* pCell = static_cast<const SwCellFrm*>(Lower()); 4877 const SwFrm* pTxt = pCell->Lower(); 4878 4879 if ( pTxt && pTxt->IsTxtFrm() ) 4880 { 4881 bRet = static_cast<const SwTxtFrm*>(pTxt)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue(); 4882 } 4883 return bRet; 4884 } 4885 4886 /************************************************************************* 4887 |* 4888 |* SwCellFrm::SwCellFrm(), ~SwCellFrm() 4889 |* 4890 |* Ersterstellung MA 09. Mar. 93 4891 |* Letzte Aenderung MA 30. May. 96 4892 |* 4893 |*************************************************************************/ 4894 SwCellFrm::SwCellFrm( const SwTableBox &rBox, SwFrm* pSib, bool bInsertContent ) : 4895 SwLayoutFrm( rBox.GetFrmFmt(), pSib ), 4896 pTabBox( &rBox ) 4897 { 4898 nType = FRMC_CELL; 4899 4900 if ( !bInsertContent ) 4901 return; 4902 4903 //Wenn ein StartIdx vorhanden ist, so werden CntntFrms in der Zelle 4904 //angelegt, andernfalls muessen Rows vorhanden sein und diese werden 4905 //angelegt. 4906 if ( rBox.GetSttIdx() ) 4907 { 4908 sal_uLong nIndex = rBox.GetSttIdx(); 4909 ::_InsertCnt( this, rBox.GetFrmFmt()->GetDoc(), ++nIndex ); 4910 } 4911 else 4912 { 4913 const SwTableLines &rLines = rBox.GetTabLines(); 4914 SwFrm *pTmpPrev = 0; 4915 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 4916 { 4917 SwRowFrm *pNew = new SwRowFrm( *rLines[i], this, bInsertContent ); 4918 pNew->InsertBehind( this, pTmpPrev ); 4919 pTmpPrev = pNew; 4920 } 4921 } 4922 } 4923 4924 SwCellFrm::~SwCellFrm() 4925 { 4926 SwModify* pMod = GetFmt(); 4927 if( pMod ) 4928 { 4929 // At this stage the lower frames aren't destroyed already, 4930 // therfor we have to do a recursive dispose. 4931 SwRootFrm *pRootFrm = getRootFrm(); 4932 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && 4933 pRootFrm->GetCurrShell() ) 4934 { 4935 pRootFrm->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, sal_True ); 4936 } 4937 4938 pMod->Remove( this ); // austragen, 4939 if( !pMod->GetDepends() ) 4940 delete pMod; // und loeschen 4941 } 4942 } 4943 4944 /************************************************************************* 4945 |* 4946 |* SwCellFrm::Format() 4947 |* 4948 |* Ersterstellung MA 09. Mar. 93 4949 |* Letzte Aenderung MA 29. Jan. 98 4950 |* 4951 |*************************************************************************/ 4952 sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva ) 4953 { 4954 sal_Bool bRet = sal_False; 4955 SwFrm *pFrm = pLay->Lower(); 4956 SWRECTFN( pLay ) 4957 while ( pFrm ) 4958 { 4959 long nFrmTop = (pFrm->Frm().*fnRect->fnGetTop)(); 4960 if( nFrmTop != lYStart ) 4961 { 4962 bRet = sal_True; 4963 const long lDiff = (*fnRect->fnYDiff)( lYStart, nFrmTop ); 4964 const long lDiffX = lYStart - nFrmTop; 4965 (pFrm->Frm().*fnRect->fnSubTop)( -lDiff ); 4966 (pFrm->Frm().*fnRect->fnAddBottom)( lDiff ); 4967 pFrm->SetCompletePaint(); 4968 if ( !pFrm->GetNext() ) 4969 pFrm->SetRetouche(); 4970 if( bInva ) 4971 pFrm->Prepare( PREP_POS_CHGD ); 4972 if ( pFrm->IsLayoutFrm() && ((SwLayoutFrm*)pFrm)->Lower() ) 4973 lcl_ArrangeLowers( (SwLayoutFrm*)pFrm, 4974 (((SwLayoutFrm*)pFrm)->Lower()->Frm().*fnRect->fnGetTop)() 4975 + lDiffX, bInva ); 4976 if ( pFrm->GetDrawObjs() ) 4977 { 4978 for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i ) 4979 { 4980 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i]; 4981 // --> OD 2004-10-08 #i26945# - check, if anchored object 4982 // is lower of layout frame by checking, if the anchor 4983 // frame, which contains the anchor position, is a lower 4984 // of the layout frame. 4985 if ( !pLay->IsAnLower( pAnchoredObj->GetAnchorFrmContainingAnchPos() ) ) 4986 { 4987 continue; 4988 } 4989 // <-- 4990 // --> OD 2005-08-08 #i52904# - distinguish between anchored 4991 // objects, whose vertical position depends on its anchor 4992 // frame and whose vertical position is independent 4993 // from its anchor frame. 4994 bool bVertPosDepOnAnchor( true ); 4995 { 4996 SwFmtVertOrient aVert( pAnchoredObj->GetFrmFmt().GetVertOrient() ); 4997 switch ( aVert.GetRelationOrient() ) 4998 { 4999 case text::RelOrientation::PAGE_FRAME: 5000 case text::RelOrientation::PAGE_PRINT_AREA: 5001 bVertPosDepOnAnchor = false; 5002 break; 5003 default: break; 5004 } 5005 } 5006 if ( pAnchoredObj->ISA(SwFlyFrm) ) 5007 { 5008 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 5009 5010 // OD 2004-05-18 #i28701# - no direct move of objects, 5011 // which are anchored to-paragraph/to-character, if 5012 // the wrapping style influence has to be considered 5013 // on the object positioning. 5014 // --> OD 2005-08-08 #i52904# - no direct move of objects, 5015 // whose vertical position doesn't depend on anchor frame. 5016 const bool bDirectMove = 5017 WEIT_WECH != pFly->Frm().Top() && 5018 bVertPosDepOnAnchor && 5019 !pFly->ConsiderObjWrapInfluenceOnObjPos(); 5020 // <-- 5021 if ( bDirectMove ) 5022 { 5023 (pFly->Frm().*fnRect->fnSubTop)( -lDiff ); 5024 (pFly->Frm().*fnRect->fnAddBottom)( lDiff ); 5025 pFly->GetVirtDrawObj()->SetRectsDirty(); 5026 // --> OD 2004-08-17 - also notify view of <SdrObject> 5027 // instance, which represents the Writer fly frame in 5028 // the drawing layer 5029 pFly->GetVirtDrawObj()->SetChanged(); 5030 // <-- 5031 // --> OD 2006-10-13 #i58280# 5032 pFly->InvalidateObjRectWithSpaces(); 5033 // <-- 5034 } 5035 5036 if ( pFly->IsFlyInCntFrm() ) 5037 { 5038 static_cast<SwFlyInCntFrm*>(pFly)->AddRefOfst( lDiff ); 5039 // --> OD 2004-12-02 #115759# - reset current relative 5040 // position to get re-positioned, if not directly moved. 5041 if ( !bDirectMove ) 5042 { 5043 pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) ); 5044 } 5045 // <-- 5046 } 5047 else if( pFly->IsAutoPos() ) 5048 { 5049 pFly->AddLastCharY( lDiff ); 5050 // OD 2004-05-18 #i28701# - follow-up of #i22341# 5051 // <mnLastTopOfLine> has also been adjusted. 5052 pFly->AddLastTopOfLineY( lDiff ); 5053 } 5054 // --> OD 2004-11-05 #i26945# - re-registration at 5055 // page frame of anchor frame, if table frame isn't 5056 // a follow table and table frame isn't in its 5057 // rebuild of last line. 5058 const SwTabFrm* pTabFrm = pLay->FindTabFrm(); 5059 // --> OD 2004-11-23 #115759# 5060 // - save: check, if table frame is found. 5061 if ( pTabFrm && 5062 !( pTabFrm->IsFollow() && 5063 pTabFrm->FindMaster()->IsRebuildLastLine() ) && 5064 pFly->IsFlyFreeFrm() ) 5065 // <-- 5066 { 5067 SwPageFrm* pPageFrm = pFly->GetPageFrm(); 5068 SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm(); 5069 if ( pPageFrm != pPageOfAnchor ) 5070 { 5071 pFly->InvalidatePos(); 5072 if ( pPageFrm ) 5073 pPageFrm->MoveFly( pFly, pPageOfAnchor ); 5074 else 5075 pPageOfAnchor->AppendFlyToPage( pFly ); 5076 } 5077 } 5078 // <-- 5079 // OD 2004-05-11 #i28701# - Because of the introduction 5080 // of new positionings and alignments (e.g. aligned at 5081 // page area, but anchored at-character), the position 5082 // of the Writer fly frame has to be invalidated. 5083 pFly->InvalidatePos(); 5084 5085 // --> OD 2004-11-04 #i26945# - follow-up of #i3317# 5086 // No arrangement of lowers, if Writer fly frame isn't 5087 // moved 5088 if ( bDirectMove && 5089 ::lcl_ArrangeLowers( pFly, 5090 (pFly->*fnRect->fnGetPrtTop)(), 5091 bInva ) ) 5092 // <-- 5093 { 5094 pFly->SetCompletePaint(); 5095 } 5096 } 5097 else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) ) 5098 { 5099 // --> OD 2004-11-05 #i26945# 5100 const SwTabFrm* pTabFrm = pLay->FindTabFrm(); 5101 if ( pTabFrm && 5102 !( pTabFrm->IsFollow() && 5103 pTabFrm->FindMaster()->IsRebuildLastLine() ) && 5104 !pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId() 5105 == FLY_AS_CHAR ) 5106 { 5107 SwPageFrm* pPageFrm = pAnchoredObj->GetPageFrm(); 5108 SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm(); 5109 if ( pPageFrm != pPageOfAnchor ) 5110 { 5111 pAnchoredObj->InvalidateObjPos(); 5112 if ( pPageFrm ) 5113 { 5114 pPageFrm->RemoveDrawObjFromPage( *pAnchoredObj ); 5115 } 5116 pPageOfAnchor->AppendDrawObjToPage( *pAnchoredObj ); 5117 } 5118 } 5119 // --> OD 2004-07-01 #i28701# - adjust last character 5120 // rectangle and last top of line. 5121 pAnchoredObj->AddLastCharY( lDiff ); 5122 pAnchoredObj->AddLastTopOfLineY( lDiff ); 5123 // --> OD 2005-08-08 #i52904# - re-introduce direct move 5124 // of drawing objects 5125 const bool bDirectMove = 5126 static_cast<const SwDrawFrmFmt&>(pAnchoredObj->GetFrmFmt()).IsPosAttrSet() && 5127 bVertPosDepOnAnchor && 5128 !pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos(); 5129 if ( bDirectMove ) 5130 { 5131 SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj ); 5132 if ( bVert ) 5133 { 5134 pAnchoredObj->DrawObj()->Move( Size( lDiff, 0 ) ); 5135 } 5136 else 5137 { 5138 pAnchoredObj->DrawObj()->Move( Size( 0, lDiff ) ); 5139 } 5140 // --> OD 2006-10-13 #i58280# 5141 pAnchoredObj->InvalidateObjRectWithSpaces(); 5142 // <-- 5143 } 5144 // <-- 5145 pAnchoredObj->InvalidateObjPos(); 5146 } 5147 else 5148 { 5149 ASSERT( false, 5150 "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" ); 5151 } 5152 } 5153 } 5154 } 5155 // Columns and cells are ordered horizontal, not vertical 5156 if( !pFrm->IsColumnFrm() && !pFrm->IsCellFrm() ) 5157 lYStart = (*fnRect->fnYInc)( lYStart, 5158 (pFrm->Frm().*fnRect->fnGetHeight)() ); 5159 5160 // Nowadays, the content inside a cell can flow into the follow table. 5161 // Thus, the cell may only grow up to the end of the environment. 5162 // So the content may have grown, but the cell could not grow. 5163 // Therefore we have to trigger a formatting for the frames, which do 5164 // not fit into the cell anymore: 5165 SwTwips nDistanceToUpperPrtBottom = 5166 (pFrm->Frm().*fnRect->fnBottomDist)( (pLay->*fnRect->fnGetPrtBottom)()); 5167 // --> OD 2006-01-19 #i56146# - Revise fix of issue #i26945# 5168 // do *not* consider content inside fly frames, if it's an undersized paragraph. 5169 // --> OD 2004-10-08 #i26945# - consider content inside fly frames 5170 if ( nDistanceToUpperPrtBottom < 0 && 5171 ( ( pFrm->IsInFly() && 5172 ( !pFrm->IsTxtFrm() || 5173 !static_cast<SwTxtFrm*>(pFrm)->IsUndersized() ) ) || 5174 pFrm->IsInSplitTableRow() ) ) 5175 // <-- 5176 { 5177 pFrm->InvalidatePos(); 5178 } 5179 5180 pFrm = pFrm->GetNext(); 5181 } 5182 return bRet; 5183 } 5184 5185 void SwCellFrm::Format( const SwBorderAttrs *pAttrs ) 5186 { 5187 ASSERT( pAttrs, "CellFrm::Format, pAttrs ist 0." ); 5188 const SwTabFrm* pTab = FindTabFrm(); 5189 SWRECTFN( pTab ) 5190 5191 if ( !bValidPrtArea ) 5192 { 5193 bValidPrtArea = sal_True; 5194 5195 //Position einstellen. 5196 if ( Lower() ) 5197 { 5198 SwTwips nTopSpace, nBottomSpace, nLeftSpace, nRightSpace; 5199 // --> collapsing borders FME 2005-05-27 #i29550# 5200 if ( pTab->IsCollapsingBorders() && !Lower()->IsRowFrm() ) 5201 { 5202 const SvxBoxItem& rBoxItem = pAttrs->GetBox(); 5203 nLeftSpace = rBoxItem.GetDistance( BOX_LINE_LEFT ); 5204 nRightSpace = rBoxItem.GetDistance( BOX_LINE_RIGHT ); 5205 nTopSpace = ((SwRowFrm*)GetUpper())->GetTopMarginForLowers(); 5206 nBottomSpace = ((SwRowFrm*)GetUpper())->GetBottomMarginForLowers(); 5207 } 5208 else 5209 { 5210 // <-- collapsing 5211 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)> 5212 nLeftSpace = pAttrs->CalcLeft( this ); 5213 nRightSpace = pAttrs->CalcRight( this ); 5214 nTopSpace = pAttrs->CalcTop(); 5215 nBottomSpace = pAttrs->CalcBottom(); 5216 } 5217 (this->*fnRect->fnSetXMargins)( nLeftSpace, nRightSpace ); 5218 (this->*fnRect->fnSetYMargins)( nTopSpace, nBottomSpace ); 5219 } 5220 } 5221 // --> OD 2004-10-04 #i26945# 5222 long nRemaining = GetTabBox()->getRowSpan() >= 1 ? 5223 ::lcl_CalcMinCellHeight( this, pTab->IsConsiderObjsForMinCellHeight(), pAttrs ) : 5224 0; 5225 // <-- 5226 if ( !bValidSize ) 5227 { 5228 bValidSize = sal_True; 5229 5230 //Die VarSize der CellFrms ist immer die Breite. 5231 //Tatsaechlich ist die Breite jedoch nicht Variabel, sie wird durch das 5232 //Format vorgegeben. Dieser Vorgegebene Wert muss aber nun wiederum 5233 //nicht der tatsaechlichen Breite entsprechen. Die Breite wird auf 5234 //Basis des Attributes errechnet, der Wert im Attribut passt zu dem 5235 //gewuenschten Wert des TabFrms. Anpassungen die dort vorgenommen 5236 //wurden werden hier Proportional beruecksichtigt. 5237 //Wenn die Celle keinen Nachbarn mehr hat beruecksichtigt sie nicht 5238 //die Attribute, sonder greift sich einfach den Rest des 5239 //Uppers 5240 SwTwips nWidth; 5241 if ( GetNext() ) 5242 { 5243 const SwTwips nWish = pTab->GetFmt()->GetFrmSize().GetWidth(); 5244 nWidth = pAttrs->GetSize().Width(); 5245 5246 ASSERT( nWish, "Tabelle ohne Breite?" ); 5247 ASSERT( nWidth <= nWish, "Zelle breiter als Tabelle." ); 5248 ASSERT( nWidth > 0, "Box without width" ); 5249 5250 const long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)(); 5251 if ( nWish != nPrtWidth ) 5252 { 5253 // Avoid rounding problems, at least for the new table model 5254 if ( pTab->GetTable()->IsNewModel() ) 5255 { 5256 // 1. sum of widths of cells up to this cell (in model) 5257 const SwTableLine* pTabLine = GetTabBox()->GetUpper(); 5258 const SwTableBoxes& rBoxes = pTabLine->GetTabBoxes(); 5259 const SwTableBox* pTmpBox = 0; 5260 5261 SwTwips nSumWidth = 0; 5262 sal_uInt16 i = 0; 5263 do 5264 { 5265 pTmpBox = rBoxes[ i++ ]; 5266 nSumWidth += pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth(); 5267 } 5268 while ( pTmpBox != GetTabBox() ); 5269 5270 // 2. calculate actual width of cells up to this one 5271 double nTmpWidth = nSumWidth; 5272 nTmpWidth *= nPrtWidth; 5273 nTmpWidth /= nWish; 5274 nWidth = (SwTwips)nTmpWidth; 5275 5276 // 3. calculate frame widths of cells up to this one: 5277 const SwFrm* pTmpCell = static_cast<const SwLayoutFrm*>(GetUpper())->Lower(); 5278 SwTwips nSumFrameWidths = 0; 5279 while ( pTmpCell != this ) 5280 { 5281 nSumFrameWidths += (pTmpCell->Frm().*fnRect->fnGetWidth)(); 5282 pTmpCell = pTmpCell->GetNext(); 5283 } 5284 5285 nWidth = nWidth - nSumFrameWidths; 5286 } 5287 else 5288 { 5289 // #i12092# use double instead of long, 5290 // otherwise this could lead to overflows 5291 double nTmpWidth = nWidth; 5292 nTmpWidth *= nPrtWidth; 5293 nTmpWidth /= nWish; 5294 nWidth = (SwTwips)nTmpWidth; 5295 } 5296 } 5297 } 5298 else 5299 { 5300 ASSERT( pAttrs->GetSize().Width() > 0, "Box without width" ); 5301 nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)(); 5302 SwFrm *pPre = GetUpper()->Lower(); 5303 while ( pPre != this ) 5304 { 5305 nWidth -= (pPre->Frm().*fnRect->fnGetWidth)(); 5306 pPre = pPre->GetNext(); 5307 } 5308 } 5309 const long nDiff = nWidth - (Frm().*fnRect->fnGetWidth)(); 5310 if( IsNeighbourFrm() && IsRightToLeft() ) 5311 (Frm().*fnRect->fnSubLeft)( nDiff ); 5312 else 5313 (Frm().*fnRect->fnAddRight)( nDiff ); 5314 (Prt().*fnRect->fnAddRight)( nDiff ); 5315 5316 //Jetzt die Hoehe einstellen, sie wird vom Inhalt und den Raendern 5317 //bestimmt. 5318 const long nDiffHeight = nRemaining - (Frm().*fnRect->fnGetHeight)(); 5319 if ( nDiffHeight ) 5320 { 5321 if ( nDiffHeight > 0 ) 5322 { 5323 //Wieder validieren wenn kein Wachstum stattgefunden hat. 5324 //Invalidiert wird durch AdjustCells von der Row. 5325 if ( !Grow( nDiffHeight ) ) 5326 bValidSize = bValidPrtArea = sal_True; 5327 } 5328 else 5329 { 5330 //Nur dann invalidiert lassen, wenn tatsaechlich 5331 //geshrinkt wurde; das kann abgelehnt werden, weil alle 5332 //nebeneinanderliegenden Zellen gleichgross sein muessen. 5333 if ( !Shrink( -nDiffHeight ) ) 5334 bValidSize = bValidPrtArea = sal_True; 5335 } 5336 } 5337 } 5338 const SwFmtVertOrient &rOri = pAttrs->GetAttrSet().GetVertOrient(); 5339 5340 if ( !Lower() ) 5341 return; 5342 5343 // From now on, all operations are related to the table cell. 5344 SWREFRESHFN( this ) 5345 5346 SwPageFrm* pPg = 0; 5347 if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE != rOri.GetVertOrient() && 5348 // --> OD 2008-07-16 #158225# no vertical alignment of covered cells 5349 !IsCoveredCell() && 5350 // <-- 5351 // --> FME 2004-06-29 #116532# Do not consider vertical alignment in grid mode 5352 !(pPg = FindPageFrm())->HasGrid() ) 5353 // <-- 5354 { 5355 if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() ) 5356 { 5357 //ASSERT fuer HTML-Import! 5358 ASSERT( !this, "VAlign an Zelle ohne Inhalt" ); 5359 return; 5360 } 5361 sal_Bool bVertDir = sal_True; 5362 // --> OD 2005-03-30 #i43913# - no vertical alignment, if wrapping 5363 // style influence is considered on object positioning and 5364 // an object is anchored inside the cell. 5365 const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ); 5366 // <-- 5367 //Keine Ausrichtung wenn Rahmen mit Umlauf in die Zelle ragen. 5368 if ( pPg->GetSortedObjs() ) 5369 { 5370 SwRect aRect( Prt() ); aRect += Frm().Pos(); 5371 for ( sal_uInt16 i = 0; i < pPg->GetSortedObjs()->Count(); ++i ) 5372 { 5373 const SwAnchoredObject* pAnchoredObj = (*pPg->GetSortedObjs())[i]; 5374 SwRect aTmp( pAnchoredObj->GetObjRect() ); 5375 if ( aTmp.IsOver( aRect ) ) 5376 { 5377 const SwFrmFmt& rAnchoredObjFrmFmt = pAnchoredObj->GetFrmFmt(); 5378 const SwFmtSurround &rSur = rAnchoredObjFrmFmt.GetSurround(); 5379 5380 if ( SURROUND_THROUGHT != rSur.GetSurround() ) 5381 { 5382 // frames, which the cell is a lower of, aren't relevant 5383 if ( pAnchoredObj->ISA(SwFlyFrm) ) 5384 { 5385 const SwFlyFrm *pFly = 5386 static_cast<const SwFlyFrm*>(pAnchoredObj); 5387 if ( pFly->IsAnLower( this ) ) 5388 continue; 5389 } 5390 5391 const SwFrm* pAnch = pAnchoredObj->GetAnchorFrm(); 5392 // --> OD 2005-03-30 #i43913# 5393 // --> OD 2005-08-08 #i52904# - no vertical alignment, 5394 // if object, anchored inside cell, has temporarly 5395 // consider its wrapping style on object positioning. 5396 // --> FME 2006-02-01 #i58806# - no vertical alignment 5397 // if object does not follow the text flow. 5398 if ( bConsiderWrapOnObjPos || 5399 !IsAnLower( pAnch ) || 5400 pAnchoredObj->IsTmpConsiderWrapInfluence() || 5401 !rAnchoredObjFrmFmt.GetFollowTextFlow().GetValue() ) 5402 // <-- 5403 { 5404 bVertDir = sal_False; 5405 break; 5406 } 5407 } 5408 } 5409 } 5410 } 5411 5412 long nPrtHeight = (Prt().*fnRect->fnGetHeight)(); 5413 if( ( bVertDir && ( nRemaining -= lcl_CalcTopAndBottomMargin( *this, *pAttrs ) ) < nPrtHeight ) || 5414 (Lower()->Frm().*fnRect->fnGetTop)() != (this->*fnRect->fnGetPrtTop)() ) 5415 { 5416 long lTopOfst = 0, 5417 nDiff = (Prt().*fnRect->fnGetHeight)() - nRemaining; 5418 if ( nDiff >= 0 ) 5419 { 5420 if ( bVertDir ) 5421 { 5422 switch ( rOri.GetVertOrient() ) 5423 { 5424 case text::VertOrientation::CENTER: lTopOfst = nDiff / 2; break; 5425 case text::VertOrientation::BOTTOM: lTopOfst = nDiff; break; 5426 default: break; 5427 }; 5428 } 5429 long nTmp = (*fnRect->fnYInc)( 5430 (this->*fnRect->fnGetPrtTop)(), lTopOfst ); 5431 if ( lcl_ArrangeLowers( this, nTmp, !bVertDir ) ) 5432 SetCompletePaint(); 5433 } 5434 } 5435 } 5436 else 5437 { 5438 //Ist noch eine alte Ausrichtung beruecksichtigt worden? 5439 if ( Lower()->IsCntntFrm() ) 5440 { 5441 const long lYStart = (this->*fnRect->fnGetPrtTop)(); 5442 lcl_ArrangeLowers( this, lYStart, sal_True ); 5443 } 5444 } 5445 } 5446 5447 /************************************************************************* 5448 |* 5449 |* SwCellFrm::Modify() 5450 |* 5451 |* Ersterstellung MA 20. Dec. 96 5452 |* Letzte Aenderung MA 20. Dec. 96 5453 |* 5454 |*************************************************************************/ 5455 5456 void SwCellFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) 5457 { 5458 sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which(); 5459 const SfxPoolItem *pItem = 0; 5460 5461 if( bAttrSetChg ) 5462 ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_VERT_ORIENT, sal_False, &pItem); 5463 else if ( RES_VERT_ORIENT == pNew->Which() ) 5464 pItem = pNew; 5465 5466 if ( pItem ) 5467 { 5468 sal_Bool bInva = sal_True; 5469 if ( text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() && 5470 // OD 04.11.2003 #112910# 5471 Lower() && Lower()->IsCntntFrm() ) 5472 { 5473 SWRECTFN( this ) 5474 const long lYStart = (this->*fnRect->fnGetPrtTop)(); 5475 bInva = lcl_ArrangeLowers( this, lYStart, sal_False ); 5476 } 5477 if ( bInva ) 5478 { 5479 SetCompletePaint(); 5480 InvalidatePrt(); 5481 } 5482 } 5483 5484 if ( ( bAttrSetChg && 5485 SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_PROTECT, sal_False ) ) || 5486 RES_PROTECT == pNew->Which() ) 5487 { 5488 ViewShell *pSh = getRootFrm()->GetCurrShell(); 5489 if( pSh && pSh->GetLayout()->IsAnyShellAccessible() ) 5490 pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this ); 5491 } 5492 5493 if ( bAttrSetChg && 5494 SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_FRAMEDIR, sal_False, &pItem ) ) 5495 { 5496 SetDerivedVert( sal_False ); 5497 CheckDirChange(); 5498 } 5499 5500 // --> collapsing borders FME 2005-05-27 #i29550# 5501 if ( bAttrSetChg && 5502 SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_BOX, sal_False, &pItem ) ) 5503 { 5504 SwFrm* pTmpUpper = GetUpper(); 5505 while ( pTmpUpper->GetUpper() && !pTmpUpper->GetUpper()->IsTabFrm() ) 5506 pTmpUpper = pTmpUpper->GetUpper(); 5507 5508 SwTabFrm* pTabFrm = (SwTabFrm*)pTmpUpper->GetUpper(); 5509 if ( pTabFrm->IsCollapsingBorders() ) 5510 { 5511 // Invalidate lowers of this and next row: 5512 lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper ); 5513 pTmpUpper = pTmpUpper->GetNext(); 5514 if ( pTmpUpper ) 5515 lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper ); 5516 else 5517 pTabFrm->InvalidatePrt(); 5518 } 5519 } 5520 // <-- collapsing 5521 5522 SwLayoutFrm::Modify( pOld, pNew ); 5523 } 5524 5525 /************************************************************************* 5526 |* SwCellFrm::GetLayoutRowSpan() const 5527 |*************************************************************************/ 5528 5529 long SwCellFrm::GetLayoutRowSpan() const 5530 { 5531 long nRet = GetTabBox()->getRowSpan(); 5532 if ( nRet < 1 ) 5533 { 5534 const SwFrm* pRow = GetUpper(); 5535 const SwTabFrm* pTab = static_cast<const SwTabFrm*>(pRow->GetUpper()); 5536 5537 if ( pTab && pTab->IsFollow() && pRow == pTab->GetFirstNonHeadlineRow() ) 5538 nRet = -nRet; 5539 } 5540 return nRet; 5541 } 5542 5543 // --> OD 2010-02-17 #i103961# 5544 void SwCellFrm::Cut() 5545 { 5546 // notification for accessibility 5547 { 5548 SwRootFrm *pRootFrm = getRootFrm(); 5549 if( pRootFrm && pRootFrm->IsAnyShellAccessible() ) 5550 { 5551 ViewShell* pVSh = pRootFrm->GetCurrShell(); 5552 if ( pVSh && pVSh->Imp() ) 5553 { 5554 pVSh->Imp()->DisposeAccessibleFrm( this ); 5555 } 5556 } 5557 } 5558 5559 SwLayoutFrm::Cut(); 5560 } 5561 // <-- 5562 5563 // 5564 // Helper functions for repeated headlines: 5565 // 5566 5567 /* 5568 * SwTabFrm::IsInHeadline( const SwFrm& rFrm ) 5569 */ 5570 bool SwTabFrm::IsInHeadline( const SwFrm& rFrm ) const 5571 { 5572 ASSERT( IsAnLower( &rFrm ) && rFrm.IsInTab(), 5573 "SwTabFrm::IsInHeadline called for frame not lower of table" ) 5574 5575 const SwFrm* pTmp = &rFrm; 5576 while ( !pTmp->GetUpper()->IsTabFrm() ) 5577 pTmp = pTmp->GetUpper(); 5578 5579 return GetTable()->IsHeadline( *((SwRowFrm*)pTmp)->GetTabLine() ); 5580 } 5581 5582 /* 5583 * SwTabFrm::GetFirstNonHeadlineRow() 5584 * 5585 * If this is a master table, we can may assume, that there are at least 5586 * nRepeat lines in the table. 5587 * If this is a follow table, there are intermediate states for the table 5588 * layout, e.g., during deletion of rows, which makes it necessary to find 5589 * the first non-headline row by evaluating the headline flag at the row frame. 5590 */ 5591 SwRowFrm* SwTabFrm::GetFirstNonHeadlineRow() const 5592 { 5593 SwRowFrm* pRet = (SwRowFrm*)Lower(); 5594 if ( pRet ) 5595 { 5596 if ( IsFollow() ) 5597 { 5598 while ( pRet && pRet->IsRepeatedHeadline() ) 5599 pRet = (SwRowFrm*)pRet->GetNext(); 5600 } 5601 else 5602 { 5603 sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat(); 5604 while ( pRet && nRepeat > 0 ) 5605 { 5606 pRet = (SwRowFrm*)pRet->GetNext(); 5607 --nRepeat; 5608 } 5609 } 5610 } 5611 5612 return (SwRowFrm*)pRet; 5613 } 5614 5615 /* 5616 * SwTable::IsHeadline() 5617 */ 5618 bool SwTable::IsHeadline( const SwTableLine& rLine ) const 5619 { 5620 for ( sal_uInt16 i = 0; i < GetRowsToRepeat(); ++i ) 5621 if ( GetTabLines()[ i ] == &rLine ) 5622 return true; 5623 5624 return false; 5625 } 5626 5627 bool SwTabFrm::IsLayoutSplitAllowed() const 5628 { 5629 return GetFmt()->GetLayoutSplit().GetValue(); 5630 } 5631 5632 // --> collapsing borders FME 2005-05-27 #i29550# 5633 5634 sal_uInt16 SwTabFrm::GetBottomLineSize() const 5635 { 5636 ASSERT( IsCollapsingBorders(), 5637 "BottomLineSize only required for collapsing borders" ) 5638 5639 ASSERT( Lower(), "Warning! Trying to prevent a crash, please inform FME" ) 5640 5641 const SwFrm* pTmp = GetLastLower(); 5642 5643 // --> FME 2005-12-07 #124755# Try to make code robust: 5644 if ( !pTmp ) return 0; 5645 // <-- 5646 5647 return static_cast<const SwRowFrm*>(pTmp)->GetBottomLineSize(); 5648 } 5649 5650 bool SwTabFrm::IsCollapsingBorders() const 5651 { 5652 return ((SfxBoolItem&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS )).GetValue(); 5653 } 5654 5655 // <-- collapsing 5656 5657 5658 // 5659 // Local helper function to calculate height of first text row 5660 // 5661 SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrm& rSourceLine ) 5662 { 5663 // Find corresponding split line in master table 5664 const SwTabFrm* pTab = rSourceLine.FindTabFrm(); 5665 SWRECTFN( pTab ) 5666 const SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower(); 5667 5668 // 5669 // 1. Case: rSourceLine is a follow flow line. 5670 // In this case we have to return the minimum of the heights 5671 // of the first lines in rSourceLine. 5672 // 5673 // 2. Case: rSourceLine is not a follow flow line. 5674 // In this case we have to return the maximum of the heights 5675 // of the first lines in rSourceLine. 5676 // 5677 bool bIsInFollowFlowLine = rSourceLine.IsInFollowFlowRow(); 5678 SwTwips nHeight = bIsInFollowFlowLine ? LONG_MAX : 0; 5679 5680 while ( pCurrSourceCell ) 5681 { 5682 // NEW TABLES 5683 // Skip cells which are not responsible for the height of 5684 // the follow flow line: 5685 if ( bIsInFollowFlowLine && pCurrSourceCell->GetLayoutRowSpan() > 1 ) 5686 { 5687 pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext(); 5688 continue; 5689 } 5690 5691 const SwFrm *pTmp = pCurrSourceCell->Lower(); 5692 if ( pTmp ) 5693 { 5694 SwTwips nTmpHeight = USHRT_MAX; 5695 // --> FME 2004-09-14 #i32456# Consider lower row frames 5696 if ( pTmp->IsRowFrm() ) 5697 { 5698 const SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower(); 5699 nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow ); 5700 } 5701 // <-- 5702 if ( pTmp->IsTabFrm() ) 5703 { 5704 nTmpHeight = ((SwTabFrm*)pTmp)->CalcHeightOfFirstContentLine(); 5705 } 5706 else if ( pTmp->IsTxtFrm() ) 5707 { 5708 SwTxtFrm* pTxtFrm = (SwTxtFrm*)pTmp; 5709 pTxtFrm->GetFormatted(); 5710 nTmpHeight = pTxtFrm->FirstLineHeight(); 5711 } 5712 5713 if ( USHRT_MAX != nTmpHeight ) 5714 { 5715 const SwCellFrm* pPrevCell = pCurrSourceCell->GetPreviousCell(); 5716 if ( pPrevCell ) 5717 { 5718 // If we are in a split row, there may be some space 5719 // left in the cell frame of the master row. 5720 // We look for the minimum of all first line heights; 5721 SwTwips nReal = (pPrevCell->Prt().*fnRect->fnGetHeight)(); 5722 const SwFrm* pFrm = pPrevCell->Lower(); 5723 const SwFrm* pLast = pFrm; 5724 while ( pFrm ) 5725 { 5726 nReal -= (pFrm->Frm().*fnRect->fnGetHeight)(); 5727 pLast = pFrm; 5728 pFrm = pFrm->GetNext(); 5729 } 5730 5731 // --> FME, OD 2004-07-15 #i26831#, #i26520# 5732 // The additional lower space of the current last. 5733 // --> OD 2004-11-25 #115759# - do *not* consider the 5734 // additional lower space for 'master' text frames 5735 if ( pLast && pLast->IsFlowFrm() && 5736 ( !pLast->IsTxtFrm() || 5737 !static_cast<const SwTxtFrm*>(pLast)->GetFollow() ) ) 5738 // <-- 5739 { 5740 nReal += SwFlowFrm::CastFlowFrm(pLast)->CalcAddLowerSpaceAsLastInTableCell(); 5741 } 5742 // Don't forget the upper space and lower space, 5743 // --> OD 2004-11-25 #115759# - do *not* consider the upper 5744 // and the lower space for follow text frames. 5745 if ( pTmp->IsFlowFrm() && 5746 ( !pTmp->IsTxtFrm() || 5747 !static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) ) 5748 { 5749 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace( NULL, pLast); 5750 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace(); 5751 } 5752 // <-- 5753 // --> OD 2004-11-25 #115759# - consider additional lower 5754 // space of <pTmp>, if contains only one line. 5755 // In this case it would be the new last text frame, which 5756 // would have no follow and thus would add this space. 5757 if ( pTmp->IsTxtFrm() && 5758 const_cast<SwTxtFrm*>(static_cast<const SwTxtFrm*>(pTmp)) 5759 ->GetLineCount( STRING_LEN ) == 1 ) 5760 { 5761 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp) 5762 ->CalcAddLowerSpaceAsLastInTableCell(); 5763 } 5764 // <-- 5765 if ( nReal > 0 ) 5766 nTmpHeight -= nReal; 5767 } 5768 else 5769 { 5770 // pFirstRow is not a FollowFlowRow. In this case, 5771 // we look for the maximum of all first line heights: 5772 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCurrSourceCell ); 5773 const SwBorderAttrs &rAttrs = *aAccess.Get(); 5774 nTmpHeight += rAttrs.CalcTop() + rAttrs.CalcBottom(); 5775 // --> OD 2004-07-16 #i26250# 5776 // Don't forget the upper space and lower space, 5777 if ( pTmp->IsFlowFrm() ) 5778 { 5779 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace(); 5780 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace(); 5781 } 5782 // <-- 5783 } 5784 } 5785 5786 if ( bIsInFollowFlowLine ) 5787 { 5788 // minimum 5789 if ( nTmpHeight < nHeight ) 5790 nHeight = nTmpHeight; 5791 } 5792 else 5793 { 5794 // maximum 5795 if ( nTmpHeight > nHeight && USHRT_MAX != nTmpHeight ) 5796 nHeight = nTmpHeight; 5797 } 5798 } 5799 5800 pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext(); 5801 } 5802 5803 return ( LONG_MAX == nHeight ) ? 0 : nHeight; 5804 } 5805 5806 // 5807 // Function to calculate height of first text row 5808 // 5809 SwTwips SwTabFrm::CalcHeightOfFirstContentLine() const 5810 { 5811 SWRECTFN( this ) 5812 5813 const bool bDontSplit = !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue(); 5814 5815 if ( bDontSplit ) 5816 { 5817 // Table is not allowed to split: Take the whole height, that's all 5818 return (Frm().*fnRect->fnGetHeight)(); 5819 } 5820 5821 SwRowFrm* pFirstRow = 0; 5822 SwTwips nTmpHeight = 0; 5823 5824 pFirstRow = GetFirstNonHeadlineRow(); 5825 ASSERT( !IsFollow() || pFirstRow, "FollowTable without Lower" ) 5826 5827 // NEW TABLES 5828 if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() ) 5829 pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext()); 5830 5831 // Calculate the height of the headlines: 5832 const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat(); 5833 SwTwips nRepeatHeight = nRepeat ? lcl_GetHeightOfRows( GetLower(), nRepeat ) : 0; 5834 5835 // Calculate the height of the keeping lines 5836 // (headlines + following keeping lines): 5837 SwTwips nKeepHeight = nRepeatHeight; 5838 if ( GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) ) 5839 { 5840 sal_uInt16 nKeepRows = nRepeat; 5841 5842 // Check how many rows want to keep together 5843 while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() ) 5844 { 5845 ++nKeepRows; 5846 pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext()); 5847 } 5848 5849 if ( nKeepRows > nRepeat ) 5850 nKeepHeight = lcl_GetHeightOfRows( GetLower(), nKeepRows ); 5851 } 5852 5853 // For master tables, the height of the headlines + the heigth of the 5854 // keeping lines (if any) has to be considered. For follow tables, we 5855 // only consider the height of the keeping rows without the repeated lines: 5856 if ( !IsFollow() ) 5857 { 5858 nTmpHeight = nKeepHeight; 5859 } 5860 else 5861 { 5862 nTmpHeight = nKeepHeight - nRepeatHeight; 5863 } 5864 5865 // pFirstRow row is the first non-heading row. 5866 // nTmpHeight is the height of the heading row if we are a follow. 5867 if ( pFirstRow ) 5868 { 5869 const bool bSplittable = pFirstRow->IsRowSplitAllowed(); 5870 const SwTwips nFirstLineHeight = (pFirstRow->Frm().*fnRect->fnGetHeight)(); 5871 5872 if ( !bSplittable ) 5873 { 5874 // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow 5875 // actually is determined by a lower cell with rowspan = -1. In this case we should not 5876 // just return the height of the first line. Basically we need to get the height of the 5877 // line as it would be on the last page. Since this is quite complicated to calculate, 5878 // we olny calculate the height of the first line. 5879 if ( pFirstRow->GetPrev() && 5880 static_cast<SwRowFrm*>(pFirstRow->GetPrev())->IsRowSpanLine() ) 5881 { 5882 // Calculate maximum height of all cells with rowspan = 1: 5883 SwTwips nMaxHeight = 0; 5884 const SwCellFrm* pLower2 = static_cast<const SwCellFrm*>(pFirstRow->Lower()); 5885 while ( pLower2 ) 5886 { 5887 if ( 1 == pLower2->GetTabBox()->getRowSpan() ) 5888 { 5889 const SwTwips nCellHeight = lcl_CalcMinCellHeight( pLower2, sal_True ); 5890 nMaxHeight = Max( nCellHeight, nMaxHeight ); 5891 } 5892 pLower2 = static_cast<const SwCellFrm*>(pLower2->GetNext()); 5893 } 5894 nTmpHeight += nMaxHeight; 5895 } 5896 else 5897 { 5898 nTmpHeight += nFirstLineHeight; 5899 } 5900 } 5901 5902 // --> FME 2004-11-18 #118411# 5903 // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger 5904 // a formatting of the row frame (via the GetFormatted()). We don't 5905 // want this formatting if the row does not have a height. 5906 else if ( 0 != nFirstLineHeight ) 5907 // <-- 5908 { 5909 const bool bOldJoinLock = IsJoinLocked(); 5910 ((SwTabFrm*)this)->LockJoin(); 5911 const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *(SwRowFrm*)pFirstRow ); 5912 5913 // Consider minimum row height: 5914 const SwFmtFrmSize &rSz = static_cast<const SwRowFrm*>(pFirstRow)->GetFmt()->GetFrmSize(); 5915 const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? 5916 rSz.GetHeight() : 0; 5917 5918 nTmpHeight += Max( nHeightOfFirstContentLine, nMinRowHeight ); 5919 5920 if ( !bOldJoinLock ) 5921 ((SwTabFrm*)this)->UnlockJoin(); 5922 } 5923 } 5924 5925 return nTmpHeight; 5926 } 5927 5928 // 5929 // Some more functions for covered/covering cells. This way inclusion of 5930 // SwCellFrm can be avoided 5931 // 5932 5933 bool SwFrm::IsLeaveUpperAllowed() const 5934 { 5935 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this); 5936 return pThisCell && pThisCell->GetLayoutRowSpan() > 1; 5937 } 5938 5939 bool SwFrm::IsCoveredCell() const 5940 { 5941 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this); 5942 return pThisCell && pThisCell->GetLayoutRowSpan() < 1; 5943 } 5944 5945 bool SwFrm::IsInCoveredCell() const 5946 { 5947 bool bRet = false; 5948 5949 const SwFrm* pThis = this; 5950 while ( pThis && !pThis->IsCellFrm() ) 5951 pThis = pThis->GetUpper(); 5952 5953 if ( pThis ) 5954 bRet = pThis->IsCoveredCell(); 5955 5956 return bRet; 5957 } 5958 5959