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 void SwTabFrm::MakeAll() 1879 { 1880 if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 ) 1881 return; 1882 1883 if ( HasFollow() ) 1884 { 1885 SwTabFrm* pFollowFrm = (SwTabFrm*)GetFollow(); 1886 ASSERT( !pFollowFrm->IsJoinLocked() || !pFollowFrm->IsRebuildLastLine(), 1887 "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" ) 1888 if ( pFollowFrm->IsJoinLocked() && pFollowFrm->IsRebuildLastLine() ) 1889 return; 1890 } 1891 1892 PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 ) 1893 1894 LockJoin(); //Ich lass mich nicht unterwegs vernichten. 1895 SwLayNotify aNotify( this ); //uebernimmt im DTor die Benachrichtigung 1896 // If pos is invalid, we have to call a SetInvaKeep at aNotify. 1897 // Otherwise the keep atribute would not work in front of a table. 1898 const sal_Bool bOldValidPos = GetValidPosFlag(); 1899 1900 //Wenn mein direkter Nachbar gleichzeitig mein Follow ist 1901 //verleibe ich mir das Teil ein. 1902 // OD 09.04.2003 #108698# - join all follows, which are placed on the 1903 // same page/column. 1904 // OD 29.04.2003 #109213# - join follow, only if join for the follow 1905 // is not locked. Otherwise, join will not be performed and this loop 1906 // will be endless. 1907 while ( GetNext() && GetNext() == GetFollow() && 1908 !GetFollow()->IsJoinLocked() 1909 ) 1910 { 1911 if ( HasFollowFlowLine() ) 1912 RemoveFollowFlowLine(); 1913 Join(); 1914 } 1915 1916 // The bRemoveFollowFlowLinePending is set if the split attribute of the 1917 // last line is set: 1918 if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() ) 1919 { 1920 if ( RemoveFollowFlowLine() ) 1921 Join(); 1922 SetRemoveFollowFlowLinePending( sal_False ); 1923 } 1924 1925 if ( bResizeHTMLTable ) //Optimiertes Zusammenspiel mit Grow/Shrink des Inhaltes 1926 { 1927 bResizeHTMLTable = sal_False; 1928 SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout(); 1929 if ( pLayout ) 1930 bCalcLowers = pLayout->Resize( 1931 pLayout->GetBrowseWidthByTabFrm( *this ), sal_False ); 1932 } 1933 1934 1935 sal_Bool bMakePage = sal_True; //solange sal_True kann eine neue Seite 1936 //angelegt werden (genau einmal) 1937 sal_Bool bMovedBwd = sal_False; //Wird sal_True wenn der Frame zurueckfliesst 1938 sal_Bool bMovedFwd = sal_False; //solange sal_False kann der Frm zurueck- 1939 //fliessen (solange, bis er einmal 1940 //vorwaerts ge'moved wurde). 1941 sal_Bool bSplit = sal_False; //Wird sal_True wenn der Frm gesplittet wurde. 1942 const sal_Bool bFtnsInDoc = 0 != GetFmt()->GetDoc()->GetFtnIdxs().Count(); 1943 sal_Bool bMoveable; 1944 const sal_Bool bFly = IsInFly(); 1945 1946 SwBorderAttrAccess *pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this ); 1947 const SwBorderAttrs *pAttrs = pAccess->Get(); 1948 1949 // The beloved keep attribute 1950 const bool bKeep = IsKeep( pAttrs->GetAttrSet() ); 1951 1952 // All rows should keep together 1953 // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next 1954 const bool bDontSplit = !IsFollow() && 1955 ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep ); 1956 1957 // The number of repeated headlines 1958 const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat(); 1959 1960 // This flag indicates that we are allowed to try to split the 1961 // table rows. 1962 bool bTryToSplit = true; 1963 1964 // --> FME 2006-02-16 #131283# 1965 // Indicates that two individual rows may keep together, based on the keep 1966 // attribute set at the first paragraph in the first cell. 1967 const bool bTableRowKeep = !bDontSplit && GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP); 1968 1969 // The Magic Move: Used for the table row keep feature. 1970 // If only the last row of the table wants to keep (implicitely by setting 1971 // keep for the first paragraph in the first cell), and this table does 1972 // not have a next, the last line will be cut. Loop prevention: Only 1973 // one try. 1974 bool bLastRowHasToMoveToFollow = false; 1975 bool bLastRowMoveNoMoreTries = false; 1976 1977 // Join follow table, if this table is not allowed to split: 1978 if ( bDontSplit ) 1979 { 1980 while ( GetFollow() && !GetFollow()->IsJoinLocked() ) 1981 { 1982 if ( HasFollowFlowLine() ) 1983 RemoveFollowFlowLine(); 1984 Join(); 1985 } 1986 } 1987 1988 // Join follow table, if this does not have enough (repeated) lines: 1989 if ( nRepeat ) 1990 { 1991 if( GetFollow() && !GetFollow()->IsJoinLocked() && 1992 0 == GetFirstNonHeadlineRow() ) 1993 { 1994 if ( HasFollowFlowLine() ) 1995 RemoveFollowFlowLine(); 1996 Join(); 1997 } 1998 } 1999 2000 // Join follow table, if last row of this table should keep: 2001 if ( bTableRowKeep && GetFollow() && !GetFollow()->IsJoinLocked() ) 2002 { 2003 const SwRowFrm* pTmpRow = static_cast<const SwRowFrm*>(GetLastLower()); 2004 if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() ) 2005 { 2006 if ( HasFollowFlowLine() ) 2007 RemoveFollowFlowLine(); 2008 Join(); 2009 } 2010 } 2011 2012 //Einen Frischling moven wir gleich schon einmal vorwaerts... 2013 if ( !Frm().Top() && IsFollow() ) 2014 { 2015 SwFrm *pPre = GetPrev(); 2016 if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this) 2017 { 2018 if ( !MoveFwd( bMakePage, sal_False ) ) 2019 bMakePage = sal_False; 2020 bMovedFwd = sal_True; 2021 } 2022 } 2023 2024 int nUnSplitted = 5; // Just another loop control :-( 2025 SWRECTFN( this ) 2026 while ( !bValidPos || !bValidSize || !bValidPrtArea ) 2027 { 2028 if ( sal_True == (bMoveable = IsMoveable()) ) 2029 if ( CheckMoveFwd( bMakePage, bKeep && KEEPTAB, bMovedBwd ) ) 2030 { 2031 bMovedFwd = sal_True; 2032 bCalcLowers = sal_True; 2033 // --> OD 2009-08-12 #i99267# 2034 // reset <bSplit> after forward move to assure that follows 2035 // can be joined, if further space is available. 2036 bSplit = sal_False; 2037 // <-- 2038 } 2039 2040 Point aOldPos( (Frm().*fnRect->fnGetPos)() ); 2041 MakePos(); 2042 2043 if ( aOldPos != (Frm().*fnRect->fnGetPos)() ) 2044 { 2045 if ( aOldPos.Y() != (Frm().*fnRect->fnGetTop)() ) 2046 { 2047 SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout(); 2048 if( pLayout ) 2049 { 2050 delete pAccess; 2051 bCalcLowers |= pLayout->Resize( 2052 pLayout->GetBrowseWidthByTabFrm( *this ), sal_False ); 2053 pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this ); 2054 pAttrs = pAccess->Get(); 2055 } 2056 2057 bValidPrtArea = sal_False; 2058 aNotify.SetLowersComplete( sal_False ); 2059 } 2060 SwFrm *pPre; 2061 if ( bKeep || (0 != (pPre = FindPrev()) && 2062 pPre->GetAttrSet()->GetKeep().GetValue()) ) 2063 { 2064 bCalcLowers = sal_True; 2065 } 2066 } 2067 2068 //Wir muessen die Hoehe der ersten Zeile kennen, denn nur wenn diese 2069 //kleiner wird muss ggf. der Master angestossen werden um noetigenfalls 2070 //die Zeile aufzunehmen. 2071 long n1StLineHeight = 0; 2072 if ( IsFollow() ) 2073 { 2074 SwFrm* pFrm = GetFirstNonHeadlineRow(); 2075 if ( pFrm ) 2076 n1StLineHeight = (pFrm->Frm().*fnRect->fnGetHeight)(); 2077 } 2078 2079 if ( !bValidSize || !bValidPrtArea ) 2080 { 2081 const long nOldPrtWidth = (Prt().*fnRect->fnGetWidth)(); 2082 const long nOldFrmWidth = (Frm().*fnRect->fnGetWidth)(); 2083 const Point aOldPrtPos = (Prt().*fnRect->fnGetPos)(); 2084 Format( pAttrs ); 2085 2086 SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout(); 2087 if ( pLayout && 2088 ((Prt().*fnRect->fnGetWidth)() != nOldPrtWidth || 2089 (Frm().*fnRect->fnGetWidth)() != nOldFrmWidth) ) 2090 { 2091 delete pAccess; 2092 bCalcLowers |= pLayout->Resize( 2093 pLayout->GetBrowseWidthByTabFrm( *this ), sal_False ); 2094 // GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() ? sal_False : sal_True ); 2095 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this ); 2096 pAttrs = pAccess->Get(); 2097 } 2098 if ( aOldPrtPos != (Prt().*fnRect->fnGetPos)() ) 2099 aNotify.SetLowersComplete( sal_False ); 2100 } 2101 2102 //Wenn ich der erste einer Kette bin koennte ich mal sehen ob 2103 //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll). 2104 //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts 2105 //geflosssen sein. 2106 if ( !bMovedFwd && (bMoveable || bFly) && lcl_NoPrev( *this ) ) 2107 { 2108 //Bei Follows muss der Master benachrichtigt 2109 //werden. Der Follow muss nur dann Moven, wenn er leere Blaetter 2110 //ueberspringen muss. 2111 if ( IsFollow() ) 2112 { 2113 //Nur wenn die Hoehe der ersten Zeile kleiner geworder ist. 2114 SwFrm *pFrm = GetFirstNonHeadlineRow(); 2115 if( pFrm && n1StLineHeight >(pFrm->Frm().*fnRect->fnGetHeight )() ) 2116 { 2117 SwTabFrm *pMaster = (SwTabFrm*)FindMaster(); 2118 sal_Bool bDummy; 2119 if ( ShouldBwdMoved( pMaster->GetUpper(), sal_False, bDummy ) ) 2120 pMaster->InvalidatePos(); 2121 } 2122 } 2123 SwFtnBossFrm *pOldBoss = bFtnsInDoc ? FindFtnBossFrm( sal_True ) : 0; 2124 sal_Bool bReformat; 2125 if ( MoveBwd( bReformat ) ) 2126 { 2127 SWREFRESHFN( this ) 2128 bMovedBwd = sal_True; 2129 aNotify.SetLowersComplete( sal_False ); 2130 if ( bFtnsInDoc ) 2131 MoveLowerFtns( 0, pOldBoss, 0, sal_True ); 2132 if ( bReformat || bKeep ) 2133 { 2134 long nOldTop = (Frm().*fnRect->fnGetTop)(); 2135 MakePos(); 2136 if( nOldTop != (Frm().*fnRect->fnGetTop)() ) 2137 { 2138 SwHTMLTableLayout *pHTMLLayout = 2139 GetTable()->GetHTMLTableLayout(); 2140 if( pHTMLLayout ) 2141 { 2142 delete pAccess; 2143 bCalcLowers |= pHTMLLayout->Resize( 2144 pHTMLLayout->GetBrowseWidthByTabFrm( *this ), 2145 sal_False ); 2146 2147 pAccess= new SwBorderAttrAccess( 2148 SwFrm::GetCache(), this ); 2149 pAttrs = pAccess->Get(); 2150 } 2151 2152 bValidPrtArea = sal_False; 2153 Format( pAttrs ); 2154 } 2155 lcl_RecalcTable( *this, 0, aNotify ); 2156 bLowersFormatted = sal_True; 2157 if ( bKeep && KEEPTAB ) 2158 { 2159 // --> OD 2005-09-28 #b6329202# 2160 // Consider case that table is inside another table, 2161 // because it has to be avoided, that superior table 2162 // is formatted. 2163 // Thus, find next content, table or section 2164 // and, if a section is found, get its first 2165 // content. 2166 // SwFrm *pNxt = FindNextCnt(); 2167 // if( pNxt && pNxt->IsInTab() ) 2168 // pNxt = pNxt->FindTabFrm(); 2169 // if ( pNxt ) 2170 // { 2171 // pNxt->Calc(); 2172 // if ( !GetNext() ) 2173 // bValidPos = sal_False; 2174 // } 2175 if ( 0 != lcl_FormatNextCntntForKeep( this ) && !GetNext() ) 2176 { 2177 bValidPos = sal_False; 2178 } 2179 // <-- 2180 } 2181 } 2182 } 2183 } 2184 2185 //Wieder ein Wert ungueltig? - dann nochmal das ganze... 2186 if ( !bValidPos || !bValidSize || !bValidPrtArea ) 2187 continue; 2188 2189 // check, if calculation of table frame is ready. 2190 2191 /// OD 23.10.2002 #103517# - Local variable <nDistanceToUpperPrtBottom> 2192 /// Introduce local variable and init it with the distance from the 2193 /// table frame bottom to the bottom of the upper printing area. 2194 /// Note: negative values denotes the situation that table frame doesn't 2195 /// fit in its upper. 2196 2197 SwTwips nDistanceToUpperPrtBottom = 2198 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)()); 2199 2200 /// OD 23.10.2002 #103517# - In online layout try to grow upper of table 2201 /// frame, if table frame doesn't fit in its upper. 2202 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 2203 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode(); 2204 if ( nDistanceToUpperPrtBottom < 0 && bBrowseMode ) 2205 { 2206 if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom ) ) 2207 { 2208 // upper is grown --> recalculate <nDistanceToUpperPrtBottom> 2209 nDistanceToUpperPrtBottom = 2210 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)()); 2211 } 2212 } 2213 2214 // If there is still some space left in the upper, we check if we 2215 // can join some rows of the follow. 2216 // Setting bLastRowHasToMoveToFollow to true means we want to force 2217 // the table to be split! Only skip this if condition once. 2218 if( nDistanceToUpperPrtBottom >= 0 && !bLastRowHasToMoveToFollow ) 2219 { 2220 // OD 23.10.2002 - translate german commentary 2221 // If there is space left in the upper printing area, join as for trial 2222 // at least one further row of an existing follow. 2223 if ( !bSplit && GetFollow() ) 2224 { 2225 sal_Bool bDummy; 2226 if ( GetFollow()->ShouldBwdMoved( GetUpper(), sal_False, bDummy ) ) 2227 { 2228 SwFrm *pTmp = GetUpper(); 2229 SwTwips nDeadLine = (pTmp->*fnRect->fnGetPrtBottom)(); 2230 if ( bBrowseMode ) 2231 nDeadLine += pTmp->Grow( LONG_MAX, sal_True ); 2232 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 ) 2233 { 2234 // 2235 // First, we remove an existing follow flow line. 2236 // 2237 if ( HasFollowFlowLine() ) 2238 { 2239 SwFrm* pLastLine = const_cast<SwFrm*>(GetLastLower()); 2240 RemoveFollowFlowLine(); 2241 // invalidate and rebuild last row 2242 if ( pLastLine ) 2243 { 2244 ::SwInvalidateAll( pLastLine, LONG_MAX ); 2245 SetRebuildLastLine( sal_True ); 2246 lcl_RecalcRow( static_cast<SwRowFrm&>(*pLastLine), LONG_MAX ); 2247 SetRebuildLastLine( sal_False ); 2248 } 2249 2250 SwFrm* pRow = GetFollow()->GetFirstNonHeadlineRow(); 2251 2252 if ( !pRow || !pRow->GetNext() ) 2253 //Der Follow wird leer und damit ueberfluessig. 2254 Join(); 2255 2256 continue; 2257 } 2258 2259 // 2260 // If there is no follow flow line, we move the first 2261 // row in the follow table to the master table. 2262 // 2263 SwRowFrm *pRow = GetFollow()->GetFirstNonHeadlineRow(); 2264 2265 //Der Follow wird leer und damit ueberfluessig. 2266 if ( !pRow ) 2267 { 2268 Join(); 2269 continue; 2270 } 2271 2272 const SwTwips nOld = (Frm().*fnRect->fnGetHeight)(); 2273 long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pRow ); 2274 SwFrm* pRowToMove = pRow; 2275 2276 while ( pRowToMove && nRowsToMove-- > 0 ) 2277 { 2278 const sal_Bool bMoveFtns = bFtnsInDoc && !GetFollow()->IsJoinLocked(); 2279 2280 SwFtnBossFrm *pOldBoss = 0; 2281 if ( bMoveFtns ) 2282 pOldBoss = pRowToMove->FindFtnBossFrm( sal_True ); 2283 2284 SwFrm* pNextRow = pRowToMove->GetNext(); 2285 2286 if ( !pNextRow ) 2287 //Der Follow wird leer und damit ueberfluessig. 2288 Join(); 2289 else 2290 { 2291 pRowToMove->Cut(); 2292 pRowToMove->Paste( this ); 2293 } 2294 2295 //Die Fussnoten verschieben! 2296 if ( bMoveFtns ) 2297 if ( ((SwLayoutFrm*)pRowToMove)->MoveLowerFtns( 2298 0, pOldBoss, FindFtnBossFrm( sal_True ), sal_True ) ) 2299 GetUpper()->Calc(); 2300 2301 pRowToMove = pNextRow; 2302 } 2303 2304 if ( nOld != (Frm().*fnRect->fnGetHeight)() ) 2305 lcl_RecalcTable( *this, (SwLayoutFrm*)pRow, aNotify ); 2306 2307 continue; 2308 } 2309 } 2310 } 2311 else if ( KEEPTAB ) 2312 { 2313 bool bFormat = false; 2314 if ( bKeep ) 2315 bFormat = true; 2316 else if ( bTableRowKeep && !bLastRowMoveNoMoreTries ) 2317 { 2318 // We only want to give the last row one chance to move 2319 // to the follow table. Set the flag as early as possible: 2320 bLastRowMoveNoMoreTries = true; 2321 2322 // The last line of the table has to be cut off if: 2323 // 1. The table does not want to keep with its next 2324 // 2. The compatibility option is set and the table is allowed to split 2325 // 3. We did not already cut off the last row 2326 // 4. There is not break after attribute set at the table 2327 // 5. There is no break before attribute set behind the table 2328 // 6. There is no section change behind the table (see IsKeep) 2329 // 7. The last table row wants to keep with its next. 2330 const SwRowFrm* pLastRow = static_cast<const SwRowFrm*>(GetLastLower()); 2331 if ( pLastRow && IsKeep( pAttrs->GetAttrSet(), true ) && 2332 pLastRow->ShouldRowKeepWithNext() ) 2333 bFormat = true; 2334 } 2335 2336 if ( bFormat ) 2337 { 2338 delete pAccess; 2339 2340 // --> OD 2005-09-28 #b6329202# 2341 // Consider case that table is inside another table, because 2342 // it has to be avoided, that superior table is formatted. 2343 // Thus, find next content, table or section and, if a section 2344 // is found, get its first content. 2345 const SwFrm* pTmpNxt = lcl_FormatNextCntntForKeep( this ); 2346 // <-- 2347 2348 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this ); 2349 pAttrs = pAccess->Get(); 2350 2351 // The last row wants to keep with the frame behind the table. 2352 // Check if the next frame is on a different page and valid. 2353 // In this case we do a magic trick: 2354 if ( !bKeep && !GetNext() && pTmpNxt && pTmpNxt->IsValid() ) 2355 { 2356 bValidPos = sal_False; 2357 bLastRowHasToMoveToFollow = true; 2358 } 2359 } 2360 } 2361 2362 if ( IsValid() ) 2363 { 2364 if ( bCalcLowers ) 2365 { 2366 lcl_RecalcTable( *this, 0, aNotify ); 2367 bLowersFormatted = sal_True; 2368 bCalcLowers = sal_False; 2369 } 2370 else if ( bONECalcLowers ) 2371 { 2372 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX ); 2373 bONECalcLowers = sal_False; 2374 } 2375 } 2376 continue; 2377 } 2378 2379 //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt 2380 //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen 2381 2382 //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe 2383 //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man 2384 //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und 2385 //zwar mit aller Kraft. 2386 if ( !bMoveable ) 2387 { 2388 if ( bCalcLowers && IsValid() ) 2389 { 2390 lcl_RecalcTable( *this, 0, aNotify ); 2391 bLowersFormatted = sal_True; 2392 bCalcLowers = sal_False; 2393 } 2394 else if ( bONECalcLowers ) 2395 { 2396 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX ); 2397 bONECalcLowers = sal_False; 2398 } 2399 2400 // It does not make sense to cut off the last line if we are 2401 // not moveable: 2402 bLastRowHasToMoveToFollow = false; 2403 2404 continue; 2405 } 2406 2407 if ( bCalcLowers && IsValid() ) 2408 { 2409 lcl_RecalcTable( *this, 0, aNotify ); 2410 bLowersFormatted = sal_True; 2411 bCalcLowers = sal_False; 2412 if( !IsValid() ) 2413 continue; 2414 } 2415 2416 // 2417 // First try to split the table. Condition: 2418 // 1. We have at least one non headline row 2419 // 2. If this row wants to keep, we need an additional row 2420 // 3. The table is allowed to split or we do not have an pIndPrev: 2421 // 2422 SwFrm* pIndPrev = GetIndPrev(); 2423 const SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow(); 2424 2425 if ( pFirstNonHeadlineRow && nUnSplitted > 0 && 2426 ( !bTableRowKeep || pFirstNonHeadlineRow->GetNext() || !pFirstNonHeadlineRow->ShouldRowKeepWithNext() ) && 2427 ( !bDontSplit || !pIndPrev ) ) 2428 { 2429 // --> FME 2004-06-03 #i29438# 2430 // Special DoNotSplit case: 2431 // We better avoid splitting of a row frame if we are inside a columned 2432 // section which has a height of 0, because this is not growable and thus 2433 // all kinds of unexpected things could happen. 2434 const SwSectionFrm* pTmpSct = 0; 2435 if ( IsInSct() && 2436 (pTmpSct = FindSctFrm())->Lower()->IsColumnFrm() && 2437 0 == (GetUpper()->Frm().*fnRect->fnGetHeight)() ) 2438 { 2439 bTryToSplit = false; 2440 } 2441 // <-- 2442 2443 // 1. Try: bTryToSplit = true => Try to split the row. 2444 // 2. Try: bTryToSplit = false => Split the table between the rows. 2445 if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit ) 2446 { 2447 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)(); 2448 if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE) 2449 nDeadLine = (*fnRect->fnYInc)( nDeadLine, 2450 GetUpper()->Grow( LONG_MAX, sal_True ) ); 2451 2452 ::lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), nDeadLine ); 2453 bLowersFormatted = sal_True; 2454 aNotify.SetLowersComplete( sal_True ); 2455 2456 // One more check if its really necessary to split the table. 2457 // 1. The table either has to exceed the deadline or 2458 // 2. We explicitly want to cut off the last row. 2459 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 && !bLastRowHasToMoveToFollow ) 2460 { 2461 continue; 2462 } 2463 2464 // Set to false again as early as possible. 2465 bLastRowHasToMoveToFollow = false; 2466 2467 // --> FME 2005-08-03 #i52781# 2468 // YaSC - Yet another special case: 2469 // If our upper is inside a table cell which is not allowed 2470 // to split, we do not try to split: 2471 if ( GetUpper()->IsInTab() ) 2472 { 2473 const SwFrm* pTmpRow = GetUpper(); 2474 while ( pTmpRow && !pTmpRow->IsRowFrm() ) 2475 pTmpRow = pTmpRow->GetUpper(); 2476 if ( pTmpRow && !static_cast<const SwRowFrm*>(pTmpRow)->IsRowSplitAllowed() ) 2477 continue; 2478 } 2479 // <-- 2480 2481 sal_uInt16 nMinNumOfLines = nRepeat; 2482 2483 if ( bTableRowKeep ) 2484 { 2485 const SwRowFrm* pTmpRow = pFirstNonHeadlineRow; 2486 while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() ) 2487 { 2488 ++nMinNumOfLines; 2489 pTmpRow = static_cast<const SwRowFrm*>(pTmpRow->GetNext()); 2490 } 2491 // Check if all lines want to keep together and we 2492 // have a pIndPrev. In this case we set nDeadLine 2493 // to 0, forcing the table to move forward. 2494 if ( !pTmpRow && pIndPrev ) 2495 nDeadLine = 0; 2496 } 2497 2498 if ( !bTryToSplit ) 2499 ++nMinNumOfLines; 2500 2501 const SwTwips nBreakLine = (*fnRect->fnYInc)( 2502 (Frm().*fnRect->fnGetTop)(), 2503 (this->*fnRect->fnGetTopMargin)() + 2504 lcl_GetHeightOfRows( GetLower(), nMinNumOfLines ) ); 2505 2506 // Some more checks if we want to call the split algorithm or not: 2507 // The repeating lines / keeping lines still fit into the upper or 2508 // if we do not have an (in)direkt Prev, we split anyway. 2509 if( (*fnRect->fnYDiff)(nDeadLine, nBreakLine) >=0 || !pIndPrev ) 2510 { 2511 aNotify.SetLowersComplete( sal_False ); 2512 bSplit = sal_True; 2513 2514 // 2515 // An existing follow flow line has to be removed. 2516 // 2517 if ( HasFollowFlowLine() ) 2518 RemoveFollowFlowLine(); 2519 2520 const bool bSplitError = !Split( nDeadLine, bTryToSplit, bTableRowKeep ); 2521 if( !bTryToSplit && !bSplitError && nUnSplitted > 0 ) 2522 --nUnSplitted; 2523 2524 // --> FME 2004-06-09 #i29771# Two tries to split the table: 2525 // If an error occured during splitting. We start a second 2526 // try, this time without splitting of table rows. 2527 if ( bSplitError ) 2528 { 2529 if ( HasFollowFlowLine() ) 2530 RemoveFollowFlowLine(); 2531 } 2532 2533 // --> FME 2005-02-10 #119477# 2534 // If splitting the table was successfull or not, 2535 // we do not want to have 'empty' follow tables. 2536 if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() ) 2537 Join(); 2538 // <-- 2539 2540 2541 // We want to restore the situation before the failed 2542 // split operation as good as possible. Therefore we 2543 // do some more calculations. Note: Restricting this 2544 // to nDeadLine may not be enough. 2545 if ( bSplitError && bTryToSplit ) // no restart if we did not try to split: i72847, i79426 2546 { 2547 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX ); 2548 bValidPos = sal_False; 2549 bTryToSplit = false; 2550 continue; 2551 } 2552 // <-- 2553 2554 bTryToSplit = !bSplitError; 2555 2556 //Damit es nicht zu Oszillationen kommt, muss der 2557 //Follow gleich gueltig gemacht werden. 2558 if ( GetFollow() ) 2559 { 2560 // --> OD 2007-11-30 #i80924# 2561 // After a successful split assure that the first row 2562 // is invalid. When graphics are present, this isn't hold. 2563 // Note: defect i80924 could also be fixed, if it is 2564 // assured, that <SwLayNotify::bLowersComplete> is only 2565 // set, if all lower are valid *and* are correct laid out. 2566 if ( !bSplitError && GetFollow()->GetLower() ) 2567 { 2568 GetFollow()->GetLower()->InvalidatePos(); 2569 } 2570 // <-- 2571 SWRECTFNX( GetFollow() ) 2572 2573 static sal_uInt8 nStack = 0; 2574 if ( !StackHack::IsLocked() && nStack < 4 ) 2575 { 2576 ++nStack; 2577 StackHack aHack; 2578 delete pAccess; 2579 2580 GetFollow()->MakeAll(); 2581 2582 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this ); 2583 pAttrs = pAccess->Get(); 2584 2585 ((SwTabFrm*)GetFollow())->SetLowersFormatted(sal_False); 2586 // --> OD 2005-03-30 #i43913# - lock follow table 2587 // to avoid its formatting during the format of 2588 // its content. 2589 const bool bOldJoinLock = GetFollow()->IsJoinLocked(); 2590 GetFollow()->LockJoin(); 2591 // <-- 2592 ::lcl_RecalcRow( static_cast<SwRowFrm&>(*GetFollow()->Lower()), 2593 (GetFollow()->GetUpper()->Frm().*fnRectX->fnGetBottom)() ); 2594 // --> OD 2005-03-30 #i43913# 2595 // --> FME 2006-04-05 #i63632# Do not unlock the 2596 // follow if it wasn't locked before. 2597 if ( !bOldJoinLock ) 2598 GetFollow()->UnlockJoin(); 2599 // <-- 2600 2601 if ( !GetFollow()->GetFollow() ) 2602 { 2603 SwFrm* pNxt = ((SwFrm*)GetFollow())->FindNext(); 2604 if ( pNxt ) 2605 { 2606 // OD 26.08.2003 #i18103# - no formatting 2607 // of found next frame, if its a follow 2608 // section of the 'ColLocked' section, 2609 // the follow table is in. 2610 bool bCalcNxt = true; 2611 if ( GetFollow()->IsInSct() && pNxt->IsSctFrm() ) 2612 { 2613 SwSectionFrm* pSct = GetFollow()->FindSctFrm(); 2614 if ( pSct->IsColLocked() && 2615 pSct->GetFollow() == pNxt ) 2616 { 2617 bCalcNxt = false; 2618 } 2619 } 2620 if ( bCalcNxt ) 2621 { 2622 pNxt->Calc(); 2623 } 2624 } 2625 } 2626 --nStack; 2627 } 2628 else if ( GetFollow() == GetNext() ) 2629 ((SwTabFrm*)GetFollow())->MoveFwd( sal_True, sal_False ); 2630 } 2631 continue; 2632 } 2633 } 2634 } 2635 2636 // Set to false again as early as possible. 2637 bLastRowHasToMoveToFollow = false; 2638 2639 if( IsInSct() && bMovedFwd && bMakePage && GetUpper()->IsColBodyFrm() && 2640 GetUpper()->GetUpper()->GetUpper()->IsSctFrm() && 2641 ( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) && 2642 ((SwSectionFrm*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) ) 2643 bMovedFwd = sal_False; 2644 2645 // --> FME 2004-06-09 #i29771# Reset bTryToSplit flag on change of upper 2646 const SwFrm* pOldUpper = GetUpper(); 2647 // <-- 2648 2649 //Mal sehen ob ich irgenwo Platz finde... 2650 if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) ) 2651 bMakePage = sal_False; 2652 2653 // --> FME 2004-06-09 #i29771# Reset bSplitError flag on change of upper 2654 if ( GetUpper() != pOldUpper ) 2655 { 2656 bTryToSplit = true; 2657 nUnSplitted = 5; 2658 } 2659 // <-- 2660 2661 SWREFRESHFN( this ) 2662 bMovedFwd = bCalcLowers = sal_True; 2663 aNotify.SetLowersComplete( sal_False ); 2664 if ( IsFollow() ) 2665 { //Um Oszillationen zu vermeiden sollte kein ungueltiger Master 2666 //zurueckbleiben. 2667 SwTabFrm *pTab = FindMaster(); 2668 if ( pTab->GetUpper() ) 2669 pTab->GetUpper()->Calc(); 2670 pTab->Calc(); 2671 pTab->SetLowersFormatted( sal_False ); 2672 } 2673 2674 //Wenn mein direkter Nachbar jetzt gleichzeitig mein Follow ist 2675 //verleibe ich mir das Teil ein. 2676 if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() ) 2677 { 2678 if ( HasFollowFlowLine() ) 2679 RemoveFollowFlowLine(); 2680 if ( GetFollow() ) 2681 Join(); 2682 } 2683 2684 if ( bMovedBwd && GetUpper() ) 2685 //Beim zurueckfliessen wurde der Upper angeregt sich vollstaendig 2686 //zu Painten, dass koennen wir uns jetzt nach dem hin und her 2687 //fliessen sparen. 2688 GetUpper()->ResetCompletePaint(); 2689 2690 if ( bCalcLowers && IsValid() ) 2691 { 2692 // --> OD 2005-05-11 #i44910# - format of lower frames unnecessary 2693 // and can cause layout loops, if table doesn't fit and isn't 2694 // allowed to split. 2695 SwTwips nDistToUpperPrtBottom = 2696 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)()); 2697 if ( nDistToUpperPrtBottom >= 0 || bTryToSplit ) 2698 { 2699 lcl_RecalcTable( *this, 0, aNotify ); 2700 bLowersFormatted = sal_True; 2701 bCalcLowers = sal_False; 2702 } 2703 #if OSL_DEBUG_LEVEL > 1 2704 else 2705 { 2706 ASSERT( false, "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" ); 2707 } 2708 #endif 2709 // <-- 2710 } 2711 2712 } //while ( !bValidPos || !bValidSize || !bValidPrtArea ) 2713 2714 //Wenn mein direkter Vorgaenger jetzt mein Master ist, so kann er mich 2715 //bei der nachstbesten Gelegenheit vernichten. 2716 if ( IsFollow() ) 2717 { 2718 SwFrm *pPre = GetPrev(); 2719 if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this) 2720 pPre->InvalidatePos(); 2721 } 2722 2723 bCalcLowers = bONECalcLowers = sal_False; 2724 delete pAccess; 2725 UnlockJoin(); 2726 if ( bMovedFwd || bMovedBwd || !bOldValidPos ) 2727 aNotify.SetInvaKeep(); 2728 } 2729 2730 /************************************************************************* 2731 |* 2732 |* SwTabFrm::CalcFlyOffsets() 2733 |* 2734 |* Beschreibung: Berechnet die Offsets, die durch FlyFrames 2735 |* entstehen. 2736 |* Ersterstellung MA/MIB 14. Apr. 99 2737 |* Letzte Aenderung 2738 |* 2739 |*************************************************************************/ 2740 sal_Bool SwTabFrm::CalcFlyOffsets( SwTwips& rUpper, 2741 long& rLeftOffset, 2742 long& rRightOffset ) const 2743 { 2744 sal_Bool bInvalidatePrtArea = sal_False; 2745 const SwPageFrm *pPage = FindPageFrm(); 2746 const SwFlyFrm* pMyFly = FindFlyFrm(); 2747 2748 // --> #108724# Page header/footer content doesn't have to wrap around 2749 // floating screen objects 2750 2751 const IDocumentSettingAccess* pIDSA = GetFmt()->getIDocumentSettingAccess(); 2752 const bool bWrapAllowed = pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) || 2753 ( !IsInFtn() && 0 == FindFooterOrHeader() ); 2754 // <-- 2755 2756 if ( pPage->GetSortedObjs() && bWrapAllowed ) 2757 { 2758 SWRECTFN( this ) 2759 const bool bConsiderWrapOnObjPos = pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION); 2760 long nPrtPos = (Frm().*fnRect->fnGetTop)(); 2761 nPrtPos = (*fnRect->fnYInc)( nPrtPos, rUpper ); 2762 SwRect aRect( Frm() ); 2763 long nYDiff = (*fnRect->fnYDiff)( (Prt().*fnRect->fnGetTop)(), rUpper ); 2764 if( nYDiff > 0 ) 2765 (aRect.*fnRect->fnAddBottom)( -nYDiff ); 2766 for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i ) 2767 { 2768 SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i]; 2769 if ( pAnchoredObj->ISA(SwFlyFrm) ) 2770 { 2771 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 2772 const SwRect aFlyRect = pFly->GetObjRectWithSpaces(); 2773 // --> OD 2004-10-07 #i26945# - correction of conditions, 2774 // if Writer fly frame has to be considered: 2775 // - no need to check, if top of Writer fly frame differs 2776 // from WEIT_WECH, because its also check, if the Writer 2777 // fly frame rectangle overlaps with <aRect> 2778 // - no check, if bottom of anchor frame is prior the top of 2779 // the table, because Writer fly frames can be negative positioned. 2780 // - correct check, if the Writer fly frame is an lower of the 2781 // table, because table lines/rows can split and a at-character 2782 // anchored Writer fly frame could be positioned in the follow 2783 // flow line. 2784 // - add condition, that an existing anchor character text frame 2785 // has to be on the same page as the table. 2786 // E.g., it could happen, that the fly frame is still registered 2787 // at the page frame, the table is on, but it's anchor character 2788 // text frame has already changed its page. 2789 //if ( WEIT_WECH != (pFly->Frm().*fnRect->fnGetTop)() && 2790 // pFly->IsFlyAtCntFrm() && aFlyRect.IsOver( aRect ) && 2791 // // OD 25.02.2003 #i9040# - use '<=' instead of '<' 2792 // (*fnRect->fnYDiff)( 2793 // (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetBottom)(), 2794 // (Frm().*fnRect->fnGetTop)() ) <= 0 && 2795 // !IsAnLower( pFly ) && !pFly->IsAnLower( this ) && 2796 // ( !pMyFly || pMyFly->IsAnLower( pFly ) ) && 2797 // pPage->GetPhyPageNum() >= 2798 // pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() && 2799 // // anchor should be in same page body/header/footer 2800 // ( pFly->GetAnchorFrm()->FindFooterOrHeader() == 2801 // FindFooterOrHeader() ) ) 2802 const SwTxtFrm* pAnchorCharFrm = pFly->FindAnchorCharFrm(); 2803 bool bConsiderFly = 2804 // --> OD 2005-04-06 #i46807# - do not consider invalid 2805 // Writer fly frames. 2806 pFly->IsValid() && 2807 // <-- 2808 // fly anchored at character 2809 pFly->IsFlyAtCntFrm() && 2810 // fly overlaps with corresponding table rectangle 2811 aFlyRect.IsOver( aRect ) && 2812 // fly isn't lower of table and 2813 // anchor character frame of fly isn't lower of table 2814 ( !IsAnLower( pFly ) && 2815 ( !pAnchorCharFrm || !IsAnLower( pAnchorCharFrm ) ) ) && 2816 // table isn't lower of fly 2817 !pFly->IsAnLower( this ) && 2818 // fly is lower of fly, the table is in 2819 // --> OD 2005-05-31 #123274# - correction: 2820 // assure that fly isn't a lower of a fly, the table isn't in. 2821 // E.g., a table in the body doesn't wrap around a graphic, 2822 // which is inside a frame. 2823 ( ( !pMyFly || 2824 pMyFly->IsAnLower( pFly ) ) && 2825 pMyFly == pFly->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) && 2826 // <-- 2827 // anchor frame not on following page 2828 pPage->GetPhyPageNum() >= 2829 pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() && 2830 // anchor character text frame on same page 2831 ( !pAnchorCharFrm || 2832 pAnchorCharFrm->FindPageFrm()->GetPhyPageNum() == 2833 pPage->GetPhyPageNum() ); 2834 2835 if ( bConsiderFly ) 2836 { 2837 const SwFrm* pFlyHeaderFooterFrm = pFly->GetAnchorFrm()->FindFooterOrHeader(); 2838 const SwFrm* pThisHeaderFooterFrm = FindFooterOrHeader(); 2839 2840 if ( pFlyHeaderFooterFrm != pThisHeaderFooterFrm && 2841 // --> FME 2007-07-02 #148493# If bConsiderWrapOnObjPos is set, 2842 // we want to consider the fly if it is located in the header and 2843 // the table is located in the body: 2844 ( !bConsiderWrapOnObjPos || 0 != pThisHeaderFooterFrm || !pFlyHeaderFooterFrm->IsHeaderFrm() ) ) 2845 bConsiderFly = false; 2846 // <-- 2847 } 2848 2849 if ( bConsiderFly ) 2850 // <-- 2851 { 2852 const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround(); 2853 const SwFmtHoriOrient &rHori= pFly->GetFmt()->GetHoriOrient(); 2854 if ( SURROUND_NONE == rSur.GetSurround() ) 2855 { 2856 long nBottom = (aFlyRect.*fnRect->fnGetBottom)(); 2857 if( (*fnRect->fnYDiff)( nPrtPos, nBottom ) < 0 ) 2858 nPrtPos = nBottom; 2859 bInvalidatePrtArea = sal_True; 2860 } 2861 if ( (SURROUND_RIGHT == rSur.GetSurround() || 2862 SURROUND_PARALLEL == rSur.GetSurround())&& 2863 text::HoriOrientation::LEFT == rHori.GetHoriOrient() ) 2864 { 2865 const long nWidth = (*fnRect->fnXDiff)( 2866 (aFlyRect.*fnRect->fnGetRight)(), 2867 (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetLeft)() ); 2868 rLeftOffset = Max( rLeftOffset, nWidth ); 2869 bInvalidatePrtArea = sal_True; 2870 } 2871 if ( (SURROUND_LEFT == rSur.GetSurround() || 2872 SURROUND_PARALLEL == rSur.GetSurround())&& 2873 text::HoriOrientation::RIGHT == rHori.GetHoriOrient() ) 2874 { 2875 const long nWidth = (*fnRect->fnXDiff)( 2876 (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetRight)(), 2877 (aFlyRect.*fnRect->fnGetLeft)() ); 2878 rRightOffset = Max( rRightOffset, nWidth ); 2879 bInvalidatePrtArea = sal_True; 2880 } 2881 } 2882 } 2883 } 2884 rUpper = (*fnRect->fnYDiff)( nPrtPos, (Frm().*fnRect->fnGetTop)() ); 2885 } 2886 2887 return bInvalidatePrtArea; 2888 } 2889 2890 /************************************************************************* 2891 |* 2892 |* SwTabFrm::Format() 2893 |* 2894 |* Beschreibung: "Formatiert" den Frame; Frm und PrtArea 2895 |* Die Fixsize wird hier nicht eingestellt. 2896 |* Ersterstellung MA 09. Mar. 93 2897 |* Letzte Aenderung MA 18. Jun. 97 2898 |* 2899 |*************************************************************************/ 2900 void SwTabFrm::Format( const SwBorderAttrs *pAttrs ) 2901 { 2902 ASSERT( pAttrs, "TabFrm::Format, pAttrs ist 0." ); 2903 2904 SWRECTFN( this ) 2905 if ( !bValidSize ) 2906 { 2907 long nDiff = (GetUpper()->Prt().*fnRect->fnGetWidth)() - 2908 (Frm().*fnRect->fnGetWidth)(); 2909 if( nDiff ) 2910 (aFrm.*fnRect->fnAddRight)( nDiff ); 2911 } 2912 2913 //VarSize ist immer die Hoehe. 2914 //Fuer den oberen/unteren Rand gelten die selben Regeln wie fuer 2915 //cntfrms (sie MakePrtArea() von diesen). 2916 2917 SwTwips nUpper = CalcUpperSpace( pAttrs ); 2918 2919 //Wir wollen Rahmen ausweichen. Zwei Moeglichkeiten: 2920 //1. Es gibt Rahmen mit SurroundNone, diesen wird vollsaendig ausgewichen 2921 //2. Es gibt Rahmen mit Umlauf nur rechts bzw. nur links und diese sind 2922 // rechts bzw. links ausgerichtet, diese geben ein Minimum fuer die 2923 // Raender vor. 2924 long nTmpRight = -1000000, 2925 nLeftOffset = 0; 2926 if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) ) 2927 bValidPrtArea = sal_False; 2928 long nRightOffset = Max( 0L, nTmpRight ); 2929 2930 SwTwips nLower = pAttrs->CalcBottomLine(); 2931 // --> collapsing borders FME 2005-05-27 #i29550# 2932 if ( IsCollapsingBorders() ) 2933 nLower += GetBottomLineSize(); 2934 // <-- collapsing 2935 2936 if ( !bValidPrtArea ) 2937 { bValidPrtArea = sal_True; 2938 2939 //Die Breite der PrtArea wird vom FrmFmt vorgegeben, die Raender 2940 //sind entsprechend einzustellen. 2941 //Mindestraender werden von Umrandung und Schatten vorgegeben. 2942 //Die Rander werden so eingestellt, dass die PrtArea nach dem 2943 //angegebenen Adjustment im Frm ausgerichtet wird. 2944 //Wenn das Adjustment 0 ist, so werden die Rander anhand des 2945 //Randattributes eingestellt. 2946 2947 const SwTwips nOldHeight = (Prt().*fnRect->fnGetHeight)(); 2948 const SwTwips nMax = (aFrm.*fnRect->fnGetWidth)(); 2949 2950 // OD 14.03.2003 #i9040# - adjust variable names. 2951 const SwTwips nLeftLine = pAttrs->CalcLeftLine(); 2952 const SwTwips nRightLine = pAttrs->CalcRightLine(); 2953 2954 //Die Breite ist evtl. eine Prozentangabe. Wenn die Tabelle irgendwo 2955 //'drinsteckt bezieht sie sich auf die Umgebung. Ist es der Body, so 2956 //bezieht sie sich in der BrowseView auf die Bildschirmbreite. 2957 const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize(); 2958 // OD 14.03.2003 #i9040# - adjust variable name. 2959 const SwTwips nWishedTableWidth = CalcRel( rSz, sal_True ); 2960 2961 sal_Bool bCheckBrowseWidth = sal_False; 2962 2963 // OD 14.03.2003 #i9040# - insert new variables for left/right spacing. 2964 SwTwips nLeftSpacing = 0; 2965 SwTwips nRightSpacing = 0; 2966 switch ( GetFmt()->GetHoriOrient().GetHoriOrient() ) 2967 { 2968 case text::HoriOrientation::LEFT: 2969 { 2970 // left indent: 2971 nLeftSpacing = nLeftLine + nLeftOffset; 2972 // OD 06.03.2003 #i9040# - correct calculation of right indent: 2973 // - Consider right indent given by right line attributes. 2974 // - Consider negative right indent. 2975 // wished right indent determined by wished table width and 2976 // left offset given by surround fly frames on the left: 2977 const SwTwips nWishRight = nMax - nWishedTableWidth - nLeftOffset; 2978 if ( nRightOffset > 0 ) 2979 { 2980 // surrounding fly frames on the right 2981 // -> right indent is maximun of given right offset 2982 // and wished right offset. 2983 nRightSpacing = nRightLine + Max( nRightOffset, nWishRight ); 2984 } 2985 else 2986 { 2987 // no surrounding fly frames on the right 2988 // If intrinsic right indent (intrinsic means not considering 2989 // determined left indent) is negative, 2990 // then hold this intrinsic indent, 2991 // otherwise non negative wished right indent is hold. 2992 nRightSpacing = nRightLine + 2993 ( ( (nWishRight+nLeftOffset) < 0 ) ? 2994 (nWishRight+nLeftOffset) : 2995 Max( 0L, nWishRight ) ); 2996 } 2997 } 2998 break; 2999 case text::HoriOrientation::RIGHT: 3000 { 3001 // right indent: 3002 nRightSpacing = nRightLine + nRightOffset; 3003 // OD 06.03.2003 #i9040# - correct calculation of left indent: 3004 // - Consider left indent given by left line attributes. 3005 // - Consider negative left indent. 3006 // wished left indent determined by wished table width and 3007 // right offset given by surrounding fyl frames on the right: 3008 const SwTwips nWishLeft = nMax - nWishedTableWidth - nRightOffset; 3009 if ( nLeftOffset > 0 ) 3010 { 3011 // surrounding fly frames on the left 3012 // -> right indent is maximun of given left offset 3013 // and wished left offset. 3014 nLeftSpacing = nLeftLine + Max( nLeftOffset, nWishLeft ); 3015 } 3016 else 3017 { 3018 // no surrounding fly frames on the left 3019 // If intrinsic left indent (intrinsic = not considering 3020 // determined right indent) is negative, 3021 // then hold this intrinsic indent, 3022 // otherwise non negative wished left indent is hold. 3023 nLeftSpacing = nLeftLine + 3024 ( ( (nWishLeft+nRightOffset) < 0 ) ? 3025 (nWishLeft+nRightOffset) : 3026 Max( 0L, nWishLeft ) ); 3027 } 3028 } 3029 break; 3030 case text::HoriOrientation::CENTER: 3031 { 3032 // OD 07.03.2003 #i9040# - consider left/right line attribute. 3033 // OD 10.03.2003 #i9040# - 3034 const SwTwips nCenterSpacing = ( nMax - nWishedTableWidth ) / 2; 3035 nLeftSpacing = nLeftLine + 3036 ( (nLeftOffset > 0) ? 3037 Max( nCenterSpacing, nLeftOffset ) : 3038 nCenterSpacing ); 3039 nRightSpacing = nRightLine + 3040 ( (nRightOffset > 0) ? 3041 Max( nCenterSpacing, nRightOffset ) : 3042 nCenterSpacing ); 3043 } 3044 break; 3045 case text::HoriOrientation::FULL: 3046 //Das Teil dehnt sich ueber die gesamte Breite aus. 3047 //Nur die fuer die Umrandung benoetigten Freiraeume 3048 //werden beruecksichtigt. 3049 //Die Attributwerte von LRSpace werden bewusst missachtet! 3050 bCheckBrowseWidth = sal_True; 3051 nLeftSpacing = nLeftLine + nLeftOffset; 3052 nRightSpacing = nRightLine + nRightOffset; 3053 break; 3054 case text::HoriOrientation::NONE: 3055 { 3056 //Die Raender werden vom Randattribut bestimmt. 3057 nLeftSpacing = pAttrs->CalcLeft( this ); 3058 if( nLeftOffset ) 3059 { 3060 // OD 07.03.2003 #i9040# - surround fly frames only, if 3061 // they overlap with the table. 3062 // Thus, take maximun of left spacing and left offset. 3063 // OD 10.03.2003 #i9040# - consider left line attribute. 3064 nLeftSpacing = Max( nLeftSpacing, ( nLeftOffset + nLeftLine ) ); 3065 } 3066 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)> 3067 nRightSpacing = pAttrs->CalcRight( this ); 3068 if( nRightOffset ) 3069 { 3070 // OD 07.03.2003 #i9040# - surround fly frames only, if 3071 // they overlap with the table. 3072 // Thus, take maximun of right spacing and right offset. 3073 // OD 10.03.2003 #i9040# - consider right line attribute. 3074 nRightSpacing = Max( nRightSpacing, ( nRightOffset + nRightLine ) ); 3075 } 3076 // OD 10.03.2003 #i9040# - do not hold wished table width. 3077 /* 3078 if ( !pAttrs->GetLRSpace().GetRight() ) 3079 nRight = Max( nRight, nMax - (nWish + nLeft + nRight)); 3080 */ 3081 } 3082 break; 3083 case text::HoriOrientation::LEFT_AND_WIDTH: 3084 { 3085 //Linker Rand und die Breite zaehlen (Word-Spezialitaet) 3086 // OD 10.03.2003 #i9040# - no width alignment in online mode. 3087 //bCheckBrowseWidth = sal_True; 3088 nLeftSpacing = pAttrs->CalcLeft( this ); 3089 if( nLeftOffset ) 3090 { 3091 // OD 10.03.2003 #i9040# - surround fly frames only, if 3092 // they overlap with the table. 3093 // Thus, take maximun of right spacing and right offset. 3094 // OD 10.03.2003 #i9040# - consider left line attribute. 3095 nLeftSpacing = Max( nLeftSpacing, ( pAttrs->CalcLeftLine() + nLeftOffset ) ); 3096 } 3097 // OD 10.03.2003 #i9040# - consider right and left line attribute. 3098 const SwTwips nWishRight = 3099 nMax - (nLeftSpacing-pAttrs->CalcLeftLine()) - nWishedTableWidth; 3100 nRightSpacing = nRightLine + 3101 ( (nRightOffset > 0) ? 3102 Max( nWishRight, nRightOffset ) : 3103 nWishRight ); 3104 } 3105 break; 3106 default: 3107 ASSERT( sal_False, "Ungueltige orientation fuer Table." ); 3108 } 3109 3110 // --> OD 2004-07-15 #i26250# - extend bottom printing area, if table 3111 // is last content inside a table cell. 3112 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) && 3113 GetUpper()->IsInTab() && !GetIndNext() ) 3114 { 3115 nLower += pAttrs->GetULSpace().GetLower(); 3116 } 3117 // <-- 3118 (this->*fnRect->fnSetYMargins)( nUpper, nLower ); 3119 if( (nMax - MINLAY) < (nLeftSpacing + nRightSpacing) ) 3120 (this->*fnRect->fnSetXMargins)( 0, 0 ); 3121 else 3122 (this->*fnRect->fnSetXMargins)( nLeftSpacing, nRightSpacing ); 3123 3124 ViewShell *pSh = getRootFrm()->GetCurrShell(); 3125 if ( bCheckBrowseWidth && 3126 pSh && pSh->GetViewOptions()->getBrowseMode() && 3127 GetUpper()->IsPageBodyFrm() && // nur PageBodyFrms, nicht etwa ColBodyFrms 3128 pSh->VisArea().Width() ) 3129 { 3130 //Nicht ueber die Kante des sichbaren Bereiches hinausragen. 3131 //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite" 3132 //geben kann (RootFrm::ImplCalcBrowseWidth()) 3133 long nWidth = pSh->GetBrowseWidth(); 3134 nWidth -= Prt().Left(); 3135 nWidth -= pAttrs->CalcRightLine(); 3136 Prt().Width( Min( nWidth, Prt().Width() ) ); 3137 } 3138 3139 if ( nOldHeight != (Prt().*fnRect->fnGetHeight)() ) 3140 bValidSize = sal_False; 3141 } 3142 3143 if ( !bValidSize ) 3144 { 3145 bValidSize = sal_True; 3146 3147 //Die Groesse wird durch den Inhalt plus den Raendern bestimmt. 3148 SwTwips nRemaining = 0, nDiff; 3149 SwFrm *pFrm = pLower; 3150 while ( pFrm ) 3151 { 3152 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)(); 3153 pFrm = pFrm->GetNext(); 3154 } 3155 //Jetzt noch die Raender addieren 3156 nRemaining += nUpper + nLower; 3157 3158 nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining; 3159 if ( nDiff > 0 ) 3160 Shrink( nDiff ); 3161 else if ( nDiff < 0 ) 3162 Grow( -nDiff ); 3163 } 3164 } 3165 /************************************************************************* 3166 |* 3167 |* SwTabFrm::GrowFrm() 3168 |* 3169 |* Ersterstellung MA 12. Mar. 93 3170 |* Letzte Aenderung MA 23. Sep. 96 3171 |* 3172 |*************************************************************************/ 3173 SwTwips SwTabFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo ) 3174 { 3175 SWRECTFN( this ) 3176 SwTwips nHeight =(Frm().*fnRect->fnGetHeight)(); 3177 if( nHeight > 0 && nDist > ( LONG_MAX - nHeight ) ) 3178 nDist = LONG_MAX - nHeight; 3179 3180 if ( bTst && !IsRestrictTableGrowth() ) 3181 return nDist; 3182 3183 if ( GetUpper() ) 3184 { 3185 SwRect aOldFrm( Frm() ); 3186 3187 //Der Upper wird nur soweit wie notwendig gegrowed. In nReal wird erstmal 3188 //die bereits zur Verfuegung stehende Strecke bereitgestellt. 3189 SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)(); 3190 SwFrm *pFrm = GetUpper()->Lower(); 3191 while ( pFrm && GetFollow() != pFrm ) 3192 { 3193 nReal -= (pFrm->Frm().*fnRect->fnGetHeight)(); 3194 pFrm = pFrm->GetNext(); 3195 } 3196 3197 long nTmp = 0; 3198 if ( nReal < nDist ) 3199 { 3200 nTmp = GetUpper()->Grow( nDist - ( nReal > 0 ? nReal : 0), bTst, bInfo ); 3201 3202 if ( IsRestrictTableGrowth() ) 3203 { 3204 nTmp = Min( nDist, nReal + nTmp ); 3205 nDist = nTmp < 0 ? 0 : nTmp; 3206 } 3207 } 3208 3209 if ( !bTst ) 3210 { 3211 (Frm().*fnRect->fnAddBottom)( nDist ); 3212 3213 SwRootFrm *pRootFrm = getRootFrm(); 3214 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && 3215 pRootFrm->GetCurrShell() ) 3216 { 3217 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm ); 3218 } 3219 } 3220 } 3221 3222 if ( !bTst && ( nDist || IsRestrictTableGrowth() ) ) 3223 { 3224 SwPageFrm *pPage = FindPageFrm(); 3225 if ( GetNext() ) 3226 { 3227 GetNext()->_InvalidatePos(); 3228 if ( GetNext()->IsCntntFrm() ) 3229 GetNext()->InvalidatePage( pPage ); 3230 } 3231 // --> OD 2004-07-05 #i28701# - Due to the new object positioning the 3232 // frame on the next page/column can flow backward (e.g. it was moved 3233 // forward due to the positioning of its objects ). Thus, invalivate this 3234 // next frame, if document compatibility option 'Consider wrapping style 3235 // influence on object positioning' is ON. 3236 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ) 3237 { 3238 InvalidateNextPos(); 3239 } 3240 // <-- 3241 _InvalidateAll(); 3242 InvalidatePage( pPage ); 3243 SetComplete(); 3244 3245 const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos(); 3246 if ( GPOS_NONE != ePos && GPOS_TILED != ePos ) 3247 SetCompletePaint(); 3248 } 3249 3250 return nDist; 3251 } 3252 /************************************************************************* 3253 |* 3254 |* SwTabFrm::Modify() 3255 |* 3256 |* Ersterstellung MA 14. Mar. 93 3257 |* Letzte Aenderung MA 06. Dec. 96 3258 |* 3259 |*************************************************************************/ 3260 void SwTabFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) 3261 { 3262 sal_uInt8 nInvFlags = 0; 3263 sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which(); 3264 3265 if( bAttrSetChg ) 3266 { 3267 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() ); 3268 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() ); 3269 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld ); 3270 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew ); 3271 while( sal_True ) 3272 { 3273 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(), 3274 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags, 3275 &aOldSet, &aNewSet ); 3276 if( aNIter.IsAtEnd() ) 3277 break; 3278 aNIter.NextItem(); 3279 aOIter.NextItem(); 3280 } 3281 if ( aOldSet.Count() || aNewSet.Count() ) 3282 SwLayoutFrm::Modify( &aOldSet, &aNewSet ); 3283 } 3284 else 3285 _UpdateAttr( pOld, pNew, nInvFlags ); 3286 3287 if ( nInvFlags != 0 ) 3288 { 3289 SwPageFrm *pPage = FindPageFrm(); 3290 InvalidatePage( pPage ); 3291 // if ( nInvFlags & 0x01 ) 3292 // SetCompletePaint(); 3293 if ( nInvFlags & 0x02 ) 3294 _InvalidatePrt(); 3295 if ( nInvFlags & 0x40 ) 3296 _InvalidatePos(); 3297 SwFrm *pTmp; 3298 if ( 0 != (pTmp = GetIndNext()) ) 3299 { 3300 if ( nInvFlags & 0x04 ) 3301 { 3302 pTmp->_InvalidatePrt(); 3303 if ( pTmp->IsCntntFrm() ) 3304 pTmp->InvalidatePage( pPage ); 3305 } 3306 if ( nInvFlags & 0x10 ) 3307 pTmp->SetCompletePaint(); 3308 } 3309 if ( nInvFlags & 0x08 && 0 != (pTmp = GetPrev()) ) 3310 { 3311 pTmp->_InvalidatePrt(); 3312 if ( pTmp->IsCntntFrm() ) 3313 pTmp->InvalidatePage( pPage ); 3314 } 3315 if ( nInvFlags & 0x20 ) 3316 { 3317 if ( pPage && pPage->GetUpper() && !IsFollow() ) 3318 ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth(); 3319 } 3320 if ( nInvFlags & 0x80 ) 3321 InvalidateNextPos(); 3322 } 3323 } 3324 3325 void SwTabFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew, 3326 sal_uInt8 &rInvFlags, 3327 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet ) 3328 { 3329 sal_Bool bClear = sal_True; 3330 const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0; 3331 switch( nWhich ) 3332 { 3333 case RES_TBLHEADLINECHG: 3334 if ( IsFollow() ) 3335 { 3336 // Delete remaining headlines: 3337 SwRowFrm* pLowerRow = 0; 3338 while ( 0 != ( pLowerRow = (SwRowFrm*)Lower() ) && pLowerRow->IsRepeatedHeadline() ) 3339 { 3340 pLowerRow->Cut(); 3341 delete pLowerRow; 3342 } 3343 3344 // insert new headlines 3345 const sal_uInt16 nNewRepeat = GetTable()->GetRowsToRepeat(); 3346 for ( sal_uInt16 nIdx = 0; nIdx < nNewRepeat; ++nIdx ) 3347 { 3348 bDontCreateObjects = sal_True; //frmtool 3349 SwRowFrm* pHeadline = new SwRowFrm( *GetTable()->GetTabLines()[ nIdx ], this ); 3350 pHeadline->SetRepeatedHeadline( true ); 3351 bDontCreateObjects = sal_False; 3352 pHeadline->Paste( this, pLowerRow ); 3353 } 3354 } 3355 rInvFlags |= 0x02; 3356 break; 3357 3358 case RES_FRM_SIZE: 3359 case RES_HORI_ORIENT: 3360 rInvFlags |= 0x22; 3361 break; 3362 3363 case RES_PAGEDESC: //Attributaenderung (an/aus) 3364 if ( IsInDocBody() ) 3365 { 3366 rInvFlags |= 0x40; 3367 SwPageFrm *pPage = FindPageFrm(); 3368 if ( !GetPrev() ) 3369 CheckPageDescs( pPage ); 3370 if ( pPage && GetFmt()->GetPageDesc().GetNumOffset() ) 3371 ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True ); 3372 SwDocPosUpdate aMsgHnt( pPage->Frm().Top() ); 3373 GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt ); 3374 } 3375 break; 3376 3377 case RES_BREAK: 3378 rInvFlags |= 0xC0; 3379 break; 3380 3381 case RES_LAYOUT_SPLIT: 3382 if ( !IsFollow() ) 3383 rInvFlags |= 0x40; 3384 break; 3385 case RES_FRAMEDIR : 3386 SetDerivedR2L( sal_False ); 3387 CheckDirChange(); 3388 break; 3389 case RES_COLLAPSING_BORDERS : 3390 rInvFlags |= 0x02; 3391 lcl_InvalidateAllLowersPrt( this ); 3392 break; 3393 case RES_UL_SPACE: 3394 rInvFlags |= 0x1C; 3395 /* kein Break hier */ 3396 3397 default: 3398 bClear = sal_False; 3399 } 3400 if ( bClear ) 3401 { 3402 if ( pOldSet || pNewSet ) 3403 { 3404 if ( pOldSet ) 3405 pOldSet->ClearItem( nWhich ); 3406 if ( pNewSet ) 3407 pNewSet->ClearItem( nWhich ); 3408 } 3409 else 3410 SwLayoutFrm::Modify( pOld, pNew ); 3411 } 3412 } 3413 3414 /************************************************************************* 3415 |* 3416 |* SwTabFrm::GetInfo() 3417 |* 3418 |* Ersterstellung MA 06. Dec. 96 3419 |* Letzte Aenderung MA 26. Jun. 98 3420 |* 3421 |*************************************************************************/ 3422 sal_Bool SwTabFrm::GetInfo( SfxPoolItem &rHnt ) const 3423 { 3424 if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && !IsFollow() ) 3425 { 3426 SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt; 3427 const SwPageFrm *pPage = FindPageFrm(); 3428 if ( pPage ) 3429 { 3430 if ( pPage == rInfo.GetOrigPage() && !GetPrev() ) 3431 { 3432 //Das sollte er sein (kann allenfalls temporaer anders sein, 3433 // sollte uns das beunruhigen?) 3434 rInfo.SetInfo( pPage, this ); 3435 return sal_False; 3436 } 3437 if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() && 3438 (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum())) 3439 { 3440 //Das koennte er sein. 3441 rInfo.SetInfo( pPage, this ); 3442 } 3443 } 3444 } 3445 return sal_True; 3446 } 3447 3448 /************************************************************************* 3449 |* 3450 |* SwTabFrm::FindLastCntnt() 3451 |* 3452 |* Ersterstellung MA 13. Apr. 93 3453 |* Letzte Aenderung MA 15. May. 98 3454 |* 3455 |*************************************************************************/ 3456 SwCntntFrm *SwTabFrm::FindLastCntnt() 3457 { 3458 SwFrm *pRet = pLower; 3459 3460 while ( pRet && !pRet->IsCntntFrm() ) 3461 { 3462 SwFrm *pOld = pRet; 3463 3464 SwFrm *pTmp = pRet; // To skip empty section frames 3465 while ( pRet->GetNext() ) 3466 { 3467 pRet = pRet->GetNext(); 3468 if( !pRet->IsSctFrm() || ((SwSectionFrm*)pRet)->GetSection() ) 3469 pTmp = pRet; 3470 } 3471 pRet = pTmp; 3472 3473 if ( pRet->GetLower() ) 3474 pRet = pRet->GetLower(); 3475 if ( pRet == pOld ) 3476 { 3477 // Wenn am Ende der letzten Zelle ein spaltiger Bereich steht, 3478 // der eine leere letzte Spalte hat, muessen wir noch die anderen 3479 // Spalten abklappern, dies erledigt SwSectionFrm::FindLastCntnt 3480 if( pRet->IsColBodyFrm() ) 3481 { 3482 #ifdef DBG_UTIL 3483 SwSectionFrm* pSect = pRet->FindSctFrm(); 3484 ASSERT( pSect, "Wo kommt denn die Spalte her?") 3485 ASSERT( IsAnLower( pSect ), "Gespaltene Zelle?" ); 3486 #endif 3487 return pRet->FindSctFrm()->FindLastCntnt(); 3488 } 3489 3490 // 3491 // pRet may be a cell frame without a lower (cell has been split). 3492 // We have to find the last content the hard way: 3493 // 3494 ASSERT( pRet->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" ) 3495 const SwFrm* pRow = pRet->GetUpper(); 3496 while ( pRow && !pRow->GetUpper()->IsTabFrm() ) 3497 pRow = pRow->GetUpper(); 3498 SwCntntFrm* pCntntFrm = ((SwLayoutFrm*)pRow)->ContainsCntnt(); 3499 pRet = 0; 3500 3501 while ( pCntntFrm && ((SwLayoutFrm*)pRow)->IsAnLower( pCntntFrm ) ) 3502 { 3503 pRet = pCntntFrm; 3504 pCntntFrm = pCntntFrm->GetNextCntntFrm(); 3505 } 3506 } 3507 } 3508 3509 // #112929# There actually is a situation, which results in pRet = 0: 3510 // Insert frame, insert table via text <-> table. This gives you a frame 3511 // containing a table without any other content frames. Split the table 3512 // and undo the splitting. This operation gives us a table frame without 3513 // a lower. 3514 if ( pRet ) 3515 { 3516 while ( pRet->GetNext() ) 3517 pRet = pRet->GetNext(); 3518 3519 if( pRet->IsSctFrm() ) 3520 pRet = ((SwSectionFrm*)pRet)->FindLastCntnt(); 3521 } 3522 3523 return (SwCntntFrm*)pRet; 3524 } 3525 3526 /************************************************************************* 3527 |* 3528 |* SwTabFrm::GetLeaf() 3529 |* 3530 |* Ersterstellung MA 19. Mar. 93 3531 |* Letzte Aenderung MA 25. Apr. 95 3532 |* 3533 |*************************************************************************/ 3534 SwLayoutFrm *SwTabFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd ) 3535 { 3536 SwLayoutFrm *pRet; 3537 if ( bFwd ) 3538 { 3539 pRet = GetNextLeaf( eMakePage ); 3540 while ( IsAnLower( pRet ) ) 3541 pRet = pRet->GetNextLeaf( eMakePage ); 3542 } 3543 else 3544 pRet = GetPrevLeaf(); 3545 if ( pRet ) 3546 pRet->Calc(); 3547 return pRet; 3548 } 3549 3550 /************************************************************************* 3551 |* 3552 |* SwTabFrm::ShouldBwdMoved() 3553 |* 3554 |* Beschreibung Returnwert sagt ob der Frm verschoben werden sollte 3555 |* Ersterstellung MA 10. Jul. 95 3556 |* Letzte Aenderung MA 04. Mar. 97 3557 |* 3558 |*************************************************************************/ 3559 sal_Bool SwTabFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool &rReformat ) 3560 { 3561 rReformat = sal_False; 3562 if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) ) 3563 { 3564 //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv. 3565 //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen 3566 //moechte die FixSize die gleiche ist, die der Frm selbst hat. 3567 //In diesem Fall kann einfach geprueft werden, ob der Frm genug 3568 //Platz fuer seine VarSize findet, ist dies nicht der Fall kann 3569 //gleich auf das Verschieben verzichtet werden. 3570 //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst 3571 //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise 3572 //aufspalten kann. 3573 //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind 3574 //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn 3575 //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt 3576 //etwas Platz zur Verfuegung steht). 3577 3578 //Die FixSize der Umgebungen in denen Tabellen herumlungern ist immer 3579 //Die Breite. 3580 3581 SwPageFrm *pOldPage = FindPageFrm(), 3582 *pNewPage = pNewUpper->FindPageFrm(); 3583 sal_Bool bMoveAnyway = sal_False; 3584 SwTwips nSpace = 0; 3585 3586 SWRECTFN( this ) 3587 if ( !SwFlowFrm::IsMoveBwdJump() ) 3588 { 3589 3590 long nOldWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)(); 3591 SWRECTFNX( pNewUpper ); 3592 long nNewWidth = (pNewUpper->Prt().*fnRectX->fnGetWidth)(); 3593 if( Abs( nNewWidth - nOldWidth ) < 2 ) 3594 { 3595 if( sal_False == 3596 ( bMoveAnyway = BwdMoveNecessary( pOldPage, Frm() ) > 1 ) ) 3597 { 3598 SwRect aRect( pNewUpper->Prt() ); 3599 aRect.Pos() += pNewUpper->Frm().Pos(); 3600 const SwFrm *pPrevFrm = pNewUpper->Lower(); 3601 while ( pPrevFrm && pPrevFrm != this ) 3602 { 3603 (aRect.*fnRectX->fnSetTop)( (pPrevFrm->Frm().*fnRectX-> 3604 fnGetBottom)() ); 3605 pPrevFrm = pPrevFrm->GetNext(); 3606 } 3607 bMoveAnyway = BwdMoveNecessary( pNewPage, aRect) > 1; 3608 3609 // --> FME 2006-01-20 #i54861# Due to changes made in PrepareMake, 3610 // the tabfrm may not have a correct position. Therefore 3611 // it is possible that pNewUpper->Prt().Height == 0. In this 3612 // case the above calculation of nSpace might give wrong 3613 // results and we really do not want to MoveBackwrd into a 3614 // 0 height frame. If nTmpSpace is already <= 0, we take this 3615 // value: 3616 const SwTwips nTmpSpace = (aRect.*fnRectX->fnGetHeight)(); 3617 if ( (pNewUpper->Prt().*fnRectX->fnGetHeight)() > 0 || nTmpSpace <= 0 ) 3618 nSpace = nTmpSpace; 3619 // <-- 3620 3621 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 3622 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 3623 nSpace += pNewUpper->Grow( LONG_MAX, sal_True ); 3624 } 3625 } 3626 else if( !bLockBackMove ) 3627 bMoveAnyway = sal_True; 3628 } 3629 else if( !bLockBackMove ) 3630 bMoveAnyway = sal_True; 3631 3632 if ( bMoveAnyway ) 3633 return rReformat = sal_True; 3634 else if ( !bLockBackMove && nSpace > 0 ) 3635 { 3636 // --> OD 2004-10-05 #i26945# - check, if follow flow line 3637 // contains frame, which are moved forward due to its object 3638 // positioning. 3639 SwRowFrm* pFirstRow = GetFirstNonHeadlineRow(); 3640 if ( pFirstRow && pFirstRow->IsInFollowFlowRow() && 3641 SwLayouter::DoesRowContainMovedFwdFrm( 3642 *(pFirstRow->GetFmt()->GetDoc()), 3643 *(pFirstRow) ) ) 3644 { 3645 return sal_False; 3646 } 3647 // <-- 3648 SwTwips nTmpHeight = CalcHeightOfFirstContentLine(); 3649 3650 // --> FME 2005-01-17 #118840# 3651 // For some mysterious reason, I changed the good old 3652 // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'. 3653 // This obviously results in problems with table frames in 3654 // sections. Remember: Every twip is sacred. 3655 return nTmpHeight <= nSpace; 3656 // <-- 3657 } 3658 } 3659 return sal_False; 3660 } 3661 3662 /************************************************************************* 3663 |* 3664 |* SwTabFrm::Cut() 3665 |* 3666 |* Ersterstellung MA 23. Feb. 94 3667 |* Letzte Aenderung MA 09. Sep. 98 3668 |* 3669 |*************************************************************************/ 3670 void SwTabFrm::Cut() 3671 { 3672 ASSERT( GetUpper(), "Cut ohne Upper()." ); 3673 3674 SwPageFrm *pPage = FindPageFrm(); 3675 InvalidatePage( pPage ); 3676 SwFrm *pFrm = GetNext(); 3677 if( pFrm ) 3678 { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger 3679 //berechnet der ist jetzt wo er der erste wird obsolete 3680 pFrm->_InvalidatePrt(); 3681 pFrm->_InvalidatePos(); 3682 if ( pFrm->IsCntntFrm() ) 3683 pFrm->InvalidatePage( pPage ); 3684 if( IsInSct() && !GetPrev() ) 3685 { 3686 SwSectionFrm* pSct = FindSctFrm(); 3687 if( !pSct->IsFollow() ) 3688 { 3689 pSct->_InvalidatePrt(); 3690 pSct->InvalidatePage( pPage ); 3691 } 3692 } 3693 } 3694 else 3695 { 3696 InvalidateNextPos(); 3697 //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper 3698 if ( 0 != (pFrm = GetPrev()) ) 3699 { pFrm->SetRetouche(); 3700 pFrm->Prepare( PREP_WIDOWS_ORPHANS ); 3701 pFrm->_InvalidatePos(); 3702 if ( pFrm->IsCntntFrm() ) 3703 pFrm->InvalidatePage( pPage ); 3704 } 3705 //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss 3706 //er die Retouche uebernehmen. 3707 //Ausserdem kann eine Leerseite entstanden sein. 3708 else 3709 { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper(); 3710 pRoot->SetSuperfluous(); 3711 GetUpper()->SetCompletePaint(); 3712 if( IsInSct() ) 3713 { 3714 SwSectionFrm* pSct = FindSctFrm(); 3715 if( !pSct->IsFollow() ) 3716 { 3717 pSct->_InvalidatePrt(); 3718 pSct->InvalidatePage( pPage ); 3719 } 3720 } 3721 } 3722 } 3723 3724 //Erst removen, dann Upper Shrinken. 3725 SwLayoutFrm *pUp = GetUpper(); 3726 SWRECTFN( this ) 3727 Remove(); 3728 if ( pUp ) 3729 { 3730 ASSERT( !pUp->IsFtnFrm(), "Tabelle in Fussnote." ); 3731 SwSectionFrm *pSct = 0; 3732 // --> OD 2006-01-04 #126020# - adjust check for empty section 3733 // --> OD 2006-02-01 #130797# - correct fix #126020# 3734 if ( !pUp->Lower() && pUp->IsInSct() && 3735 !(pSct = pUp->FindSctFrm())->ContainsCntnt() && 3736 !pSct->ContainsAny( true ) ) 3737 // <-- 3738 { 3739 if ( pUp->GetUpper() ) 3740 { 3741 pSct->DelEmpty( sal_False ); 3742 pSct->_InvalidateSize(); 3743 } 3744 } 3745 else if( (Frm().*fnRect->fnGetHeight)() ) 3746 { 3747 // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section - 3748 // undo changes of fix for #104992# 3749 pUp->Shrink( Frm().Height() ); 3750 } 3751 } 3752 3753 if ( pPage && !IsFollow() && pPage->GetUpper() ) 3754 ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth(); 3755 } 3756 3757 /************************************************************************* 3758 |* 3759 |* SwTabFrm::Paste() 3760 |* 3761 |* Ersterstellung MA 23. Feb. 94 3762 |* Letzte Aenderung MA 09. Sep. 98 3763 |* 3764 |*************************************************************************/ 3765 void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling ) 3766 { 3767 ASSERT( pParent, "Kein Parent fuer Paste." ); 3768 ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." ); 3769 ASSERT( pParent != this, "Bin selbst der Parent." ); 3770 ASSERT( pSibling != this, "Bin mein eigener Nachbar." ); 3771 ASSERT( !GetPrev() && !GetNext() && !GetUpper(), 3772 "Bin noch irgendwo angemeldet." ); 3773 3774 //In den Baum einhaengen. 3775 InsertBefore( (SwLayoutFrm*)pParent, pSibling ); 3776 3777 _InvalidateAll(); 3778 SwPageFrm *pPage = FindPageFrm(); 3779 InvalidatePage( pPage ); 3780 3781 if ( GetNext() ) 3782 { 3783 GetNext()->_InvalidatePos(); 3784 GetNext()->_InvalidatePrt(); 3785 if ( GetNext()->IsCntntFrm() ) 3786 GetNext()->InvalidatePage( pPage ); 3787 } 3788 3789 SWRECTFN( this ) 3790 if( (Frm().*fnRect->fnGetHeight)() ) 3791 pParent->Grow( (Frm().*fnRect->fnGetHeight)() ); 3792 3793 if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)() ) 3794 Prepare( PREP_FIXSIZE_CHG ); 3795 if ( GetPrev() ) 3796 { 3797 if ( !IsFollow() ) 3798 { 3799 GetPrev()->InvalidateSize(); 3800 if ( GetPrev()->IsCntntFrm() ) 3801 GetPrev()->InvalidatePage( pPage ); 3802 } 3803 } 3804 else if ( GetNext() ) 3805 //Bei CntntFrm's gilt es den Abstand zum Vorgaenger/Nachfolger 3806 //zu beachten. Faelle (beide treten immer gleichzeitig auf): 3807 //a) Der Cntnt wird der erste einer Kette 3808 //b) Der neue Nachfolger war vorher der erste einer Kette 3809 GetNext()->_InvalidatePrt(); 3810 3811 if ( pPage && !IsFollow() ) 3812 { 3813 if ( pPage->GetUpper() ) 3814 ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth(); 3815 3816 if ( !GetPrev() )//Mindestens fuer HTML mit Tabelle am Anfang notwendig. 3817 { 3818 const SwPageDesc *pDesc = GetFmt()->GetPageDesc().GetPageDesc(); 3819 if ( (pDesc && pDesc != pPage->GetPageDesc()) || 3820 (!pDesc && pPage->GetPageDesc() != 3821 &(const_cast<const SwDoc *>(GetFmt()->GetDoc()) 3822 ->GetPageDesc(0))) ) 3823 CheckPageDescs( pPage, sal_True ); 3824 } 3825 } 3826 } 3827 3828 /************************************************************************* 3829 |* 3830 |* SwTabFrm::Prepare() 3831 |* 3832 |* Created AMA 01/10/02 3833 |* Last Change AMA 01/10/02 3834 |* 3835 |*************************************************************************/ 3836 void SwTabFrm::Prepare( const PrepareHint eHint, const void *, sal_Bool ) 3837 { 3838 if( PREP_BOSS_CHGD == eHint ) 3839 CheckDirChange(); 3840 } 3841 3842 /************************************************************************* 3843 |* 3844 |* SwRowFrm::SwRowFrm(), ~SwRowFrm() 3845 |* 3846 |* Ersterstellung MA 09. Mar. 93 3847 |* Letzte Aenderung MA 30. May. 96 3848 |* 3849 |*************************************************************************/ 3850 SwRowFrm::SwRowFrm( const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent ): 3851 SwLayoutFrm( rLine.GetFrmFmt(), pSib ), 3852 pTabLine( &rLine ), 3853 pFollowRow( 0 ), 3854 // --> collapsing borders FME 2005-05-27 #i29550# 3855 mnTopMarginForLowers( 0 ), 3856 mnBottomMarginForLowers( 0 ), 3857 mnBottomLineSize( 0 ), 3858 // <-- collapsing 3859 // --> split table rows 3860 bIsFollowFlowRow( false ), 3861 // <-- split table rows 3862 bIsRepeatedHeadline( false ), 3863 mbIsRowSpanLine( false ) 3864 { 3865 nType = FRMC_ROW; 3866 3867 //Gleich die Boxen erzeugen und einfuegen. 3868 const SwTableBoxes &rBoxes = rLine.GetTabBoxes(); 3869 SwFrm *pTmpPrev = 0; 3870 for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i ) 3871 { 3872 SwCellFrm *pNew = new SwCellFrm( *rBoxes[i], this, bInsertContent ); 3873 pNew->InsertBehind( this, pTmpPrev ); 3874 pTmpPrev = pNew; 3875 } 3876 } 3877 3878 SwRowFrm::~SwRowFrm() 3879 { 3880 SwModify* pMod = GetFmt(); 3881 if( pMod ) 3882 { 3883 pMod->Remove( this ); // austragen, 3884 if( !pMod->GetDepends() ) 3885 delete pMod; // und loeschen 3886 } 3887 } 3888 3889 /************************************************************************* 3890 |* 3891 |* SwRowFrm::RegistFlys() 3892 |* 3893 |* Ersterstellung MA 08. Jul. 93 3894 |* Letzte Aenderung MA 08. Jul. 93 3895 |* 3896 |*************************************************************************/ 3897 void SwRowFrm::RegistFlys( SwPageFrm *pPage ) 3898 { 3899 ::RegistFlys( pPage ? pPage : FindPageFrm(), this ); 3900 } 3901 3902 /************************************************************************* 3903 |* 3904 |* SwRowFrm::Modify() 3905 |* 3906 |* Ersterstellung MA 12. Nov. 97 3907 |* Letzte Aenderung MA 12. Nov. 97 3908 |* 3909 |*************************************************************************/ 3910 void SwRowFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) 3911 { 3912 sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which(); 3913 const SfxPoolItem *pItem = 0; 3914 3915 if( bAttrSetChg ) 3916 { 3917 const SwAttrSet* pChgSet = ((SwAttrSetChg*)pNew)->GetChgSet(); 3918 pChgSet->GetItemState( RES_FRM_SIZE, sal_False, &pItem); 3919 if ( !pItem ) 3920 pChgSet->GetItemState( RES_ROW_SPLIT, sal_False, &pItem); 3921 } 3922 else if ( RES_FRM_SIZE == pNew->Which() || RES_ROW_SPLIT == pNew->Which() ) 3923 pItem = pNew; 3924 3925 if ( pItem ) 3926 { 3927 SwTabFrm *pTab = FindTabFrm(); 3928 if ( pTab ) 3929 { 3930 const bool bInFirstNonHeadlineRow = pTab->IsFollow() && 3931 this == pTab->GetFirstNonHeadlineRow(); 3932 // --> FME 2004-10-27 #i35063# 3933 // Invalidation required is pRow is last row 3934 if ( bInFirstNonHeadlineRow || !GetNext() ) 3935 // <-- 3936 { 3937 if ( bInFirstNonHeadlineRow ) 3938 pTab = pTab->FindMaster(); 3939 pTab->InvalidatePos(); 3940 } 3941 } 3942 } 3943 3944 SwLayoutFrm::Modify( pOld, pNew ); 3945 } 3946 3947 3948 3949 /************************************************************************* 3950 |* 3951 |* SwRowFrm::MakeAll() 3952 |* 3953 |* Ersterstellung MA 01. Mar. 94 3954 |* Letzte Aenderung MA 01. Mar. 94 3955 |* 3956 |*************************************************************************/ 3957 void SwRowFrm::MakeAll() 3958 { 3959 if ( !GetNext() ) 3960 bValidSize = sal_False; 3961 SwLayoutFrm::MakeAll(); 3962 } 3963 3964 /************************************************************************* 3965 |* 3966 |* SwRowFrm::Format() 3967 |* 3968 |* Ersterstellung MA 13. Mar. 93 3969 |* Letzte Aenderung MA 20. Jun. 96 3970 |* 3971 |*************************************************************************/ 3972 long MA_FASTCALL CalcHeightWidthFlys( const SwFrm *pFrm ) 3973 { 3974 SWRECTFN( pFrm ) 3975 long nHeight = 0; 3976 const SwFrm* pTmp = pFrm->IsSctFrm() ? 3977 ((SwSectionFrm*)pFrm)->ContainsCntnt() : pFrm; 3978 while( pTmp ) 3979 { 3980 // --> OD 2004-10-08 #i26945# - consider follow text frames 3981 const SwSortedObjs* pObjs( 0L ); 3982 bool bIsFollow( false ); 3983 if ( pTmp->IsTxtFrm() && static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) 3984 { 3985 const SwFrm* pMaster; 3986 // --> FME 2005-04-01 #i46450# Master does not necessarily have 3987 // to exist if this function is called from JoinFrm() -> 3988 // Cut() -> Shrink() 3989 const SwTxtFrm* pTmpFrm = static_cast<const SwTxtFrm*>(pTmp); 3990 if ( pTmpFrm->GetPrev() && pTmpFrm->GetPrev()->IsTxtFrm() && 3991 static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() && 3992 static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() != pTmp ) 3993 pMaster = 0; 3994 else 3995 pMaster = pTmpFrm->FindMaster(); 3996 3997 if ( pMaster ) 3998 { 3999 pObjs = static_cast<const SwTxtFrm*>(pTmp)->FindMaster()->GetDrawObjs(); 4000 bIsFollow = true; 4001 } 4002 } 4003 else 4004 { 4005 pObjs = pTmp->GetDrawObjs(); 4006 } 4007 if ( pObjs ) 4008 // <-- 4009 { 4010 for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i ) 4011 { 4012 const SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; 4013 // --> OD 2004-10-08 #i26945# - if <pTmp> is follow, the 4014 // anchor character frame has to be <pTmp>. 4015 if ( bIsFollow && 4016 const_cast<SwAnchoredObject*>(pAnchoredObj)->FindAnchorCharFrm() != pTmp ) 4017 { 4018 continue; 4019 } 4020 // <-- 4021 // --> OD 2004-10-04 #i26945# - consider also drawing objects 4022 { 4023 // OD 30.09.2003 #i18732# - only objects, which follow 4024 // the text flow have to be considered. 4025 const SwFrmFmt& rFrmFmt = pAnchoredObj->GetFrmFmt(); 4026 const bool bConsiderObj = 4027 (rFrmFmt.GetAnchor().GetAnchorId() != FLY_AS_CHAR) && 4028 pAnchoredObj->GetObjRect().Top() != WEIT_WECH && 4029 rFrmFmt.GetFollowTextFlow().GetValue() && 4030 pAnchoredObj->GetPageFrm() == pTmp->FindPageFrm(); 4031 if ( bConsiderObj ) 4032 { 4033 const SwFmtFrmSize &rSz = rFrmFmt.GetFrmSize(); 4034 if( !rSz.GetHeightPercent() ) 4035 { 4036 const SwTwips nDistOfFlyBottomToAnchorTop = 4037 (pAnchoredObj->GetObjRect().*fnRect->fnGetHeight)() + 4038 ( bVert ? 4039 pAnchoredObj->GetCurrRelPos().X() : 4040 pAnchoredObj->GetCurrRelPos().Y() ); 4041 4042 const SwTwips nFrmDiff = 4043 (*fnRect->fnYDiff)( 4044 (pTmp->Frm().*fnRect->fnGetTop)(), 4045 (pFrm->Frm().*fnRect->fnGetTop)() ); 4046 4047 nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop + nFrmDiff - 4048 (pFrm->Frm().*fnRect->fnGetHeight)() ); 4049 4050 // --> FME 2006-01-24 #i56115# The first height calculation 4051 // gives wrong results if pFrm->Prt().Y() > 0. We do 4052 // a second calculation based on the actual rectangles of 4053 // pFrm and pAnchoredObj, and use the maximum of the results. 4054 // I do not want to remove the first calculation because 4055 // if clipping has been applied, using the GetCurrRelPos 4056 // might be the better option to calculate nHeight. 4057 const SwTwips nDistOfFlyBottomToAnchorTop2 = (*fnRect->fnYDiff)( 4058 (pAnchoredObj->GetObjRect().*fnRect->fnGetBottom)(), 4059 (pFrm->Frm().*fnRect->fnGetBottom)() ); 4060 4061 nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop2 ); 4062 // <-- 4063 } 4064 } 4065 } 4066 // <-- 4067 } 4068 } 4069 if( !pFrm->IsSctFrm() ) 4070 break; 4071 pTmp = pTmp->FindNextCnt(); 4072 if( !((SwSectionFrm*)pFrm)->IsAnLower( pTmp ) ) 4073 break; 4074 } 4075 return nHeight; 4076 } 4077 4078 SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm& rCell, const SwBorderAttrs& rAttrs ) 4079 { 4080 const SwTabFrm* pTab = rCell.FindTabFrm(); 4081 SwTwips nTopSpace = 0; 4082 SwTwips nBottomSpace = 0; 4083 4084 // --> collapsing borders FME 2005-05-27 #i29550# 4085 if ( pTab->IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrm() ) 4086 { 4087 nTopSpace = ((SwRowFrm*)rCell.GetUpper())->GetTopMarginForLowers(); 4088 nBottomSpace = ((SwRowFrm*)rCell.GetUpper())->GetBottomMarginForLowers(); 4089 } 4090 // <-- collapsing 4091 else 4092 { 4093 if ( pTab->IsVertical() != rCell.IsVertical() ) 4094 { 4095 nTopSpace = rAttrs.CalcLeft( &rCell ); 4096 nBottomSpace = rAttrs.CalcRight( &rCell ); 4097 } 4098 else 4099 { 4100 nTopSpace = rAttrs.CalcTop(); 4101 nBottomSpace = rAttrs.CalcBottom(); 4102 } 4103 } 4104 4105 return nTopSpace + nBottomSpace; 4106 } 4107 4108 4109 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to 4110 // control, if floating screen objects have to be considered for the minimal 4111 // cell height. 4112 SwTwips MA_FASTCALL lcl_CalcMinCellHeight( const SwLayoutFrm *_pCell, 4113 const sal_Bool _bConsiderObjs, 4114 const SwBorderAttrs *pAttrs = 0 ) 4115 { 4116 SWRECTFN( _pCell ) 4117 SwTwips nHeight = 0; 4118 const SwFrm* pLow = _pCell->Lower(); 4119 if ( pLow ) 4120 { 4121 long nFlyAdd = 0; 4122 while ( pLow ) 4123 { 4124 // OD 2004-02-18 #106629# - change condition and switch then-body 4125 // and else-body 4126 if ( pLow->IsRowFrm() ) 4127 { 4128 // --> OD 2004-10-04 #i26945# 4129 nHeight += ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm*>(pLow), 4130 _bConsiderObjs ); 4131 // <-- 4132 } 4133 else 4134 { 4135 long nLowHeight = (pLow->Frm().*fnRect->fnGetHeight)(); 4136 nHeight += nLowHeight; 4137 // --> OD 2004-10-04 #i26945# 4138 if ( _bConsiderObjs ) 4139 { 4140 nFlyAdd = Max( 0L, nFlyAdd - nLowHeight ); 4141 nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) ); 4142 } 4143 // <-- 4144 } 4145 4146 pLow = pLow->GetNext(); 4147 } 4148 if ( nFlyAdd ) 4149 nHeight += nFlyAdd; 4150 } 4151 //Der Border will natuerlich auch mitspielen, er kann leider nicht 4152 //aus PrtArea und Frm errechnet werden, da diese in beliebiger 4153 //Kombination ungueltig sein koennen. 4154 if ( _pCell->Lower() ) 4155 { 4156 if ( pAttrs ) 4157 nHeight += lcl_CalcTopAndBottomMargin( *_pCell, *pAttrs ); 4158 else 4159 { 4160 SwBorderAttrAccess aAccess( SwFrm::GetCache(), _pCell ); 4161 const SwBorderAttrs &rAttrs = *aAccess.Get(); 4162 nHeight += lcl_CalcTopAndBottomMargin( *_pCell, rAttrs ); 4163 } 4164 } 4165 return nHeight; 4166 } 4167 4168 // OD 2004-02-18 #106629# - correct type of 1st parameter 4169 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to control, 4170 // if floating screen objects have to be considered for the minimal cell height 4171 SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm* _pRow, 4172 const sal_Bool _bConsiderObjs ) 4173 { 4174 SWRECTFN( _pRow ) 4175 4176 const SwFmtFrmSize &rSz = _pRow->GetFmt()->GetFrmSize(); 4177 4178 if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() ) 4179 { 4180 ASSERT( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" ) 4181 return rSz.GetHeight(); 4182 } 4183 4184 SwTwips nHeight = 0; 4185 const SwCellFrm* pLow = static_cast<const SwCellFrm*>(_pRow->Lower()); 4186 while ( pLow ) 4187 { 4188 SwTwips nTmp = 0; 4189 const long nRowSpan = pLow->GetLayoutRowSpan(); 4190 // --> NEW TABLES 4191 // Consider height of 4192 // 1. current cell if RowSpan == 1 4193 // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1 4194 // 3. master cell if RowSpan == -1 4195 if ( 1 == nRowSpan ) 4196 { 4197 nTmp = ::lcl_CalcMinCellHeight( pLow, _bConsiderObjs ); 4198 } 4199 else if ( -1 == nRowSpan ) 4200 { 4201 // Height of the last cell of a row span is height of master cell 4202 // minus the height of the other rows which are covered by the master 4203 // cell: 4204 const SwCellFrm& rMaster = pLow->FindStartEndOfRowSpanCell( true, true ); 4205 nTmp = ::lcl_CalcMinCellHeight( &rMaster, _bConsiderObjs ); 4206 const SwFrm* pMasterRow = rMaster.GetUpper(); 4207 while ( pMasterRow && pMasterRow != _pRow ) 4208 { 4209 nTmp -= (pMasterRow->Frm().*fnRect->fnGetHeight)(); 4210 pMasterRow = pMasterRow->GetNext(); 4211 } 4212 } 4213 // <-- NEW TABLES 4214 4215 // Do not consider rotated cells: 4216 if ( ( 0 != pLow->IsVertical() ) == ( 0 != bVert ) && nTmp > nHeight ) 4217 nHeight = nTmp; 4218 4219 pLow = static_cast<const SwCellFrm*>(pLow->GetNext()); 4220 } 4221 if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() ) 4222 nHeight = Max( nHeight, rSz.GetHeight() ); 4223 return nHeight; 4224 } 4225 4226 // --> collapsing borders FME 2005-05-27 #i29550# 4227 4228 // Calculate the maximum of (TopLineSize + TopLineDist) over all lowers: 4229 sal_uInt16 lcl_GetTopSpace( const SwRowFrm& rRow ) 4230 { 4231 sal_uInt16 nTopSpace = 0; 4232 for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower; 4233 pCurrLower = (SwCellFrm*)pCurrLower->GetNext() ) 4234 { 4235 sal_uInt16 nTmpTopSpace = 0; 4236 if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() ) 4237 nTmpTopSpace = lcl_GetTopSpace( *(SwRowFrm*)pCurrLower->Lower() ); 4238 else 4239 { 4240 const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet(); 4241 const SvxBoxItem& rBoxItem = rSet.GetBox(); 4242 nTmpTopSpace = rBoxItem.CalcLineSpace( BOX_LINE_TOP, sal_True ); 4243 } 4244 nTopSpace = Max( nTopSpace, nTmpTopSpace ); 4245 } 4246 return nTopSpace; 4247 } 4248 4249 // Calculate the maximum of TopLineDist over all lowers: 4250 sal_uInt16 lcl_GetTopLineDist( const SwRowFrm& rRow ) 4251 { 4252 sal_uInt16 nTopLineDist = 0; 4253 for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower; 4254 pCurrLower = (SwCellFrm*)pCurrLower->GetNext() ) 4255 { 4256 sal_uInt16 nTmpTopLineDist = 0; 4257 if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() ) 4258 nTmpTopLineDist = lcl_GetTopLineDist( *(SwRowFrm*)pCurrLower->Lower() ); 4259 else 4260 { 4261 const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet(); 4262 const SvxBoxItem& rBoxItem = rSet.GetBox(); 4263 nTmpTopLineDist = rBoxItem.GetDistance( BOX_LINE_TOP ); 4264 } 4265 nTopLineDist = Max( nTopLineDist, nTmpTopLineDist ); 4266 } 4267 return nTopLineDist; 4268 } 4269 4270 // Calculate the maximum of BottomLineSize over all lowers: 4271 sal_uInt16 lcl_GetBottomLineSize( const SwRowFrm& rRow ) 4272 { 4273 sal_uInt16 nBottomLineSize = 0; 4274 for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower; 4275 pCurrLower = (SwCellFrm*)pCurrLower->GetNext() ) 4276 { 4277 sal_uInt16 nTmpBottomLineSize = 0; 4278 if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() ) 4279 { 4280 const SwFrm* pRow = pCurrLower->GetLastLower(); 4281 nTmpBottomLineSize = lcl_GetBottomLineSize( *(SwRowFrm*)pRow ); 4282 } 4283 else 4284 { 4285 const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet(); 4286 const SvxBoxItem& rBoxItem = rSet.GetBox(); 4287 nTmpBottomLineSize = rBoxItem.CalcLineSpace( BOX_LINE_BOTTOM, sal_True ) - 4288 rBoxItem.GetDistance( BOX_LINE_BOTTOM ); 4289 } 4290 nBottomLineSize = Max( nBottomLineSize, nTmpBottomLineSize ); 4291 } 4292 return nBottomLineSize; 4293 } 4294 4295 // Calculate the maximum of BottomLineDist over all lowers: 4296 sal_uInt16 lcl_GetBottomLineDist( const SwRowFrm& rRow ) 4297 { 4298 sal_uInt16 nBottomLineDist = 0; 4299 for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower; 4300 pCurrLower = (SwCellFrm*)pCurrLower->GetNext() ) 4301 { 4302 sal_uInt16 nTmpBottomLineDist = 0; 4303 if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() ) 4304 { 4305 const SwFrm* pRow = pCurrLower->GetLastLower(); 4306 nTmpBottomLineDist = lcl_GetBottomLineDist( *(SwRowFrm*)pRow ); 4307 } 4308 else 4309 { 4310 const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet(); 4311 const SvxBoxItem& rBoxItem = rSet.GetBox(); 4312 nTmpBottomLineDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM ); 4313 } 4314 nBottomLineDist = Max( nBottomLineDist, nTmpBottomLineDist ); 4315 } 4316 return nBottomLineDist; 4317 } 4318 4319 // <-- collapsing 4320 4321 void SwRowFrm::Format( const SwBorderAttrs *pAttrs ) 4322 { 4323 SWRECTFN( this ) 4324 ASSERT( pAttrs, "SwRowFrm::Format ohne Attrs." ); 4325 4326 const sal_Bool bFix = bFixSize; 4327 4328 if ( !bValidPrtArea ) 4329 { 4330 //RowFrms haben keine Umrandung usw. also entspricht die PrtArea immer 4331 //dem Frm. 4332 bValidPrtArea = sal_True; 4333 aPrt.Left( 0 ); 4334 aPrt.Top( 0 ); 4335 aPrt.Width ( aFrm.Width() ); 4336 aPrt.Height( aFrm.Height() ); 4337 4338 // --> collapsing borders FME 2005-05-27 #i29550# 4339 // Here we calculate the top-printing area for the lower cell frames 4340 SwTabFrm* pTabFrm = FindTabFrm(); 4341 if ( pTabFrm->IsCollapsingBorders() ) 4342 { 4343 const sal_uInt16 nTopSpace = lcl_GetTopSpace( *this ); 4344 const sal_uInt16 nTopLineDist = lcl_GetTopLineDist( *this ); 4345 const sal_uInt16 nBottomLineSize = lcl_GetBottomLineSize( *this ); 4346 const sal_uInt16 nBottomLineDist = lcl_GetBottomLineDist( *this ); 4347 4348 4349 const SwRowFrm* pPreviousRow = 0; 4350 4351 // --> FME 2004-09-14 #i32456# 4352 // In order to calculate the top printing area for the lower cell 4353 // frames, we have to find the 'previous' row frame and compare 4354 // the bottom values of the 'previous' row with the 'top' values 4355 // of this row. The best way to find the 'previous' row is to 4356 // use the table structure: 4357 const SwTable* pTable = pTabFrm->GetTable(); 4358 const SwTableLine* pPrevTabLine = 0; 4359 const SwRowFrm* pTmpRow = this; 4360 4361 while ( pTmpRow && !pPrevTabLine ) 4362 { 4363 sal_uInt16 nIdx = 0; 4364 const SwTableLines& rLines = pTmpRow->GetTabLine()->GetUpper() ? 4365 pTmpRow->GetTabLine()->GetUpper()->GetTabLines() : 4366 pTable->GetTabLines(); 4367 4368 while ( rLines[ nIdx ] != pTmpRow->GetTabLine() ) 4369 ++nIdx; 4370 4371 if ( nIdx > 0 ) 4372 { 4373 // pTmpRow has a 'previous' row in the table structure: 4374 pPrevTabLine = rLines[ nIdx - 1 ]; 4375 } 4376 else 4377 { 4378 // pTmpRow is a first row in the table structue. 4379 // We go up in the table structure: 4380 pTmpRow = pTmpRow->GetUpper()->GetUpper() && 4381 pTmpRow->GetUpper()->GetUpper()->IsRowFrm() ? 4382 static_cast<const SwRowFrm*>( pTmpRow->GetUpper()->GetUpper() ) : 4383 0; 4384 } 4385 } 4386 4387 // If we found a 'previous' row, we look for the appropriate row frame: 4388 if ( pPrevTabLine ) 4389 { 4390 SwIterator<SwRowFrm,SwFmt> aIter( *pPrevTabLine->GetFrmFmt() ); 4391 for ( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() ) 4392 { 4393 // --> OD 2004-11-23 #115759# - do *not* take repeated 4394 // headlines, because during split of table it can be 4395 // invalid and thus can't provide correct border values. 4396 if ( pRow->GetTabLine() == pPrevTabLine && 4397 !pRow->IsRepeatedHeadline() ) 4398 // <-- 4399 { 4400 pPreviousRow = pRow; 4401 break; 4402 } 4403 } 4404 } 4405 // <-- 4406 4407 sal_uInt16 nTopPrtMargin = nTopSpace; 4408 if ( pPreviousRow ) 4409 { 4410 const sal_uInt16 nTmpPrtMargin = pPreviousRow->GetBottomLineSize() + nTopLineDist; 4411 if ( nTmpPrtMargin > nTopPrtMargin ) 4412 nTopPrtMargin = nTmpPrtMargin; 4413 } 4414 4415 // table has to be notified if it has to change its lower 4416 // margin due to changes of nBottomLineSize: 4417 if ( !GetNext() && nBottomLineSize != GetBottomLineSize() ) 4418 pTabFrm->_InvalidatePrt(); 4419 4420 // If there are rows nested inside this row, the nested rows 4421 // may not have been calculated yet. Therefore the 4422 // ::lcl_CalcMinRowHeight( this ) operation later in this 4423 // function cannot consider the correct border values. We 4424 // have to trigger the invalidation of the outer row frame 4425 // manually: 4426 // Note: If any further invalidations should be necessary, we 4427 // should consider moving the invalidation stuff to the 4428 // appropriate SwNotify object. 4429 if ( GetUpper()->GetUpper()->IsRowFrm() && 4430 ( nBottomLineDist != GetBottomMarginForLowers() || 4431 nTopPrtMargin != GetTopMarginForLowers() ) ) 4432 GetUpper()->GetUpper()->_InvalidateSize(); 4433 4434 SetBottomMarginForLowers( nBottomLineDist ); // 3. 4435 SetBottomLineSize( nBottomLineSize ); // 4. 4436 SetTopMarginForLowers( nTopPrtMargin ); // 5. 4437 4438 } 4439 // <-- collapsing 4440 } 4441 4442 while ( !bValidSize ) 4443 { 4444 bValidSize = sal_True; 4445 4446 #ifdef DBG_UTIL 4447 if ( HasFixSize() ) 4448 { 4449 const SwFmtFrmSize &rFrmSize = GetFmt()->GetFrmSize(); 4450 ASSERT( rFrmSize.GetSize().Height() > 0, "Hat ihn" ); 4451 } 4452 #endif 4453 const SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - 4454 ( HasFixSize() && !IsRowSpanLine() 4455 ? pAttrs->GetSize().Height() 4456 // --> OD 2004-10-04 #i26945# 4457 : ::lcl_CalcMinRowHeight( this, 4458 FindTabFrm()->IsConsiderObjsForMinCellHeight() ) ); 4459 // <-- 4460 if ( nDiff ) 4461 { 4462 bFixSize = sal_False; 4463 if ( nDiff > 0 ) 4464 Shrink( nDiff, sal_False, sal_True ); 4465 else if ( nDiff < 0 ) 4466 Grow( -nDiff ); 4467 bFixSize = bFix; 4468 } 4469 } 4470 4471 // last row will fill the space in its upper. 4472 if ( !GetNext() ) 4473 { 4474 //Der letzte fuellt den verbleibenden Raum im Upper aus. 4475 SwTwips nDiff = (GetUpper()->Prt().*fnRect->fnGetHeight)(); 4476 SwFrm *pSibling = GetUpper()->Lower(); 4477 do 4478 { nDiff -= (pSibling->Frm().*fnRect->fnGetHeight)(); 4479 pSibling = pSibling->GetNext(); 4480 } while ( pSibling ); 4481 if ( nDiff > 0 ) 4482 { 4483 bFixSize = sal_False; 4484 Grow( nDiff ); 4485 bFixSize = bFix; 4486 bValidSize = sal_True; 4487 } 4488 } 4489 } 4490 4491 /************************************************************************* 4492 |* 4493 |* SwRowFrm::AdjustCells() 4494 |* 4495 |* Ersterstellung MA 10. Aug. 93 4496 |* Letzte Aenderung MA 16. Dec. 96 4497 |* 4498 |*************************************************************************/ 4499 void SwRowFrm::AdjustCells( const SwTwips nHeight, const sal_Bool bHeight ) 4500 { 4501 SwFrm *pFrm = Lower(); 4502 if ( bHeight ) 4503 { 4504 SwRootFrm *pRootFrm = getRootFrm(); 4505 SWRECTFN( this ) 4506 SwRect aOldFrm; 4507 4508 while ( pFrm ) 4509 { 4510 SwFrm* pNotify = 0; 4511 4512 SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pFrm); 4513 4514 // NEW TABLES 4515 // Which cells need to be adjusted if the current row changes 4516 // its height? 4517 4518 // Current frame is a covered frame: 4519 // Set new height for covered cell and adjust master cell: 4520 if ( pCellFrm->GetTabBox()->getRowSpan() < 1 ) 4521 { 4522 // Set height of current (covered) cell to new line height. 4523 const long nDiff = nHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)(); 4524 if ( nDiff ) 4525 { 4526 (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff ); 4527 pCellFrm->_InvalidatePrt(); 4528 } 4529 } 4530 4531 SwCellFrm* pToAdjust = 0; 4532 SwFrm* pToAdjustRow = 0; 4533 4534 // If current frame is covered frame, we still want to adjust the 4535 // height of the cell starting the row span 4536 if ( pCellFrm->GetLayoutRowSpan() < 1 ) 4537 { 4538 pToAdjust = const_cast< SwCellFrm*>(&pCellFrm->FindStartEndOfRowSpanCell( true, true )); 4539 pToAdjustRow = pToAdjust->GetUpper(); 4540 } 4541 else 4542 { 4543 pToAdjust = pCellFrm; 4544 pToAdjustRow = this; 4545 } 4546 4547 // Set height of master cell to height of all lines spanned by this line. 4548 long nRowSpan = pToAdjust->GetLayoutRowSpan(); 4549 SwTwips nSumRowHeight = 0; 4550 while ( pToAdjustRow ) 4551 { 4552 // Use new height for the current row: 4553 nSumRowHeight += pToAdjustRow == this ? 4554 nHeight : 4555 (pToAdjustRow->Frm().*fnRect->fnGetHeight)(); 4556 4557 if ( nRowSpan-- == 1 ) 4558 break; 4559 4560 pToAdjustRow = pToAdjustRow->GetNext(); 4561 } 4562 4563 if ( pToAdjustRow && pToAdjustRow != this ) 4564 pToAdjustRow->_InvalidateSize(); 4565 4566 const long nDiff = nSumRowHeight - (pToAdjust->Frm().*fnRect->fnGetHeight)(); 4567 if ( nDiff ) 4568 { 4569 aOldFrm = pToAdjust->Frm(); 4570 (pToAdjust->Frm().*fnRect->fnAddBottom)( nDiff ); 4571 pNotify = pToAdjust; 4572 } 4573 4574 if ( pNotify ) 4575 { 4576 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && pRootFrm->GetCurrShell() ) 4577 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify, aOldFrm ); 4578 4579 pNotify->_InvalidatePrt(); 4580 } 4581 4582 pFrm = pFrm->GetNext(); 4583 } 4584 } 4585 else 4586 { while ( pFrm ) 4587 { 4588 pFrm->_InvalidateAll(); 4589 pFrm = pFrm->GetNext(); 4590 } 4591 } 4592 InvalidatePage(); 4593 } 4594 4595 /************************************************************************* 4596 |* 4597 |* SwRowFrm::Cut() 4598 |* 4599 |* Ersterstellung MA 12. Nov. 97 4600 |* Letzte Aenderung MA 12. Nov. 97 4601 |* 4602 |*************************************************************************/ 4603 void SwRowFrm::Cut() 4604 { 4605 SwTabFrm *pTab = FindTabFrm(); 4606 if ( pTab && pTab->IsFollow() && this == pTab->GetFirstNonHeadlineRow() ) 4607 { 4608 pTab->FindMaster()->InvalidatePos(); 4609 } 4610 4611 // --> OD 2010-02-17 #i103961# 4612 // notification for accessibility 4613 { 4614 SwRootFrm *pRootFrm = getRootFrm(); 4615 if( pRootFrm && pRootFrm->IsAnyShellAccessible() ) 4616 { 4617 ViewShell* pVSh = pRootFrm->GetCurrShell(); 4618 if ( pVSh && pVSh->Imp() ) 4619 { 4620 SwFrm* pCellFrm( GetLower() ); 4621 while ( pCellFrm ) 4622 { 4623 ASSERT( pCellFrm->IsCellFrm(), 4624 "<SwRowFrm::Cut()> - unexpected type of SwRowFrm lower." ); 4625 pVSh->Imp()->DisposeAccessibleFrm( pCellFrm ); 4626 4627 pCellFrm = pCellFrm->GetNext(); 4628 } 4629 } 4630 } 4631 } 4632 // <-- 4633 4634 SwLayoutFrm::Cut(); 4635 } 4636 4637 /************************************************************************* 4638 |* 4639 |* SwRowFrm::GrowFrm() 4640 |* 4641 |* Ersterstellung MA 15. Mar. 93 4642 |* Letzte Aenderung MA 05. May. 94 4643 |* 4644 |*************************************************************************/ 4645 4646 4647 SwTwips SwRowFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo ) 4648 { 4649 SwTwips nReal = 0; 4650 4651 SwTabFrm* pTab = FindTabFrm(); 4652 SWRECTFN( pTab ) 4653 4654 bool bRestrictTableGrowth; 4655 bool bHasFollowFlowLine = pTab->HasFollowFlowLine(); 4656 4657 if ( GetUpper()->IsTabFrm() ) 4658 { 4659 const SwRowFrm* pFollowFlowRow = IsInSplitTableRow(); 4660 bRestrictTableGrowth = pFollowFlowRow && !pFollowFlowRow->IsRowSpanLine(); 4661 } 4662 else 4663 { 4664 ASSERT( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" ) 4665 bRestrictTableGrowth = GetFollowRow() && bHasFollowFlowLine; 4666 ASSERT( !bRestrictTableGrowth || !GetNext(), 4667 "GetFollowRow for row frame that has a Next" ) 4668 4669 // 4670 // There may still be some space left in my direct upper: 4671 // 4672 const SwTwips nAdditionalSpace = 4673 (Frm().*fnRect->fnBottomDist)( (GetUpper()->GetUpper()->*fnRect->fnGetPrtBottom)() ); 4674 if ( bRestrictTableGrowth && nAdditionalSpace > 0 ) 4675 { 4676 nReal = Min( nAdditionalSpace, nDist ); 4677 nDist -= nReal; 4678 if ( !bTst ) 4679 (Frm().*fnRect->fnAddBottom)( nReal ); 4680 } 4681 } 4682 4683 if ( bRestrictTableGrowth ) 4684 pTab->SetRestrictTableGrowth( sal_True ); 4685 else 4686 { 4687 // Ok, this looks like a hack, indeed, it is a hack. 4688 // If the current row frame is inside another cell frame, 4689 // and the current row frame has no follow, it should not 4690 // be allowed to grow. In fact, setting bRestrictTableGrowth 4691 // to 'false' does not work, because the surrounding RowFrm 4692 // would set this to 'true'. 4693 pTab->SetFollowFlowLine( sal_False ); 4694 } 4695 4696 nReal += SwLayoutFrm::GrowFrm( nDist, bTst, bInfo); 4697 4698 pTab->SetRestrictTableGrowth( sal_False ); 4699 pTab->SetFollowFlowLine( bHasFollowFlowLine ); 4700 4701 //Hoehe der Zellen auf den neuesten Stand bringen. 4702 if ( !bTst ) 4703 { 4704 SWRECTFNX( this ) 4705 AdjustCells( (Prt().*fnRectX->fnGetHeight)() + nReal, sal_True ); 4706 if ( nReal ) 4707 SetCompletePaint(); 4708 } 4709 4710 return nReal; 4711 } 4712 4713 /************************************************************************* 4714 |* 4715 |* SwRowFrm::ShrinkFrm() 4716 |* 4717 |* Ersterstellung MA 15. Mar. 93 4718 |* Letzte Aenderung MA 20. Jun. 96 4719 |* 4720 |*************************************************************************/ 4721 SwTwips SwRowFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo ) 4722 { 4723 SWRECTFN( this ) 4724 if( HasFixSize() ) 4725 { 4726 AdjustCells( (Prt().*fnRect->fnGetHeight)(), sal_True ); 4727 return 0L; 4728 } 4729 4730 //bInfo wird ggf. vom SwRowFrm::Format auf sal_True gesetzt, hier muss dann 4731 //entsprechend reagiert werden 4732 const sal_Bool bShrinkAnyway = bInfo; 4733 4734 //Nur soweit Shrinken, wie es der Inhalt der groessten Zelle zulaesst. 4735 SwTwips nRealDist = nDist; 4736 { 4737 const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize(); 4738 SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? 4739 rSz.GetHeight() : 4740 0; 4741 4742 // Only necessary to calculate minimal row height if height 4743 // of pRow is at least nMinHeight. Otherwise nMinHeight is the 4744 // minimum height. 4745 if( nMinHeight < (Frm().*fnRect->fnGetHeight)() ) 4746 { 4747 // --> OD 2004-10-04 #i26945# 4748 ASSERT( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." ); 4749 const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() ); 4750 // <-- 4751 nMinHeight = lcl_CalcMinRowHeight( this, bConsiderObjs ); 4752 } 4753 4754 if ( ((Frm().*fnRect->fnGetHeight)() - nRealDist) < nMinHeight ) 4755 nRealDist = (Frm().*fnRect->fnGetHeight)() - nMinHeight; 4756 } 4757 if ( nRealDist < 0 ) 4758 nRealDist = 0; 4759 4760 SwTwips nReal = nRealDist; 4761 if ( nReal ) 4762 { 4763 if ( !bTst ) 4764 { 4765 SwTwips nHeight = (Frm().*fnRect->fnGetHeight)(); 4766 (Frm().*fnRect->fnSetHeight)( nHeight - nReal ); 4767 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 4768 if( IsVertical() && !IsVertLR() && !bRev ) 4769 Frm().Pos().X() += nReal; 4770 } 4771 4772 SwTwips nTmp = GetUpper()->Shrink( nReal, bTst ); 4773 if ( !bShrinkAnyway && !GetNext() && nTmp != nReal ) 4774 { 4775 //Der letzte bekommt den Rest im Upper und nimmt deshalb 4776 //ggf. Ruecksichten (sonst: Endlosschleife) 4777 if ( !bTst ) 4778 { 4779 nReal -= nTmp; 4780 SwTwips nHeight = (Frm().*fnRect->fnGetHeight)(); 4781 (Frm().*fnRect->fnSetHeight)( nHeight + nReal ); 4782 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 4783 if( IsVertical() && !IsVertLR() && !bRev ) 4784 Frm().Pos().X() -= nReal; 4785 } 4786 nReal = nTmp; 4787 } 4788 } 4789 4790 //Geeignet invalidieren und die Hoehe der Zellen auf den neuesten 4791 //Stand bringen. 4792 if ( !bTst ) 4793 { 4794 if ( nReal ) 4795 { 4796 if ( GetNext() ) 4797 GetNext()->_InvalidatePos(); 4798 _InvalidateAll(); 4799 SetCompletePaint(); 4800 4801 SwTabFrm *pTab = FindTabFrm(); 4802 if ( !pTab->IsRebuildLastLine() && pTab->IsFollow() && 4803 this == pTab->GetFirstNonHeadlineRow() ) 4804 { 4805 SwTabFrm* pMasterTab = const_cast< SwTabFrm* >( pTab->FindMaster() ); 4806 pMasterTab->InvalidatePos(); 4807 } 4808 } 4809 AdjustCells( (Prt().*fnRect->fnGetHeight)() - nReal, sal_True ); 4810 } 4811 return nReal; 4812 } 4813 4814 /************************************************************************* 4815 |* 4816 |* SwRowFrm::IsRowSplitAllowed() 4817 |* 4818 |*************************************************************************/ 4819 bool SwRowFrm::IsRowSplitAllowed() const 4820 { 4821 // Fixed size rows are never allowed to split: 4822 if ( HasFixSize() ) 4823 { 4824 ASSERT( ATT_FIX_SIZE == GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" ) 4825 return false; 4826 } 4827 4828 // Repeated headlines are never allowed to split: 4829 const SwTabFrm* pTabFrm = FindTabFrm(); 4830 if ( pTabFrm->GetTable()->GetRowsToRepeat() > 0 && 4831 pTabFrm->IsInHeadline( *this ) ) 4832 return false; 4833 4834 const SwTableLineFmt* pFrmFmt = (SwTableLineFmt*)GetTabLine()->GetFrmFmt(); 4835 const SwFmtRowSplit& rLP = pFrmFmt->GetRowSplit(); 4836 return 0 != rLP.GetValue(); 4837 } 4838 4839 /************************************************************************* 4840 |* 4841 |* SwRowFrm::ShouldRowKeepWithNext() 4842 |* 4843 |*************************************************************************/ 4844 bool SwRowFrm::ShouldRowKeepWithNext() const 4845 { 4846 bool bRet = false; 4847 4848 const SwCellFrm* pCell = static_cast<const SwCellFrm*>(Lower()); 4849 const SwFrm* pTxt = pCell->Lower(); 4850 4851 if ( pTxt && pTxt->IsTxtFrm() ) 4852 { 4853 bRet = static_cast<const SwTxtFrm*>(pTxt)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue(); 4854 } 4855 return bRet; 4856 } 4857 4858 /************************************************************************* 4859 |* 4860 |* SwCellFrm::SwCellFrm(), ~SwCellFrm() 4861 |* 4862 |* Ersterstellung MA 09. Mar. 93 4863 |* Letzte Aenderung MA 30. May. 96 4864 |* 4865 |*************************************************************************/ 4866 SwCellFrm::SwCellFrm( const SwTableBox &rBox, SwFrm* pSib, bool bInsertContent ) : 4867 SwLayoutFrm( rBox.GetFrmFmt(), pSib ), 4868 pTabBox( &rBox ) 4869 { 4870 nType = FRMC_CELL; 4871 4872 if ( !bInsertContent ) 4873 return; 4874 4875 //Wenn ein StartIdx vorhanden ist, so werden CntntFrms in der Zelle 4876 //angelegt, andernfalls muessen Rows vorhanden sein und diese werden 4877 //angelegt. 4878 if ( rBox.GetSttIdx() ) 4879 { 4880 sal_uLong nIndex = rBox.GetSttIdx(); 4881 ::_InsertCnt( this, rBox.GetFrmFmt()->GetDoc(), ++nIndex ); 4882 } 4883 else 4884 { 4885 const SwTableLines &rLines = rBox.GetTabLines(); 4886 SwFrm *pTmpPrev = 0; 4887 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) 4888 { 4889 SwRowFrm *pNew = new SwRowFrm( *rLines[i], this, bInsertContent ); 4890 pNew->InsertBehind( this, pTmpPrev ); 4891 pTmpPrev = pNew; 4892 } 4893 } 4894 } 4895 4896 SwCellFrm::~SwCellFrm() 4897 { 4898 SwModify* pMod = GetFmt(); 4899 if( pMod ) 4900 { 4901 // At this stage the lower frames aren't destroyed already, 4902 // therfor we have to do a recursive dispose. 4903 SwRootFrm *pRootFrm = getRootFrm(); 4904 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && 4905 pRootFrm->GetCurrShell() ) 4906 { 4907 pRootFrm->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, sal_True ); 4908 } 4909 4910 pMod->Remove( this ); // austragen, 4911 if( !pMod->GetDepends() ) 4912 delete pMod; // und loeschen 4913 } 4914 } 4915 4916 /************************************************************************* 4917 |* 4918 |* SwCellFrm::Format() 4919 |* 4920 |* Ersterstellung MA 09. Mar. 93 4921 |* Letzte Aenderung MA 29. Jan. 98 4922 |* 4923 |*************************************************************************/ 4924 sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva ) 4925 { 4926 sal_Bool bRet = sal_False; 4927 SwFrm *pFrm = pLay->Lower(); 4928 SWRECTFN( pLay ) 4929 while ( pFrm ) 4930 { 4931 long nFrmTop = (pFrm->Frm().*fnRect->fnGetTop)(); 4932 if( nFrmTop != lYStart ) 4933 { 4934 bRet = sal_True; 4935 const long lDiff = (*fnRect->fnYDiff)( lYStart, nFrmTop ); 4936 const long lDiffX = lYStart - nFrmTop; 4937 (pFrm->Frm().*fnRect->fnSubTop)( -lDiff ); 4938 (pFrm->Frm().*fnRect->fnAddBottom)( lDiff ); 4939 pFrm->SetCompletePaint(); 4940 if ( !pFrm->GetNext() ) 4941 pFrm->SetRetouche(); 4942 if( bInva ) 4943 pFrm->Prepare( PREP_POS_CHGD ); 4944 if ( pFrm->IsLayoutFrm() && ((SwLayoutFrm*)pFrm)->Lower() ) 4945 lcl_ArrangeLowers( (SwLayoutFrm*)pFrm, 4946 (((SwLayoutFrm*)pFrm)->Lower()->Frm().*fnRect->fnGetTop)() 4947 + lDiffX, bInva ); 4948 if ( pFrm->GetDrawObjs() ) 4949 { 4950 for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i ) 4951 { 4952 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i]; 4953 // --> OD 2004-10-08 #i26945# - check, if anchored object 4954 // is lower of layout frame by checking, if the anchor 4955 // frame, which contains the anchor position, is a lower 4956 // of the layout frame. 4957 if ( !pLay->IsAnLower( pAnchoredObj->GetAnchorFrmContainingAnchPos() ) ) 4958 { 4959 continue; 4960 } 4961 // <-- 4962 // --> OD 2005-08-08 #i52904# - distinguish between anchored 4963 // objects, whose vertical position depends on its anchor 4964 // frame and whose vertical position is independent 4965 // from its anchor frame. 4966 bool bVertPosDepOnAnchor( true ); 4967 { 4968 SwFmtVertOrient aVert( pAnchoredObj->GetFrmFmt().GetVertOrient() ); 4969 switch ( aVert.GetRelationOrient() ) 4970 { 4971 case text::RelOrientation::PAGE_FRAME: 4972 case text::RelOrientation::PAGE_PRINT_AREA: 4973 bVertPosDepOnAnchor = false; 4974 break; 4975 default: break; 4976 } 4977 } 4978 if ( pAnchoredObj->ISA(SwFlyFrm) ) 4979 { 4980 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 4981 4982 // OD 2004-05-18 #i28701# - no direct move of objects, 4983 // which are anchored to-paragraph/to-character, if 4984 // the wrapping style influence has to be considered 4985 // on the object positioning. 4986 // --> OD 2005-08-08 #i52904# - no direct move of objects, 4987 // whose vertical position doesn't depend on anchor frame. 4988 const bool bDirectMove = 4989 WEIT_WECH != pFly->Frm().Top() && 4990 bVertPosDepOnAnchor && 4991 !pFly->ConsiderObjWrapInfluenceOnObjPos(); 4992 // <-- 4993 if ( bDirectMove ) 4994 { 4995 (pFly->Frm().*fnRect->fnSubTop)( -lDiff ); 4996 (pFly->Frm().*fnRect->fnAddBottom)( lDiff ); 4997 pFly->GetVirtDrawObj()->SetRectsDirty(); 4998 // --> OD 2004-08-17 - also notify view of <SdrObject> 4999 // instance, which represents the Writer fly frame in 5000 // the drawing layer 5001 pFly->GetVirtDrawObj()->SetChanged(); 5002 // <-- 5003 // --> OD 2006-10-13 #i58280# 5004 pFly->InvalidateObjRectWithSpaces(); 5005 // <-- 5006 } 5007 5008 if ( pFly->IsFlyInCntFrm() ) 5009 { 5010 static_cast<SwFlyInCntFrm*>(pFly)->AddRefOfst( lDiff ); 5011 // --> OD 2004-12-02 #115759# - reset current relative 5012 // position to get re-positioned, if not directly moved. 5013 if ( !bDirectMove ) 5014 { 5015 pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) ); 5016 } 5017 // <-- 5018 } 5019 else if( pFly->IsAutoPos() ) 5020 { 5021 pFly->AddLastCharY( lDiff ); 5022 // OD 2004-05-18 #i28701# - follow-up of #i22341# 5023 // <mnLastTopOfLine> has also been adjusted. 5024 pFly->AddLastTopOfLineY( lDiff ); 5025 } 5026 // --> OD 2004-11-05 #i26945# - re-registration at 5027 // page frame of anchor frame, if table frame isn't 5028 // a follow table and table frame isn't in its 5029 // rebuild of last line. 5030 const SwTabFrm* pTabFrm = pLay->FindTabFrm(); 5031 // --> OD 2004-11-23 #115759# 5032 // - save: check, if table frame is found. 5033 if ( pTabFrm && 5034 !( pTabFrm->IsFollow() && 5035 pTabFrm->FindMaster()->IsRebuildLastLine() ) && 5036 pFly->IsFlyFreeFrm() ) 5037 // <-- 5038 { 5039 SwPageFrm* pPageFrm = pFly->GetPageFrm(); 5040 SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm(); 5041 if ( pPageFrm != pPageOfAnchor ) 5042 { 5043 pFly->InvalidatePos(); 5044 if ( pPageFrm ) 5045 pPageFrm->MoveFly( pFly, pPageOfAnchor ); 5046 else 5047 pPageOfAnchor->AppendFlyToPage( pFly ); 5048 } 5049 } 5050 // <-- 5051 // OD 2004-05-11 #i28701# - Because of the introduction 5052 // of new positionings and alignments (e.g. aligned at 5053 // page area, but anchored at-character), the position 5054 // of the Writer fly frame has to be invalidated. 5055 pFly->InvalidatePos(); 5056 5057 // --> OD 2004-11-04 #i26945# - follow-up of #i3317# 5058 // No arrangement of lowers, if Writer fly frame isn't 5059 // moved 5060 if ( bDirectMove && 5061 ::lcl_ArrangeLowers( pFly, 5062 (pFly->*fnRect->fnGetPrtTop)(), 5063 bInva ) ) 5064 // <-- 5065 { 5066 pFly->SetCompletePaint(); 5067 } 5068 } 5069 else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) ) 5070 { 5071 // --> OD 2004-11-05 #i26945# 5072 const SwTabFrm* pTabFrm = pLay->FindTabFrm(); 5073 if ( pTabFrm && 5074 !( pTabFrm->IsFollow() && 5075 pTabFrm->FindMaster()->IsRebuildLastLine() ) && 5076 !pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId() 5077 == FLY_AS_CHAR ) 5078 { 5079 SwPageFrm* pPageFrm = pAnchoredObj->GetPageFrm(); 5080 SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm(); 5081 if ( pPageFrm != pPageOfAnchor ) 5082 { 5083 pAnchoredObj->InvalidateObjPos(); 5084 if ( pPageFrm ) 5085 { 5086 pPageFrm->RemoveDrawObjFromPage( *pAnchoredObj ); 5087 } 5088 pPageOfAnchor->AppendDrawObjToPage( *pAnchoredObj ); 5089 } 5090 } 5091 // --> OD 2004-07-01 #i28701# - adjust last character 5092 // rectangle and last top of line. 5093 pAnchoredObj->AddLastCharY( lDiff ); 5094 pAnchoredObj->AddLastTopOfLineY( lDiff ); 5095 // --> OD 2005-08-08 #i52904# - re-introduce direct move 5096 // of drawing objects 5097 const bool bDirectMove = 5098 static_cast<const SwDrawFrmFmt&>(pAnchoredObj->GetFrmFmt()).IsPosAttrSet() && 5099 bVertPosDepOnAnchor && 5100 !pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos(); 5101 if ( bDirectMove ) 5102 { 5103 SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj ); 5104 if ( bVert ) 5105 { 5106 pAnchoredObj->DrawObj()->Move( Size( lDiff, 0 ) ); 5107 } 5108 else 5109 { 5110 pAnchoredObj->DrawObj()->Move( Size( 0, lDiff ) ); 5111 } 5112 // --> OD 2006-10-13 #i58280# 5113 pAnchoredObj->InvalidateObjRectWithSpaces(); 5114 // <-- 5115 } 5116 // <-- 5117 pAnchoredObj->InvalidateObjPos(); 5118 } 5119 else 5120 { 5121 ASSERT( false, 5122 "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" ); 5123 } 5124 } 5125 } 5126 } 5127 // Columns and cells are ordered horizontal, not vertical 5128 if( !pFrm->IsColumnFrm() && !pFrm->IsCellFrm() ) 5129 lYStart = (*fnRect->fnYInc)( lYStart, 5130 (pFrm->Frm().*fnRect->fnGetHeight)() ); 5131 5132 // Nowadays, the content inside a cell can flow into the follow table. 5133 // Thus, the cell may only grow up to the end of the environment. 5134 // So the content may have grown, but the cell could not grow. 5135 // Therefore we have to trigger a formatting for the frames, which do 5136 // not fit into the cell anymore: 5137 SwTwips nDistanceToUpperPrtBottom = 5138 (pFrm->Frm().*fnRect->fnBottomDist)( (pLay->*fnRect->fnGetPrtBottom)()); 5139 // --> OD 2006-01-19 #i56146# - Revise fix of issue #i26945# 5140 // do *not* consider content inside fly frames, if it's an undersized paragraph. 5141 // --> OD 2004-10-08 #i26945# - consider content inside fly frames 5142 if ( nDistanceToUpperPrtBottom < 0 && 5143 ( ( pFrm->IsInFly() && 5144 ( !pFrm->IsTxtFrm() || 5145 !static_cast<SwTxtFrm*>(pFrm)->IsUndersized() ) ) || 5146 pFrm->IsInSplitTableRow() ) ) 5147 // <-- 5148 { 5149 pFrm->InvalidatePos(); 5150 } 5151 5152 pFrm = pFrm->GetNext(); 5153 } 5154 return bRet; 5155 } 5156 5157 void SwCellFrm::Format( const SwBorderAttrs *pAttrs ) 5158 { 5159 ASSERT( pAttrs, "CellFrm::Format, pAttrs ist 0." ); 5160 const SwTabFrm* pTab = FindTabFrm(); 5161 SWRECTFN( pTab ) 5162 5163 if ( !bValidPrtArea ) 5164 { 5165 bValidPrtArea = sal_True; 5166 5167 //Position einstellen. 5168 if ( Lower() ) 5169 { 5170 SwTwips nTopSpace, nBottomSpace, nLeftSpace, nRightSpace; 5171 // --> collapsing borders FME 2005-05-27 #i29550# 5172 if ( pTab->IsCollapsingBorders() && !Lower()->IsRowFrm() ) 5173 { 5174 const SvxBoxItem& rBoxItem = pAttrs->GetBox(); 5175 nLeftSpace = rBoxItem.GetDistance( BOX_LINE_LEFT ); 5176 nRightSpace = rBoxItem.GetDistance( BOX_LINE_RIGHT ); 5177 nTopSpace = ((SwRowFrm*)GetUpper())->GetTopMarginForLowers(); 5178 nBottomSpace = ((SwRowFrm*)GetUpper())->GetBottomMarginForLowers(); 5179 } 5180 else 5181 { 5182 // <-- collapsing 5183 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)> 5184 nLeftSpace = pAttrs->CalcLeft( this ); 5185 nRightSpace = pAttrs->CalcRight( this ); 5186 nTopSpace = pAttrs->CalcTop(); 5187 nBottomSpace = pAttrs->CalcBottom(); 5188 } 5189 (this->*fnRect->fnSetXMargins)( nLeftSpace, nRightSpace ); 5190 (this->*fnRect->fnSetYMargins)( nTopSpace, nBottomSpace ); 5191 } 5192 } 5193 // --> OD 2004-10-04 #i26945# 5194 long nRemaining = GetTabBox()->getRowSpan() >= 1 ? 5195 ::lcl_CalcMinCellHeight( this, pTab->IsConsiderObjsForMinCellHeight(), pAttrs ) : 5196 0; 5197 // <-- 5198 if ( !bValidSize ) 5199 { 5200 bValidSize = sal_True; 5201 5202 //Die VarSize der CellFrms ist immer die Breite. 5203 //Tatsaechlich ist die Breite jedoch nicht Variabel, sie wird durch das 5204 //Format vorgegeben. Dieser Vorgegebene Wert muss aber nun wiederum 5205 //nicht der tatsaechlichen Breite entsprechen. Die Breite wird auf 5206 //Basis des Attributes errechnet, der Wert im Attribut passt zu dem 5207 //gewuenschten Wert des TabFrms. Anpassungen die dort vorgenommen 5208 //wurden werden hier Proportional beruecksichtigt. 5209 //Wenn die Celle keinen Nachbarn mehr hat beruecksichtigt sie nicht 5210 //die Attribute, sonder greift sich einfach den Rest des 5211 //Uppers 5212 SwTwips nWidth; 5213 if ( GetNext() ) 5214 { 5215 const SwTwips nWish = pTab->GetFmt()->GetFrmSize().GetWidth(); 5216 nWidth = pAttrs->GetSize().Width(); 5217 5218 ASSERT( nWish, "Tabelle ohne Breite?" ); 5219 ASSERT( nWidth <= nWish, "Zelle breiter als Tabelle." ); 5220 ASSERT( nWidth > 0, "Box without width" ); 5221 5222 const long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)(); 5223 if ( nWish != nPrtWidth ) 5224 { 5225 // Avoid rounding problems, at least for the new table model 5226 if ( pTab->GetTable()->IsNewModel() ) 5227 { 5228 // 1. sum of widths of cells up to this cell (in model) 5229 const SwTableLine* pTabLine = GetTabBox()->GetUpper(); 5230 const SwTableBoxes& rBoxes = pTabLine->GetTabBoxes(); 5231 const SwTableBox* pTmpBox = 0; 5232 5233 SwTwips nSumWidth = 0; 5234 sal_uInt16 i = 0; 5235 do 5236 { 5237 pTmpBox = rBoxes[ i++ ]; 5238 nSumWidth += pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth(); 5239 } 5240 while ( pTmpBox != GetTabBox() ); 5241 5242 // 2. calculate actual width of cells up to this one 5243 double nTmpWidth = nSumWidth; 5244 nTmpWidth *= nPrtWidth; 5245 nTmpWidth /= nWish; 5246 nWidth = (SwTwips)nTmpWidth; 5247 5248 // 3. calculate frame widths of cells up to this one: 5249 const SwFrm* pTmpCell = static_cast<const SwLayoutFrm*>(GetUpper())->Lower(); 5250 SwTwips nSumFrameWidths = 0; 5251 while ( pTmpCell != this ) 5252 { 5253 nSumFrameWidths += (pTmpCell->Frm().*fnRect->fnGetWidth)(); 5254 pTmpCell = pTmpCell->GetNext(); 5255 } 5256 5257 nWidth = nWidth - nSumFrameWidths; 5258 } 5259 else 5260 { 5261 // #i12092# use double instead of long, 5262 // otherwise this could lead to overflows 5263 double nTmpWidth = nWidth; 5264 nTmpWidth *= nPrtWidth; 5265 nTmpWidth /= nWish; 5266 nWidth = (SwTwips)nTmpWidth; 5267 } 5268 } 5269 } 5270 else 5271 { 5272 ASSERT( pAttrs->GetSize().Width() > 0, "Box without width" ); 5273 nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)(); 5274 SwFrm *pPre = GetUpper()->Lower(); 5275 while ( pPre != this ) 5276 { 5277 nWidth -= (pPre->Frm().*fnRect->fnGetWidth)(); 5278 pPre = pPre->GetNext(); 5279 } 5280 } 5281 const long nDiff = nWidth - (Frm().*fnRect->fnGetWidth)(); 5282 if( IsNeighbourFrm() && IsRightToLeft() ) 5283 (Frm().*fnRect->fnSubLeft)( nDiff ); 5284 else 5285 (Frm().*fnRect->fnAddRight)( nDiff ); 5286 (Prt().*fnRect->fnAddRight)( nDiff ); 5287 5288 //Jetzt die Hoehe einstellen, sie wird vom Inhalt und den Raendern 5289 //bestimmt. 5290 const long nDiffHeight = nRemaining - (Frm().*fnRect->fnGetHeight)(); 5291 if ( nDiffHeight ) 5292 { 5293 if ( nDiffHeight > 0 ) 5294 { 5295 //Wieder validieren wenn kein Wachstum stattgefunden hat. 5296 //Invalidiert wird durch AdjustCells von der Row. 5297 if ( !Grow( nDiffHeight ) ) 5298 bValidSize = bValidPrtArea = sal_True; 5299 } 5300 else 5301 { 5302 //Nur dann invalidiert lassen, wenn tatsaechlich 5303 //geshrinkt wurde; das kann abgelehnt werden, weil alle 5304 //nebeneinanderliegenden Zellen gleichgross sein muessen. 5305 if ( !Shrink( -nDiffHeight ) ) 5306 bValidSize = bValidPrtArea = sal_True; 5307 } 5308 } 5309 } 5310 const SwFmtVertOrient &rOri = pAttrs->GetAttrSet().GetVertOrient(); 5311 5312 if ( !Lower() ) 5313 return; 5314 5315 // From now on, all operations are related to the table cell. 5316 SWREFRESHFN( this ) 5317 5318 SwPageFrm* pPg = 0; 5319 if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE != rOri.GetVertOrient() && 5320 // --> OD 2008-07-16 #158225# no vertical alignment of covered cells 5321 !IsCoveredCell() && 5322 // <-- 5323 // --> FME 2004-06-29 #116532# Do not consider vertical alignment in grid mode 5324 !(pPg = FindPageFrm())->HasGrid() ) 5325 // <-- 5326 { 5327 if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() ) 5328 { 5329 //ASSERT fuer HTML-Import! 5330 ASSERT( !this, "VAlign an Zelle ohne Inhalt" ); 5331 return; 5332 } 5333 sal_Bool bVertDir = sal_True; 5334 // --> OD 2005-03-30 #i43913# - no vertical alignment, if wrapping 5335 // style influence is considered on object positioning and 5336 // an object is anchored inside the cell. 5337 const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ); 5338 // <-- 5339 //Keine Ausrichtung wenn Rahmen mit Umlauf in die Zelle ragen. 5340 if ( pPg->GetSortedObjs() ) 5341 { 5342 SwRect aRect( Prt() ); aRect += Frm().Pos(); 5343 for ( sal_uInt16 i = 0; i < pPg->GetSortedObjs()->Count(); ++i ) 5344 { 5345 const SwAnchoredObject* pAnchoredObj = (*pPg->GetSortedObjs())[i]; 5346 SwRect aTmp( pAnchoredObj->GetObjRect() ); 5347 if ( aTmp.IsOver( aRect ) ) 5348 { 5349 const SwFrmFmt& rAnchoredObjFrmFmt = pAnchoredObj->GetFrmFmt(); 5350 const SwFmtSurround &rSur = rAnchoredObjFrmFmt.GetSurround(); 5351 5352 if ( SURROUND_THROUGHT != rSur.GetSurround() ) 5353 { 5354 // frames, which the cell is a lower of, aren't relevant 5355 if ( pAnchoredObj->ISA(SwFlyFrm) ) 5356 { 5357 const SwFlyFrm *pFly = 5358 static_cast<const SwFlyFrm*>(pAnchoredObj); 5359 if ( pFly->IsAnLower( this ) ) 5360 continue; 5361 } 5362 5363 const SwFrm* pAnch = pAnchoredObj->GetAnchorFrm(); 5364 // --> OD 2005-03-30 #i43913# 5365 // --> OD 2005-08-08 #i52904# - no vertical alignment, 5366 // if object, anchored inside cell, has temporarly 5367 // consider its wrapping style on object positioning. 5368 // --> FME 2006-02-01 #i58806# - no vertical alignment 5369 // if object does not follow the text flow. 5370 if ( bConsiderWrapOnObjPos || 5371 !IsAnLower( pAnch ) || 5372 pAnchoredObj->IsTmpConsiderWrapInfluence() || 5373 !rAnchoredObjFrmFmt.GetFollowTextFlow().GetValue() ) 5374 // <-- 5375 { 5376 bVertDir = sal_False; 5377 break; 5378 } 5379 } 5380 } 5381 } 5382 } 5383 5384 long nPrtHeight = (Prt().*fnRect->fnGetHeight)(); 5385 if( ( bVertDir && ( nRemaining -= lcl_CalcTopAndBottomMargin( *this, *pAttrs ) ) < nPrtHeight ) || 5386 (Lower()->Frm().*fnRect->fnGetTop)() != (this->*fnRect->fnGetPrtTop)() ) 5387 { 5388 long lTopOfst = 0, 5389 nDiff = (Prt().*fnRect->fnGetHeight)() - nRemaining; 5390 if ( nDiff >= 0 ) 5391 { 5392 if ( bVertDir ) 5393 { 5394 switch ( rOri.GetVertOrient() ) 5395 { 5396 case text::VertOrientation::CENTER: lTopOfst = nDiff / 2; break; 5397 case text::VertOrientation::BOTTOM: lTopOfst = nDiff; break; 5398 default: break; 5399 }; 5400 } 5401 long nTmp = (*fnRect->fnYInc)( 5402 (this->*fnRect->fnGetPrtTop)(), lTopOfst ); 5403 if ( lcl_ArrangeLowers( this, nTmp, !bVertDir ) ) 5404 SetCompletePaint(); 5405 } 5406 } 5407 } 5408 else 5409 { 5410 //Ist noch eine alte Ausrichtung beruecksichtigt worden? 5411 if ( Lower()->IsCntntFrm() ) 5412 { 5413 const long lYStart = (this->*fnRect->fnGetPrtTop)(); 5414 lcl_ArrangeLowers( this, lYStart, sal_True ); 5415 } 5416 } 5417 } 5418 5419 /************************************************************************* 5420 |* 5421 |* SwCellFrm::Modify() 5422 |* 5423 |* Ersterstellung MA 20. Dec. 96 5424 |* Letzte Aenderung MA 20. Dec. 96 5425 |* 5426 |*************************************************************************/ 5427 5428 void SwCellFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) 5429 { 5430 sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which(); 5431 const SfxPoolItem *pItem = 0; 5432 5433 if( bAttrSetChg ) 5434 ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_VERT_ORIENT, sal_False, &pItem); 5435 else if ( RES_VERT_ORIENT == pNew->Which() ) 5436 pItem = pNew; 5437 5438 if ( pItem ) 5439 { 5440 sal_Bool bInva = sal_True; 5441 if ( text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() && 5442 // OD 04.11.2003 #112910# 5443 Lower() && Lower()->IsCntntFrm() ) 5444 { 5445 SWRECTFN( this ) 5446 const long lYStart = (this->*fnRect->fnGetPrtTop)(); 5447 bInva = lcl_ArrangeLowers( this, lYStart, sal_False ); 5448 } 5449 if ( bInva ) 5450 { 5451 SetCompletePaint(); 5452 InvalidatePrt(); 5453 } 5454 } 5455 5456 if ( ( bAttrSetChg && 5457 SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_PROTECT, sal_False ) ) || 5458 RES_PROTECT == pNew->Which() ) 5459 { 5460 ViewShell *pSh = getRootFrm()->GetCurrShell(); 5461 if( pSh && pSh->GetLayout()->IsAnyShellAccessible() ) 5462 pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this ); 5463 } 5464 5465 if ( bAttrSetChg && 5466 SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_FRAMEDIR, sal_False, &pItem ) ) 5467 { 5468 SetDerivedVert( sal_False ); 5469 CheckDirChange(); 5470 } 5471 5472 // --> collapsing borders FME 2005-05-27 #i29550# 5473 if ( bAttrSetChg && 5474 SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_BOX, sal_False, &pItem ) ) 5475 { 5476 SwFrm* pTmpUpper = GetUpper(); 5477 while ( pTmpUpper->GetUpper() && !pTmpUpper->GetUpper()->IsTabFrm() ) 5478 pTmpUpper = pTmpUpper->GetUpper(); 5479 5480 SwTabFrm* pTabFrm = (SwTabFrm*)pTmpUpper->GetUpper(); 5481 if ( pTabFrm->IsCollapsingBorders() ) 5482 { 5483 // Invalidate lowers of this and next row: 5484 lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper ); 5485 pTmpUpper = pTmpUpper->GetNext(); 5486 if ( pTmpUpper ) 5487 lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper ); 5488 else 5489 pTabFrm->InvalidatePrt(); 5490 } 5491 } 5492 // <-- collapsing 5493 5494 SwLayoutFrm::Modify( pOld, pNew ); 5495 } 5496 5497 /************************************************************************* 5498 |* SwCellFrm::GetLayoutRowSpan() const 5499 |*************************************************************************/ 5500 5501 long SwCellFrm::GetLayoutRowSpan() const 5502 { 5503 long nRet = GetTabBox()->getRowSpan(); 5504 if ( nRet < 1 ) 5505 { 5506 const SwFrm* pRow = GetUpper(); 5507 const SwTabFrm* pTab = static_cast<const SwTabFrm*>(pRow->GetUpper()); 5508 5509 if ( pTab && pTab->IsFollow() && pRow == pTab->GetFirstNonHeadlineRow() ) 5510 nRet = -nRet; 5511 } 5512 return nRet; 5513 } 5514 5515 // --> OD 2010-02-17 #i103961# 5516 void SwCellFrm::Cut() 5517 { 5518 // notification for accessibility 5519 { 5520 SwRootFrm *pRootFrm = getRootFrm(); 5521 if( pRootFrm && pRootFrm->IsAnyShellAccessible() ) 5522 { 5523 ViewShell* pVSh = pRootFrm->GetCurrShell(); 5524 if ( pVSh && pVSh->Imp() ) 5525 { 5526 pVSh->Imp()->DisposeAccessibleFrm( this ); 5527 } 5528 } 5529 } 5530 5531 SwLayoutFrm::Cut(); 5532 } 5533 // <-- 5534 5535 // 5536 // Helper functions for repeated headlines: 5537 // 5538 5539 /* 5540 * SwTabFrm::IsInHeadline( const SwFrm& rFrm ) 5541 */ 5542 bool SwTabFrm::IsInHeadline( const SwFrm& rFrm ) const 5543 { 5544 ASSERT( IsAnLower( &rFrm ) && rFrm.IsInTab(), 5545 "SwTabFrm::IsInHeadline called for frame not lower of table" ) 5546 5547 const SwFrm* pTmp = &rFrm; 5548 while ( !pTmp->GetUpper()->IsTabFrm() ) 5549 pTmp = pTmp->GetUpper(); 5550 5551 return GetTable()->IsHeadline( *((SwRowFrm*)pTmp)->GetTabLine() ); 5552 } 5553 5554 /* 5555 * SwTabFrm::GetFirstNonHeadlineRow() 5556 * 5557 * If this is a master table, we can may assume, that there are at least 5558 * nRepeat lines in the table. 5559 * If this is a follow table, there are intermediate states for the table 5560 * layout, e.g., during deletion of rows, which makes it necessary to find 5561 * the first non-headline row by evaluating the headline flag at the row frame. 5562 */ 5563 SwRowFrm* SwTabFrm::GetFirstNonHeadlineRow() const 5564 { 5565 SwRowFrm* pRet = (SwRowFrm*)Lower(); 5566 if ( pRet ) 5567 { 5568 if ( IsFollow() ) 5569 { 5570 while ( pRet && pRet->IsRepeatedHeadline() ) 5571 pRet = (SwRowFrm*)pRet->GetNext(); 5572 } 5573 else 5574 { 5575 sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat(); 5576 while ( pRet && nRepeat > 0 ) 5577 { 5578 pRet = (SwRowFrm*)pRet->GetNext(); 5579 --nRepeat; 5580 } 5581 } 5582 } 5583 5584 return (SwRowFrm*)pRet; 5585 } 5586 5587 /* 5588 * SwTable::IsHeadline() 5589 */ 5590 bool SwTable::IsHeadline( const SwTableLine& rLine ) const 5591 { 5592 for ( sal_uInt16 i = 0; i < GetRowsToRepeat(); ++i ) 5593 if ( GetTabLines()[ i ] == &rLine ) 5594 return true; 5595 5596 return false; 5597 } 5598 5599 bool SwTabFrm::IsLayoutSplitAllowed() const 5600 { 5601 return GetFmt()->GetLayoutSplit().GetValue(); 5602 } 5603 5604 // --> collapsing borders FME 2005-05-27 #i29550# 5605 5606 sal_uInt16 SwTabFrm::GetBottomLineSize() const 5607 { 5608 ASSERT( IsCollapsingBorders(), 5609 "BottomLineSize only required for collapsing borders" ) 5610 5611 ASSERT( Lower(), "Warning! Trying to prevent a crash, please inform FME" ) 5612 5613 const SwFrm* pTmp = GetLastLower(); 5614 5615 // --> FME 2005-12-07 #124755# Try to make code robust: 5616 if ( !pTmp ) return 0; 5617 // <-- 5618 5619 return static_cast<const SwRowFrm*>(pTmp)->GetBottomLineSize(); 5620 } 5621 5622 bool SwTabFrm::IsCollapsingBorders() const 5623 { 5624 return ((SfxBoolItem&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS )).GetValue(); 5625 } 5626 5627 // <-- collapsing 5628 5629 5630 // 5631 // Local helper function to calculate height of first text row 5632 // 5633 SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrm& rSourceLine ) 5634 { 5635 // Find corresponding split line in master table 5636 const SwTabFrm* pTab = rSourceLine.FindTabFrm(); 5637 SWRECTFN( pTab ) 5638 const SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower(); 5639 5640 // 5641 // 1. Case: rSourceLine is a follow flow line. 5642 // In this case we have to return the minimum of the heights 5643 // of the first lines in rSourceLine. 5644 // 5645 // 2. Case: rSourceLine is not a follow flow line. 5646 // In this case we have to return the maximum of the heights 5647 // of the first lines in rSourceLine. 5648 // 5649 bool bIsInFollowFlowLine = rSourceLine.IsInFollowFlowRow(); 5650 SwTwips nHeight = bIsInFollowFlowLine ? LONG_MAX : 0; 5651 5652 while ( pCurrSourceCell ) 5653 { 5654 // NEW TABLES 5655 // Skip cells which are not responsible for the height of 5656 // the follow flow line: 5657 if ( bIsInFollowFlowLine && pCurrSourceCell->GetLayoutRowSpan() > 1 ) 5658 { 5659 pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext(); 5660 continue; 5661 } 5662 5663 const SwFrm *pTmp = pCurrSourceCell->Lower(); 5664 if ( pTmp ) 5665 { 5666 SwTwips nTmpHeight = USHRT_MAX; 5667 // --> FME 2004-09-14 #i32456# Consider lower row frames 5668 if ( pTmp->IsRowFrm() ) 5669 { 5670 const SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower(); 5671 nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow ); 5672 } 5673 // <-- 5674 if ( pTmp->IsTabFrm() ) 5675 { 5676 nTmpHeight = ((SwTabFrm*)pTmp)->CalcHeightOfFirstContentLine(); 5677 } 5678 else if ( pTmp->IsTxtFrm() ) 5679 { 5680 SwTxtFrm* pTxtFrm = (SwTxtFrm*)pTmp; 5681 pTxtFrm->GetFormatted(); 5682 nTmpHeight = pTxtFrm->FirstLineHeight(); 5683 } 5684 5685 if ( USHRT_MAX != nTmpHeight ) 5686 { 5687 const SwCellFrm* pPrevCell = pCurrSourceCell->GetPreviousCell(); 5688 if ( pPrevCell ) 5689 { 5690 // If we are in a split row, there may be some space 5691 // left in the cell frame of the master row. 5692 // We look for the minimum of all first line heights; 5693 SwTwips nReal = (pPrevCell->Prt().*fnRect->fnGetHeight)(); 5694 const SwFrm* pFrm = pPrevCell->Lower(); 5695 const SwFrm* pLast = pFrm; 5696 while ( pFrm ) 5697 { 5698 nReal -= (pFrm->Frm().*fnRect->fnGetHeight)(); 5699 pLast = pFrm; 5700 pFrm = pFrm->GetNext(); 5701 } 5702 5703 // --> FME, OD 2004-07-15 #i26831#, #i26520# 5704 // The additional lower space of the current last. 5705 // --> OD 2004-11-25 #115759# - do *not* consider the 5706 // additional lower space for 'master' text frames 5707 if ( pLast && pLast->IsFlowFrm() && 5708 ( !pLast->IsTxtFrm() || 5709 !static_cast<const SwTxtFrm*>(pLast)->GetFollow() ) ) 5710 // <-- 5711 { 5712 nReal += SwFlowFrm::CastFlowFrm(pLast)->CalcAddLowerSpaceAsLastInTableCell(); 5713 } 5714 // Don't forget the upper space and lower space, 5715 // --> OD 2004-11-25 #115759# - do *not* consider the upper 5716 // and the lower space for follow text frames. 5717 if ( pTmp->IsFlowFrm() && 5718 ( !pTmp->IsTxtFrm() || 5719 !static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) ) 5720 { 5721 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace( NULL, pLast); 5722 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace(); 5723 } 5724 // <-- 5725 // --> OD 2004-11-25 #115759# - consider additional lower 5726 // space of <pTmp>, if contains only one line. 5727 // In this case it would be the new last text frame, which 5728 // would have no follow and thus would add this space. 5729 if ( pTmp->IsTxtFrm() && 5730 const_cast<SwTxtFrm*>(static_cast<const SwTxtFrm*>(pTmp)) 5731 ->GetLineCount( STRING_LEN ) == 1 ) 5732 { 5733 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp) 5734 ->CalcAddLowerSpaceAsLastInTableCell(); 5735 } 5736 // <-- 5737 if ( nReal > 0 ) 5738 nTmpHeight -= nReal; 5739 } 5740 else 5741 { 5742 // pFirstRow is not a FollowFlowRow. In this case, 5743 // we look for the maximum of all first line heights: 5744 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCurrSourceCell ); 5745 const SwBorderAttrs &rAttrs = *aAccess.Get(); 5746 nTmpHeight += rAttrs.CalcTop() + rAttrs.CalcBottom(); 5747 // --> OD 2004-07-16 #i26250# 5748 // Don't forget the upper space and lower space, 5749 if ( pTmp->IsFlowFrm() ) 5750 { 5751 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace(); 5752 nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace(); 5753 } 5754 // <-- 5755 } 5756 } 5757 5758 if ( bIsInFollowFlowLine ) 5759 { 5760 // minimum 5761 if ( nTmpHeight < nHeight ) 5762 nHeight = nTmpHeight; 5763 } 5764 else 5765 { 5766 // maximum 5767 if ( nTmpHeight > nHeight && USHRT_MAX != nTmpHeight ) 5768 nHeight = nTmpHeight; 5769 } 5770 } 5771 5772 pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext(); 5773 } 5774 5775 return ( LONG_MAX == nHeight ) ? 0 : nHeight; 5776 } 5777 5778 // 5779 // Function to calculate height of first text row 5780 // 5781 SwTwips SwTabFrm::CalcHeightOfFirstContentLine() const 5782 { 5783 SWRECTFN( this ) 5784 5785 const bool bDontSplit = !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue(); 5786 5787 if ( bDontSplit ) 5788 { 5789 // Table is not allowed to split: Take the whole height, that's all 5790 return (Frm().*fnRect->fnGetHeight)(); 5791 } 5792 5793 SwRowFrm* pFirstRow = 0; 5794 SwTwips nTmpHeight = 0; 5795 5796 pFirstRow = GetFirstNonHeadlineRow(); 5797 ASSERT( !IsFollow() || pFirstRow, "FollowTable without Lower" ) 5798 5799 // NEW TABLES 5800 if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() ) 5801 pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext()); 5802 5803 // Calculate the height of the headlines: 5804 const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat(); 5805 SwTwips nRepeatHeight = nRepeat ? lcl_GetHeightOfRows( GetLower(), nRepeat ) : 0; 5806 5807 // Calculate the height of the keeping lines 5808 // (headlines + following keeping lines): 5809 SwTwips nKeepHeight = nRepeatHeight; 5810 if ( GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) ) 5811 { 5812 sal_uInt16 nKeepRows = nRepeat; 5813 5814 // Check how many rows want to keep together 5815 while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() ) 5816 { 5817 ++nKeepRows; 5818 pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext()); 5819 } 5820 5821 if ( nKeepRows > nRepeat ) 5822 nKeepHeight = lcl_GetHeightOfRows( GetLower(), nKeepRows ); 5823 } 5824 5825 // For master tables, the height of the headlines + the heigth of the 5826 // keeping lines (if any) has to be considered. For follow tables, we 5827 // only consider the height of the keeping rows without the repeated lines: 5828 if ( !IsFollow() ) 5829 { 5830 nTmpHeight = nKeepHeight; 5831 } 5832 else 5833 { 5834 nTmpHeight = nKeepHeight - nRepeatHeight; 5835 } 5836 5837 // pFirstRow row is the first non-heading row. 5838 // nTmpHeight is the height of the heading row if we are a follow. 5839 if ( pFirstRow ) 5840 { 5841 const bool bSplittable = pFirstRow->IsRowSplitAllowed(); 5842 const SwTwips nFirstLineHeight = (pFirstRow->Frm().*fnRect->fnGetHeight)(); 5843 5844 if ( !bSplittable ) 5845 { 5846 // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow 5847 // actually is determined by a lower cell with rowspan = -1. In this case we should not 5848 // just return the height of the first line. Basically we need to get the height of the 5849 // line as it would be on the last page. Since this is quite complicated to calculate, 5850 // we olny calculate the height of the first line. 5851 if ( pFirstRow->GetPrev() && 5852 static_cast<SwRowFrm*>(pFirstRow->GetPrev())->IsRowSpanLine() ) 5853 { 5854 // Calculate maximum height of all cells with rowspan = 1: 5855 SwTwips nMaxHeight = 0; 5856 const SwCellFrm* pLower2 = static_cast<const SwCellFrm*>(pFirstRow->Lower()); 5857 while ( pLower2 ) 5858 { 5859 if ( 1 == pLower2->GetTabBox()->getRowSpan() ) 5860 { 5861 const SwTwips nCellHeight = lcl_CalcMinCellHeight( pLower2, sal_True ); 5862 nMaxHeight = Max( nCellHeight, nMaxHeight ); 5863 } 5864 pLower2 = static_cast<const SwCellFrm*>(pLower2->GetNext()); 5865 } 5866 nTmpHeight += nMaxHeight; 5867 } 5868 else 5869 { 5870 nTmpHeight += nFirstLineHeight; 5871 } 5872 } 5873 5874 // --> FME 2004-11-18 #118411# 5875 // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger 5876 // a formatting of the row frame (via the GetFormatted()). We don't 5877 // want this formatting if the row does not have a height. 5878 else if ( 0 != nFirstLineHeight ) 5879 // <-- 5880 { 5881 const bool bOldJoinLock = IsJoinLocked(); 5882 ((SwTabFrm*)this)->LockJoin(); 5883 const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *(SwRowFrm*)pFirstRow ); 5884 5885 // Consider minimum row height: 5886 const SwFmtFrmSize &rSz = static_cast<const SwRowFrm*>(pFirstRow)->GetFmt()->GetFrmSize(); 5887 const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? 5888 rSz.GetHeight() : 0; 5889 5890 nTmpHeight += Max( nHeightOfFirstContentLine, nMinRowHeight ); 5891 5892 if ( !bOldJoinLock ) 5893 ((SwTabFrm*)this)->UnlockJoin(); 5894 } 5895 } 5896 5897 return nTmpHeight; 5898 } 5899 5900 // 5901 // Some more functions for covered/covering cells. This way inclusion of 5902 // SwCellFrm can be avoided 5903 // 5904 5905 bool SwFrm::IsLeaveUpperAllowed() const 5906 { 5907 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this); 5908 return pThisCell && pThisCell->GetLayoutRowSpan() > 1; 5909 } 5910 5911 bool SwFrm::IsCoveredCell() const 5912 { 5913 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this); 5914 return pThisCell && pThisCell->GetLayoutRowSpan() < 1; 5915 } 5916 5917 bool SwFrm::IsInCoveredCell() const 5918 { 5919 bool bRet = false; 5920 5921 const SwFrm* pThis = this; 5922 while ( pThis && !pThis->IsCellFrm() ) 5923 pThis = pThis->GetUpper(); 5924 5925 if ( pThis ) 5926 bRet = pThis->IsCoveredCell(); 5927 5928 return bRet; 5929 } 5930 5931