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