Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "hintids.hxx"
21 :
22 : #include "layfrm.hxx"
23 : #include "ftnboss.hxx"
24 : #include "ndtxt.hxx"
25 : #include "paratr.hxx"
26 : #include <editeng/orphitem.hxx>
27 : #include <editeng/widwitem.hxx>
28 : #include <editeng/keepitem.hxx>
29 : #include <editeng/spltitem.hxx>
30 : #include <frmatr.hxx>
31 : #include <txtftn.hxx>
32 : #include <fmtftn.hxx>
33 : #include <rowfrm.hxx>
34 :
35 : #include "widorp.hxx"
36 : #include "txtfrm.hxx"
37 : #include "itrtxt.hxx"
38 : #include "sectfrm.hxx" //SwSectionFrm
39 : #include "ftnfrm.hxx"
40 :
41 : #undef WIDOWTWIPS
42 :
43 :
44 : /*************************************************************************
45 : * inline IsNastyFollow()
46 : *************************************************************************/
47 : // A Follow on the same page as its master ist nasty.
48 390 : inline sal_Bool IsNastyFollow( const SwTxtFrm *pFrm )
49 : {
50 : OSL_ENSURE( !pFrm->IsFollow() || !pFrm->GetPrev() ||
51 : ((const SwTxtFrm*)pFrm->GetPrev())->GetFollow() == pFrm,
52 : "IsNastyFollow: Was ist denn hier los?" );
53 390 : return pFrm->IsFollow() && pFrm->GetPrev();
54 : }
55 :
56 : /*************************************************************************
57 : * SwTxtFrmBreak::SwTxtFrmBreak()
58 : *************************************************************************/
59 :
60 664 : SwTxtFrmBreak::SwTxtFrmBreak( SwTxtFrm *pNewFrm, const SwTwips nRst )
61 664 : : nRstHeight(nRst), pFrm(pNewFrm)
62 : {
63 664 : SWAP_IF_SWAPPED( pFrm )
64 664 : SWRECTFN( pFrm )
65 664 : nOrigin = (pFrm->*fnRect->fnGetPrtTop)();
66 : SwSectionFrm* pSct;
67 1054 : bKeep = !pFrm->IsMoveable() || IsNastyFollow( pFrm ) ||
68 410 : ( pFrm->IsInSct() && (pSct=pFrm->FindSctFrm())->Lower()->IsColumnFrm()
69 0 : && !pSct->MoveAllowed( pFrm ) ) ||
70 390 : !pFrm->GetTxtNode()->GetSwAttrSet().GetSplit().GetValue() ||
71 1854 : pFrm->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
72 664 : bBreak = sal_False;
73 :
74 664 : if( !nRstHeight && !pFrm->IsFollow() && pFrm->IsInFtn() && pFrm->HasPara() )
75 : {
76 10 : nRstHeight = pFrm->GetFtnFrmHeight();
77 10 : nRstHeight += (pFrm->Prt().*fnRect->fnGetHeight)() -
78 10 : (pFrm->Frm().*fnRect->fnGetHeight)();
79 10 : if( nRstHeight < 0 )
80 0 : nRstHeight = 0;
81 : }
82 :
83 664 : UNDO_SWAP( pFrm )
84 664 : }
85 :
86 : /* BP 18.6.93: Widows.
87 : * In contrast to the first implementation the Widows are not calculated
88 : * in advance but detected when formating the split Follow.
89 : * In Master the Widows-calculation is dropped completely
90 : * (nWidows is manipulated). If the Follow detects that the
91 : * Widows rule applies it sends a Prepare to its predecessor.
92 : * A special problem is when the Widow rule applies but in Master
93 : * there are some lines available.
94 : *
95 : */
96 :
97 : /*************************************************************************
98 : * SwTxtFrmBreak::IsInside()
99 : *************************************************************************/
100 :
101 : /* BP(22.07.92): Calculation of Widows and Orphans.
102 : * The method returns sal_True if one of the rules matches.
103 : *
104 : * One difficulty with Widows and different formats between
105 : * Master- and Follow-Frame:
106 : * Example: If the first column is 3cm and the second is 4cm and
107 : * Widows is set to 3, the decision if the Widows rule matches can not
108 : * be done until the Follow is formated. Unfortunately this is crucial
109 : * to decide if the whole paragraph goes to the next page or not.
110 : */
111 :
112 1202 : sal_Bool SwTxtFrmBreak::IsInside( SwTxtMargin &rLine ) const
113 : {
114 1202 : sal_Bool bFit = sal_False;
115 :
116 1202 : SWAP_IF_SWAPPED( pFrm )
117 1202 : SWRECTFN( pFrm )
118 : // nOrigin is an absolut value, rLine referes to the swapped situation.
119 :
120 : SwTwips nTmpY;
121 1202 : if ( pFrm->IsVertical() )
122 0 : nTmpY = pFrm->SwitchHorizontalToVertical( rLine.Y() + rLine.GetLineHeight() );
123 : else
124 1202 : nTmpY = rLine.Y() + rLine.GetLineHeight();
125 :
126 1202 : SwTwips nLineHeight = (*fnRect->fnYDiff)( nTmpY , nOrigin );
127 :
128 : // 7455 und 6114: Calculate extra space for bottom border.
129 1202 : nLineHeight += (pFrm->*fnRect->fnGetBottomMargin)();
130 :
131 1202 : if( nRstHeight )
132 38 : bFit = nRstHeight >= nLineHeight;
133 : else
134 : {
135 : // The Frm has a height to fit on the page.
136 : SwTwips nHeight =
137 1164 : (*fnRect->fnYDiff)( (pFrm->GetUpper()->*fnRect->fnGetPrtBottom)(), nOrigin );
138 : // If everything is inside the existing frame the result is sal_True;
139 1164 : bFit = nHeight >= nLineHeight;
140 :
141 : // --> OD #i103292#
142 1164 : if ( !bFit )
143 : {
144 15 : if ( rLine.GetNext() &&
145 0 : pFrm->IsInTab() && !pFrm->GetFollow() && !pFrm->GetIndNext() )
146 : {
147 : // add additional space taken as lower space as last content in a table
148 : // for all text lines except the last one.
149 0 : nHeight += pFrm->CalcAddLowerSpaceAsLastInTableCell();
150 0 : bFit = nHeight >= nLineHeight;
151 : }
152 : }
153 : // <--
154 1164 : if( !bFit )
155 : {
156 : // The LineHeight exceeds the current Frm height.
157 : // Call a test Grow to detect if the Frame could
158 : // grow the requested area.
159 15 : nHeight += pFrm->GrowTst( LONG_MAX );
160 :
161 : // The Grow() returns the height by which the Upper of the TxtFrm
162 : // would let the TxtFrm grow.
163 : // The TxtFrm itself can grow as much as it wants.
164 15 : bFit = nHeight >= nLineHeight;
165 : }
166 : }
167 :
168 1202 : UNDO_SWAP( pFrm );
169 :
170 1202 : return bFit;
171 : }
172 :
173 : /*************************************************************************
174 : * SwTxtFrmBreak::IsBreakNow()
175 : *************************************************************************/
176 :
177 2358 : sal_Bool SwTxtFrmBreak::IsBreakNow( SwTxtMargin &rLine )
178 : {
179 2358 : SWAP_IF_SWAPPED( pFrm )
180 :
181 : // bKeep is stronger than IsBreakNow()
182 : // Is there enough space ?
183 2358 : if( bKeep || IsInside( rLine ) )
184 2357 : bBreak = sal_False;
185 : else
186 : {
187 : /* This class assumes that the SwTxtMargin is processed from Top to
188 : * Bottom. Because of performance reasons we stop splitting in the
189 : * following cases:
190 : * If only one line does not fit.
191 : * Special case: with DummyPortions there is LineNr == 1, though we
192 : * want to split.
193 : */
194 : // 6010: include DropLines
195 :
196 1 : bool bFirstLine = 1 == rLine.GetLineNr() && !rLine.GetPrev();
197 1 : bBreak = sal_True;
198 1 : if( ( bFirstLine && pFrm->GetIndPrev() )
199 0 : || ( rLine.GetLineNr() <= rLine.GetDropLines() ) )
200 : {
201 1 : bKeep = sal_True;
202 1 : bBreak = sal_False;
203 : }
204 0 : else if(bFirstLine && pFrm->IsInFtn() && !pFrm->FindFtnFrm()->GetPrev())
205 : {
206 0 : SwLayoutFrm* pTmp = pFrm->FindFtnBossFrm()->FindBodyCont();
207 0 : if( !pTmp || !pTmp->Lower() )
208 0 : bBreak = sal_False;
209 : }
210 : }
211 :
212 2358 : UNDO_SWAP( pFrm )
213 :
214 2358 : return bBreak;
215 : }
216 :
217 : // OD 2004-02-27 #106629# - no longer inline
218 0 : void SwTxtFrmBreak::SetRstHeight( const SwTxtMargin &rLine )
219 : {
220 : // OD, FME 2004-02-27 #106629# - consider bottom margin
221 0 : SWRECTFN( pFrm )
222 :
223 0 : nRstHeight = (pFrm->*fnRect->fnGetBottomMargin)();
224 :
225 0 : if ( bVert )
226 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
227 : {
228 0 : if ( pFrm->IsVertLR() )
229 0 : nRstHeight = (*fnRect->fnYDiff)( pFrm->SwitchHorizontalToVertical( rLine.Y() ) , nOrigin );
230 : else
231 0 : nRstHeight += nOrigin - pFrm->SwitchHorizontalToVertical( rLine.Y() );
232 : }
233 : else
234 0 : nRstHeight += rLine.Y() - nOrigin;
235 0 : }
236 :
237 : /*************************************************************************
238 : * WidowsAndOrphans::WidowsAndOrphans()
239 : *************************************************************************/
240 :
241 664 : WidowsAndOrphans::WidowsAndOrphans( SwTxtFrm *pNewFrm, const SwTwips nRst,
242 : sal_Bool bChkKeep )
243 664 : : SwTxtFrmBreak( pNewFrm, nRst ), nWidLines( 0 ), nOrphLines( 0 )
244 : {
245 664 : SWAP_IF_SWAPPED( pFrm )
246 :
247 664 : if( bKeep )
248 : {
249 : // 5652: If pararagraph should not be split but is larger than
250 : // the page, then bKeep is overruled.
251 569 : if( bChkKeep && !pFrm->GetPrev() && !pFrm->IsInFtn() &&
252 273 : pFrm->IsMoveable() &&
253 5 : ( !pFrm->IsInSct() || pFrm->FindSctFrm()->MoveAllowed(pFrm) ) )
254 5 : bKeep = sal_False;
255 : // Even if Keep is set, Orphans has to be respected.
256 : // e.g. if there are chained frames where a Follow in the last frame
257 : // receives a Keep, because it is not (forward) movable -
258 : // nevertheless the paragraph can request lines from the Master
259 : // because of the Orphan rule.
260 291 : if( pFrm->IsFollow() )
261 0 : nWidLines = pFrm->GetTxtNode()->GetSwAttrSet().GetWidows().GetValue();
262 : }
263 : else
264 : {
265 373 : const SwAttrSet& rSet = pFrm->GetTxtNode()->GetSwAttrSet();
266 373 : const SvxOrphansItem &rOrph = rSet.GetOrphans();
267 373 : if ( rOrph.GetValue() > 1 )
268 99 : nOrphLines = rOrph.GetValue();
269 373 : if ( pFrm->IsFollow() )
270 0 : nWidLines = rSet.GetWidows().GetValue();
271 :
272 : }
273 :
274 664 : if ( bKeep || nWidLines || nOrphLines )
275 : {
276 385 : bool bResetFlags = false;
277 :
278 385 : if ( pFrm->IsInTab() )
279 : {
280 : // For compatibility reasons, we disable Keep/Widows/Orphans
281 : // inside splittable row frames:
282 177 : if ( pFrm->GetNextCellLeaf( MAKEPAGE_NONE ) || pFrm->IsInFollowFlowRow() )
283 : {
284 0 : const SwFrm* pTmpFrm = pFrm->GetUpper();
285 0 : while ( !pTmpFrm->IsRowFrm() )
286 0 : pTmpFrm = pTmpFrm->GetUpper();
287 0 : if ( static_cast<const SwRowFrm*>(pTmpFrm)->IsRowSplitAllowed() )
288 0 : bResetFlags = true;
289 : }
290 : }
291 :
292 385 : if( pFrm->IsInFtn() && !pFrm->GetIndPrev() )
293 : {
294 : // Inside of footnotes there are good reasons to turn off the Keep attribute
295 : // as well as Widows/Orphans.
296 0 : SwFtnFrm *pFtn = pFrm->FindFtnFrm();
297 0 : sal_Bool bFt = !pFtn->GetAttr()->GetFtn().IsEndNote();
298 0 : if( !pFtn->GetPrev() &&
299 0 : pFtn->FindFtnBossFrm( bFt ) != pFtn->GetRef()->FindFtnBossFrm( bFt )
300 0 : && ( !pFrm->IsInSct() || pFrm->FindSctFrm()->MoveAllowed(pFrm) ) )
301 : {
302 0 : bResetFlags = true;
303 : }
304 : }
305 :
306 385 : if ( bResetFlags )
307 : {
308 0 : bKeep = sal_False;
309 0 : nOrphLines = 0;
310 0 : nWidLines = 0;
311 : }
312 : }
313 :
314 664 : UNDO_SWAP( pFrm )
315 664 : }
316 :
317 : /*************************************************************************
318 : * WidowsAndOrphans::FindBreak()
319 : *************************************************************************/
320 :
321 : /* The Find*-Methodes do not only search, but adjust the SwTxtMargin to the
322 : * line where the paragraph should have a break and truncate the paragraph there.
323 : * FindBreak()
324 : */
325 :
326 662 : sal_Bool WidowsAndOrphans::FindBreak( SwTxtFrm *pFrame, SwTxtMargin &rLine,
327 : sal_Bool bHasToFit )
328 : {
329 : // OD 2004-02-25 #i16128# - Why member <pFrm> _*and*_ parameter <pFrame>??
330 : // Thus, assertion on situation, that these are different to figure out why.
331 : OSL_ENSURE( pFrm == pFrame, "<WidowsAndOrphans::FindBreak> - pFrm != pFrame" );
332 :
333 662 : SWAP_IF_SWAPPED( pFrm )
334 :
335 662 : sal_Bool bRet = sal_True;
336 662 : MSHORT nOldOrphans = nOrphLines;
337 662 : if( bHasToFit )
338 0 : nOrphLines = 0;
339 662 : rLine.Bottom();
340 : // OD 2004-02-25 #i16128# - method renamed
341 662 : if( !IsBreakNowWidAndOrp( rLine ) )
342 662 : bRet = sal_False;
343 662 : if( !FindWidows( pFrame, rLine ) )
344 : {
345 662 : sal_Bool bBack = sal_False;
346 : // OD 2004-02-25 #i16128# - method renamed
347 1324 : while( IsBreakNowWidAndOrp( rLine ) )
348 : {
349 0 : if( rLine.PrevLine() )
350 0 : bBack = sal_True;
351 : else
352 0 : break;
353 : }
354 : // Usually Orphans are not taken into account for HasToFit.
355 : // But if Dummy-Lines are concerned and the Orphans rule is violated
356 : // we make an exception: We leave behind one Dummyline and take
357 : // the whole text to the next page/column.
358 757 : if( rLine.GetLineNr() <= nOldOrphans &&
359 93 : rLine.GetInfo().GetParaPortion()->IsDummy() &&
360 2 : ( ( bHasToFit && bRet ) || IsBreakNow( rLine ) ) )
361 0 : rLine.Top();
362 :
363 662 : rLine.TruncLines( true );
364 662 : bRet = bBack;
365 : }
366 662 : nOrphLines = nOldOrphans;
367 :
368 662 : UNDO_SWAP( pFrm )
369 :
370 662 : return bRet;
371 : }
372 :
373 : /*************************************************************************
374 : * WidowsAndOrphans::FindWidows()
375 : *************************************************************************/
376 :
377 : /* FindWidows positions the SwTxtMargin of the Master to the line where to
378 : * break by examining and formatting the Follow.
379 : * Returns sal_True if the Widows-rule matches, that means that the
380 : * paragraph should not be split (keep) !
381 : */
382 :
383 662 : sal_Bool WidowsAndOrphans::FindWidows( SwTxtFrm *pFrame, SwTxtMargin &rLine )
384 : {
385 : OSL_ENSURE( ! pFrame->IsVertical() || ! pFrame->IsSwapped(),
386 : "WidowsAndOrphans::FindWidows with swapped frame" );
387 :
388 662 : if( !nWidLines || !pFrame->IsFollow() )
389 662 : return sal_False;
390 :
391 0 : rLine.Bottom();
392 :
393 : // Wir koennen noch was abzwacken
394 0 : SwTxtFrm *pMaster = pFrame->FindMaster();
395 : OSL_ENSURE(pMaster, "+WidowsAndOrphans::FindWidows: Widows in a master?");
396 0 : if( !pMaster )
397 0 : return sal_False;
398 :
399 : // 5156: If the first line of the Follow does not fit, the master
400 : // probably is full of Dummies. In this case a PREP_WIDOWS would be fatal.
401 0 : if( pMaster->GetOfst() == pFrame->GetOfst() )
402 0 : return sal_False;
403 :
404 : // Remaining height of the master
405 0 : SWRECTFN( pFrame )
406 :
407 0 : const SwTwips nDocPrtTop = (pFrame->*fnRect->fnGetPrtTop)();
408 : SwTwips nOldHeight;
409 0 : SwTwips nTmpY = rLine.Y() + rLine.GetLineHeight();
410 :
411 0 : if ( bVert )
412 : {
413 0 : nTmpY = pFrame->SwitchHorizontalToVertical( nTmpY );
414 0 : nOldHeight = -(pFrame->Prt().*fnRect->fnGetHeight)();
415 : }
416 : else
417 0 : nOldHeight = (pFrame->Prt().*fnRect->fnGetHeight)();
418 :
419 0 : const SwTwips nChg = (*fnRect->fnYDiff)( nTmpY, nDocPrtTop + nOldHeight );
420 :
421 : // below the Widows-treshold...
422 0 : if( rLine.GetLineNr() >= nWidLines )
423 : {
424 : // 8575: Follow to Master I
425 : // If the Follow *grows*, there is the chance for the Master to
426 : // receive lines, that it was forced to hand over to the Follow lately:
427 : // Prepare(Need); check that below nChg!
428 : // (0W, 2O, 2M, 2F) + 1F = 3M, 2F
429 0 : if( rLine.GetLineNr() > nWidLines && pFrame->IsJustWidow() )
430 : {
431 : // If the Master is locked, it has probably just donated a line
432 : // to us, we don't return that just because we turned it into
433 : // multiple lines (e.g. via frames).
434 0 : if( !pMaster->IsLocked() && pMaster->GetUpper() )
435 : {
436 0 : const SwTwips nTmpRstHeight = (pMaster->Frm().*fnRect->fnBottomDist)
437 0 : ( (pMaster->GetUpper()->*fnRect->fnGetPrtBottom)() );
438 0 : if ( nTmpRstHeight >=
439 0 : SwTwips(rLine.GetInfo().GetParaPortion()->Height() ) )
440 : {
441 0 : pMaster->Prepare( PREP_ADJUST_FRM );
442 0 : pMaster->_InvalidateSize();
443 0 : pMaster->InvalidatePage();
444 : }
445 : }
446 :
447 0 : pFrame->SetJustWidow( sal_False );
448 : }
449 0 : return sal_False;
450 : }
451 :
452 : // 8575: Follow to Master II
453 : // If the Follow *shrinks*, maybe the Master can absorb the whole Orphan.
454 : // (0W, 2O, 2M, 1F) - 1F = 3M, 0F -> PREP_ADJUST_FRM
455 : // (0W, 2O, 3M, 2F) - 1F = 2M, 2F -> PREP_WIDOWS
456 :
457 0 : if( 0 > nChg && !pMaster->IsLocked() && pMaster->GetUpper() )
458 : {
459 0 : SwTwips nTmpRstHeight = (pMaster->Frm().*fnRect->fnBottomDist)
460 0 : ( (pMaster->GetUpper()->*fnRect->fnGetPrtBottom)() );
461 0 : if( nTmpRstHeight >= SwTwips(rLine.GetInfo().GetParaPortion()->Height() ) )
462 : {
463 0 : pMaster->Prepare( PREP_ADJUST_FRM );
464 0 : pMaster->_InvalidateSize();
465 0 : pMaster->InvalidatePage();
466 0 : pFrame->SetJustWidow( sal_False );
467 0 : return sal_False;
468 : }
469 : }
470 :
471 : // Master to Follow
472 : // Wenn der Follow nach seiner Formatierung weniger Zeilen enthaelt
473 : // als Widows, so besteht noch die Chance, einige Zeilen des Masters
474 : // abzuzwacken. Wenn dadurch die Orphans-Regel des Masters in Kraft
475 : // tritt muss im CalcPrep() des Master-Frame der Frame so vergroessert
476 : // werden, dass er nicht mehr auf seine urspruengliche Seite passt.
477 : // Wenn er noch ein paar Zeilen entbehren kann, dann muss im CalcPrep()
478 : // ein Shrink() erfolgen, der Follow mit dem Widows rutscht dann auf
479 : // die Seite des Masters, haelt sich aber zusammen, so dass er (endlich)
480 : // auf die naechste Seite rutscht. - So die Theorie!
481 :
482 :
483 : // Wir fordern nur noch ein Zeile zur Zeit an, weil eine Zeile des Masters
484 : // bei uns durchaus mehrere Zeilen ergeben koennten.
485 : // Dafuer behaelt CalcFollow solange die Kontrolle, bis der Follow alle
486 : // notwendigen Zeilen bekommen hat.
487 0 : MSHORT nNeed = 1; // frueher: nWidLines - rLine.GetLineNr();
488 :
489 : // Special case: Master cannot give lines to follow
490 : // #i91421#
491 0 : if ( !pMaster->GetIndPrev() )
492 : {
493 0 : sal_uLong nLines = pMaster->GetThisLines();
494 0 : if(nLines == 0 && pMaster->HasPara())
495 : {
496 0 : const SwParaPortion *pMasterPara = pMaster->GetPara();
497 0 : if(pMasterPara && pMasterPara->GetNext())
498 0 : nLines = 2;
499 : }
500 0 : if( nLines <= nNeed )
501 0 : return sal_False;
502 : }
503 :
504 0 : pMaster->Prepare( PREP_WIDOWS, (void*)&nNeed );
505 0 : return sal_True;
506 : }
507 :
508 : /*************************************************************************
509 : * WidowsAndOrphans::WouldFit()
510 : *************************************************************************/
511 :
512 0 : sal_Bool WidowsAndOrphans::WouldFit( SwTxtMargin &rLine, SwTwips &rMaxHeight, sal_Bool bTst )
513 : {
514 : // Here it does not matter, if pFrm is swapped or not.
515 : // IsInside() takes care for itself
516 :
517 : // We expect that rLine is set to the last line
518 : OSL_ENSURE( !rLine.GetNext(), "WouldFit: aLine::Bottom missed!" );
519 0 : MSHORT nLineCnt = rLine.GetLineNr();
520 :
521 : // First satisfy the Orphans-rule and the wish for initials ...
522 0 : const MSHORT nMinLines = Max( GetOrphansLines(), rLine.GetDropLines() );
523 0 : if ( nLineCnt < nMinLines )
524 0 : return sal_False;
525 :
526 0 : rLine.Top();
527 0 : SwTwips nLineSum = rLine.GetLineHeight();
528 :
529 0 : while( nMinLines > rLine.GetLineNr() )
530 : {
531 0 : if( !rLine.NextLine() )
532 0 : return sal_False;
533 0 : nLineSum += rLine.GetLineHeight();
534 : }
535 :
536 : // We do not fit
537 0 : if( !IsInside( rLine ) )
538 0 : return sal_False;
539 :
540 : // Check the Widows-rule
541 0 : if( !nWidLines && !pFrm->IsFollow() )
542 : {
543 : // Usually we only have to check for Widows if we are a Follow.
544 : // On WouldFit the rule has to be checked for the Master too,
545 : // because we are just in the middle of calculating the break.
546 : // In Ctor of WidowsAndOrphans the nWidLines are only calced for
547 : // Follows from the AttrSet - so we catch up now:
548 0 : const SwAttrSet& rSet = pFrm->GetTxtNode()->GetSwAttrSet();
549 0 : nWidLines = rSet.GetWidows().GetValue();
550 : }
551 :
552 : // After Orphans/Initials, do enough lines remain for Widows?
553 : // #111937#: If we are currently doing a test formatting, we may not
554 : // consider the widows rule for two reasons:
555 : // 1. The columns may have different widths.
556 : // Widow lines would have wrong width.
557 : // 2. Test formatting is only done up to the given space.
558 : // we do not have any lines for widows at all.
559 0 : if( bTst || nLineCnt - nMinLines >= GetWidowsLines() )
560 : {
561 0 : if( rMaxHeight >= nLineSum )
562 : {
563 0 : rMaxHeight -= nLineSum;
564 0 : return sal_True;
565 : }
566 : }
567 0 : return sal_False;
568 : }
569 :
570 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|