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