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