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 31 32 #include "hintids.hxx" 33 34 #include "layfrm.hxx" 35 #include "ftnboss.hxx" 36 #include "ndtxt.hxx" 37 #include "paratr.hxx" 38 #include <editeng/orphitem.hxx> 39 #include <editeng/widwitem.hxx> 40 #include <editeng/keepitem.hxx> 41 #include <editeng/spltitem.hxx> 42 #include <frmatr.hxx> 43 #include <txtftn.hxx> 44 #include <fmtftn.hxx> 45 #include <rowfrm.hxx> 46 47 #include "txtcfg.hxx" 48 #include "widorp.hxx" 49 #include "txtfrm.hxx" 50 #include "itrtxt.hxx" 51 #include "sectfrm.hxx" //SwSectionFrm 52 #include "ftnfrm.hxx" 53 54 #undef WIDOWTWIPS 55 56 57 /************************************************************************* 58 * inline IsNastyFollow() 59 *************************************************************************/ 60 // Ein Follow, der auf der selben Seite steht, wie sein Master ist nasty. 61 inline sal_Bool IsNastyFollow( const SwTxtFrm *pFrm ) 62 { 63 ASSERT( !pFrm->IsFollow() || !pFrm->GetPrev() || 64 ((const SwTxtFrm*)pFrm->GetPrev())->GetFollow() == pFrm, 65 "IsNastyFollow: Was ist denn hier los?" ); 66 return pFrm->IsFollow() && pFrm->GetPrev(); 67 } 68 69 /************************************************************************* 70 * SwTxtFrmBreak::SwTxtFrmBreak() 71 *************************************************************************/ 72 73 SwTxtFrmBreak::SwTxtFrmBreak( SwTxtFrm *pNewFrm, const SwTwips nRst ) 74 : nRstHeight(nRst), pFrm(pNewFrm) 75 { 76 SWAP_IF_SWAPPED( pFrm ) 77 SWRECTFN( pFrm ) 78 nOrigin = (pFrm->*fnRect->fnGetPrtTop)(); 79 SwSectionFrm* pSct; 80 bKeep = !pFrm->IsMoveable() || IsNastyFollow( pFrm ) || 81 ( pFrm->IsInSct() && (pSct=pFrm->FindSctFrm())->Lower()->IsColumnFrm() 82 && !pSct->MoveAllowed( pFrm ) ) || 83 !pFrm->GetTxtNode()->GetSwAttrSet().GetSplit().GetValue() || 84 pFrm->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue(); 85 bBreak = sal_False; 86 87 if( !nRstHeight && !pFrm->IsFollow() && pFrm->IsInFtn() && pFrm->HasPara() ) 88 { 89 nRstHeight = pFrm->GetFtnFrmHeight(); 90 nRstHeight += (pFrm->Prt().*fnRect->fnGetHeight)() - 91 (pFrm->Frm().*fnRect->fnGetHeight)(); 92 if( nRstHeight < 0 ) 93 nRstHeight = 0; 94 } 95 96 UNDO_SWAP( pFrm ) 97 } 98 99 /* BP 18.6.93: Widows. 100 * Im Gegensatz zur ersten Implementierung werden die Widows nicht 101 * mehr vorausschauend berechnet, sondern erst beim Formatieren des 102 * gesplitteten Follows festgestellt. Im Master faellt die Widows- 103 * Berechnung also generell weg (nWidows wird manipuliert). 104 * Wenn der Follow feststellt, dass die Widowsregel zutrifft, 105 * verschickt er an seinen Vorgaenger ein Prepare. 106 * Ein besonderes Problem ergibt sich, wenn die Widows zuschlagen, 107 * aber im Master noch ein paar Zeilen zur Verfuegung stehen. 108 * 109 */ 110 111 /************************************************************************* 112 * SwTxtFrmBreak::IsInside() 113 *************************************************************************/ 114 115 /* BP(22.07.92): Berechnung von Witwen und Waisen. 116 * Die Methode liefert sal_True zurueck, wenn eine dieser Regelung zutrifft. 117 * 118 * Eine Schwierigkeit gibt es im Zusammenhang mit Widows und 119 * unterschiedlichen Formaten zwischen Master- und Folgeframes: 120 * Beispiel: Wenn die erste Spalte 3cm und die zweite 4cm breit ist 121 * und Widows auf sagen wir 3 gesetzt ist, so ist erst bei der Formatierung 122 * des Follows entscheidbar, ob die Widowsbedingung einhaltbar ist oder 123 * nicht. Leider ist davon abhaengig, ob der Absatz als Ganzes auf die 124 * naechste Seite rutscht. 125 */ 126 127 sal_Bool SwTxtFrmBreak::IsInside( SwTxtMargin &rLine ) const 128 { 129 sal_Bool bFit = sal_False; 130 131 SWAP_IF_SWAPPED( pFrm ) 132 SWRECTFN( pFrm ) 133 // nOrigin is an absolut value, rLine referes to the swapped situation. 134 135 SwTwips nTmpY; 136 if ( pFrm->IsVertical() ) 137 nTmpY = pFrm->SwitchHorizontalToVertical( rLine.Y() + rLine.GetLineHeight() ); 138 else 139 nTmpY = rLine.Y() + rLine.GetLineHeight(); 140 141 SwTwips nLineHeight = (*fnRect->fnYDiff)( nTmpY , nOrigin ); 142 143 // 7455 und 6114: Raum fuer die Umrandung unten einkalkulieren. 144 nLineHeight += (pFrm->*fnRect->fnGetBottomMargin)(); 145 146 if( nRstHeight ) 147 bFit = nRstHeight >= nLineHeight; 148 else 149 { 150 // Der Frm besitzt eine Hoehe, mit der er auf die Seite passt. 151 SwTwips nHeight = 152 (*fnRect->fnYDiff)( (pFrm->GetUpper()->*fnRect->fnGetPrtBottom)(), nOrigin ); 153 // Wenn sich alles innerhalb des bestehenden Frames abspielt, 154 // ist das Ergebnis sal_True; 155 bFit = nHeight >= nLineHeight; 156 157 // --> OD #i103292# 158 if ( !bFit ) 159 { 160 if ( rLine.GetNext() && 161 pFrm->IsInTab() && !pFrm->GetFollow() && !pFrm->GetIndNext() ) 162 { 163 // add additional space taken as lower space as last content in a table 164 // for all text lines except the last one. 165 nHeight += pFrm->CalcAddLowerSpaceAsLastInTableCell(); 166 bFit = nHeight >= nLineHeight; 167 } 168 } 169 // <-- 170 if( !bFit ) 171 { 172 // Die LineHeight sprengt die aktuelle Frm-Hoehe. 173 // Nun rufen wir ein Probe-Grow, um zu ermitteln, ob der 174 // Frame um den gewuenschten Bereich wachsen wuerde. 175 nHeight += pFrm->GrowTst( LONG_MAX ); 176 177 // Das Grow() returnt die Hoehe, um die der Upper des TxtFrm 178 // den TxtFrm wachsen lassen wuerde. 179 // Der TxtFrm selbst darf wachsen wie er will. 180 bFit = nHeight >= nLineHeight; 181 } 182 } 183 184 UNDO_SWAP( pFrm ); 185 186 return bFit; 187 } 188 189 /************************************************************************* 190 * SwTxtFrmBreak::IsBreakNow() 191 *************************************************************************/ 192 193 sal_Bool SwTxtFrmBreak::IsBreakNow( SwTxtMargin &rLine ) 194 { 195 SWAP_IF_SWAPPED( pFrm ) 196 197 // bKeep ist staerker als IsBreakNow() 198 // Ist noch genug Platz ? 199 if( bKeep || IsInside( rLine ) ) 200 bBreak = sal_False; 201 else 202 { 203 /* Diese Klasse geht davon aus, dass der SwTxtMargin von Top nach Bottom 204 * durchgearbeitet wird. Aus Performancegruenden wird in folgenden 205 * Faellen der Laden fuer das weitere Aufspalten dicht gemacht: 206 * Wenn eine einzige Zeile nicht mehr passt. 207 * Sonderfall: bei DummyPortions ist LineNr == 1, obwohl wir splitten 208 * wollen. 209 */ 210 // 6010: DropLines mit einbeziehen 211 212 sal_Bool bFirstLine = 1 == rLine.GetLineNr() && !rLine.GetPrev(); 213 bBreak = sal_True; 214 if( ( bFirstLine && pFrm->GetIndPrev() ) 215 || ( rLine.GetLineNr() <= rLine.GetDropLines() ) ) 216 { 217 bKeep = sal_True; 218 bBreak = sal_False; 219 } 220 else if(bFirstLine && pFrm->IsInFtn() && !pFrm->FindFtnFrm()->GetPrev()) 221 { 222 SwLayoutFrm* pTmp = pFrm->FindFtnBossFrm()->FindBodyCont(); 223 if( !pTmp || !pTmp->Lower() ) 224 bBreak = sal_False; 225 } 226 } 227 228 UNDO_SWAP( pFrm ) 229 230 return bBreak; 231 } 232 233 // OD 2004-02-27 #106629# - no longer inline 234 void SwTxtFrmBreak::SetRstHeight( const SwTxtMargin &rLine ) 235 { 236 // OD, FME 2004-02-27 #106629# - consider bottom margin 237 SWRECTFN( pFrm ) 238 239 nRstHeight = (pFrm->*fnRect->fnGetBottomMargin)(); 240 241 if ( bVert ) 242 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 243 { 244 if ( pFrm->IsVertLR() ) 245 nRstHeight = (*fnRect->fnYDiff)( pFrm->SwitchHorizontalToVertical( rLine.Y() ) , nOrigin ); 246 else 247 nRstHeight += nOrigin - pFrm->SwitchHorizontalToVertical( rLine.Y() ); 248 } 249 else 250 nRstHeight += rLine.Y() - nOrigin; 251 } 252 253 /************************************************************************* 254 * WidowsAndOrphans::WidowsAndOrphans() 255 *************************************************************************/ 256 257 WidowsAndOrphans::WidowsAndOrphans( SwTxtFrm *pNewFrm, const SwTwips nRst, 258 sal_Bool bChkKeep ) 259 : SwTxtFrmBreak( pNewFrm, nRst ), nWidLines( 0 ), nOrphLines( 0 ) 260 { 261 SWAP_IF_SWAPPED( pFrm ) 262 263 if( bKeep ) 264 { 265 // 5652: bei Absaetzen, die zusammengehalten werden sollen und 266 // groesser sind als die Seite wird bKeep aufgehoben. 267 if( bChkKeep && !pFrm->GetPrev() && !pFrm->IsInFtn() && 268 pFrm->IsMoveable() && 269 ( !pFrm->IsInSct() || pFrm->FindSctFrm()->MoveAllowed(pFrm) ) ) 270 bKeep = sal_False; 271 //Auch bei gesetztem Keep muessen Orphans beachtet werden, 272 //z.B. bei verketteten Rahmen erhaelt ein Follow im letzten Rahmen ein Keep, 273 //da er nicht (vorwaerts) Moveable ist, 274 //er darf aber trotzdem vom Master Zeilen anfordern wg. der Orphanregel. 275 if( pFrm->IsFollow() ) 276 nWidLines = pFrm->GetTxtNode()->GetSwAttrSet().GetWidows().GetValue(); 277 } 278 else 279 { 280 const SwAttrSet& rSet = pFrm->GetTxtNode()->GetSwAttrSet(); 281 const SvxOrphansItem &rOrph = rSet.GetOrphans(); 282 if ( rOrph.GetValue() > 1 ) 283 nOrphLines = rOrph.GetValue(); 284 if ( pFrm->IsFollow() ) 285 nWidLines = rSet.GetWidows().GetValue(); 286 287 } 288 289 if ( bKeep || nWidLines || nOrphLines ) 290 { 291 bool bResetFlags = false; 292 293 if ( pFrm->IsInTab() ) 294 { 295 // For compatibility reasons, we disable Keep/Widows/Orphans 296 // inside splittable row frames: 297 if ( pFrm->GetNextCellLeaf( MAKEPAGE_NONE ) || pFrm->IsInFollowFlowRow() ) 298 { 299 const SwFrm* pTmpFrm = pFrm->GetUpper(); 300 while ( !pTmpFrm->IsRowFrm() ) 301 pTmpFrm = pTmpFrm->GetUpper(); 302 if ( static_cast<const SwRowFrm*>(pTmpFrm)->IsRowSplitAllowed() ) 303 bResetFlags = true; 304 } 305 } 306 307 if( pFrm->IsInFtn() && !pFrm->GetIndPrev() ) 308 { 309 // Innerhalb von Fussnoten gibt es gute Gruende, das Keep-Attribut und 310 // die Widows/Orphans abzuschalten. 311 SwFtnFrm *pFtn = pFrm->FindFtnFrm(); 312 sal_Bool bFt = !pFtn->GetAttr()->GetFtn().IsEndNote(); 313 if( !pFtn->GetPrev() && 314 pFtn->FindFtnBossFrm( bFt ) != pFtn->GetRef()->FindFtnBossFrm( bFt ) 315 && ( !pFrm->IsInSct() || pFrm->FindSctFrm()->MoveAllowed(pFrm) ) ) 316 { 317 bResetFlags = true; 318 } 319 } 320 321 if ( bResetFlags ) 322 { 323 bKeep = sal_False; 324 nOrphLines = 0; 325 nWidLines = 0; 326 } 327 } 328 329 UNDO_SWAP( pFrm ) 330 } 331 332 /************************************************************************* 333 * WidowsAndOrphans::FindBreak() 334 *************************************************************************/ 335 336 /* Die Find*-Methoden suchen nicht nur, sondern stellen den SwTxtMargin auf 337 * die Zeile ein, wo der Absatz gebrochen werden soll und kuerzen ihn dort. 338 * FindBreak() 339 */ 340 341 sal_Bool WidowsAndOrphans::FindBreak( SwTxtFrm *pFrame, SwTxtMargin &rLine, 342 sal_Bool bHasToFit ) 343 { 344 // OD 2004-02-25 #i16128# - Why member <pFrm> _*and*_ parameter <pFrame>?? 345 // Thus, assertion on situation, that these are different to figure out why. 346 ASSERT( pFrm == pFrame, "<WidowsAndOrphans::FindBreak> - pFrm != pFrame" ); 347 348 SWAP_IF_SWAPPED( pFrm ) 349 350 sal_Bool bRet = sal_True; 351 MSHORT nOldOrphans = nOrphLines; 352 if( bHasToFit ) 353 nOrphLines = 0; 354 rLine.Bottom(); 355 // OD 2004-02-25 #i16128# - method renamed 356 if( !IsBreakNowWidAndOrp( rLine ) ) 357 bRet = sal_False; 358 if( !FindWidows( pFrame, rLine ) ) 359 { 360 sal_Bool bBack = sal_False; 361 // OD 2004-02-25 #i16128# - method renamed 362 while( IsBreakNowWidAndOrp( rLine ) ) 363 { 364 if( rLine.PrevLine() ) 365 bBack = sal_True; 366 else 367 break; 368 } 369 // Eigentlich werden bei HasToFit Schusterjungen (Orphans) nicht 370 // beruecksichtigt, wenn allerdings Dummy-Lines im Spiel sind und 371 // die Orphansregel verletzt wird, machen wir mal eine Ausnahme: 372 // Wir lassen einfach eine Dummyline zurueck und wandern mit dem Text 373 // komplett auf die naechste Seite/Spalte. 374 if( rLine.GetLineNr() <= nOldOrphans && 375 rLine.GetInfo().GetParaPortion()->IsDummy() && 376 ( ( bHasToFit && bRet ) || IsBreakNow( rLine ) ) ) 377 rLine.Top(); 378 379 rLine.TruncLines( sal_True ); 380 bRet = bBack; 381 } 382 nOrphLines = nOldOrphans; 383 384 UNDO_SWAP( pFrm ) 385 386 return bRet; 387 } 388 389 /************************************************************************* 390 * WidowsAndOrphans::FindWidows() 391 *************************************************************************/ 392 393 /* FindWidows positioniert den SwTxtMargin des Masters auf die umzubrechende 394 * Zeile, indem der Follow formatiert und untersucht wird. 395 * Liefert sal_True zurueck, wenn die Widows-Regelung in Kraft tritt, 396 * d.h. der Absatz _zusammengehalten_ werden soll ! 397 */ 398 399 sal_Bool WidowsAndOrphans::FindWidows( SwTxtFrm *pFrame, SwTxtMargin &rLine ) 400 { 401 ASSERT( ! pFrame->IsVertical() || ! pFrame->IsSwapped(), 402 "WidowsAndOrphans::FindWidows with swapped frame" ) 403 404 if( !nWidLines || !pFrame->IsFollow() ) 405 return sal_False; 406 407 rLine.Bottom(); 408 409 // Wir koennen noch was abzwacken 410 SwTxtFrm *pMaster = pFrame->FindMaster(); 411 ASSERT(pMaster, "+WidowsAndOrphans::FindWidows: Widows in a master?"); 412 if( !pMaster ) 413 return sal_False; 414 415 // 5156: Wenn die erste Zeile des Follows nicht passt, wird der Master 416 // wohl voll mit Dummies sein. In diesem Fall waere ein PREP_WIDOWS fatal. 417 if( pMaster->GetOfst() == pFrame->GetOfst() ) 418 return sal_False; 419 420 // Resthoehe des Masters 421 SWRECTFN( pFrame ) 422 423 const SwTwips nDocPrtTop = (pFrame->*fnRect->fnGetPrtTop)(); 424 SwTwips nOldHeight; 425 SwTwips nTmpY = rLine.Y() + rLine.GetLineHeight(); 426 427 if ( bVert ) 428 { 429 nTmpY = pFrame->SwitchHorizontalToVertical( nTmpY ); 430 nOldHeight = -(pFrame->Prt().*fnRect->fnGetHeight)(); 431 } 432 else 433 nOldHeight = (pFrame->Prt().*fnRect->fnGetHeight)(); 434 435 const SwTwips nChg = (*fnRect->fnYDiff)( nTmpY, nDocPrtTop + nOldHeight ); 436 437 // Unterhalb der Widows-Schwelle... 438 if( rLine.GetLineNr() >= nWidLines ) 439 { 440 // 8575: Follow to Master I 441 // Wenn der Follow *waechst*, so besteht fuer den Master die Chance, 442 // Zeilen entgegenzunehmen, die er vor Kurzem gezwungen war an den 443 // Follow abzugeben: Prepare(Need); diese Abfrage unterhalb von nChg! 444 // (0W, 2O, 2M, 2F) + 1F = 3M, 2F 445 if( rLine.GetLineNr() > nWidLines && pFrame->IsJustWidow() ) 446 { 447 // Wenn der Master gelockt ist, so hat er vermutlich gerade erst 448 // eine Zeile an uns abgegeben, diese geben nicht zurueck, nur 449 // weil bei uns daraus mehrere geworden sind (z.B. durch Rahmen). 450 if( !pMaster->IsLocked() && pMaster->GetUpper() ) 451 { 452 const SwTwips nTmpRstHeight = (pMaster->Frm().*fnRect->fnBottomDist) 453 ( (pMaster->GetUpper()->*fnRect->fnGetPrtBottom)() ); 454 if ( nTmpRstHeight >= 455 SwTwips(rLine.GetInfo().GetParaPortion()->Height() ) ) 456 { 457 pMaster->Prepare( PREP_ADJUST_FRM ); 458 pMaster->_InvalidateSize(); 459 pMaster->InvalidatePage(); 460 } 461 } 462 463 pFrame->SetJustWidow( sal_False ); 464 } 465 return sal_False; 466 } 467 468 // 8575: Follow to Master II 469 // Wenn der Follow *schrumpft*, so besteht fuer den Master die Chance, 470 // den kompletten Orphan zu inhalieren. 471 // (0W, 2O, 2M, 1F) - 1F = 3M, 0F -> PREP_ADJUST_FRM 472 // (0W, 2O, 3M, 2F) - 1F = 2M, 2F -> PREP_WIDOWS 473 474 if( 0 > nChg && !pMaster->IsLocked() && pMaster->GetUpper() ) 475 { 476 SwTwips nTmpRstHeight = (pMaster->Frm().*fnRect->fnBottomDist) 477 ( (pMaster->GetUpper()->*fnRect->fnGetPrtBottom)() ); 478 if( nTmpRstHeight >= SwTwips(rLine.GetInfo().GetParaPortion()->Height() ) ) 479 { 480 pMaster->Prepare( PREP_ADJUST_FRM ); 481 pMaster->_InvalidateSize(); 482 pMaster->InvalidatePage(); 483 pFrame->SetJustWidow( sal_False ); 484 return sal_False; 485 } 486 } 487 488 // Master to Follow 489 // Wenn der Follow nach seiner Formatierung weniger Zeilen enthaelt 490 // als Widows, so besteht noch die Chance, einige Zeilen des Masters 491 // abzuzwacken. Wenn dadurch die Orphans-Regel des Masters in Kraft 492 // tritt muss im CalcPrep() des Master-Frame der Frame so vergroessert 493 // werden, dass er nicht mehr auf seine urspruengliche Seite passt. 494 // Wenn er noch ein paar Zeilen entbehren kann, dann muss im CalcPrep() 495 // ein Shrink() erfolgen, der Follow mit dem Widows rutscht dann auf 496 // die Seite des Masters, haelt sich aber zusammen, so dass er (endlich) 497 // auf die naechste Seite rutscht. - So die Theorie! 498 499 500 // Wir fordern nur noch ein Zeile zur Zeit an, weil eine Zeile des Masters 501 // bei uns durchaus mehrere Zeilen ergeben koennten. 502 // Dafuer behaelt CalcFollow solange die Kontrolle, bis der Follow alle 503 // notwendigen Zeilen bekommen hat. 504 MSHORT nNeed = 1; // frueher: nWidLines - rLine.GetLineNr(); 505 506 // Special case: Master cannot give lines to follow 507 // --> FME 2008-09-16 #i91421# 508 if ( !pMaster->GetIndPrev() ) 509 { 510 sal_uLong nLines = pMaster->GetThisLines(); 511 if(nLines == 0 && pMaster->HasPara()) 512 { 513 const SwParaPortion *pMasterPara = pMaster->GetPara(); 514 if(pMasterPara && pMasterPara->GetNext()) 515 nLines = 2; 516 } 517 if( nLines <= nNeed ) 518 return sal_False; 519 } 520 521 pMaster->Prepare( PREP_WIDOWS, (void*)&nNeed ); 522 return sal_True; 523 } 524 525 /************************************************************************* 526 * WidowsAndOrphans::WouldFit() 527 *************************************************************************/ 528 529 sal_Bool WidowsAndOrphans::WouldFit( SwTxtMargin &rLine, SwTwips &rMaxHeight, sal_Bool bTst ) 530 { 531 // Here it does not matter, if pFrm is swapped or not. 532 // IsInside() takes care for itself 533 534 // Wir erwarten, dass rLine auf der letzten Zeile steht!! 535 ASSERT( !rLine.GetNext(), "WouldFit: aLine::Bottom missed!" ); 536 MSHORT nLineCnt = rLine.GetLineNr(); 537 538 // Erstmal die Orphansregel und den Initialenwunsch erfuellen ... 539 const MSHORT nMinLines = Max( GetOrphansLines(), rLine.GetDropLines() ); 540 if ( nLineCnt < nMinLines ) 541 return sal_False; 542 543 rLine.Top(); 544 SwTwips nLineSum = rLine.GetLineHeight(); 545 546 while( nMinLines > rLine.GetLineNr() ) 547 { 548 DBG_LOOP; 549 if( !rLine.NextLine() ) 550 return sal_False; 551 nLineSum += rLine.GetLineHeight(); 552 } 553 554 // Wenn wir jetzt schon nicht mehr passen ... 555 if( !IsInside( rLine ) ) 556 return sal_False; 557 558 // Jetzt noch die Widows-Regel ueberpruefen 559 if( !nWidLines && !pFrm->IsFollow() ) 560 { 561 // I.A. brauchen Widows nur ueberprueft werden, wenn wir ein Follow 562 // sind. Bei WouldFit muss aber auch fuer den Master die Regel ueber- 563 // prueft werden, weil wir ja gerade erst die Trennstelle ermitteln. 564 // Im Ctor von WidowsAndOrphans wurde nWidLines aber nur fuer Follows 565 // aus dem AttrSet ermittelt, deshalb holen wir es hier nach: 566 const SwAttrSet& rSet = pFrm->GetTxtNode()->GetSwAttrSet(); 567 nWidLines = rSet.GetWidows().GetValue(); 568 } 569 570 // Sind nach Orphans/Initialen noch genug Zeilen fuer die Widows uebrig? 571 // #111937#: If we are currently doing a test formatting, we may not 572 // consider the widows rule for two reasons: 573 // 1. The columns may have different widths. 574 // Widow lines would have wrong width. 575 // 2. Test formatting is only done up to the given space. 576 // we do not have any lines for widows at all. 577 if( bTst || nLineCnt - nMinLines >= GetWidowsLines() ) 578 { 579 if( rMaxHeight >= nLineSum ) 580 { 581 rMaxHeight -= nLineSum; 582 return sal_True; 583 } 584 } 585 return sal_False; 586 } 587 588