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 "rootfrm.hxx" 31 #include "pagefrm.hxx" 32 #include "cntfrm.hxx" 33 #include "viewsh.hxx" 34 #include "doc.hxx" 35 #include "viewimp.hxx" 36 #include "viewopt.hxx" 37 #include "swtypes.hxx" 38 #include "dflyobj.hxx" 39 #include "dcontact.hxx" 40 #include "flyfrm.hxx" 41 #include "frmtool.hxx" 42 #include "txtftn.hxx" 43 #include "fmtftn.hxx" 44 #include <editeng/ulspitem.hxx> 45 #include <editeng/keepitem.hxx> 46 47 #include <vcl/outdev.hxx> 48 #include <fmtfsize.hxx> 49 #include <fmtanchr.hxx> 50 #include <fmtclbl.hxx> 51 52 #include "tabfrm.hxx" 53 #include "ftnfrm.hxx" 54 #include "txtfrm.hxx" 55 #include "pagedesc.hxx" 56 #include "ftninfo.hxx" 57 #include "sectfrm.hxx" 58 #include "dbg_lay.hxx" 59 60 // --> OD 2004-06-23 #i28701# 61 #include <sortedobjs.hxx> 62 #include <layouter.hxx> 63 // --> OD 2004-11-01 #i36347# 64 #include <flyfrms.hxx> 65 // <-- 66 67 //------------------------------------------------------------------------ 68 // Move-Methoden 69 //------------------------------------------------------------------------ 70 71 /************************************************************************* 72 |* 73 |* SwCntntFrm::ShouldBwdMoved() 74 |* 75 |* Beschreibung Returnwert sagt, ob der Frm verschoben werden sollte. 76 |* Ersterstellung MA 05. Dec. 96 77 |* Letzte Aenderung MA 05. Dec. 96 78 |* 79 |*************************************************************************/ 80 81 82 sal_Bool SwCntntFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool & ) 83 { 84 if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove())) 85 { 86 //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv. 87 //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen 88 //moechte die FixSize die gleiche ist, die der Frm selbst hat. 89 //In diesem Fall kann einfach geprueft werden, ob der Frm genug 90 //Platz fuer seine VarSize findet, ist dies nicht der Fall kann 91 //gleich auf das Verschieben verzichtet werden. 92 //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst 93 //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise 94 //aufspalten kann. 95 //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind 96 //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn 97 //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt 98 //etwas Platz zur Verfuegung steht). 99 100 //Die FixSize der Umgebungen in denen Cntnts herumlungern ist immer 101 //Die Breite. 102 103 //Wenn mehr als ein Blatt zurueckgegangen wurde (z.B. ueberspringen 104 //von Leerseiten), so muss in jedemfall gemoved werden - sonst wuerde, 105 //falls der Frm nicht in das Blatt passt, nicht mehr auf die 106 //dazwischenliegenden Blaetter geachtet werden. 107 sal_uInt8 nMoveAnyway = 0; 108 SwPageFrm * const pNewPage = pNewUpper->FindPageFrm(); 109 SwPageFrm *pOldPage = FindPageFrm(); 110 111 if ( SwFlowFrm::IsMoveBwdJump() ) 112 return sal_True; 113 114 if( IsInFtn() && IsInSct() ) 115 { 116 SwFtnFrm* pFtn = FindFtnFrm(); 117 SwSectionFrm* pMySect = pFtn->FindSctFrm(); 118 if( pMySect && pMySect->IsFtnLock() ) 119 { 120 SwSectionFrm *pSect = pNewUpper->FindSctFrm(); 121 while( pSect && pSect->IsInFtn() ) 122 pSect = pSect->GetUpper()->FindSctFrm(); 123 ASSERT( pSect, "Escaping footnote" ); 124 if( pSect != pMySect ) 125 return sal_False; 126 } 127 } 128 SWRECTFN( this ) 129 SWRECTFNX( pNewUpper ) 130 if( Abs( (pNewUpper->Prt().*fnRectX->fnGetWidth)() - 131 (GetUpper()->Prt().*fnRect->fnGetWidth)() ) > 1 ) 132 nMoveAnyway = 2; // Damit kommt nur noch ein _WouldFit mit Umhaengen in Frage 133 134 // OD 2004-05-26 #i25904# - do *not* move backward, 135 // if <nMoveAnyway> equals 3 and no space is left in new upper. 136 nMoveAnyway |= BwdMoveNecessary( pOldPage, Frm() ); 137 { 138 const IDocumentSettingAccess* pIDSA = pNewPage->GetFmt()->getIDocumentSettingAccess(); 139 SwTwips nSpace = 0; 140 SwRect aRect( pNewUpper->Prt() ); 141 aRect.Pos() += pNewUpper->Frm().Pos(); 142 const SwFrm *pPrevFrm = pNewUpper->Lower(); 143 while ( pPrevFrm ) 144 { 145 SwTwips nNewTop = (pPrevFrm->Frm().*fnRectX->fnGetBottom)(); 146 // OD 2004-03-01 #106629#: 147 // consider lower spacing of last frame in a table cell 148 { 149 // check, if last frame is inside table and if it includes 150 // its lower spacing. 151 if ( !pPrevFrm->GetNext() && pPrevFrm->IsInTab() && 152 pIDSA->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) ) 153 { 154 const SwFrm* pLastFrm = pPrevFrm; 155 // if last frame is a section, take its last content 156 if ( pPrevFrm->IsSctFrm() ) 157 { 158 pLastFrm = static_cast<const SwSectionFrm*>(pPrevFrm)->FindLastCntnt(); 159 if ( pLastFrm && 160 pLastFrm->FindTabFrm() != pPrevFrm->FindTabFrm() ) 161 { 162 pLastFrm = pLastFrm->FindTabFrm(); 163 } 164 } 165 166 if ( pLastFrm ) 167 { 168 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pLastFrm ); 169 const SwBorderAttrs& rAttrs = *aAccess.Get(); 170 nNewTop -= rAttrs.GetULSpace().GetLower(); 171 } 172 } 173 } 174 (aRect.*fnRectX->fnSetTop)( nNewTop ); 175 176 pPrevFrm = pPrevFrm->GetNext(); 177 } 178 179 nMoveAnyway |= BwdMoveNecessary( pNewPage, aRect); 180 181 //determine space left in new upper frame 182 nSpace = (aRect.*fnRectX->fnGetHeight)(); 183 const ViewShell *pSh = pNewUpper->getRootFrm()->GetCurrShell(); 184 if ( IsInFtn() || 185 (pSh && pSh->GetViewOptions()->getBrowseMode()) || 186 pNewUpper->IsCellFrm() || 187 ( pNewUpper->IsInSct() && ( pNewUpper->IsSctFrm() || 188 ( pNewUpper->IsColBodyFrm() && 189 !pNewUpper->GetUpper()->GetPrev() && 190 !pNewUpper->GetUpper()->GetNext() ) ) ) ) 191 nSpace += pNewUpper->Grow( LONG_MAX, sal_True ); 192 193 if ( nMoveAnyway < 3 ) 194 { 195 if ( nSpace ) 196 { 197 //Keine Beruecksichtigung der Fussnoten die an dem Absatz 198 //kleben, denn dies wuerde extrem unuebersichtlichen Code 199 //beduerfen (wg. Beruecksichtung der Breiten und vor allem 200 //der Flys, die ja wieder Einfluss auf die Fussnoten nehmen...). 201 202 // _WouldFit kann bei gleicher Breite und _nur_ selbst verankerten Flys 203 // befragt werden. 204 // _WouldFit kann auch gefragt werden, wenn _nur_ fremdverankerte Flys vorliegen, 205 // dabei ist sogar die Breite egal, da ein TestFormat in der neuen Umgebung 206 // vorgenommen wird. 207 // --> OD 2007-11-26 #b6614158# 208 const sal_uInt8 nBwdMoveNecessaryResult = 209 BwdMoveNecessary( pNewPage, aRect); 210 const bool bObjsInNewUpper( nBwdMoveNecessaryResult == 2 || 211 nBwdMoveNecessaryResult == 3 ); 212 213 return _WouldFit( nSpace, pNewUpper, nMoveAnyway == 2, 214 bObjsInNewUpper ); 215 // <-- 216 } 217 //Bei einem spaltigen Bereichsfrischling kann _WouldFit kein 218 //brauchbares Ergebnis liefern, also muessen wir wirklich 219 //zurueckfliessen 220 else if( pNewUpper->IsInSct() && pNewUpper->IsColBodyFrm() && 221 !(pNewUpper->Prt().*fnRectX->fnGetWidth)() && 222 ( pNewUpper->GetUpper()->GetPrev() || 223 pNewUpper->GetUpper()->GetNext() ) ) 224 return sal_True; 225 else 226 return sal_False; // Kein Platz, dann ist es sinnlos, zurueckzufliessen 227 } 228 else 229 { 230 // OD 2004-05-26 #i25904# - check for space left in new upper 231 if ( nSpace ) 232 return sal_True; 233 else 234 return sal_False; 235 } 236 } 237 } 238 return sal_False; 239 } 240 241 //------------------------------------------------------------------------ 242 // Calc-Methoden 243 //------------------------------------------------------------------------ 244 245 /************************************************************************* 246 |* 247 |* SwFrm::Prepare() 248 |* 249 |* Beschreibung Bereitet den Frm auf die 'Formatierung' (MakeAll()) 250 |* vor. Diese Methode dient dazu auf dem Stack Platz einzusparen, 251 |* denn zur Positionsberechnung des Frm muss sichergestellt sein, dass 252 |* die Position von Upper und Prev gueltig sind, mithin also ein 253 |* rekursiver Aufruf (Schleife waere relativ teuer, da selten notwendig). 254 |* Jeder Aufruf von MakeAll verbraucht aber ca. 500Byte Stack - 255 |* das Ende ist leicht abzusehen. _Prepare benoetigt nur wenig Stack, 256 |* deshalb solle der Rekursive Aufruf hier kein Problem sein. 257 |* Ein weiterer Vorteil ist, das eines schoenen Tages das _Prepare und 258 |* damit die Formatierung von Vorgaengern umgangen werden kann. 259 |* So kann evtl. mal 'schnell' an's Dokumentende gesprungen werden. 260 |* Ersterstellung MA ?? 261 |* Letzte Aenderung MA 13. Dec. 93 262 |* 263 |*************************************************************************/ 264 //Zwei kleine Freundschaften werden hier zu einem Geheimbund. 265 inline void PrepareLock( SwFlowFrm *pTab ) 266 { 267 pTab->LockJoin(); 268 } 269 inline void PrepareUnlock( SwFlowFrm *pTab ) 270 { 271 pTab->UnlockJoin(); 272 273 } 274 275 // hopefully, one day this function simply will return 'false' 276 bool lcl_IsCalcUpperAllowed( const SwFrm& rFrm ) 277 { 278 return !rFrm.GetUpper()->IsSctFrm() && 279 !rFrm.GetUpper()->IsFooterFrm() && 280 // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame 281 !rFrm.GetUpper()->IsFlyFrm() && 282 // <-- 283 !( rFrm.GetUpper()->IsTabFrm() && rFrm.GetUpper()->GetUpper()->IsInTab() ) && 284 !( rFrm.IsTabFrm() && rFrm.GetUpper()->IsInTab() ); 285 } 286 287 void SwFrm::PrepareMake() 288 { 289 StackHack aHack; 290 if ( GetUpper() ) 291 { 292 if ( lcl_IsCalcUpperAllowed( *this ) ) 293 GetUpper()->Calc(); 294 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." ); 295 if ( !GetUpper() ) 296 return; 297 298 const sal_Bool bCnt = IsCntntFrm(); 299 const sal_Bool bTab = IsTabFrm(); 300 sal_Bool bNoSect = IsInSct(); 301 sal_Bool bOldTabLock = sal_False, bFoll = sal_False; 302 SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL; 303 304 if ( bTab ) 305 { 306 pThis = (SwTabFrm*)this; 307 bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked(); 308 ::PrepareLock( (SwTabFrm*)this ); 309 bFoll = pThis->IsFollow(); 310 } 311 else if( IsSctFrm() ) 312 { 313 pThis = (SwSectionFrm*)this; 314 bFoll = pThis->IsFollow(); 315 bNoSect = sal_False; 316 } 317 else if ( bCnt && sal_True == (bFoll = pThis->IsFollow()) && 318 GetPrev() ) 319 { 320 //Wenn der Master gereade ein CalcFollow ruft braucht die Kette 321 //nicht durchlaufen werden. Das spart Zeit und vermeidet Probleme. 322 if ( ((SwTxtFrm*)((SwTxtFrm*)this)->FindMaster())->IsLocked() ) 323 { 324 MakeAll(); 325 return; 326 } 327 } 328 329 // --> OD 2005-03-04 #i44049# - no format of previous frame, if current 330 // frame is a table frame and its previous frame wants to keep with it. 331 const bool bFormatPrev = !bTab || 332 !GetPrev() || 333 !GetPrev()->GetAttrSet()->GetKeep().GetValue(); 334 if ( bFormatPrev ) 335 { 336 SwFrm *pFrm = GetUpper()->Lower(); 337 while ( pFrm != this ) 338 { 339 ASSERT( pFrm, ":-( Layoutgeruest wackelig (this not found)." ); 340 if ( !pFrm ) 341 return; //Oioioioi ... 342 343 if ( !pFrm->IsValid() ) 344 { 345 //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung 346 //der Stabilitaet beitraegt: 347 //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin, 348 //so wuerde dieser mich beim Formatieren deleten; wie jeder 349 //leicht sehen kann waere dies eine etwas unuebersichtliche 350 //Situation die es zu vermeiden gilt. 351 if ( bFoll && pFrm->IsFlowFrm() && 352 (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) ) 353 break; 354 355 //MA: 24. Mar. 94, Calc wuerde doch nur wieder in ein _Prepare laufen und so 356 //die ganze Kette nocheinmal abhuenern. 357 // pFrm->Calc(); 358 pFrm->MakeAll(); 359 if( IsSctFrm() && !((SwSectionFrm*)this)->GetSection() ) 360 break; 361 } 362 //Die Kette kann bei CntntFrms waehrend des durchlaufens 363 //aufgebrochen werden, deshalb muss der Nachfolger etwas 364 //umstaendlich ermittelt werden. However, irgendwann _muss_ 365 //ich wieder bei mir selbst ankommen. 366 pFrm = pFrm->FindNext(); 367 368 //Wenn wir in einem SectionFrm gestartet sind, koennen wir durch die 369 //MakeAll-Aufrufe in einen Section-Follow gewandert sein. 370 //FindNext liefert allerdings den SectionFrm, nicht seinen Inhalt. 371 // => wir finden uns selbst nicht mehr! 372 if( bNoSect && pFrm && pFrm->IsSctFrm() ) 373 { 374 SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny(); 375 if( pCnt ) 376 pFrm = pCnt; 377 } 378 } 379 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." ); 380 if ( !GetUpper() ) 381 return; 382 383 if ( lcl_IsCalcUpperAllowed( *this ) ) 384 GetUpper()->Calc(); 385 386 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." ); 387 } 388 389 if ( bTab && !bOldTabLock ) 390 ::PrepareUnlock( (SwTabFrm*)this ); 391 } 392 MakeAll(); 393 } 394 395 void SwFrm::OptPrepareMake() 396 { 397 // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame 398 if ( GetUpper() && !GetUpper()->IsFooterFrm() && 399 !GetUpper()->IsFlyFrm() ) 400 // <-- 401 { 402 GetUpper()->Calc(); 403 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." ); 404 if ( !GetUpper() ) 405 return; 406 } 407 if ( GetPrev() && !GetPrev()->IsValid() ) 408 PrepareMake(); 409 else 410 { 411 StackHack aHack; 412 MakeAll(); 413 } 414 } 415 416 417 418 void SwFrm::PrepareCrsr() 419 { 420 StackHack aHack; 421 if( GetUpper() && !GetUpper()->IsSctFrm() ) 422 { 423 GetUpper()->PrepareCrsr(); 424 GetUpper()->Calc(); 425 426 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." ); 427 if ( !GetUpper() ) 428 return; 429 430 const sal_Bool bCnt = IsCntntFrm(); 431 const sal_Bool bTab = IsTabFrm(); 432 sal_Bool bNoSect = IsInSct(); 433 434 sal_Bool bOldTabLock = sal_False, bFoll; 435 SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL; 436 437 if ( bTab ) 438 { 439 bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked(); 440 ::PrepareLock( (SwTabFrm*)this ); 441 pThis = (SwTabFrm*)this; 442 } 443 else if( IsSctFrm() ) 444 { 445 pThis = (SwSectionFrm*)this; 446 bNoSect = sal_False; 447 } 448 bFoll = pThis && pThis->IsFollow(); 449 450 SwFrm *pFrm = GetUpper()->Lower(); 451 while ( pFrm != this ) 452 { 453 ASSERT( pFrm, ":-( Layoutgeruest wackelig (this not found)." ); 454 if ( !pFrm ) 455 return; //Oioioioi ... 456 457 if ( !pFrm->IsValid() ) 458 { 459 //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung 460 //der Stabilitaet beitraegt: 461 //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin, 462 //so wuerde dieser mich beim Formatieren deleten; wie jeder 463 //leicht sehen kann waere dies eine etwas unuebersichtliche 464 //Situation die es zu vermeiden gilt. 465 if ( bFoll && pFrm->IsFlowFrm() && 466 (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) ) 467 break; 468 469 pFrm->MakeAll(); 470 } 471 //Die Kette kann bei CntntFrms waehrend des durchlaufens 472 //aufgebrochen werden, deshalb muss der Nachfolger etwas 473 //umstaendlich ermittelt werden. However, irgendwann _muss_ 474 //ich wieder bei mir selbst ankommen. 475 pFrm = pFrm->FindNext(); 476 if( bNoSect && pFrm && pFrm->IsSctFrm() ) 477 { 478 SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny(); 479 if( pCnt ) 480 pFrm = pCnt; 481 } 482 } 483 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." ); 484 if ( !GetUpper() ) 485 return; 486 487 GetUpper()->Calc(); 488 489 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." ); 490 491 if ( bTab && !bOldTabLock ) 492 ::PrepareUnlock( (SwTabFrm*)this ); 493 } 494 Calc(); 495 } 496 497 /************************************************************************* 498 |* 499 |* SwFrm::MakePos() 500 |* 501 |* Ersterstellung MA ?? 502 |* Letzte Aenderung MA 24. May. 93 503 |* 504 |*************************************************************************/ 505 506 // Hier wird GetPrev() zurueckgegeben, allerdings werden 507 // dabei leere SectionFrms ueberlesen 508 SwFrm* lcl_Prev( SwFrm* pFrm, sal_Bool bSectPrv = sal_True ) 509 { 510 SwFrm* pRet = pFrm->GetPrev(); 511 if( !pRet && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm() && 512 bSectPrv && !pFrm->IsColumnFrm() ) 513 pRet = pFrm->GetUpper()->GetPrev(); 514 while( pRet && pRet->IsSctFrm() && 515 !((SwSectionFrm*)pRet)->GetSection() ) 516 pRet = pRet->GetPrev(); 517 return pRet; 518 } 519 520 SwFrm* lcl_NotHiddenPrev( SwFrm* pFrm ) 521 { 522 SwFrm *pRet = pFrm; 523 do 524 { 525 pRet = lcl_Prev( pRet ); 526 } while ( pRet && pRet->IsTxtFrm() && ((SwTxtFrm*)pRet)->IsHiddenNow() ); 527 return pRet; 528 } 529 530 void SwFrm::MakePos() 531 { 532 if ( !bValidPos ) 533 { 534 bValidPos = sal_True; 535 sal_Bool bUseUpper = sal_False; 536 SwFrm* pPrv = lcl_Prev( this ); 537 if ( pPrv && 538 ( !pPrv->IsCntntFrm() || 539 ( ((SwCntntFrm*)pPrv)->GetFollow() != this ) ) 540 ) 541 { 542 if ( !StackHack::IsLocked() && 543 ( !IsInSct() || IsSctFrm() ) && 544 !pPrv->IsSctFrm() && 545 !pPrv->GetAttrSet()->GetKeep().GetValue() 546 ) 547 { 548 pPrv->Calc(); //hierbei kann der Prev verschwinden! 549 } 550 else if ( pPrv->Frm().Top() == 0 ) 551 { 552 bUseUpper = sal_True; 553 } 554 } 555 556 pPrv = lcl_Prev( this, sal_False ); 557 sal_uInt16 nMyType = GetType(); 558 SWRECTFN( ( IsCellFrm() && GetUpper() ? GetUpper() : this ) ) 559 if ( !bUseUpper && pPrv ) 560 { 561 aFrm.Pos( pPrv->Frm().Pos() ); 562 if( FRM_NEIGHBOUR & nMyType ) 563 { 564 sal_Bool bR2L = IsRightToLeft(); 565 if( bR2L ) 566 (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() - 567 (aFrm.*fnRect->fnGetWidth)() ); 568 else 569 (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() + 570 (pPrv->Frm().*fnRect->fnGetWidth)() ); 571 572 // cells may now leave their uppers 573 if( bVert && FRM_CELL & nMyType && !bReverse ) 574 aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width(); 575 } 576 else if( bVert && FRM_NOTE_VERT & nMyType ) 577 { 578 if( bReverse ) 579 aFrm.Pos().X() += pPrv->Frm().Width(); 580 else 581 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 582 { 583 if ( bVertL2R ) 584 aFrm.Pos().X() += pPrv->Frm().Width(); 585 else 586 aFrm.Pos().X() -= aFrm.Width(); 587 } 588 } 589 else 590 aFrm.Pos().Y() += pPrv->Frm().Height(); 591 } 592 else if ( GetUpper() ) 593 { 594 // OD 15.10.2002 #103517# - add safeguard for <SwFooterFrm::Calc()> 595 // If parent frame is a footer frame and its <ColLocked()>, then 596 // do *not* calculate it. 597 // NOTE: Footer frame is <ColLocked()> during its 598 // <FormatSize(..)>, which is called from <Format(..)>, which 599 // is called from <MakeAll()>, which is called from <Calc()>. 600 // --> OD 2005-11-17 #i56850# 601 // - no format of upper Writer fly frame, which is anchored 602 // at-paragraph or at-character. 603 if ( !GetUpper()->IsTabFrm() && 604 !( IsTabFrm() && GetUpper()->IsInTab() ) && 605 !GetUpper()->IsSctFrm() && 606 !dynamic_cast<SwFlyAtCntFrm*>(GetUpper()) && 607 !( GetUpper()->IsFooterFrm() && 608 GetUpper()->IsColLocked() ) 609 ) 610 { 611 GetUpper()->Calc(); 612 } 613 // <-- 614 pPrv = lcl_Prev( this, sal_False ); 615 if ( !bUseUpper && pPrv ) 616 { 617 aFrm.Pos( pPrv->Frm().Pos() ); 618 if( FRM_NEIGHBOUR & nMyType ) 619 { 620 sal_Bool bR2L = IsRightToLeft(); 621 if( bR2L ) 622 (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() - 623 (aFrm.*fnRect->fnGetWidth)() ); 624 else 625 (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() + 626 (pPrv->Frm().*fnRect->fnGetWidth)() ); 627 628 // cells may now leave their uppers 629 if( bVert && FRM_CELL & nMyType && !bReverse ) 630 aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width(); 631 } 632 else if( bVert && FRM_NOTE_VERT & nMyType ) 633 { 634 if( bReverse ) 635 aFrm.Pos().X() += pPrv->Frm().Width(); 636 else 637 aFrm.Pos().X() -= aFrm.Width(); 638 } 639 else 640 aFrm.Pos().Y() += pPrv->Frm().Height(); 641 } 642 else 643 { 644 aFrm.Pos( GetUpper()->Frm().Pos() ); 645 aFrm.Pos() += GetUpper()->Prt().Pos(); 646 if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() ) 647 { 648 if( bVert ) 649 aFrm.Pos().Y() += GetUpper()->Prt().Height() 650 - aFrm.Height(); 651 else 652 aFrm.Pos().X() += GetUpper()->Prt().Width() 653 - aFrm.Width(); 654 } 655 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 656 else if( bVert && !bVertL2R && FRM_NOTE_VERT & nMyType && !bReverse ) 657 aFrm.Pos().X() -= aFrm.Width() - GetUpper()->Prt().Width(); 658 } 659 } 660 else 661 aFrm.Pos().X() = aFrm.Pos().Y() = 0; 662 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 663 if( IsBodyFrm() && bVert && !bVertL2R && !bReverse && GetUpper() ) 664 aFrm.Pos().X() += GetUpper()->Prt().Width() - aFrm.Width(); 665 bValidPos = sal_True; 666 } 667 } 668 669 /************************************************************************* 670 |* 671 |* SwPageFrm::MakeAll() 672 |* 673 |* Ersterstellung MA 23. Feb. 93 674 |* Letzte Aenderung MA 20. Jul. 98 675 |* 676 |*************************************************************************/ 677 // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs> 678 void lcl_CheckObjects( SwSortedObjs* pSortedObjs, SwFrm* pFrm, long& rBot ) 679 { 680 //Und dann kann es natuerlich noch Absatzgebundene 681 //Rahmen geben, die unterhalb ihres Absatzes stehen. 682 long nMax = 0; 683 for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i ) 684 { 685 // --> OD 2004-07-01 #i28701# - consider changed type of <SwSortedObjs> 686 // entries. 687 SwAnchoredObject* pObj = (*pSortedObjs)[i]; 688 long nTmp = 0; 689 if ( pObj->ISA(SwFlyFrm) ) 690 { 691 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj); 692 if( pFly->Frm().Top() != WEIT_WECH && 693 ( pFrm->IsPageFrm() ? pFly->IsFlyLayFrm() : 694 ( pFly->IsFlyAtCntFrm() && 695 ( pFrm->IsBodyFrm() ? pFly->GetAnchorFrm()->IsInDocBody() : 696 pFly->GetAnchorFrm()->IsInFtn() ) ) ) ) 697 { 698 nTmp = pFly->Frm().Bottom(); 699 } 700 } 701 else 702 nTmp = pObj->GetObjRect().Bottom(); 703 nMax = Max( nTmp, nMax ); 704 // <-- 705 } 706 ++nMax; //Unterkante vs. Hoehe! 707 rBot = Max( rBot, nMax ); 708 } 709 710 void SwPageFrm::MakeAll() 711 { 712 PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 ) 713 714 const SwRect aOldRect( Frm() ); //Anpassung der Root-Groesse 715 const SwLayNotify aNotify( this ); //uebernimmt im DTor die Benachrichtigung 716 SwBorderAttrAccess *pAccess = 0; 717 const SwBorderAttrs*pAttrs = 0; 718 719 while ( !bValidPos || !bValidSize || !bValidPrtArea ) 720 { 721 if ( !bValidPos ) 722 { 723 // PAGES01 724 bValidPos = sal_True; // positioning of the pages is taken care of by the root frame 725 } 726 727 if ( !bValidSize || !bValidPrtArea ) 728 { 729 if ( IsEmptyPage() ) 730 { 731 Frm().Width( 0 ); Prt().Width( 0 ); 732 Frm().Height( 0 ); Prt().Height( 0 ); 733 Prt().Left( 0 ); Prt().Top( 0 ); 734 bValidSize = bValidPrtArea = sal_True; 735 } 736 else 737 { 738 if ( !pAccess ) 739 { 740 pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this ); 741 pAttrs = pAccess->Get(); 742 } 743 //Bei der BrowseView gelten feste Einstellungen. 744 ViewShell *pSh = getRootFrm()->GetCurrShell(); 745 if ( pSh && pSh->GetViewOptions()->getBrowseMode() ) 746 { 747 const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() ); 748 const long nTop = pAttrs->CalcTopLine() + aBorder.Height(); 749 const long nBottom = pAttrs->CalcBottomLine()+ aBorder.Height(); 750 751 long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() : 0; 752 if ( nWidth < pSh->GetBrowseWidth() ) 753 nWidth = pSh->GetBrowseWidth(); 754 nWidth += + 2 * aBorder.Width(); 755 /* 756 long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() + 2 * aBorder.Width() : 0; 757 if ( nWidth < pSh->VisArea().Width() ) 758 nWidth = pSh->VisArea().Width(); */ 759 760 nWidth = Max( nWidth, 2L * aBorder.Width() + 4L*MM50 ); 761 Frm().Width( nWidth ); 762 763 SwLayoutFrm *pBody = FindBodyCont(); 764 if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() ) 765 { 766 //Fuer Spalten gilt eine feste Hoehe 767 Frm().Height( pAttrs->GetSize().Height() ); 768 } 769 else 770 { 771 //Fuer Seiten ohne Spalten bestimmt der Inhalt die 772 //Groesse. 773 long nBot = Frm().Top() + nTop; 774 SwFrm *pFrm = Lower(); 775 while ( pFrm ) 776 { 777 long nTmp = 0; 778 SwFrm *pCnt = ((SwLayoutFrm*)pFrm)->ContainsAny(); 779 while ( pCnt && (pCnt->GetUpper() == pFrm || 780 ((SwLayoutFrm*)pFrm)->IsAnLower( pCnt ))) 781 { 782 nTmp += pCnt->Frm().Height(); 783 if( pCnt->IsTxtFrm() && 784 ((SwTxtFrm*)pCnt)->IsUndersized() ) 785 nTmp += ((SwTxtFrm*)pCnt)->GetParHeight() 786 - pCnt->Prt().Height(); 787 else if( pCnt->IsSctFrm() && 788 ((SwSectionFrm*)pCnt)->IsUndersized() ) 789 nTmp += ((SwSectionFrm*)pCnt)->Undersize(); 790 pCnt = pCnt->FindNext(); 791 } 792 // OD 29.10.2002 #97265# - consider invalid body frame properties 793 if ( pFrm->IsBodyFrm() && 794 ( !pFrm->GetValidSizeFlag() || 795 !pFrm->GetValidPrtAreaFlag() ) && 796 ( pFrm->Frm().Height() < pFrm->Prt().Height() ) 797 ) 798 { 799 nTmp = Min( nTmp, pFrm->Frm().Height() ); 800 } 801 else 802 { 803 // OD 30.10.2002 #97265# - assert invalid lower property 804 ASSERT( !(pFrm->Frm().Height() < pFrm->Prt().Height()), 805 "SwPageFrm::MakeAll(): Lower with frame height < printing height" ); 806 nTmp += pFrm->Frm().Height() - pFrm->Prt().Height(); 807 } 808 if ( !pFrm->IsBodyFrm() ) 809 nTmp = Min( nTmp, pFrm->Frm().Height() ); 810 nBot += nTmp; 811 // Hier werden die absatzgebundenen Objekte ueberprueft, 812 // ob sie ueber den Body/FtnCont hinausragen. 813 if( pSortedObjs && !pFrm->IsHeaderFrm() && 814 !pFrm->IsFooterFrm() ) 815 lcl_CheckObjects( pSortedObjs, pFrm, nBot ); 816 pFrm = pFrm->GetNext(); 817 } 818 nBot += nBottom; 819 //Und die Seitengebundenen 820 if ( pSortedObjs ) 821 lcl_CheckObjects( pSortedObjs, this, nBot ); 822 nBot -= Frm().Top(); 823 // --> OD 2004-11-10 #i35143# - If second page frame 824 // exists, the first page doesn't have to fulfill the 825 // visible area. 826 if ( !GetPrev() && !GetNext() ) 827 // <-- 828 { 829 nBot = Max( nBot, pSh->VisArea().Height() ); 830 } 831 // --> OD 2004-11-10 #i35143# - Assure, that the page 832 // doesn't exceed the defined browse height. 833 Frm().Height( Min( nBot, BROWSE_HEIGHT ) ); 834 // <-- 835 } 836 Prt().Left ( pAttrs->CalcLeftLine() + aBorder.Width() ); 837 Prt().Top ( nTop ); 838 Prt().Width( Frm().Width() - ( Prt().Left() 839 + pAttrs->CalcRightLine() + aBorder.Width() ) ); 840 Prt().Height( Frm().Height() - (nTop + nBottom) ); 841 bValidSize = bValidPrtArea = sal_True; 842 } 843 else 844 { //FixSize einstellen, bei Seiten nicht vom Upper sondern vom 845 //Attribut vorgegeben. 846 Frm().SSize( pAttrs->GetSize() ); 847 Format( pAttrs ); 848 } 849 } 850 } 851 } //while ( !bValidPos || !bValidSize || !bValidPrtArea ) 852 delete pAccess; 853 854 // PAGES01 855 if ( Frm() != aOldRect && GetUpper() ) 856 static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 ); 857 858 #ifdef DBG_UTIL 859 //Der Upper (Root) muss mindestens so breit 860 //sein, dass er die breiteste Seite aufnehmen kann. 861 if ( GetUpper() ) 862 { 863 ASSERT( GetUpper()->Prt().Width() >= aFrm.Width(), "Rootsize" ); 864 } 865 #endif 866 } 867 868 /************************************************************************* 869 |* 870 |* SwLayoutFrm::MakeAll() 871 |* 872 |* Ersterstellung MA ?? 873 |* Letzte Aenderung MA 28. Nov. 95 874 |* 875 |*************************************************************************/ 876 877 878 void SwLayoutFrm::MakeAll() 879 { 880 PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 ) 881 882 //uebernimmt im DTor die Benachrichtigung 883 const SwLayNotify aNotify( this ); 884 sal_Bool bVert = IsVertical(); 885 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 886 SwRectFn fnRect = ( IsNeighbourFrm() == bVert )? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert ); 887 888 SwBorderAttrAccess *pAccess = 0; 889 const SwBorderAttrs*pAttrs = 0; 890 891 while ( !bValidPos || !bValidSize || !bValidPrtArea ) 892 { 893 if ( !bValidPos ) 894 MakePos(); 895 896 if ( GetUpper() ) 897 { 898 // NEW TABLES 899 if ( IsLeaveUpperAllowed() ) 900 { 901 if ( !bValidSize ) 902 bValidPrtArea = sal_False; 903 } 904 else 905 { 906 if ( !bValidSize ) 907 { 908 //FixSize einstellen, die VarSize wird von Format() nach 909 //Berechnung der PrtArea eingestellt. 910 bValidPrtArea = sal_False; 911 912 SwTwips nPrtWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)(); 913 if( bVert && ( IsBodyFrm() || IsFtnContFrm() ) ) 914 { 915 SwFrm* pNxt = GetPrev(); 916 while( pNxt && !pNxt->IsHeaderFrm() ) 917 pNxt = pNxt->GetPrev(); 918 if( pNxt ) 919 nPrtWidth -= pNxt->Frm().Height(); 920 pNxt = GetNext(); 921 while( pNxt && !pNxt->IsFooterFrm() ) 922 pNxt = pNxt->GetNext(); 923 if( pNxt ) 924 nPrtWidth -= pNxt->Frm().Height(); 925 } 926 927 const long nDiff = nPrtWidth - (Frm().*fnRect->fnGetWidth)(); 928 929 if( IsNeighbourFrm() && IsRightToLeft() ) 930 (Frm().*fnRect->fnSubLeft)( nDiff ); 931 else 932 (Frm().*fnRect->fnAddRight)( nDiff ); 933 } 934 else 935 { 936 // Don't leave your upper 937 const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)(); 938 if( (Frm().*fnRect->fnOverStep)( nDeadLine ) ) 939 bValidSize = sal_False; 940 } 941 } 942 } 943 if ( !bValidSize || !bValidPrtArea ) 944 { 945 if ( !pAccess ) 946 { 947 pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this ); 948 pAttrs = pAccess->Get(); 949 } 950 Format( pAttrs ); 951 } 952 } //while ( !bValidPos || !bValidSize || !bValidPrtArea ) 953 if ( pAccess ) 954 delete pAccess; 955 } 956 957 /************************************************************************* 958 |* 959 |* SwCntntFrm::MakePrtArea() 960 |* 961 |* Ersterstellung MA 17. Nov. 92 962 |* Letzte Aenderung MA 03. Mar. 96 963 |* 964 |*************************************************************************/ 965 966 sal_Bool SwCntntFrm::MakePrtArea( const SwBorderAttrs &rAttrs ) 967 { 968 sal_Bool bSizeChgd = sal_False; 969 970 if ( !bValidPrtArea ) 971 { 972 bValidPrtArea = sal_True; 973 974 SWRECTFN( this ) 975 const sal_Bool bTxtFrm = IsTxtFrm(); 976 SwTwips nUpper = 0; 977 if ( bTxtFrm && ((SwTxtFrm*)this)->IsHiddenNow() ) 978 { 979 if ( ((SwTxtFrm*)this)->HasFollow() ) 980 ((SwTxtFrm*)this)->JoinFrm(); 981 982 if( (Prt().*fnRect->fnGetHeight)() ) 983 ((SwTxtFrm*)this)->HideHidden(); 984 Prt().Pos().X() = Prt().Pos().Y() = 0; 985 (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() ); 986 (Prt().*fnRect->fnSetHeight)( 0 ); 987 nUpper = -( (Frm().*fnRect->fnGetHeight)() ); 988 } 989 else 990 { 991 //Vereinfachung: CntntFrms sind immer in der Hoehe Variabel! 992 993 //An der FixSize gibt der umgebende Frame die Groesse vor, die 994 //Raender werden einfach abgezogen. 995 const long nLeft = rAttrs.CalcLeft( this ); 996 const long nRight = ((SwBorderAttrs&)rAttrs).CalcRight( this ); 997 (this->*fnRect->fnSetXMargins)( nLeft, nRight ); 998 999 ViewShell *pSh = getRootFrm()->GetCurrShell(); 1000 SwTwips nWidthArea; 1001 if( pSh && 0!=(nWidthArea=(pSh->VisArea().*fnRect->fnGetWidth)()) && 1002 GetUpper()->IsPageBodyFrm() && // nicht dagegen bei BodyFrms in Columns 1003 pSh->GetViewOptions()->getBrowseMode() ) 1004 { 1005 //Nicht ueber die Kante des sichbaren Bereiches hinausragen. 1006 //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite" 1007 //geben kann (RootFrm::ImplCalcBrowseWidth()) 1008 long nMinWidth = 0; 1009 1010 for (sal_uInt16 i = 0; GetDrawObjs() && i < GetDrawObjs()->Count();++i) 1011 { 1012 // --> OD 2004-07-01 #i28701# - consider changed type of 1013 // <SwSortedObjs> entries 1014 SwAnchoredObject* pObj = (*GetDrawObjs())[i]; 1015 const SwFrmFmt& rFmt = pObj->GetFrmFmt(); 1016 const sal_Bool bFly = pObj->ISA(SwFlyFrm); 1017 if ((bFly && (WEIT_WECH == pObj->GetObjRect().Width())) 1018 || rFmt.GetFrmSize().GetWidthPercent()) 1019 { 1020 continue; 1021 } 1022 1023 if ( FLY_AS_CHAR == rFmt.GetAnchor().GetAnchorId() ) 1024 { 1025 nMinWidth = Max( nMinWidth, 1026 bFly ? rFmt.GetFrmSize().GetWidth() 1027 : pObj->GetObjRect().Width() ); 1028 } 1029 // <-- 1030 } 1031 1032 const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() ); 1033 long nWidth = nWidthArea - 2 * ( IsVertical() ? aBorder.Height() : aBorder.Width() ); 1034 nWidth -= (Prt().*fnRect->fnGetLeft)(); 1035 nWidth -= rAttrs.CalcRightLine(); 1036 nWidth = Max( nMinWidth, nWidth ); 1037 (Prt().*fnRect->fnSetWidth)( Min( nWidth, 1038 (Prt().*fnRect->fnGetWidth)() ) ); 1039 } 1040 1041 if ( (Prt().*fnRect->fnGetWidth)() <= MINLAY ) 1042 { 1043 //Die PrtArea sollte schon wenigstens MINLAY breit sein, passend 1044 //zu den Minimalwerten des UI 1045 (Prt().*fnRect->fnSetWidth)( Min( long(MINLAY), 1046 (Frm().*fnRect->fnGetWidth)() ) ); 1047 SwTwips nTmp = (Frm().*fnRect->fnGetWidth)() - 1048 (Prt().*fnRect->fnGetWidth)(); 1049 if( (Prt().*fnRect->fnGetLeft)() > nTmp ) 1050 (Prt().*fnRect->fnSetLeft)( nTmp ); 1051 } 1052 1053 //Fuer die VarSize gelten folgende Regeln: 1054 //1. Der erste einer Kette hat keinen Rand nach oben 1055 //2. Nach unten gibt es nie einen Rand 1056 //3. Der Rand nach oben ist das Maximum aus dem Abstand des 1057 // Prev nach unten und dem eigenen Abstand nach oben. 1058 //Die drei Regeln werden auf die Berechnung der Freiraeume, die von 1059 //UL- bzw. LRSpace vorgegeben werden, angewand. Es gibt in alle 1060 //Richtungen jedoch ggf. trotzdem einen Abstand; dieser wird durch 1061 //Umrandung und/oder Schatten vorgegeben. 1062 //4. Der Abstand fuer TextFrms entspricht mindestens dem Durchschuss 1063 1064 nUpper = CalcUpperSpace( &rAttrs, NULL ); 1065 1066 // OD 2004-03-02 #106629# - use new method <CalcLowerSpace(..)> 1067 SwTwips nLower = CalcLowerSpace( &rAttrs ); 1068 // // in balanced columned section frames we do not want the 1069 // // common border 1070 // sal_Bool bCommonBorder = sal_True; 1071 // if ( IsInSct() && GetUpper()->IsColBodyFrm() ) 1072 // { 1073 // const SwSectionFrm* pSct = FindSctFrm(); 1074 // bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue(); 1075 // } 1076 // SwTwips nLower = bCommonBorder ? 1077 // rAttrs.GetBottomLine( this ) : 1078 // rAttrs.CalcBottomLine(); 1079 1080 (Prt().*fnRect->fnSetPosY)( (!bVert || bReverse) ? nUpper : nLower); 1081 nUpper += nLower; 1082 nUpper -= (Frm().*fnRect->fnGetHeight)() - 1083 (Prt().*fnRect->fnGetHeight)(); 1084 } 1085 //Wenn Unterschiede zwischen Alter und neuer Groesse, 1086 //Grow() oder Shrink() rufen 1087 if ( nUpper ) 1088 { 1089 if ( nUpper > 0 ) 1090 GrowFrm( nUpper ); 1091 else 1092 ShrinkFrm( -nUpper ); 1093 bSizeChgd = sal_True; 1094 } 1095 } 1096 return bSizeChgd; 1097 } 1098 1099 /************************************************************************* 1100 |* 1101 |* SwCntntFrm::MakeAll() 1102 |* 1103 |* Ersterstellung MA ?? 1104 |* Letzte Aenderung MA 16. Dec. 96 1105 |* 1106 |*************************************************************************/ 1107 1108 #define STOP_FLY_FORMAT 10 1109 // --> OD 2006-09-25 #b6448963# - loop prevention 1110 const int cnStopFormat = 15; 1111 // <-- 1112 1113 inline void ValidateSz( SwFrm *pFrm ) 1114 { 1115 if ( pFrm ) 1116 { 1117 pFrm->bValidSize = sal_True; 1118 pFrm->bValidPrtArea = sal_True; 1119 } 1120 } 1121 1122 void SwCntntFrm::MakeAll() 1123 { 1124 ASSERT( GetUpper(), "keinen Upper?" ); 1125 ASSERT( IsTxtFrm(), "MakeAll(), NoTxt" ); 1126 1127 if ( !IsFollow() && StackHack::IsLocked() ) 1128 return; 1129 1130 if ( IsJoinLocked() ) 1131 return; 1132 1133 ASSERT( !((SwTxtFrm*)this)->IsSwapped(), "Calculation of a swapped frame" ); 1134 1135 StackHack aHack; 1136 1137 if ( ((SwTxtFrm*)this)->IsLocked() ) 1138 { 1139 ASSERT( sal_False, "Format fuer gelockten TxtFrm." ); 1140 return; 1141 } 1142 1143 LockJoin(); 1144 long nFormatCount = 0; 1145 // --> OD 2006-09-25 #b6448963# - loop prevention 1146 int nConsequetiveFormatsWithoutChange = 0; 1147 // <-- 1148 PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 ) 1149 1150 #ifdef DBG_UTIL 1151 const SwDoc *pDoc = GetAttrSet()->GetDoc(); 1152 if( pDoc ) 1153 { 1154 static sal_Bool bWarn = sal_False; 1155 if( pDoc->InXMLExport() ) 1156 { 1157 ASSERT( bWarn, "Formatting during XML-export!" ); 1158 bWarn = sal_True; 1159 } 1160 else 1161 bWarn = sal_False; 1162 } 1163 #endif 1164 1165 //uebernimmt im DTor die Benachrichtigung 1166 SwCntntNotify *pNotify = new SwCntntNotify( this ); 1167 1168 sal_Bool bMakePage = sal_True; //solange sal_True kann eine neue Seite 1169 //angelegt werden (genau einmal) 1170 sal_Bool bMovedBwd = sal_False; //Wird sal_True wenn der Frame zurueckfliesst 1171 sal_Bool bMovedFwd = sal_False; //solange sal_False kann der Frm zurueck- 1172 //fliessen (solange, bis er einmal 1173 //vorwaerts ge'moved wurde). 1174 sal_Bool bFormatted = sal_False; //Fuer die Witwen und Waisen Regelung 1175 //wird der letzte CntntFrm einer Kette 1176 //u.U. zum Formatieren angeregt, dies 1177 //braucht nur einmal zu passieren. 1178 //Immer wenn der Frm gemoved wird muss 1179 //das Flag zurueckgesetzt werden. 1180 sal_Bool bMustFit = sal_False; //Wenn einmal die Notbremse gezogen wurde, 1181 //werden keine anderen Prepares mehr 1182 //abgesetzt. 1183 sal_Bool bFitPromise = sal_False; //Wenn ein Absatz nicht passte, mit WouldFit 1184 //aber verspricht, dass er sich passend 1185 //einstellt wird dieses Flag gesetzt. 1186 //Wenn er dann sein Versprechen nicht haelt, 1187 //kann kontrolliert verfahren werden. 1188 sal_Bool bMoveable; 1189 const sal_Bool bFly = IsInFly(); 1190 const sal_Bool bTab = IsInTab(); 1191 const sal_Bool bFtn = IsInFtn(); 1192 const sal_Bool bSct = IsInSct(); 1193 Point aOldFrmPos; //Damit bei Turnarounds jew. mit der 1194 Point aOldPrtPos; //letzten Pos verglichen und geprueft 1195 //werden kann, ob ein Prepare sinnvoll ist. 1196 1197 SwBorderAttrAccess aAccess( SwFrm::GetCache(), this ); 1198 const SwBorderAttrs &rAttrs = *aAccess.Get(); 1199 1200 // OD 2004-02-26 #i25029# 1201 if ( !IsFollow() && rAttrs.JoinedWithPrev( *(this) ) ) 1202 { 1203 pNotify->SetBordersJoinedWithPrev(); 1204 } 1205 1206 const sal_Bool bKeep = IsKeep( rAttrs.GetAttrSet() ); 1207 1208 SwSaveFtnHeight *pSaveFtn = 0; 1209 if ( bFtn ) 1210 { 1211 SwFtnFrm *pFtn = FindFtnFrm(); 1212 SwSectionFrm* pSct = pFtn->FindSctFrm(); 1213 if ( !((SwTxtFrm*)pFtn->GetRef())->IsLocked() ) 1214 { 1215 SwFtnBossFrm* pBoss = pFtn->GetRef()->FindFtnBossFrm( 1216 pFtn->GetAttr()->GetFtn().IsEndNote() ); 1217 if( !pSct || pSct->IsColLocked() || !pSct->Growable() ) 1218 pSaveFtn = new SwSaveFtnHeight( pBoss, 1219 ((SwTxtFrm*)pFtn->GetRef())->GetFtnLine( pFtn->GetAttr() ) ); 1220 } 1221 } 1222 1223 // --> OD 2008-08-12 #b6732519# 1224 if ( GetUpper()->IsSctFrm() && 1225 HasFollow() && 1226 GetFollow()->GetFrm() == GetNext() ) 1227 { 1228 dynamic_cast<SwTxtFrm*>(this)->JoinFrm(); 1229 } 1230 // <-- 1231 1232 // --> OD 2004-06-23 #i28701# - move master forward, if it has to move, 1233 // because of its object positioning. 1234 if ( !static_cast<SwTxtFrm*>(this)->IsFollow() ) 1235 { 1236 sal_uInt32 nToPageNum = 0L; 1237 const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos( 1238 *(GetAttrSet()->GetDoc()), 1239 *(static_cast<SwTxtFrm*>(this)), 1240 nToPageNum ); 1241 // --> OD 2006-01-27 #i58182# 1242 // Also move a paragraph forward, which is the first one inside a table cell. 1243 if ( bMoveFwdByObjPos && 1244 FindPageFrm()->GetPhyPageNum() < nToPageNum && 1245 ( lcl_Prev( this ) || 1246 GetUpper()->IsCellFrm() || 1247 ( GetUpper()->IsSctFrm() && 1248 GetUpper()->GetUpper()->IsCellFrm() ) ) && 1249 IsMoveable() ) 1250 { 1251 bMovedFwd = sal_True; 1252 MoveFwd( bMakePage, sal_False ); 1253 } 1254 // <-- 1255 } 1256 // <-- 1257 1258 //Wenn ein Follow neben seinem Master steht und nicht passt, kann er 1259 //gleich verschoben werden. 1260 if ( lcl_Prev( this ) && ((SwTxtFrm*)this)->IsFollow() && IsMoveable() ) 1261 { 1262 bMovedFwd = sal_True; 1263 // OD 2004-03-02 #106629# - If follow frame is in table, it's master 1264 // will be the last in the current table cell. Thus, invalidate the 1265 // printing area of the master, 1266 if ( IsInTab() ) 1267 { 1268 lcl_Prev( this )->InvalidatePrt(); 1269 } 1270 MoveFwd( bMakePage, sal_False ); 1271 } 1272 1273 // OD 08.11.2002 #104840# - check footnote content for forward move. 1274 // If a content of a footnote is on a prior page/column as its invalid 1275 // reference, it can be moved forward. 1276 if ( bFtn && !bValidPos ) 1277 { 1278 SwFtnFrm* pFtn = FindFtnFrm(); 1279 SwCntntFrm* pRefCnt = pFtn ? pFtn->GetRef() : 0; 1280 if ( pRefCnt && !pRefCnt->IsValid() ) 1281 { 1282 SwFtnBossFrm* pFtnBossOfFtn = pFtn->FindFtnBossFrm(); 1283 SwFtnBossFrm* pFtnBossOfRef = pRefCnt->FindFtnBossFrm(); 1284 //<loop of movefwd until condition held or no move> 1285 if ( pFtnBossOfFtn && pFtnBossOfRef && 1286 pFtnBossOfFtn != pFtnBossOfRef && 1287 pFtnBossOfFtn->IsBefore( pFtnBossOfRef ) ) 1288 { 1289 bMovedFwd = sal_True; 1290 MoveFwd( bMakePage, sal_False ); 1291 } 1292 } 1293 } 1294 1295 SWRECTFN( this ) 1296 1297 while ( !bValidPos || !bValidSize || !bValidPrtArea ) 1298 { 1299 // --> OD 2006-09-25 #b6448963# - loop prevention 1300 SwRect aOldFrm_StopFormat( Frm() ); 1301 SwRect aOldPrt_StopFormat( Prt() ); 1302 // <-- 1303 if ( sal_True == (bMoveable = IsMoveable()) ) 1304 { 1305 SwFrm *pPre = GetIndPrev(); 1306 if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) ) 1307 { 1308 SWREFRESHFN( this ) 1309 bMovedFwd = sal_True; 1310 if ( bMovedBwd ) 1311 { 1312 //Beim zurueckfliessen wurde der Upper angeregt sich 1313 //vollstaendig zu Painten, dass koennen wir uns jetzt 1314 //nach dem hin und her fliessen sparen. 1315 GetUpper()->ResetCompletePaint(); 1316 //Der Vorgaenger wurde Invalidiert, das ist jetzt auch obsolete. 1317 ASSERT( pPre, "missing old Prev" ); 1318 if( !pPre->IsSctFrm() ) 1319 ::ValidateSz( pPre ); 1320 } 1321 bMoveable = IsMoveable(); 1322 } 1323 } 1324 1325 aOldFrmPos = (Frm().*fnRect->fnGetPos)(); 1326 aOldPrtPos = (Prt().*fnRect->fnGetPos)(); 1327 1328 if ( !bValidPos ) 1329 MakePos(); 1330 1331 //FixSize einstellen, die VarSize wird von Format() justiert. 1332 if ( !bValidSize ) 1333 { 1334 // --> OD 2006-01-03 #125452# 1335 // invalidate printing area flag, if the following conditions are hold: 1336 // - current frame width is 0. 1337 // - current printing area width is 0. 1338 // - frame width is adjusted to a value greater than 0. 1339 // - printing area flag is sal_True. 1340 // Thus, it's assured that the printing area is adjusted, if the 1341 // frame area width changes its width from 0 to something greater 1342 // than 0. 1343 // Note: A text frame can be in such a situation, if the format is 1344 // triggered by method call <SwCrsrShell::SetCrsr()> after 1345 // loading the document. 1346 const SwTwips nNewFrmWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)(); 1347 if ( bValidPrtArea && nNewFrmWidth > 0 && 1348 (Frm().*fnRect->fnGetWidth)() == 0 && 1349 (Prt().*fnRect->fnGetWidth)() == 0 ) 1350 { 1351 bValidPrtArea = sal_False; 1352 } 1353 1354 (Frm().*fnRect->fnSetWidth)( nNewFrmWidth ); 1355 // <-- 1356 } 1357 if ( !bValidPrtArea ) 1358 { 1359 const long nOldW = (Prt().*fnRect->fnGetWidth)(); 1360 // --> OD 2004-09-28 #i34730# - keep current frame height 1361 const SwTwips nOldH = (Frm().*fnRect->fnGetHeight)(); 1362 // <-- 1363 MakePrtArea( rAttrs ); 1364 if ( nOldW != (Prt().*fnRect->fnGetWidth)() ) 1365 Prepare( PREP_FIXSIZE_CHG ); 1366 // --> OD 2004-09-28 #i34730# - check, if frame height has changed. 1367 // If yes, send a PREP_ADJUST_FRM and invalidate the size flag to 1368 // force a format. The format will check in its method 1369 // <SwTxtFrm::CalcPreps()>, if the already formatted lines still 1370 // fit and if not, performs necessary actions. 1371 // --> OD 2005-01-10 #i40150# - no check, if frame is undersized. 1372 if ( bValidSize && !IsUndersized() && 1373 nOldH != (Frm().*fnRect->fnGetHeight)() ) 1374 { 1375 // --> OD 2004-11-25 #115759# - no PREP_ADJUST_FRM and size 1376 // invalidation, if height decreases only by the additional 1377 // lower space as last content of a table cell and an existing 1378 // follow containing one line exists. 1379 const SwTwips nHDiff = nOldH - (Frm().*fnRect->fnGetHeight)(); 1380 const bool bNoPrepAdjustFrm = 1381 nHDiff > 0 && IsInTab() && GetFollow() && 1382 ( 1 == static_cast<SwTxtFrm*>(GetFollow())->GetLineCount( STRING_LEN ) || (static_cast<SwTxtFrm*>(GetFollow())->Frm().*fnRect->fnGetWidth)() < 0 ) && 1383 GetFollow()->CalcAddLowerSpaceAsLastInTableCell() == nHDiff; 1384 if ( !bNoPrepAdjustFrm ) 1385 { 1386 Prepare( PREP_ADJUST_FRM ); 1387 bValidSize = sal_False; 1388 } 1389 // <-- 1390 } 1391 // <-- 1392 } 1393 1394 //Damit die Witwen- und Waisen-Regelung eine Change bekommt muss der 1395 //CntntFrm benachrichtigt werden. 1396 //Kriterium: 1397 //- Er muss Moveable sein (sonst mach das Spalten keinen Sinn.) 1398 //- Er muss mit der Unterkante der PrtArea des Upper ueberlappen. 1399 if ( !bMustFit ) 1400 { 1401 sal_Bool bWidow = sal_True; 1402 const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)(); 1403 if ( bMoveable && !bFormatted && ( GetFollow() || 1404 ( (Frm().*fnRect->fnOverStep)( nDeadLine ) ) ) ) 1405 { 1406 Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False ); 1407 bValidSize = bWidow = sal_False; 1408 } 1409 if( (Frm().*fnRect->fnGetPos)() != aOldFrmPos || 1410 (Prt().*fnRect->fnGetPos)() != aOldPrtPos ) 1411 { 1412 // In diesem Prepare erfolgt ggf. ein _InvalidateSize(). 1413 // bValidSize wird sal_False und das Format() wird gerufen. 1414 Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False ); 1415 if ( bWidow && GetFollow() ) 1416 { Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False ); 1417 bValidSize = sal_False; 1418 } 1419 } 1420 } 1421 if ( !bValidSize ) 1422 { 1423 bValidSize = bFormatted = sal_True; 1424 ++nFormatCount; 1425 if( nFormatCount > STOP_FLY_FORMAT ) 1426 SetFlyLock( sal_True ); 1427 // --> OD 2006-09-25 #b6448963# - loop prevention 1428 // No format any longer, if <cnStopFormat> consequetive formats 1429 // without change occur. 1430 if ( nConsequetiveFormatsWithoutChange <= cnStopFormat ) 1431 { 1432 Format(); 1433 } 1434 #if OSL_DEBUG_LEVEL > 1 1435 else 1436 { 1437 ASSERT( false, "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" ); 1438 } 1439 #endif 1440 // <-- 1441 } 1442 1443 // FME 16.07.2003 #i16930# - removed this code because it did not work 1444 1445 // OD 04.04.2003 #108446# - react on the situation detected in the text 1446 // formatting - see <SwTxtFrm::FormatAdjust(..)>: 1447 // text frame has to move forward, because its text formatting stopped, 1448 // created a follow and detected, that it contains no content. 1449 /* if ( IsTxtFrm() && bValidPos && bValidSize && bValidPrtArea && 1450 (Frm().*fnRect->fnGetHeight)() == 0 && 1451 HasFollow() 1452 ) 1453 { 1454 SwFrm* pOldUpper = GetUpper(); 1455 MoveFwd( sal_True, sal_False ); 1456 if ( GetUpper() != pOldUpper ) 1457 { 1458 bMovedFwd = sal_True; 1459 SWREFRESHFN( this ) 1460 continue; 1461 } 1462 } */ 1463 1464 //Wenn ich der erste einer Kette bin koennte ich mal sehen ob 1465 //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll). 1466 //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts 1467 //geflossen sein. 1468 sal_Bool bDummy; 1469 if ( !lcl_Prev( this ) && 1470 !bMovedFwd && 1471 ( bMoveable || ( bFly && !bTab ) ) && 1472 ( !bFtn || !GetUpper()->FindFtnFrm()->GetPrev() ) 1473 && MoveBwd( bDummy ) ) 1474 { 1475 SWREFRESHFN( this ) 1476 bMovedBwd = sal_True; 1477 bFormatted = sal_False; 1478 if ( bKeep && bMoveable ) 1479 { 1480 if( CheckMoveFwd( bMakePage, sal_False, bMovedBwd ) ) 1481 { 1482 bMovedFwd = sal_True; 1483 bMoveable = IsMoveable(); 1484 SWREFRESHFN( this ) 1485 } 1486 Point aOldPos = (Frm().*fnRect->fnGetPos)(); 1487 MakePos(); 1488 if( aOldPos != (Frm().*fnRect->fnGetPos)() ) 1489 { 1490 Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False ); 1491 if ( !bValidSize ) 1492 { 1493 (Frm().*fnRect->fnSetWidth)( (GetUpper()-> 1494 Prt().*fnRect->fnGetWidth)() ); 1495 if ( !bValidPrtArea ) 1496 { 1497 const long nOldW = (Prt().*fnRect->fnGetWidth)(); 1498 MakePrtArea( rAttrs ); 1499 if( nOldW != (Prt().*fnRect->fnGetWidth)() ) 1500 Prepare( PREP_FIXSIZE_CHG, 0, sal_False ); 1501 } 1502 if( GetFollow() ) 1503 Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False ); 1504 bValidSize = bFormatted = sal_True; 1505 Format(); 1506 } 1507 } 1508 SwFrm *pNxt = HasFollow() ? NULL : FindNext(); 1509 while( pNxt && pNxt->IsSctFrm() ) 1510 { // Leere Bereiche auslassen, in die anderen hinein 1511 if( ((SwSectionFrm*)pNxt)->GetSection() ) 1512 { 1513 SwFrm* pTmp = ((SwSectionFrm*)pNxt)->ContainsAny(); 1514 if( pTmp ) 1515 { 1516 pNxt = pTmp; 1517 break; 1518 } 1519 } 1520 pNxt = pNxt->FindNext(); 1521 } 1522 if ( pNxt ) 1523 { 1524 pNxt->Calc(); 1525 if( bValidPos && !GetIndNext() ) 1526 { 1527 SwSectionFrm *pSct = FindSctFrm(); 1528 if( pSct && !pSct->GetValidSizeFlag() ) 1529 { 1530 SwSectionFrm* pNxtSct = pNxt->FindSctFrm(); 1531 if( pNxtSct && pSct->IsAnFollow( pNxtSct ) ) 1532 bValidPos = sal_False; 1533 } 1534 else 1535 bValidPos = sal_False; 1536 } 1537 } 1538 } 1539 } 1540 1541 //Der TxtFrm Validiert sich bei Fussnoten ggf. selbst, dass kann leicht 1542 //dazu fuehren, dass seine Position obwohl unrichtig valide ist. 1543 if ( bValidPos ) 1544 { 1545 // --> OD 2006-01-23 #i59341# 1546 // Workaround for inadequate layout algorithm: 1547 // suppress invalidation and calculation of position, if paragraph 1548 // has formatted itself at least STOP_FLY_FORMAT times and 1549 // has anchored objects. 1550 // Thus, the anchored objects get the possibility to format itself 1551 // and this probably solve the layout loop. 1552 if ( bFtn && 1553 nFormatCount <= STOP_FLY_FORMAT && 1554 !GetDrawObjs() ) 1555 // <-- 1556 { 1557 bValidPos = sal_False; 1558 MakePos(); 1559 aOldFrmPos = (Frm().*fnRect->fnGetPos)(); 1560 aOldPrtPos = (Prt().*fnRect->fnGetPos)(); 1561 } 1562 } 1563 1564 // --> OD 2006-09-25 #b6448963# - loop prevention 1565 { 1566 if ( aOldFrm_StopFormat == Frm() && 1567 aOldPrt_StopFormat == Prt() ) 1568 { 1569 ++nConsequetiveFormatsWithoutChange; 1570 } 1571 else 1572 { 1573 nConsequetiveFormatsWithoutChange = 0; 1574 } 1575 } 1576 // <-- 1577 1578 //Wieder ein Wert ungueltig? - dann nochmal das ganze... 1579 if ( !bValidPos || !bValidSize || !bValidPrtArea ) 1580 continue; 1581 1582 //Fertig? 1583 // Achtung, wg. Hoehe==0, ist es besser statt Bottom() Top()+Height() zu nehmen 1584 // (kommt bei Undersized TxtFrms an der Unterkante eines spaltigen Bereichs vor) 1585 const long nPrtBottom = (GetUpper()->*fnRect->fnGetPrtBottom)(); 1586 const long nBottomDist = (Frm().*fnRect->fnBottomDist)( nPrtBottom ); 1587 if( nBottomDist >= 0 ) 1588 { 1589 if ( bKeep && bMoveable ) 1590 { 1591 //Wir sorgen dafuer, dass der Nachfolger gleich mit formatiert 1592 //wird. Dadurch halten wir das Heft in der Hand, bis wirklich 1593 //(fast) alles stabil ist. So vermeiden wir Endlosschleifen, 1594 //die durch staendig wiederholte Versuche entstehen. 1595 //Das bMoveFwdInvalid ist fuer #38407# notwendig. War urspruenglich 1596 //in flowfrm.cxx rev 1.38 behoben, das unterbrach aber obiges 1597 //Schema und spielte lieber Tuerme von Hanoi (#43669#). 1598 SwFrm *pNxt = HasFollow() ? NULL : FindNext(); 1599 // Bei Bereichen nehmen wir lieber den Inhalt, denn nur 1600 // dieser kann ggf. die Seite wechseln 1601 while( pNxt && pNxt->IsSctFrm() ) 1602 { 1603 if( ((SwSectionFrm*)pNxt)->GetSection() ) 1604 { 1605 pNxt = ((SwSectionFrm*)pNxt)->ContainsAny(); 1606 break; 1607 } 1608 pNxt = pNxt->FindNext(); 1609 } 1610 if ( pNxt ) 1611 { 1612 const sal_Bool bMoveFwdInvalid = 0 != GetIndNext(); 1613 const sal_Bool bNxtNew = 1614 ( 0 == (pNxt->Prt().*fnRect->fnGetHeight)() ) && 1615 (!pNxt->IsTxtFrm() ||!((SwTxtFrm*)pNxt)->IsHiddenNow()); 1616 1617 pNxt->Calc(); 1618 1619 if ( !bMovedBwd && 1620 ((bMoveFwdInvalid && !GetIndNext()) || 1621 bNxtNew) ) 1622 { 1623 if( bMovedFwd ) 1624 pNotify->SetInvaKeep(); 1625 bMovedFwd = sal_False; 1626 } 1627 } 1628 } 1629 continue; 1630 } 1631 1632 //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt 1633 //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen 1634 1635 //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe 1636 //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man 1637 //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und 1638 //zwar mit aller Kraft. 1639 if ( !bMoveable || IsUndersized() ) 1640 { 1641 if( !bMoveable && IsInTab() ) 1642 { 1643 long nDiff = -(Frm().*fnRect->fnBottomDist)( 1644 (GetUpper()->*fnRect->fnGetPrtBottom)() ); 1645 long nReal = GetUpper()->Grow( nDiff ); 1646 if( nReal ) 1647 continue; 1648 } 1649 break; 1650 } 1651 1652 //Wenn ich nun ueberhaupt ganz und garnicht in meinen Upper passe 1653 //so kann die Situation vielleicht doch noch durch Aufbrechen 1654 //aufgeklart werden. Diese Situation tritt bei einem frisch 1655 //erzeugten Follow auf, der zwar auf die Folgeseite geschoben wurde 1656 //aber selbst noch zu gross fuer diese ist; also wiederum 1657 //aufgespalten werden muss. 1658 //Wenn ich nicht passe und nicht Spaltbar (WouldFit()) bin, so schicke 1659 //ich meinem TxtFrmanteil die Nachricht, dass eben falls moeglich 1660 //trotz des Attributes 'nicht aufspalten' aufgespalten werden muss. 1661 sal_Bool bMoveOrFit = sal_False; 1662 sal_Bool bDontMoveMe = !GetIndPrev(); 1663 if( bDontMoveMe && IsInSct() ) 1664 { 1665 SwFtnBossFrm* pBoss = FindFtnBossFrm(); 1666 bDontMoveMe = !pBoss->IsInSct() || 1667 ( !pBoss->Lower()->GetNext() && !pBoss->GetPrev() ); 1668 } 1669 1670 // Finally, we are able to split table rows. Therefore, bDontMoveMe 1671 // can be set to sal_False: 1672 if( bDontMoveMe && IsInTab() && 1673 0 != const_cast<SwCntntFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) 1674 bDontMoveMe = sal_False; 1675 1676 if ( bDontMoveMe && (Frm().*fnRect->fnGetHeight)() > 1677 (GetUpper()->Prt().*fnRect->fnGetHeight)() ) 1678 { 1679 if ( !bFitPromise ) 1680 { 1681 SwTwips nTmp = (GetUpper()->Prt().*fnRect->fnGetHeight)() - 1682 (Prt().*fnRect->fnGetTop)(); 1683 sal_Bool bSplit = !IsFwdMoveAllowed(); 1684 if ( nTmp > 0 && WouldFit( nTmp, bSplit, sal_False ) ) 1685 { 1686 Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False ); 1687 bValidSize = sal_False; 1688 bFitPromise = sal_True; 1689 continue; 1690 } 1691 /* -----------------19.02.99 12:58------------------- 1692 * Frueher wurde in Rahmen und Bereichen niemals versucht, 1693 * durch bMoveOrFit den TxtFrm unter Verzicht auf seine 1694 * Attribute (Widows,Keep) doch noch passend zu bekommen. 1695 * Dies haette zumindest bei spaltigen Rahmen versucht 1696 * werden muessen, spaetestens bei verketteten Rahmen und 1697 * in Bereichen muss es versucht werden. 1698 * Ausnahme: Wenn wir im FormatWidthCols stehen, duerfen die 1699 * Attribute nicht ausser Acht gelassen werden. 1700 * --------------------------------------------------*/ 1701 else if ( !bFtn && bMoveable && 1702 ( !bFly || !FindFlyFrm()->IsColLocked() ) && 1703 ( !bSct || !FindSctFrm()->IsColLocked() ) ) 1704 bMoveOrFit = sal_True; 1705 } 1706 #ifdef DBG_UTIL 1707 else 1708 { 1709 ASSERT( sal_False, "+TxtFrm hat WouldFit-Versprechen nicht eingehalten." ); 1710 } 1711 #endif 1712 } 1713 1714 //Mal sehen ob ich irgenwo Platz finde... 1715 //Benachbarte Fussnoten werden in _MoveFtnCntFwd 'vorgeschoben' 1716 SwFrm *pPre = GetIndPrev(); 1717 SwFrm *pOldUp = GetUpper(); 1718 1719 /* MA 13. Oct. 98: Was soll das denn sein!? 1720 * AMA 14. Dec 98: Wenn ein spaltiger Bereich keinen Platz mehr fuer seinen ersten ContentFrm 1721 * bietet, so soll dieser nicht nur in die naechste Spalte, sondern ggf. bis zur naechsten 1722 * Seite wandern und dort einen Section-Follow erzeugen. 1723 */ 1724 if( IsInSct() && bMovedFwd && bMakePage && pOldUp->IsColBodyFrm() && 1725 pOldUp->GetUpper()->GetUpper()->IsSctFrm() && 1726 ( pPre || pOldUp->GetUpper()->GetPrev() ) && 1727 ((SwSectionFrm*)pOldUp->GetUpper()->GetUpper())->MoveAllowed(this) ) 1728 bMovedFwd = sal_False; 1729 1730 const sal_Bool bCheckForGrownBody = pOldUp->IsBodyFrm(); 1731 const long nOldBodyHeight = (pOldUp->Frm().*fnRect->fnGetHeight)(); 1732 1733 if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) ) 1734 bMakePage = sal_False; 1735 SWREFRESHFN( this ) 1736 1737 // If MoveFwd moves the paragraph to the next page, a following 1738 // paragraph, which contains footnotes can can cause the old upper 1739 // frame to grow. In this case we explicitely allow a new check 1740 // for MoveBwd. Robust: We also check the bMovedBwd flag again. 1741 // If pOldUp was a footnote frame, it has been deleted inside MoveFwd. 1742 // Therefore we only check for growing body frames. 1743 if ( bCheckForGrownBody && ! bMovedBwd && pOldUp != GetUpper() && 1744 (pOldUp->Frm().*fnRect->fnGetHeight)() > nOldBodyHeight ) 1745 bMovedFwd = sal_False; 1746 else 1747 bMovedFwd = sal_True; 1748 1749 bFormatted = sal_False; 1750 if ( bMoveOrFit && GetUpper() == pOldUp ) 1751 { 1752 // FME 2007-08-30 #i81146# new loop control 1753 if ( nConsequetiveFormatsWithoutChange <= cnStopFormat ) 1754 { 1755 Prepare( PREP_MUST_FIT, 0, sal_False ); 1756 bValidSize = sal_False; 1757 bMustFit = sal_True; 1758 continue; 1759 } 1760 1761 #if OSL_DEBUG_LEVEL > 1 1762 ASSERT( false, "LoopControl in SwCntntFrm::MakeAll" ) 1763 #endif 1764 } 1765 if ( bMovedBwd && GetUpper() ) 1766 { //Unuetz gewordene Invalidierungen zuruecknehmen. 1767 GetUpper()->ResetCompletePaint(); 1768 if( pPre && !pPre->IsSctFrm() ) 1769 ::ValidateSz( pPre ); 1770 } 1771 1772 } //while ( !bValidPos || !bValidSize || !bValidPrtArea ) 1773 1774 1775 // NEW: Looping Louie (Light). Should not be applied in balanced sections. 1776 // Should only be applied if there is no better solution! 1777 LOOPING_LOUIE_LIGHT( bMovedFwd && bMovedBwd && !IsInBalancedSection() && 1778 ( 1779 1780 // --> FME 2005-01-26 #118572# 1781 ( bFtn && !FindFtnFrm()->GetRef()->IsInSct() ) || 1782 // <-- 1783 1784 // --> FME 2005-01-27 #i33887# 1785 ( IsInSct() && bKeep ) 1786 // <-- 1787 1788 // ... add your conditions here ... 1789 1790 ), 1791 static_cast<SwTxtFrm&>(*this) ); 1792 1793 1794 if ( pSaveFtn ) 1795 delete pSaveFtn; 1796 1797 UnlockJoin(); 1798 if ( bMovedFwd || bMovedBwd ) 1799 pNotify->SetInvaKeep(); 1800 // OD 2004-02-26 #i25029# 1801 if ( bMovedFwd ) 1802 { 1803 pNotify->SetInvalidatePrevPrtArea(); 1804 } 1805 delete pNotify; 1806 SetFlyLock( sal_False ); 1807 } 1808 1809 /************************************************************************* 1810 |* 1811 |* SwCntntFrm::_WouldFit() 1812 |* 1813 |* Ersterstellung MA 28. Feb. 95 1814 |* Letzte Aenderung AMA 15. Feb. 99 1815 |* 1816 |*************************************************************************/ 1817 1818 1819 1820 1821 void MakeNxt( SwFrm *pFrm, SwFrm *pNxt ) 1822 { 1823 //fix(25455): Validieren, sonst kommt es zu einer Rekursion. 1824 //Der erste Versuch, der Abbruch mit pFrm = 0 wenn !Valid, 1825 //fuehrt leider zu dem Problem, dass das Keep dann u.U. nicht mehr 1826 //korrekt beachtet wird (27417) 1827 const sal_Bool bOldPos = pFrm->GetValidPosFlag(); 1828 const sal_Bool bOldSz = pFrm->GetValidSizeFlag(); 1829 const sal_Bool bOldPrt = pFrm->GetValidPrtAreaFlag(); 1830 pFrm->bValidPos = pFrm->bValidPrtArea = pFrm->bValidSize = sal_True; 1831 1832 //fix(29272): Nicht MakeAll rufen, dort wird evtl. pFrm wieder invalidert 1833 //und kommt rekursiv wieder herein. 1834 if ( pNxt->IsCntntFrm() ) 1835 { 1836 SwCntntNotify aNotify( (SwCntntFrm*)pNxt ); 1837 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt ); 1838 const SwBorderAttrs &rAttrs = *aAccess.Get(); 1839 if ( !pNxt->GetValidSizeFlag() ) 1840 { 1841 if( pNxt->IsVertical() ) 1842 pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() ); 1843 else 1844 pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() ); 1845 } 1846 ((SwCntntFrm*)pNxt)->MakePrtArea( rAttrs ); 1847 pNxt->Format( &rAttrs ); 1848 } 1849 else 1850 { 1851 SwLayNotify aNotify( (SwLayoutFrm*)pNxt ); 1852 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt ); 1853 const SwBorderAttrs &rAttrs = *aAccess.Get(); 1854 if ( !pNxt->GetValidSizeFlag() ) 1855 { 1856 if( pNxt->IsVertical() ) 1857 pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() ); 1858 else 1859 pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() ); 1860 } 1861 pNxt->Format( &rAttrs ); 1862 } 1863 1864 pFrm->bValidPos = bOldPos; 1865 pFrm->bValidSize = bOldSz; 1866 pFrm->bValidPrtArea = bOldPrt; 1867 } 1868 1869 // Diese Routine ueberprueft, ob zwischen dem FtnBoss von pFrm und dem 1870 // von pNxt keine anderen FtnBosse liegen 1871 1872 sal_Bool lcl_IsNextFtnBoss( const SwFrm *pFrm, const SwFrm* pNxt ) 1873 { 1874 ASSERT( pFrm && pNxt, "lcl_IsNextFtnBoss: No Frames?" ); 1875 pFrm = pFrm->FindFtnBossFrm(); 1876 pNxt = pNxt->FindFtnBossFrm(); 1877 // Falls pFrm eine letzte Spalte ist, wird stattdessen die Seite genommen 1878 while( pFrm && pFrm->IsColumnFrm() && !pFrm->GetNext() ) 1879 pFrm = pFrm->GetUpper()->FindFtnBossFrm(); 1880 // Falls pNxt eine erste Spalte ist, wird stattdessen die Seite genommen 1881 while( pNxt && pNxt->IsColumnFrm() && !pNxt->GetPrev() ) 1882 pNxt = pNxt->GetUpper()->FindFtnBossFrm(); 1883 // So, jetzt muessen pFrm und pNxt entweder zwei benachbarte Seiten oder Spalten sein. 1884 return ( pFrm && pNxt && pFrm->GetNext() == pNxt ); 1885 } 1886 1887 // --> OD 2007-11-26 #b6614158# 1888 sal_Bool SwCntntFrm::_WouldFit( SwTwips nSpace, 1889 SwLayoutFrm *pNewUpper, 1890 sal_Bool bTstMove, 1891 const bool bObjsInNewUpper ) 1892 // <-- 1893 { 1894 //Damit die Fussnote sich ihren Platz sorgsam waehlt, muss 1895 //sie in jedem Fall gemoved werden, wenn zwischen dem 1896 //neuen Upper und ihrer aktuellen Seite/Spalte mindestens eine 1897 //Seite/Spalte liegt. 1898 SwFtnFrm* pFtnFrm = 0; 1899 if ( IsInFtn() ) 1900 { 1901 if( !lcl_IsNextFtnBoss( pNewUpper, this ) ) 1902 return sal_True; 1903 pFtnFrm = FindFtnFrm(); 1904 } 1905 1906 sal_Bool bRet; 1907 sal_Bool bSplit = !pNewUpper->Lower(); 1908 SwCntntFrm *pFrm = this; 1909 const SwFrm *pTmpPrev = pNewUpper->Lower(); 1910 if( pTmpPrev && pTmpPrev->IsFtnFrm() ) 1911 pTmpPrev = ((SwFtnFrm*)pTmpPrev)->Lower(); 1912 while ( pTmpPrev && pTmpPrev->GetNext() ) 1913 pTmpPrev = pTmpPrev->GetNext(); 1914 do 1915 { 1916 // --> FME 2005-03-31 #b6236853# #i46181# 1917 SwTwips nSecondCheck = 0; 1918 SwTwips nOldSpace = nSpace; 1919 sal_Bool bOldSplit = bSplit; 1920 // <-- 1921 1922 if ( bTstMove || IsInFly() || ( IsInSct() && 1923 ( pFrm->GetUpper()->IsColBodyFrm() || ( pFtnFrm && 1924 pFtnFrm->GetUpper()->GetUpper()->IsColumnFrm() ) ) ) ) 1925 { 1926 //Jetzt wirds ein bischen hinterlistig; empfindliche Gemueter sollten 1927 //lieber wegsehen. Wenn ein Flys Spalten enthaelt so sind die Cntnts 1928 //moveable, mit Ausnahme der in der letzten Spalte (siehe 1929 //SwFrm::IsMoveable()). Zurueckfliessen duerfen sie aber natuerlich. 1930 //Das WouldFit() liefert leider nur dann einen vernueftigen Wert, wenn 1931 //der Frm moveable ist. Um dem WouldFit() einen Moveable Frm 1932 //vorzugaukeln haenge ich ihn einfach solange um. 1933 // Auch bei spaltigen Bereichen muss umgehaengt werden, damit 1934 // SwSectionFrm::Growable() den richtigen Wert liefert. 1935 // Innerhalb von Fussnoten muss ggf. sogar der SwFtnFrm umgehaengt werden, 1936 // falls es dort keinen SwFtnFrm gibt. 1937 SwFrm* pTmpFrm = pFrm->IsInFtn() && !pNewUpper->FindFtnFrm() ? 1938 (SwFrm*)pFrm->FindFtnFrm() : pFrm; 1939 SwLayoutFrm *pUp = pTmpFrm->GetUpper(); 1940 SwFrm *pOldNext = pTmpFrm->GetNext(); 1941 pTmpFrm->Remove(); 1942 pTmpFrm->InsertBefore( pNewUpper, 0 ); 1943 if ( pFrm->IsTxtFrm() && 1944 ( bTstMove || 1945 ((SwTxtFrm*)pFrm)->HasFollow() || 1946 ( !((SwTxtFrm*)pFrm)->HasPara() && 1947 !((SwTxtFrm*)pFrm)->IsEmpty() 1948 ) 1949 ) 1950 ) 1951 { 1952 bTstMove = sal_True; 1953 bRet = ((SwTxtFrm*)pFrm)->TestFormat( pTmpPrev, nSpace, bSplit ); 1954 } 1955 else 1956 bRet = pFrm->WouldFit( nSpace, bSplit, sal_False ); 1957 1958 pTmpFrm->Remove(); 1959 pTmpFrm->InsertBefore( pUp, pOldNext ); 1960 } 1961 else 1962 { 1963 bRet = pFrm->WouldFit( nSpace, bSplit, sal_False ); 1964 nSecondCheck = !bSplit ? 1 : 0; 1965 } 1966 1967 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm ); 1968 const SwBorderAttrs &rAttrs = *aAccess.Get(); 1969 1970 //Bitter aber wahr: Der Abstand muss auch noch mit einkalkuliert werden. 1971 //Bei TestFormatierung ist dies bereits geschehen. 1972 if ( bRet && !bTstMove ) 1973 { 1974 SwTwips nUpper; 1975 1976 if ( pTmpPrev ) 1977 { 1978 nUpper = CalcUpperSpace( NULL, pTmpPrev ); 1979 1980 // in balanced columned section frames we do not want the 1981 // common border 1982 sal_Bool bCommonBorder = sal_True; 1983 if ( pFrm->IsInSct() && pFrm->GetUpper()->IsColBodyFrm() ) 1984 { 1985 const SwSectionFrm* pSct = pFrm->FindSctFrm(); 1986 bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue(); 1987 } 1988 1989 // --> FME 2005-03-31 #b6236853# #i46181# 1990 nSecondCheck = ( 1 == nSecondCheck && 1991 pFrm == this && 1992 IsTxtFrm() && 1993 bCommonBorder && 1994 !static_cast<const SwTxtFrm*>(this)->IsEmpty() ) ? 1995 nUpper : 1996 0; 1997 // <-- 1998 1999 nUpper += bCommonBorder ? 2000 rAttrs.GetBottomLine( *(pFrm) ) : 2001 rAttrs.CalcBottomLine(); 2002 2003 } 2004 else 2005 { 2006 // --> FME 2005-03-31 #b6236853# #i46181# 2007 nSecondCheck = 0; 2008 // <-- 2009 2010 if( pFrm->IsVertical() ) 2011 nUpper = pFrm->Frm().Width() - pFrm->Prt().Width(); 2012 else 2013 nUpper = pFrm->Frm().Height() - pFrm->Prt().Height(); 2014 } 2015 2016 nSpace -= nUpper; 2017 2018 if ( nSpace < 0 ) 2019 { 2020 bRet = sal_False; 2021 2022 // --> FME 2005-03-31 #b6236853# #i46181# 2023 if ( nSecondCheck > 0 ) 2024 { 2025 // The following code is indented to solve a (rare) problem 2026 // causing some frames not to move backward: 2027 // SwTxtFrm::WouldFit() claims that the whole paragraph 2028 // fits into the given space and subtracts the height of 2029 // all lines from nSpace. nSpace - nUpper is not a valid 2030 // indicator if the frame should be allowed to move backward. 2031 // We do a second check with the original remaining space 2032 // reduced by the required upper space: 2033 nOldSpace -= nSecondCheck; 2034 const bool bSecondRet = nOldSpace >= 0 && pFrm->WouldFit( nOldSpace, bOldSplit, sal_False ); 2035 if ( bSecondRet && bOldSplit && nOldSpace >= 0 ) 2036 { 2037 bRet = sal_True; 2038 bSplit = sal_True; 2039 } 2040 } 2041 // <-- 2042 } 2043 } 2044 2045 // OD 2004-03-01 #106629# - also consider lower spacing in table cells 2046 if ( bRet && IsInTab() && 2047 pNewUpper->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) ) 2048 { 2049 nSpace -= rAttrs.GetULSpace().GetLower(); 2050 if ( nSpace < 0 ) 2051 { 2052 bRet = sal_False; 2053 } 2054 } 2055 2056 if ( bRet && !bSplit && pFrm->IsKeep( rAttrs.GetAttrSet() ) ) 2057 { 2058 if( bTstMove ) 2059 { 2060 while( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() ) 2061 { 2062 pFrm = ((SwTxtFrm*)pFrm)->GetFollow(); 2063 } 2064 // OD 11.04.2003 #108824# - If last follow frame of <this> text 2065 // frame isn't valid, a formatting of the next content frame 2066 // doesn't makes sense. Thus, return sal_True. 2067 if ( IsAnFollow( pFrm ) && !pFrm->IsValid() ) 2068 { 2069 ASSERT( false, "Only a warning for task 108824:/n<SwCntntFrm::_WouldFit(..) - follow not valid!" ); 2070 return sal_True; 2071 } 2072 } 2073 SwFrm *pNxt; 2074 if( 0 != (pNxt = pFrm->FindNext()) && pNxt->IsCntntFrm() && 2075 ( !pFtnFrm || ( pNxt->IsInFtn() && 2076 pNxt->FindFtnFrm()->GetAttr() == pFtnFrm->GetAttr() ) ) ) 2077 { 2078 // ProbeFormatierung vertraegt keine absatz- oder gar zeichengebundene Objekte 2079 // --> OD 2007-11-26 #b6614158# 2080 // current solution for the test formatting doesn't work, if 2081 // objects are present in the remaining area of the new upper 2082 if ( bTstMove && 2083 ( pNxt->GetDrawObjs() || bObjsInNewUpper ) ) 2084 { 2085 return sal_True; 2086 } 2087 // <-- 2088 2089 if ( !pNxt->IsValid() ) 2090 MakeNxt( pFrm, pNxt ); 2091 2092 //Kleiner Trick: Wenn der naechste einen Vorgaenger hat, so hat 2093 //er den Absatzabstand bereits berechnet. Er braucht dann nicht 2094 //teuer kalkuliert werden. 2095 if( lcl_NotHiddenPrev( pNxt ) ) 2096 pTmpPrev = 0; 2097 else 2098 { 2099 if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow() ) 2100 pTmpPrev = lcl_NotHiddenPrev( pFrm ); 2101 else 2102 pTmpPrev = pFrm; 2103 } 2104 pFrm = (SwCntntFrm*)pNxt; 2105 } 2106 else 2107 pFrm = 0; 2108 } 2109 else 2110 pFrm = 0; 2111 2112 } while ( bRet && pFrm ); 2113 2114 return bRet; 2115 } 2116