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 "rootfrm.hxx"
21 : #include "pagefrm.hxx"
22 : #include "viewopt.hxx"
23 : #include "frmtool.hxx"
24 : #include "txtftn.hxx"
25 : #include "fmtftn.hxx"
26 : #include <editeng/ulspitem.hxx>
27 : #include <editeng/keepitem.hxx>
28 : #include <svx/sdtaitm.hxx>
29 :
30 : #include <fmtfsize.hxx>
31 : #include <fmtanchr.hxx>
32 : #include <fmtclbl.hxx>
33 :
34 : #include "tabfrm.hxx"
35 : #include "ftnfrm.hxx"
36 : #include "txtfrm.hxx"
37 : #include "sectfrm.hxx"
38 : #include "dbg_lay.hxx"
39 :
40 : #include <sortedobjs.hxx>
41 : #include <layouter.hxx>
42 : #include <flyfrms.hxx>
43 :
44 : #include <DocumentSettingManager.hxx>
45 : #include <IDocumentLayoutAccess.hxx>
46 :
47 : // Move methods
48 :
49 : /// Return value tells whether the Frm should be moved.
50 12960 : bool SwCntntFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, bool, bool & )
51 : {
52 12960 : if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()))
53 : {
54 : // Floating back a frm uses a bit of time unfortunately.
55 : // The most common case is the following: The Frm wants to float to
56 : // somewhere where the FixSize is the same that the Frm itself has already.
57 : // In that case it's pretty easy to check if the Frm has enough space
58 : // for its VarSize. If this is NOT the case, we already know that
59 : // we don't need to move.
60 : // The Frm checks itself whether it has enough space - respecting the fact
61 : // that it could possibly split itself if needed.
62 : // If, however, the FixSize differs from the Frm or Flys are involved
63 : // (either in the old or the new position), checking is pointless,
64 : // and we have to move the Frm just to see what happens - if there's
65 : // some space available to do it, that is.
66 :
67 : // The FixSize of the containers of Cntnts is always the width.
68 :
69 : // If we moved more than one sheet back (for example jumping over empty
70 : // pages), we have to move either way. Otherwise, if the Frm doesn't fit
71 : // into the page, empty pages wouldn't be respected anymore.
72 12960 : sal_uInt8 nMoveAnyway = 0;
73 12960 : SwPageFrm * const pNewPage = pNewUpper->FindPageFrm();
74 12960 : SwPageFrm *pOldPage = FindPageFrm();
75 :
76 12960 : if ( SwFlowFrm::IsMoveBwdJump() )
77 8148 : return true;
78 :
79 4812 : if( IsInFtn() && IsInSct() )
80 : {
81 0 : SwFtnFrm* pFtn = FindFtnFrm();
82 0 : SwSectionFrm* pMySect = pFtn->FindSctFrm();
83 0 : if( pMySect && pMySect->IsFtnLock() )
84 : {
85 0 : SwSectionFrm *pSect = pNewUpper->FindSctFrm();
86 0 : while( pSect && pSect->IsInFtn() )
87 0 : pSect = pSect->GetUpper()->FindSctFrm();
88 : OSL_ENSURE( pSect, "Escaping footnote" );
89 0 : if( pSect != pMySect )
90 0 : return false;
91 : }
92 : }
93 4812 : SWRECTFN( this )
94 4812 : SWRECTFNX( pNewUpper )
95 9624 : if( std::abs( (pNewUpper->Prt().*fnRectX->fnGetWidth)() -
96 4812 : (GetUpper()->Prt().*fnRect->fnGetWidth)() ) > 1 ) {
97 : // In this case, only a _WouldFit with test move is possible
98 156 : nMoveAnyway = 2;
99 : }
100 :
101 : // OD 2004-05-26 #i25904# - do *not* move backward,
102 : // if <nMoveAnyway> equals 3 and no space is left in new upper.
103 4812 : nMoveAnyway |= BwdMoveNecessary( pOldPage, Frm() );
104 : {
105 4812 : const IDocumentSettingAccess* pIDSA = pNewPage->GetFmt()->getIDocumentSettingAccess();
106 4812 : SwTwips nSpace = 0;
107 4812 : SwRect aRect( pNewUpper->Prt() );
108 4812 : aRect.Pos() += pNewUpper->Frm().Pos();
109 4812 : const SwFrm *pPrevFrm = pNewUpper->Lower();
110 62734 : while ( pPrevFrm )
111 : {
112 53110 : SwTwips nNewTop = (pPrevFrm->Frm().*fnRectX->fnGetBottom)();
113 : // OD 2004-03-01 #106629#:
114 : // consider lower spacing of last frame in a table cell
115 : {
116 : // check, if last frame is inside table and if it includes
117 : // its lower spacing.
118 53124 : if ( !pPrevFrm->GetNext() && pPrevFrm->IsInTab() &&
119 14 : pIDSA->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
120 : {
121 14 : const SwFrm* pLastFrm = pPrevFrm;
122 : // if last frame is a section, take its last content
123 14 : if ( pPrevFrm->IsSctFrm() )
124 : {
125 0 : pLastFrm = static_cast<const SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
126 0 : if ( pLastFrm &&
127 0 : pLastFrm->FindTabFrm() != pPrevFrm->FindTabFrm() )
128 : {
129 0 : pLastFrm = pLastFrm->FindTabFrm();
130 : }
131 : }
132 :
133 14 : if ( pLastFrm )
134 : {
135 14 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pLastFrm );
136 14 : const SwBorderAttrs& rAttrs = *aAccess.Get();
137 14 : nNewTop -= rAttrs.GetULSpace().GetLower();
138 : }
139 : }
140 : }
141 53110 : (aRect.*fnRectX->fnSetTop)( nNewTop );
142 :
143 53110 : pPrevFrm = pPrevFrm->GetNext();
144 : }
145 :
146 4812 : nMoveAnyway |= BwdMoveNecessary( pNewPage, aRect);
147 :
148 : //determine space left in new upper frame
149 4812 : nSpace = (aRect.*fnRectX->fnGetHeight)();
150 4812 : const SwViewShell *pSh = pNewUpper->getRootFrm()->GetCurrShell();
151 14436 : if ( IsInFtn() ||
152 9624 : (pSh && pSh->GetViewOptions()->getBrowseMode()) ||
153 14796 : pNewUpper->IsCellFrm() ||
154 5860 : ( pNewUpper->IsInSct() && ( pNewUpper->IsSctFrm() ||
155 688 : ( pNewUpper->IsColBodyFrm() &&
156 556 : !pNewUpper->GetUpper()->GetPrev() &&
157 212 : !pNewUpper->GetUpper()->GetNext() ) ) ) )
158 360 : nSpace += pNewUpper->Grow( LONG_MAX, true );
159 :
160 4812 : if ( nMoveAnyway < 3 )
161 : {
162 4812 : if ( nSpace )
163 : {
164 : // Do not notify footnotes which are stuck to the paragraph:
165 : // This would require extremely confusing code, taking into
166 : // account the widths
167 : // and Flys, that in turn influence the footnotes, ...
168 :
169 : // _WouldFit can only be used if the width is the same and
170 : // ONLY self-anchored Flys are present.
171 :
172 : // _WouldFit can also be used if ONLY Flys anchored
173 : // somewhere else are present.
174 : // In this case, the width doesn't even matter,
175 : // because we're running a TestFormat in the new upper.
176 : const sal_uInt8 nBwdMoveNecessaryResult =
177 4754 : BwdMoveNecessary( pNewPage, aRect);
178 4754 : const bool bObjsInNewUpper( nBwdMoveNecessaryResult == 2 ||
179 4754 : nBwdMoveNecessaryResult == 3 );
180 :
181 : return _WouldFit( nSpace, pNewUpper, nMoveAnyway == 2,
182 4754 : bObjsInNewUpper );
183 : }
184 : // It's impossible for _WouldFit to return a usable result if
185 : // we have a fresh multi-column section - so we really have to
186 : // float back unless there is no space.
187 174 : return pNewUpper->IsInSct() && pNewUpper->IsColBodyFrm() &&
188 116 : !(pNewUpper->Prt().*fnRectX->fnGetWidth)() &&
189 0 : ( pNewUpper->GetUpper()->GetPrev() ||
190 58 : pNewUpper->GetUpper()->GetNext() );
191 : }
192 :
193 : // OD 2004-05-26 #i25904# - check for space left in new upper
194 0 : return nSpace != 0;
195 : }
196 : }
197 0 : return false;
198 : }
199 :
200 : // Calc methods
201 :
202 : // Two little friendships form a secret society
203 27290 : inline void PrepareLock( SwFlowFrm *pTab )
204 : {
205 27290 : pTab->LockJoin();
206 27290 : }
207 6690 : inline void PrepareUnlock( SwFlowFrm *pTab )
208 : {
209 6690 : pTab->UnlockJoin();
210 :
211 6690 : }
212 :
213 : // hopefully, one day this function simply will return 'false'
214 445388 : static bool lcl_IsCalcUpperAllowed( const SwFrm& rFrm )
215 : {
216 876764 : return !rFrm.GetUpper()->IsSctFrm() &&
217 847964 : !rFrm.GetUpper()->IsFooterFrm() &&
218 : // #i23129#, #i36347# - no format of upper Writer fly frame
219 831360 : !rFrm.GetUpper()->IsFlyFrm() &&
220 1740304 : !( rFrm.GetUpper()->IsTabFrm() && rFrm.GetUpper()->GetUpper()->IsInTab() ) &&
221 903746 : !( rFrm.IsTabFrm() && rFrm.GetUpper()->IsInTab() );
222 : }
223 :
224 : /** Prepares the Frame for "formatting" (MakeAll()).
225 : *
226 : * This method serves to save stack space: To calculate the position of the Frm
227 : * we have to make sure that the positions of Upper and Prev respectively are
228 : * valid. This may require a recursive call (a loop would be quite expensive,
229 : * as it's not required very often).
230 : *
231 : * Every call of MakeAll requires around 500 bytes on the stack - you easily
232 : * see where this leads to. This method requires only a little bit of stack
233 : * space, so the recursive call should not be a problem here.
234 : *
235 : * Another advantage is that one nice day, this method and with it the
236 : * formatting of predecessors could be avoided. Then it could probably be
237 : * possible to jump "quickly" to the document's end.
238 : *
239 : * @see MakeAll()
240 : */
241 255618 : void SwFrm::PrepareMake()
242 : {
243 255618 : StackHack aHack;
244 255618 : if ( GetUpper() )
245 : {
246 223510 : if ( lcl_IsCalcUpperAllowed( *this ) )
247 203692 : GetUpper()->Calc();
248 : OSL_ENSURE( GetUpper(), ":-( Layout unstable (Upper gone)." );
249 223510 : if ( !GetUpper() )
250 0 : return;
251 :
252 223510 : const bool bCnt = IsCntntFrm();
253 223510 : const bool bTab = IsTabFrm();
254 223510 : bool bNoSect = IsInSct();
255 223510 : bool bOldTabLock = false, bFoll = false;
256 223510 : SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
257 :
258 223510 : if ( bTab )
259 : {
260 27290 : pThis = (SwTabFrm*)this;
261 27290 : bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
262 27290 : ::PrepareLock( (SwTabFrm*)this );
263 27290 : bFoll = pThis->IsFollow();
264 : }
265 196220 : else if( IsSctFrm() )
266 : {
267 1396 : pThis = (SwSectionFrm*)this;
268 1396 : bFoll = pThis->IsFollow();
269 1396 : bNoSect = false;
270 : }
271 194824 : else if ( bCnt && (bFoll = pThis->IsFollow()) && GetPrev() )
272 : {
273 : //Do not follow the chain when we need only one instance
274 1278 : const SwTxtFrm* pMaster = ((SwCntntFrm*)this)->FindMaster();
275 1278 : if ( pMaster && pMaster->IsLocked() )
276 : {
277 1262 : MakeAll();
278 1262 : return;
279 : }
280 : }
281 :
282 : // #i44049# - no format of previous frame, if current
283 : // frame is a table frame and its previous frame wants to keep with it.
284 249538 : const bool bFormatPrev = !bTab ||
285 225976 : !GetPrev() ||
286 225976 : !GetPrev()->GetAttrSet()->GetKeep().GetValue();
287 222248 : if ( bFormatPrev )
288 : {
289 221878 : SwFrm *pFrm = GetUpper()->Lower();
290 1355656 : while ( pFrm != this )
291 : {
292 : OSL_ENSURE( pFrm, ":-( Layout unstable (this not found)." );
293 912144 : if ( !pFrm )
294 0 : return; //Oioioioi ...
295 :
296 912144 : if ( !pFrm->IsValid() )
297 : {
298 : // A small interference that hopefully improves on the stability:
299 : // If I'm Follow AND neighbor of a Frm before me, it would delete
300 : // me when formatting. This as you can see could easily become a
301 : // confusing situation that we want to avoid.
302 12556 : if ( bFoll && pFrm->IsFlowFrm() &&
303 244 : (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
304 244 : break;
305 :
306 12068 : pFrm->MakeAll();
307 12068 : if( IsSctFrm() && !((SwSectionFrm*)this)->GetSection() )
308 0 : break;
309 : }
310 : // With CntntFrms, the chain may be broken while walking through
311 : // it. Therefore we have to figure out the follower in a bit more
312 : // complicated way. However, I'll HAVE to get back to myself
313 : // sometime again.
314 911900 : pFrm = pFrm->FindNext();
315 :
316 : // If we started out in a SectionFrm, it might have happened that
317 : // we landed in a Section Follow via the MakeAll calls.
318 : // FindNext only gives us the SectionFrm, not it's content - we
319 : // won't find ourselves anymore!
320 911900 : if( bNoSect && pFrm && pFrm->IsSctFrm() )
321 : {
322 2 : SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
323 2 : if( pCnt )
324 2 : pFrm = pCnt;
325 : }
326 : }
327 : OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone II)." );
328 221878 : if ( !GetUpper() )
329 0 : return;
330 :
331 221878 : if ( lcl_IsCalcUpperAllowed( *this ) )
332 202068 : GetUpper()->Calc();
333 :
334 : OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone III)." );
335 : }
336 :
337 222248 : if ( bTab && !bOldTabLock )
338 6690 : ::PrepareUnlock( (SwTabFrm*)this );
339 : }
340 254356 : MakeAll();
341 : }
342 :
343 66514 : void SwFrm::OptPrepareMake()
344 : {
345 : // #i23129#, #i36347# - no format of upper Writer fly frame
346 129402 : if ( GetUpper() && !GetUpper()->IsFooterFrm() &&
347 62888 : !GetUpper()->IsFlyFrm() )
348 : {
349 54368 : GetUpper()->Calc();
350 : OSL_ENSURE( GetUpper(), ":-( Layout unstable (Upper gone)." );
351 54368 : if ( !GetUpper() )
352 66514 : return;
353 : }
354 66514 : if ( GetPrev() && !GetPrev()->IsValid() )
355 422 : PrepareMake();
356 : else
357 : {
358 66092 : StackHack aHack;
359 66092 : MakeAll();
360 : }
361 : }
362 :
363 56 : void SwFrm::PrepareCrsr()
364 : {
365 56 : StackHack aHack;
366 56 : if( GetUpper() && !GetUpper()->IsSctFrm() )
367 : {
368 42 : GetUpper()->PrepareCrsr();
369 42 : GetUpper()->Calc();
370 :
371 : OSL_ENSURE( GetUpper(), ":-( Layout unstable (Upper gone)." );
372 42 : if ( !GetUpper() )
373 0 : return;
374 :
375 42 : const bool bCnt = IsCntntFrm();
376 42 : const bool bTab = IsTabFrm();
377 42 : bool bNoSect = IsInSct();
378 :
379 42 : bool bOldTabLock = false, bFoll;
380 42 : SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
381 :
382 42 : if ( bTab )
383 : {
384 0 : bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
385 0 : ::PrepareLock( (SwTabFrm*)this );
386 0 : pThis = (SwTabFrm*)this;
387 : }
388 42 : else if( IsSctFrm() )
389 : {
390 0 : pThis = (SwSectionFrm*)this;
391 0 : bNoSect = false;
392 : }
393 42 : bFoll = pThis && pThis->IsFollow();
394 :
395 42 : SwFrm *pFrm = GetUpper()->Lower();
396 136 : while ( pFrm != this )
397 : {
398 : OSL_ENSURE( pFrm, ":-( Layout unstable (this not found)." );
399 52 : if ( !pFrm )
400 0 : return; //Oioioioi ...
401 :
402 52 : if ( !pFrm->IsValid() )
403 : {
404 : // A small interference that hopefully improves on the stability:
405 : // If I'm Follow AND neighbor of a Frm before me, it would delete
406 : // me when formatting. This as you can see could easily become a
407 : // confusing situation that we want to avoid.
408 0 : if ( bFoll && pFrm->IsFlowFrm() &&
409 0 : (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
410 0 : break;
411 :
412 0 : pFrm->MakeAll();
413 : }
414 : // With CntntFrms, the chain may be broken while walking through
415 : // it. Therefore we have to figure out the follower in a bit more
416 : // complicated way. However, I'll HAVE to get back to myself
417 : // sometime again.
418 52 : pFrm = pFrm->FindNext();
419 52 : if( bNoSect && pFrm && pFrm->IsSctFrm() )
420 : {
421 0 : SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
422 0 : if( pCnt )
423 0 : pFrm = pCnt;
424 : }
425 : }
426 : OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone II)." );
427 42 : if ( !GetUpper() )
428 0 : return;
429 :
430 42 : GetUpper()->Calc();
431 :
432 : OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone III)." );
433 :
434 42 : if ( bTab && !bOldTabLock )
435 0 : ::PrepareUnlock( (SwTabFrm*)this );
436 : }
437 56 : Calc();
438 : }
439 :
440 : // Here we return GetPrev(); however we will ignore empty SectionFrms
441 993783 : static SwFrm* lcl_Prev( SwFrm* pFrm, bool bSectPrv = true )
442 : {
443 993783 : SwFrm* pRet = pFrm->GetPrev();
444 1630173 : if( !pRet && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm() &&
445 999477 : bSectPrv && !pFrm->IsColumnFrm() )
446 3836 : pRet = pFrm->GetUpper()->GetPrev();
447 1993782 : while( pRet && pRet->IsSctFrm() &&
448 4394 : !((SwSectionFrm*)pRet)->GetSection() )
449 1822 : pRet = pRet->GetPrev();
450 993783 : return pRet;
451 : }
452 :
453 808 : static SwFrm* lcl_NotHiddenPrev( SwFrm* pFrm )
454 : {
455 808 : SwFrm *pRet = pFrm;
456 808 : do
457 : {
458 808 : pRet = lcl_Prev( pRet );
459 808 : } while ( pRet && pRet->IsTxtFrm() && ((SwTxtFrm*)pRet)->IsHiddenNow() );
460 808 : return pRet;
461 : }
462 :
463 266595 : void SwFrm::MakePos()
464 : {
465 266595 : if ( !mbValidPos )
466 : {
467 262664 : mbValidPos = true;
468 262664 : bool bUseUpper = false;
469 262664 : SwFrm* pPrv = lcl_Prev( this );
470 502212 : if ( pPrv &&
471 166288 : ( !pPrv->IsCntntFrm() ||
472 46514 : ( ((SwCntntFrm*)pPrv)->GetFollow() != this ) )
473 : )
474 : {
475 359322 : if ( !StackHack::IsLocked() &&
476 240044 : ( !IsInSct() || IsSctFrm() ) &&
477 337476 : !pPrv->IsSctFrm() &&
478 108560 : !pPrv->GetAttrSet()->GetKeep().GetValue()
479 : )
480 : {
481 106144 : pPrv->Calc(); // This may cause Prev to vanish!
482 : }
483 13630 : else if ( pPrv->Frm().Top() == 0 )
484 : {
485 2 : bUseUpper = true;
486 : }
487 : }
488 :
489 262664 : pPrv = lcl_Prev( this, false );
490 262664 : sal_uInt16 nMyType = GetType();
491 262664 : SWRECTFN( ( IsCellFrm() && GetUpper() ? GetUpper() : this ) )
492 262664 : if ( !bUseUpper && pPrv )
493 : {
494 119294 : maFrm.Pos( pPrv->Frm().Pos() );
495 119294 : if( FRM_NEIGHBOUR & nMyType )
496 : {
497 31244 : bool bR2L = IsRightToLeft();
498 31244 : if( bR2L )
499 0 : (maFrm.*fnRect->fnSetPosX)( (maFrm.*fnRect->fnGetLeft)() -
500 0 : (maFrm.*fnRect->fnGetWidth)() );
501 : else
502 31244 : (maFrm.*fnRect->fnSetPosX)( (maFrm.*fnRect->fnGetLeft)() +
503 62488 : (pPrv->Frm().*fnRect->fnGetWidth)() );
504 :
505 : // cells may now leave their uppers
506 31244 : if( bVert && FRM_CELL & nMyType && !mbReverse )
507 0 : maFrm.Pos().setX(maFrm.Pos().getX() - maFrm.Width() + pPrv->Frm().Width());
508 : }
509 88050 : else if( bVert && FRM_NOTE_VERT & nMyType )
510 : {
511 0 : if( mbReverse )
512 0 : maFrm.Pos().setX(maFrm.Pos().getX() + pPrv->Frm().Width());
513 : else
514 : {
515 0 : if ( bVertL2R )
516 0 : maFrm.Pos().setX(maFrm.Pos().getX() + pPrv->Frm().Width());
517 : else
518 0 : maFrm.Pos().setX(maFrm.Pos().getX() - maFrm.Width());
519 : }
520 : }
521 : else
522 88050 : maFrm.Pos().setY(maFrm.Pos().getY() + pPrv->Frm().Height());
523 : }
524 143370 : else if ( GetUpper() )
525 : {
526 : // OD 15.10.2002 #103517# - add safeguard for <SwFooterFrm::Calc()>
527 : // If parent frame is a footer frame and its <ColLocked()>, then
528 : // do *not* calculate it.
529 : // NOTE: Footer frame is <ColLocked()> during its
530 : // <FormatSize(..)>, which is called from <Format(..)>, which
531 : // is called from <MakeAll()>, which is called from <Calc()>.
532 : // #i56850#
533 : // - no format of upper Writer fly frame, which is anchored
534 : // at-paragraph or at-character.
535 423052 : if ( !GetUpper()->IsTabFrm() &&
536 280018 : !( IsTabFrm() && GetUpper()->IsInTab() ) &&
537 268668 : !GetUpper()->IsSctFrm() &&
538 662292 : !dynamic_cast<SwFlyAtCntFrm*>(GetUpper()) &&
539 128638 : !( GetUpper()->IsFooterFrm() &&
540 6218 : GetUpper()->IsColLocked() )
541 : )
542 : {
543 124572 : GetUpper()->Calc();
544 : }
545 143370 : pPrv = lcl_Prev( this, false );
546 143370 : if ( !bUseUpper && pPrv )
547 : {
548 0 : maFrm.Pos( pPrv->Frm().Pos() );
549 0 : if( FRM_NEIGHBOUR & nMyType )
550 : {
551 0 : bool bR2L = IsRightToLeft();
552 0 : if( bR2L )
553 0 : (maFrm.*fnRect->fnSetPosX)( (maFrm.*fnRect->fnGetLeft)() -
554 0 : (maFrm.*fnRect->fnGetWidth)() );
555 : else
556 0 : (maFrm.*fnRect->fnSetPosX)( (maFrm.*fnRect->fnGetLeft)() +
557 0 : (pPrv->Frm().*fnRect->fnGetWidth)() );
558 :
559 : // cells may now leave their uppers
560 0 : if( bVert && FRM_CELL & nMyType && !mbReverse )
561 0 : maFrm.Pos().setX(maFrm.Pos().getX() - maFrm.Width() + pPrv->Frm().Width());
562 : }
563 0 : else if( bVert && FRM_NOTE_VERT & nMyType )
564 : {
565 0 : if( mbReverse )
566 0 : maFrm.Pos().setX(maFrm.Pos().getX() + pPrv->Frm().Width());
567 : else
568 0 : maFrm.Pos().setX(maFrm.Pos().getX() - maFrm.Width());
569 : }
570 : else
571 0 : maFrm.Pos().setY(maFrm.Pos().getY() + pPrv->Frm().Height());
572 : }
573 : else
574 : {
575 143370 : maFrm.Pos( GetUpper()->Frm().Pos() );
576 143370 : if( GetUpper()->IsFlyFrm() )
577 7436 : maFrm.Pos() += static_cast<SwFlyFrm*>(GetUpper())->ContentPos();
578 : else
579 135934 : maFrm.Pos() += GetUpper()->Prt().Pos();
580 :
581 143370 : if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() )
582 : {
583 0 : if( bVert )
584 0 : maFrm.Pos().setY(maFrm.Pos().getY() + GetUpper()->Prt().Height()
585 0 : - maFrm.Height());
586 : else
587 0 : maFrm.Pos().setX(maFrm.Pos().getX() + GetUpper()->Prt().Width()
588 0 : - maFrm.Width());
589 : }
590 143370 : else if( bVert && !bVertL2R && FRM_NOTE_VERT & nMyType && !mbReverse )
591 4 : maFrm.Pos().setX(maFrm.Pos().getX() - maFrm.Width() + GetUpper()->Prt().Width());
592 : }
593 : }
594 : else
595 : {
596 0 : maFrm.Pos().setX(0);
597 0 : maFrm.Pos().setY(0);
598 : }
599 :
600 262664 : if( IsBodyFrm() && bVert && !bVertL2R && !mbReverse && GetUpper() )
601 0 : maFrm.Pos().setX(maFrm.Pos().getX() + GetUpper()->Prt().Width() - maFrm.Width());
602 262664 : mbValidPos = true;
603 : }
604 266595 : }
605 :
606 : // #i28701# - new type <SwSortedObjs>
607 4 : static void lcl_CheckObjects( SwSortedObjs* pSortedObjs, SwFrm* pFrm, long& rBot )
608 : {
609 : // And then there can be paragraph anchored frames that sit below their paragraph.
610 4 : long nMax = 0;
611 8 : for ( size_t i = 0; i < pSortedObjs->size(); ++i )
612 : {
613 : // #i28701# - consider changed type of <SwSortedObjs>
614 : // entries.
615 4 : SwAnchoredObject* pObj = (*pSortedObjs)[i];
616 4 : long nTmp = 0;
617 4 : if ( pObj->ISA(SwFlyFrm) )
618 : {
619 4 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
620 4 : if( pFly->Frm().Top() != FAR_AWAY &&
621 0 : ( pFrm->IsPageFrm() ? pFly->IsFlyLayFrm() :
622 0 : ( pFly->IsFlyAtCntFrm() &&
623 0 : ( pFrm->IsBodyFrm() ? pFly->GetAnchorFrm()->IsInDocBody() :
624 0 : pFly->GetAnchorFrm()->IsInFtn() ) ) ) )
625 : {
626 0 : nTmp = pFly->Frm().Bottom();
627 : }
628 : }
629 : else
630 0 : nTmp = pObj->GetObjRect().Bottom();
631 4 : nMax = std::max( nTmp, nMax );
632 : }
633 4 : ++nMax; // Lower edge vs. height!
634 4 : rBot = std::max( rBot, nMax );
635 4 : }
636 :
637 15348 : void SwPageFrm::MakeAll()
638 : {
639 : PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
640 :
641 15348 : const SwRect aOldRect( Frm() ); // Adjust root size
642 15348 : const SwLayNotify aNotify( this ); // takes care of the notification in the dtor
643 15348 : SwBorderAttrAccess *pAccess = 0;
644 15348 : const SwBorderAttrs*pAttrs = 0;
645 :
646 46044 : while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
647 : {
648 15348 : if ( !mbValidPos )
649 : {
650 15154 : mbValidPos = true; // positioning of the pages is taken care of by the root frame
651 : }
652 :
653 15348 : if ( !mbValidSize || !mbValidPrtArea )
654 : {
655 13204 : if ( IsEmptyPage() )
656 : {
657 44 : Frm().Width( 0 ); Prt().Width( 0 );
658 44 : Frm().Height( 0 ); Prt().Height( 0 );
659 44 : Prt().Left( 0 ); Prt().Top( 0 );
660 44 : mbValidSize = mbValidPrtArea = true;
661 : }
662 : else
663 : {
664 13160 : if ( !pAccess )
665 : {
666 13160 : pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
667 13160 : pAttrs = pAccess->Get();
668 : }
669 : // In BrowseView, we use fixed settings
670 13160 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
671 13160 : if ( pSh && pSh->GetViewOptions()->getBrowseMode() )
672 : {
673 202 : const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
674 202 : const long nTop = pAttrs->CalcTopLine() + aBorder.Height();
675 202 : const long nBottom = pAttrs->CalcBottomLine()+ aBorder.Height();
676 :
677 202 : long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() : 0;
678 202 : if ( nWidth < pSh->GetBrowseWidth() )
679 190 : nWidth = pSh->GetBrowseWidth();
680 202 : nWidth += + 2 * aBorder.Width();
681 :
682 202 : nWidth = std::max( nWidth, 2L * aBorder.Width() + 4L*MM50 );
683 202 : Frm().Width( nWidth );
684 :
685 202 : SwLayoutFrm *pBody = FindBodyCont();
686 202 : if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
687 : {
688 : // Columns have a fixed height
689 0 : Frm().Height( pAttrs->GetSize().Height() );
690 : }
691 : else
692 : {
693 : // In pages without columns, the content defines the size.
694 202 : long nBot = Frm().Top() + nTop;
695 202 : SwFrm *pFrm = Lower();
696 600 : while ( pFrm )
697 : {
698 196 : long nTmp = 0;
699 196 : SwFrm *pCnt = ((SwLayoutFrm*)pFrm)->ContainsAny();
700 608 : while ( pCnt && (pCnt->GetUpper() == pFrm ||
701 0 : ((SwLayoutFrm*)pFrm)->IsAnLower( pCnt )))
702 : {
703 216 : nTmp += pCnt->Frm().Height();
704 404 : if( pCnt->IsTxtFrm() &&
705 188 : ((SwTxtFrm*)pCnt)->IsUndersized() )
706 0 : nTmp += ((SwTxtFrm*)pCnt)->GetParHeight()
707 0 : - pCnt->Prt().Height();
708 244 : else if( pCnt->IsSctFrm() &&
709 28 : ((SwSectionFrm*)pCnt)->IsUndersized() )
710 0 : nTmp += ((SwSectionFrm*)pCnt)->Undersize();
711 216 : pCnt = pCnt->FindNext();
712 : }
713 : // OD 29.10.2002 #97265# - consider invalid body frame properties
714 588 : if ( pFrm->IsBodyFrm() &&
715 392 : ( !pFrm->GetValidSizeFlag() ||
716 392 : !pFrm->GetValidPrtAreaFlag() ) &&
717 0 : ( pFrm->Frm().Height() < pFrm->Prt().Height() )
718 : )
719 : {
720 0 : nTmp = std::min( nTmp, pFrm->Frm().Height() );
721 : }
722 : else
723 : {
724 : // OD 30.10.2002 #97265# - assert invalid lower property
725 : OSL_ENSURE( !(pFrm->Frm().Height() < pFrm->Prt().Height()),
726 : "SwPageFrm::MakeAll(): Lower with frame height < printing height" );
727 196 : nTmp += pFrm->Frm().Height() - pFrm->Prt().Height();
728 : }
729 196 : if ( !pFrm->IsBodyFrm() )
730 0 : nTmp = std::min( nTmp, pFrm->Frm().Height() );
731 196 : nBot += nTmp;
732 : // Here we check whether paragraph anchored objects
733 : // protrude outside the Body/FtnCont.
734 198 : if( pSortedObjs && !pFrm->IsHeaderFrm() &&
735 2 : !pFrm->IsFooterFrm() )
736 2 : lcl_CheckObjects( pSortedObjs, pFrm, nBot );
737 196 : pFrm = pFrm->GetNext();
738 : }
739 202 : nBot += nBottom;
740 : // And the page anchored ones
741 202 : if ( pSortedObjs )
742 2 : lcl_CheckObjects( pSortedObjs, this, nBot );
743 202 : nBot -= Frm().Top();
744 : // #i35143# - If second page frame
745 : // exists, the first page doesn't have to fulfill the
746 : // visible area.
747 202 : if ( !GetPrev() && !GetNext() )
748 : {
749 202 : nBot = std::max( nBot, pSh->VisArea().Height() );
750 : }
751 : // #i35143# - Assure, that the page
752 : // doesn't exceed the defined browse height.
753 202 : Frm().Height( std::min( nBot, BROWSE_HEIGHT ) );
754 : }
755 202 : Prt().Left ( pAttrs->CalcLeftLine() + aBorder.Width() );
756 202 : Prt().Top ( nTop );
757 404 : Prt().Width( Frm().Width() - ( Prt().Left()
758 404 : + pAttrs->CalcRightLine() + aBorder.Width() ) );
759 202 : Prt().Height( Frm().Height() - (nTop + nBottom) );
760 202 : mbValidSize = mbValidPrtArea = true;
761 : }
762 : else
763 : { // Set FixSize. For pages, this is not done from Upper, but from
764 : // the attribute.
765 12958 : Frm().SSize( pAttrs->GetSize() );
766 12958 : Format( pAttrs );
767 : }
768 : }
769 : }
770 : } //while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
771 15348 : delete pAccess;
772 :
773 15348 : if ( Frm() != aOldRect && GetUpper() )
774 28 : static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
775 :
776 : OSL_ENSURE( !GetUpper() || GetUpper()->Prt().Width() >= maFrm.Width(),
777 15348 : "Upper (Root) must be wide enough to contain the widest page");
778 15348 : }
779 :
780 131706 : void SwLayoutFrm::MakeAll()
781 : {
782 : PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
783 :
784 : // takes care of the notification in the dtor
785 131706 : const SwLayNotify aNotify( this );
786 131706 : bool bVert = IsVertical();
787 :
788 131706 : SwRectFn fnRect = ( IsNeighbourFrm() == bVert )? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert );
789 :
790 131706 : SwBorderAttrAccess *pAccess = 0;
791 131706 : const SwBorderAttrs*pAttrs = 0;
792 :
793 401012 : while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
794 : {
795 137600 : if ( !mbValidPos )
796 127112 : MakePos();
797 :
798 137600 : if ( GetUpper() )
799 : {
800 : // NEW TABLES
801 137600 : if ( IsLeaveUpperAllowed() )
802 : {
803 354 : if ( !mbValidSize )
804 164 : mbValidPrtArea = false;
805 : }
806 : else
807 : {
808 137246 : if ( !mbValidSize )
809 : {
810 : // Set FixSize; VarSize is set by Format() after calculating the PrtArea
811 80702 : mbValidPrtArea = false;
812 :
813 80702 : SwTwips nPrtWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
814 80702 : if( bVert && ( IsBodyFrm() || IsFtnContFrm() ) )
815 : {
816 0 : SwFrm* pNxt = GetPrev();
817 0 : while( pNxt && !pNxt->IsHeaderFrm() )
818 0 : pNxt = pNxt->GetPrev();
819 0 : if( pNxt )
820 0 : nPrtWidth -= pNxt->Frm().Height();
821 0 : pNxt = GetNext();
822 0 : while( pNxt && !pNxt->IsFooterFrm() )
823 0 : pNxt = pNxt->GetNext();
824 0 : if( pNxt )
825 0 : nPrtWidth -= pNxt->Frm().Height();
826 : }
827 :
828 80702 : const long nDiff = nPrtWidth - (Frm().*fnRect->fnGetWidth)();
829 :
830 80702 : if( IsNeighbourFrm() && IsRightToLeft() )
831 0 : (Frm().*fnRect->fnSubLeft)( nDiff );
832 : else
833 80702 : (Frm().*fnRect->fnAddRight)( nDiff );
834 : }
835 : else
836 : {
837 : // Don't leave your upper
838 56544 : const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
839 56544 : if( (Frm().*fnRect->fnOverStep)( nDeadLine ) )
840 0 : mbValidSize = false;
841 : }
842 : }
843 : }
844 137600 : if ( !mbValidSize || !mbValidPrtArea )
845 : {
846 102058 : if ( !pAccess )
847 : {
848 96330 : pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
849 96330 : pAttrs = pAccess->Get();
850 : }
851 102058 : Format( pAttrs );
852 : }
853 : } //while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
854 131706 : delete pAccess;
855 131706 : }
856 :
857 285242 : bool SwTxtNode::IsCollapse() const
858 : {
859 570484 : if (GetDoc()->GetDocumentSettingManager().get( IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA )
860 285242 : && GetTxt().isEmpty())
861 : {
862 202428 : sal_uLong nIdx=GetIndex();
863 202428 : const SwEndNode *pNdBefore=GetNodes()[nIdx-1]->GetEndNode();
864 202428 : const SwEndNode *pNdAfter=GetNodes()[nIdx+1]->GetEndNode();
865 :
866 : // The paragraph is collapsed only if the NdAfter is the end of a cell
867 202428 : bool bInTable = this->FindTableNode( ) != NULL;
868 :
869 202428 : SwSortedObjs* pObjs = this->getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() )->GetDrawObjs( );
870 202428 : const size_t nObjs = ( pObjs != NULL ) ? pObjs->size( ) : 0;
871 :
872 202428 : return pNdBefore!=NULL && pNdAfter!=NULL && nObjs == 0 && bInTable;
873 : }
874 :
875 82814 : return false;
876 : }
877 :
878 286991 : bool SwFrm::IsCollapse() const
879 : {
880 286991 : if (!IsTxtFrm())
881 1749 : return false;
882 :
883 285242 : const SwTxtFrm *pTxtFrm=(SwTxtFrm*)this;
884 285242 : const SwTxtNode *pTxtNode=pTxtFrm->GetTxtNode();
885 285242 : return pTxtNode && pTxtNode->IsCollapse();
886 : }
887 :
888 149125 : bool SwCntntFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
889 : {
890 149125 : bool bSizeChgd = false;
891 :
892 149125 : if ( !mbValidPrtArea )
893 : {
894 147361 : mbValidPrtArea = true;
895 :
896 147361 : SWRECTFN( this )
897 147361 : const bool bTxtFrm = IsTxtFrm();
898 147361 : SwTwips nUpper = 0;
899 147361 : if ( bTxtFrm && ((SwTxtFrm*)this)->IsHiddenNow() )
900 : {
901 608 : if ( ((SwTxtFrm*)this)->HasFollow() )
902 0 : ((SwTxtFrm*)this)->JoinFrm();
903 :
904 608 : if( (Prt().*fnRect->fnGetHeight)() )
905 42 : ((SwTxtFrm*)this)->HideHidden();
906 608 : Prt().Pos().setX(0);
907 608 : Prt().Pos().setY(0);
908 608 : (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
909 608 : (Prt().*fnRect->fnSetHeight)( 0 );
910 608 : nUpper = -( (Frm().*fnRect->fnGetHeight)() );
911 : }
912 : else
913 : {
914 : // Simplification: CntntFrms are always variable in height!
915 :
916 : // At the FixSize, the surrounding Frame enforces the size;
917 : // the borders are simply subtracted.
918 146753 : const long nLeft = rAttrs.CalcLeft( this );
919 146753 : const long nRight = ((SwBorderAttrs&)rAttrs).CalcRight( this );
920 146753 : (this->*fnRect->fnSetXMargins)( nLeft, nRight );
921 :
922 146753 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
923 : SwTwips nWidthArea;
924 425293 : if( pSh && 0!=(nWidthArea=(pSh->VisArea().*fnRect->fnGetWidth)()) &&
925 338080 : GetUpper()->IsPageBodyFrm() && // but not for BodyFrms in Columns
926 59540 : pSh->GetViewOptions()->getBrowseMode() )
927 : {
928 : // Do not protrude the edge of the visible area. The page may be
929 : // wider, because there may be objects with excess width
930 : // (RootFrm::ImplCalcBrowseWidth())
931 58 : long nMinWidth = 0;
932 :
933 58 : for (size_t i = 0; GetDrawObjs() && i < GetDrawObjs()->size(); ++i)
934 : {
935 : // #i28701# - consider changed type of
936 : // <SwSortedObjs> entries
937 0 : SwAnchoredObject* pObj = (*GetDrawObjs())[i];
938 0 : const SwFrmFmt& rFmt = pObj->GetFrmFmt();
939 0 : const bool bFly = pObj->ISA(SwFlyFrm);
940 0 : if ((bFly && (FAR_AWAY == pObj->GetObjRect().Width()))
941 0 : || rFmt.GetFrmSize().GetWidthPercent())
942 : {
943 0 : continue;
944 : }
945 :
946 0 : if ( FLY_AS_CHAR == rFmt.GetAnchor().GetAnchorId() )
947 : {
948 : nMinWidth = std::max( nMinWidth,
949 0 : bFly ? rFmt.GetFrmSize().GetWidth()
950 0 : : pObj->GetObjRect().Width() );
951 : }
952 : }
953 :
954 58 : const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
955 58 : long nWidth = nWidthArea - 2 * ( IsVertical() ? aBorder.Height() : aBorder.Width() );
956 58 : nWidth -= (Prt().*fnRect->fnGetLeft)();
957 58 : nWidth -= rAttrs.CalcRightLine();
958 58 : nWidth = std::max( nMinWidth, nWidth );
959 58 : (Prt().*fnRect->fnSetWidth)( std::min( nWidth,
960 58 : (Prt().*fnRect->fnGetWidth)() ) );
961 : }
962 :
963 146753 : if ( (Prt().*fnRect->fnGetWidth)() <= MINLAY )
964 : {
965 : // The PrtArea should already be at least MINLAY wide, matching the
966 : // minimal values of the UI
967 1174 : (Prt().*fnRect->fnSetWidth)( std::min( long(MINLAY),
968 1174 : (Frm().*fnRect->fnGetWidth)() ) );
969 1174 : SwTwips nTmp = (Frm().*fnRect->fnGetWidth)() -
970 1174 : (Prt().*fnRect->fnGetWidth)();
971 1174 : if( (Prt().*fnRect->fnGetLeft)() > nTmp )
972 0 : (Prt().*fnRect->fnSetLeft)( nTmp );
973 : }
974 :
975 : // The following rules apply for VarSize:
976 : // 1. The first entry of a chain has no top border
977 : // 2. There is never a bottom border
978 : // 3. The top border is the maximum of the distance
979 : // of Prev downwards and our own distance upwards
980 : // Those three rules apply when calculating spacings
981 : // that are given by UL- and LRSpace. There might be a spacing
982 : // in all directions however; this may be caused by borders
983 : // and / or shadows.
984 : // 4. The spacing for TextFrms corresponds to the interline lead,
985 : // at a minimum.
986 :
987 146753 : nUpper = CalcUpperSpace( &rAttrs, NULL );
988 :
989 146753 : SwTwips nLower = CalcLowerSpace( &rAttrs );
990 146753 : if (IsCollapse()) {
991 206 : nUpper=0;
992 206 : nLower=0;
993 : }
994 :
995 146753 : (Prt().*fnRect->fnSetPosY)( (!bVert || mbReverse) ? nUpper : nLower);
996 146753 : nUpper += nLower;
997 146753 : nUpper -= (Frm().*fnRect->fnGetHeight)() -
998 146753 : (Prt().*fnRect->fnGetHeight)();
999 : }
1000 : // If there's a difference between old and new size, call Grow() or
1001 : // Shrink() respectively.
1002 147361 : if ( nUpper )
1003 : {
1004 20202 : if ( nUpper > 0 )
1005 17702 : GrowFrm( nUpper );
1006 : else
1007 2500 : ShrinkFrm( -nUpper );
1008 20202 : bSizeChgd = true;
1009 : }
1010 : }
1011 149125 : return bSizeChgd;
1012 : }
1013 :
1014 : #define STOP_FLY_FORMAT 10
1015 : // - loop prevention
1016 : const int cnStopFormat = 15;
1017 :
1018 706 : inline void ValidateSz( SwFrm *pFrm )
1019 : {
1020 706 : if ( pFrm )
1021 : {
1022 706 : pFrm->mbValidSize = true;
1023 706 : pFrm->mbValidPrtArea = true;
1024 : }
1025 706 : }
1026 :
1027 130337 : void SwCntntFrm::MakeAll()
1028 : {
1029 : OSL_ENSURE( GetUpper(), "no Upper?" );
1030 : OSL_ENSURE( IsTxtFrm(), "MakeAll(), NoTxt" );
1031 :
1032 130337 : if ( !IsFollow() && StackHack::IsLocked() )
1033 122 : return;
1034 :
1035 130337 : if ( IsJoinLocked() )
1036 122 : return;
1037 :
1038 : OSL_ENSURE( !((SwTxtFrm*)this)->IsSwapped(), "Calculation of a swapped frame" );
1039 :
1040 130215 : StackHack aHack;
1041 :
1042 130215 : if ( ((SwTxtFrm*)this)->IsLocked() )
1043 : {
1044 : OSL_FAIL( "Format for locked TxtFrm." );
1045 0 : return;
1046 : }
1047 :
1048 130215 : LockJoin();
1049 130215 : long nFormatCount = 0;
1050 : // - loop prevention
1051 130215 : int nConsequetiveFormatsWithoutChange = 0;
1052 : PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
1053 :
1054 : #ifdef DBG_UTIL
1055 : const SwDoc *pDoc = GetAttrSet()->GetDoc();
1056 : if( pDoc )
1057 : {
1058 : static bool bWarned = false;
1059 : if( pDoc->InXMLExport() )
1060 : {
1061 : SAL_WARN_IF( !bWarned, "sw", "Formatting during XML-export!" );
1062 : bWarned = true;
1063 : }
1064 : else
1065 : bWarned = false;
1066 : }
1067 : #endif
1068 :
1069 : // takes care of the notification in the dtor
1070 130215 : SwCntntNotify *pNotify = new SwCntntNotify( this );
1071 :
1072 : // as long as bMakePage is true, a new page can be created (exactly once)
1073 130215 : bool bMakePage = true;
1074 : // bMovedBwd gets set to true when the frame flows backwards
1075 130215 : bool bMovedBwd = false;
1076 : // as long as bMovedFwd is false, the Frm may flow backwards (until
1077 : // it has been moved forward once)
1078 130215 : bool bMovedFwd = false;
1079 130215 : sal_Bool bFormatted = sal_False; // For the widow/orphan rules, we encourage the
1080 : // last CntntFrm of a chain to format. This only
1081 : // needs to happen once. Every time the Frm is
1082 : // moved, the flag will have to be reset.
1083 130215 : bool bMustFit = false; // Once the emergency brake is pulled,
1084 : // no other prepares will be triggered
1085 130215 : bool bFitPromise = false; // If a paragraph didn't fit, but promises
1086 : // with WouldFit that it would adjust accordingly,
1087 : // this flag is set. If it turns out that it
1088 : // didn't keep it's promise, we can act in a
1089 : // controlled fashion.
1090 : bool bMoveable;
1091 130215 : const bool bFly = IsInFly();
1092 130215 : const bool bTab = IsInTab();
1093 130215 : const bool bFtn = IsInFtn();
1094 130215 : const bool bSct = IsInSct();
1095 130215 : Point aOldFrmPos; // This is so we can compare with the last pos
1096 130215 : Point aOldPrtPos; // and determine whether it makes sense to Prepare
1097 :
1098 260430 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
1099 130215 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1100 :
1101 : // OD 2004-02-26 #i25029#
1102 130215 : if ( !IsFollow() && rAttrs.JoinedWithPrev( *(this) ) )
1103 : {
1104 32954 : pNotify->SetBordersJoinedWithPrev();
1105 : }
1106 :
1107 130215 : const bool bKeep = IsKeep( rAttrs.GetAttrSet() );
1108 :
1109 130215 : SwSaveFtnHeight *pSaveFtn = 0;
1110 130215 : if ( bFtn )
1111 : {
1112 546 : SwFtnFrm *pFtn = FindFtnFrm();
1113 546 : SwSectionFrm* pSct = pFtn->FindSctFrm();
1114 546 : if ( !((SwTxtFrm*)pFtn->GetRef())->IsLocked() )
1115 : {
1116 124 : SwFtnBossFrm* pBoss = pFtn->GetRef()->FindFtnBossFrm(
1117 248 : pFtn->GetAttr()->GetFtn().IsEndNote() );
1118 124 : if( !pSct || pSct->IsColLocked() || !pSct->Growable() )
1119 : pSaveFtn = new SwSaveFtnHeight( pBoss,
1120 124 : ((SwTxtFrm*)pFtn->GetRef())->GetFtnLine( pFtn->GetAttr() ) );
1121 : }
1122 : }
1123 :
1124 263474 : if ( GetUpper()->IsSctFrm() &&
1125 130215 : HasFollow() &&
1126 0 : &GetFollow()->GetFrm() == GetNext() )
1127 : {
1128 0 : dynamic_cast<SwTxtFrm&>(*this).JoinFrm();
1129 : }
1130 :
1131 : // #i28701# - move master forward, if it has to move,
1132 : // because of its object positioning.
1133 130215 : if ( !static_cast<SwTxtFrm*>(this)->IsFollow() )
1134 : {
1135 127022 : sal_uInt32 nToPageNum = 0L;
1136 : const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
1137 127022 : *(GetAttrSet()->GetDoc()),
1138 : *(static_cast<SwTxtFrm*>(this)),
1139 127022 : nToPageNum );
1140 : // #i58182#
1141 : // Also move a paragraph forward, which is the first one inside a table cell.
1142 127022 : if ( bMoveFwdByObjPos &&
1143 0 : FindPageFrm()->GetPhyPageNum() < nToPageNum &&
1144 0 : ( lcl_Prev( this ) ||
1145 0 : GetUpper()->IsCellFrm() ||
1146 0 : ( GetUpper()->IsSctFrm() &&
1147 127022 : GetUpper()->GetUpper()->IsCellFrm() ) ) &&
1148 0 : IsMoveable() )
1149 : {
1150 0 : bMovedFwd = true;
1151 0 : MoveFwd( bMakePage, false );
1152 : }
1153 : }
1154 :
1155 : // If a Follow sits next to it's Master and doesn't fit, we know it can
1156 : // be moved right now.
1157 130215 : if ( lcl_Prev( this ) && ((SwTxtFrm*)this)->IsFollow() && IsMoveable() )
1158 : {
1159 1278 : bMovedFwd = true;
1160 : // OD 2004-03-02 #106629# - If follow frame is in table, it's master
1161 : // will be the last in the current table cell. Thus, invalidate the
1162 : // printing area of the master,
1163 1278 : if ( IsInTab() )
1164 : {
1165 254 : lcl_Prev( this )->InvalidatePrt();
1166 : }
1167 1278 : MoveFwd( bMakePage, false );
1168 : }
1169 :
1170 : // OD 08.11.2002 #104840# - check footnote content for forward move.
1171 : // If a content of a footnote is on a prior page/column as its invalid
1172 : // reference, it can be moved forward.
1173 130215 : if ( bFtn && !mbValidPos )
1174 : {
1175 500 : SwFtnFrm* pFtn = FindFtnFrm();
1176 500 : SwCntntFrm* pRefCnt = pFtn ? pFtn->GetRef() : 0;
1177 500 : if ( pRefCnt && !pRefCnt->IsValid() )
1178 : {
1179 222 : SwFtnBossFrm* pFtnBossOfFtn = pFtn->FindFtnBossFrm();
1180 222 : SwFtnBossFrm* pFtnBossOfRef = pRefCnt->FindFtnBossFrm();
1181 : //<loop of movefwd until condition held or no move>
1182 444 : if ( pFtnBossOfFtn && pFtnBossOfRef &&
1183 228 : pFtnBossOfFtn != pFtnBossOfRef &&
1184 6 : pFtnBossOfFtn->IsBefore( pFtnBossOfRef ) )
1185 : {
1186 0 : bMovedFwd = true;
1187 0 : MoveFwd( bMakePage, false );
1188 : }
1189 : }
1190 : }
1191 :
1192 130215 : SWRECTFN( this )
1193 :
1194 453984 : while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
1195 : {
1196 : // - loop prevention
1197 193808 : SwRect aOldFrm_StopFormat( Frm() );
1198 193808 : SwRect aOldPrt_StopFormat( Prt() );
1199 193808 : if ( (bMoveable = IsMoveable()) )
1200 : {
1201 98357 : SwFrm *pPre = GetIndPrev();
1202 98357 : if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) )
1203 : {
1204 508 : SWREFRESHFN( this )
1205 508 : bMovedFwd = true;
1206 508 : if ( bMovedBwd )
1207 : {
1208 : // While flowing back, the Upper was encouraged to
1209 : // completely re-paint itself. We can skip this now after
1210 : // flowing back and forth.
1211 218 : GetUpper()->ResetCompletePaint();
1212 : // The predecessor was invalidated, so this is obsolete as well now.
1213 : OSL_ENSURE( pPre, "missing old Prev" );
1214 218 : if( !pPre->IsSctFrm() )
1215 210 : ::ValidateSz( pPre );
1216 : }
1217 508 : bMoveable = IsMoveable();
1218 : }
1219 : }
1220 :
1221 193808 : aOldFrmPos = (Frm().*fnRect->fnGetPos)();
1222 193808 : aOldPrtPos = (Prt().*fnRect->fnGetPos)();
1223 :
1224 193808 : if ( !mbValidPos )
1225 116202 : MakePos();
1226 :
1227 : //Set FixSize. VarSize is being adjusted by Format().
1228 193808 : if ( !mbValidSize )
1229 : {
1230 : // #125452#
1231 : // invalidate printing area flag, if the following conditions are hold:
1232 : // - current frame width is 0.
1233 : // - current printing area width is 0.
1234 : // - frame width is adjusted to a value greater than 0.
1235 : // - printing area flag is sal_True.
1236 : // Thus, it's assured that the printing area is adjusted, if the
1237 : // frame area width changes its width from 0 to something greater
1238 : // than 0.
1239 : // Note: A text frame can be in such a situation, if the format is
1240 : // triggered by method call <SwCrsrShell::SetCrsr()> after
1241 : // loading the document.
1242 129426 : const SwTwips nNewFrmWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1243 195048 : if ( mbValidPrtArea && nNewFrmWidth > 0 &&
1244 162225 : (Frm().*fnRect->fnGetWidth)() == 0 &&
1245 0 : (Prt().*fnRect->fnGetWidth)() == 0 )
1246 : {
1247 0 : mbValidPrtArea = false;
1248 : }
1249 :
1250 129426 : (Frm().*fnRect->fnSetWidth)( nNewFrmWidth );
1251 :
1252 : // When a lower of a vertically aligned fly frame changes its size we need to recalculate content pos.
1253 135073 : if( GetUpper() && GetUpper()->IsFlyFrm() &&
1254 5647 : GetUpper()->GetFmt()->GetTextVertAdjust().GetValue() != SDRTEXTVERTADJUST_TOP )
1255 : {
1256 1218 : static_cast<SwFlyFrm*>(GetUpper())->InvalidateContentPos();
1257 1218 : GetUpper()->SetCompletePaint();
1258 : }
1259 : }
1260 193808 : if ( !mbValidPrtArea )
1261 : {
1262 144232 : const long nOldW = (Prt().*fnRect->fnGetWidth)();
1263 : // #i34730# - keep current frame height
1264 144232 : const SwTwips nOldH = (Frm().*fnRect->fnGetHeight)();
1265 144232 : MakePrtArea( rAttrs );
1266 144232 : if ( nOldW != (Prt().*fnRect->fnGetWidth)() )
1267 58955 : Prepare( PREP_FIXSIZE_CHG );
1268 : // #i34730# - check, if frame height has changed.
1269 : // If yes, send a PREP_ADJUST_FRM and invalidate the size flag to
1270 : // force a format. The format will check in its method
1271 : // <SwTxtFrm::CalcPreps()>, if the already formatted lines still
1272 : // fit and if not, performs necessary actions.
1273 : // #i40150# - no check, if frame is undersized.
1274 191057 : if ( mbValidSize && !IsUndersized() &&
1275 46825 : nOldH != (Frm().*fnRect->fnGetHeight)() )
1276 : {
1277 : // #115759# - no PREP_ADJUST_FRM and size
1278 : // invalidation, if height decreases only by the additional
1279 : // lower space as last content of a table cell and an existing
1280 : // follow containing one line exists.
1281 84 : const SwTwips nHDiff = nOldH - (Frm().*fnRect->fnGetHeight)();
1282 : const bool bNoPrepAdjustFrm =
1283 88 : nHDiff > 0 && IsInTab() && GetFollow() &&
1284 156 : ( 1 == static_cast<SwTxtFrm*>(GetFollow())->GetLineCount( COMPLETE_STRING ) || (static_cast<SwTxtFrm*>(GetFollow())->Frm().*fnRect->fnGetWidth)() < 0 ) &&
1285 102 : GetFollow()->CalcAddLowerSpaceAsLastInTableCell() == nHDiff;
1286 84 : if ( !bNoPrepAdjustFrm )
1287 : {
1288 66 : Prepare( PREP_ADJUST_FRM );
1289 66 : mbValidSize = false;
1290 : }
1291 : }
1292 : }
1293 :
1294 : // To make the widow and orphan rules work, we need to notify the CntntFrm.
1295 : // Criteria:
1296 : // - It needs to be movable (otherwise, splitting doesn't make sense)
1297 : // - It needs to overlap with the lower edge of the PrtArea of the Upper
1298 193808 : if ( !bMustFit )
1299 : {
1300 192766 : bool bWidow = true;
1301 192766 : const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1302 265359 : if ( bMoveable && !bFormatted && ( GetFollow() ||
1303 72593 : ( (Frm().*fnRect->fnOverStep)( nDeadLine ) ) ) )
1304 : {
1305 2497 : Prepare( PREP_WIDOWS_ORPHANS, 0, false );
1306 2497 : mbValidSize = bWidow = false;
1307 : }
1308 585398 : if( (Frm().*fnRect->fnGetPos)() != aOldFrmPos ||
1309 392632 : (Prt().*fnRect->fnGetPos)() != aOldPrtPos )
1310 : {
1311 : // In this Prepare, an _InvalidateSize() might happen.
1312 : // mbValidSize becomes sal_False and Format() gets called.
1313 93341 : Prepare( PREP_POS_CHGD, (const void*)&bFormatted, false );
1314 93341 : if ( bWidow && GetFollow() )
1315 : {
1316 30 : Prepare( PREP_WIDOWS_ORPHANS, 0, false );
1317 30 : mbValidSize = false;
1318 : }
1319 : }
1320 : }
1321 193808 : if ( !mbValidSize )
1322 : {
1323 129963 : mbValidSize = true;
1324 129963 : bFormatted = sal_True;
1325 129963 : ++nFormatCount;
1326 129963 : if( nFormatCount > STOP_FLY_FORMAT )
1327 0 : SetFlyLock( true );
1328 : // - loop prevention
1329 : // No format any longer, if <cnStopFormat> consequetive formats
1330 : // without change occur.
1331 129963 : if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
1332 : {
1333 129963 : Format();
1334 : }
1335 : #if OSL_DEBUG_LEVEL > 0
1336 : else
1337 : {
1338 : OSL_FAIL( "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" );
1339 : }
1340 : #endif
1341 : }
1342 :
1343 : // If this is the first one in a chain, check if this can flow
1344 : // backwards (if this is movable at all).
1345 : // To prevent oscillations/loops, check that this has not just
1346 : // flowed forwards.
1347 : bool bDummy;
1348 506969 : if ( !lcl_Prev( this ) &&
1349 232044 : !bMovedFwd &&
1350 118506 : ( bMoveable || ( bFly && !bTab ) ) &&
1351 43575 : ( !bFtn || !GetUpper()->FindFtnFrm()->GetPrev() )
1352 236605 : && MoveBwd( bDummy ) )
1353 : {
1354 12766 : SWREFRESHFN( this )
1355 12766 : bMovedBwd = true;
1356 12766 : bFormatted = sal_False;
1357 12766 : if ( bKeep && bMoveable )
1358 : {
1359 736 : if( CheckMoveFwd( bMakePage, false, bMovedBwd ) )
1360 : {
1361 0 : bMovedFwd = true;
1362 0 : bMoveable = IsMoveable();
1363 0 : SWREFRESHFN( this )
1364 : }
1365 736 : Point aOldPos = (Frm().*fnRect->fnGetPos)();
1366 736 : MakePos();
1367 736 : if( aOldPos != (Frm().*fnRect->fnGetPos)() )
1368 : {
1369 736 : Prepare( PREP_POS_CHGD, (const void*)&bFormatted, false );
1370 736 : if ( !mbValidSize )
1371 : {
1372 1472 : (Frm().*fnRect->fnSetWidth)( (GetUpper()->
1373 1472 : Prt().*fnRect->fnGetWidth)() );
1374 736 : if ( !mbValidPrtArea )
1375 : {
1376 736 : const long nOldW = (Prt().*fnRect->fnGetWidth)();
1377 736 : MakePrtArea( rAttrs );
1378 736 : if( nOldW != (Prt().*fnRect->fnGetWidth)() )
1379 0 : Prepare( PREP_FIXSIZE_CHG, 0, false );
1380 : }
1381 736 : if( GetFollow() )
1382 0 : Prepare( PREP_WIDOWS_ORPHANS, 0, false );
1383 736 : mbValidSize = true;
1384 736 : bFormatted = sal_True;
1385 736 : Format();
1386 : }
1387 : }
1388 736 : SwFrm *pNxt = HasFollow() ? NULL : FindNext();
1389 1500 : while( pNxt && pNxt->IsSctFrm() )
1390 : { // Leave empty sections out, go into the other ones.
1391 88 : if( ((SwSectionFrm*)pNxt)->GetSection() )
1392 : {
1393 74 : SwFrm* pTmp = ((SwSectionFrm*)pNxt)->ContainsAny();
1394 74 : if( pTmp )
1395 : {
1396 60 : pNxt = pTmp;
1397 60 : break;
1398 : }
1399 : }
1400 28 : pNxt = pNxt->FindNext();
1401 : }
1402 736 : if ( pNxt )
1403 : {
1404 736 : pNxt->Calc();
1405 736 : if( mbValidPos && !GetIndNext() )
1406 : {
1407 0 : SwSectionFrm *pSct = FindSctFrm();
1408 0 : if( pSct && !pSct->GetValidSizeFlag() )
1409 : {
1410 0 : SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
1411 0 : if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1412 0 : mbValidPos = false;
1413 : }
1414 : else
1415 0 : mbValidPos = false;
1416 : }
1417 : }
1418 : }
1419 : }
1420 :
1421 : // In footnotes, the TxtFrm may validate itself, which can lead to the
1422 : // situation that it's position is wrong despite being "valid".
1423 193808 : if ( mbValidPos )
1424 : {
1425 : // #i59341#
1426 : // Workaround for inadequate layout algorithm:
1427 : // suppress invalidation and calculation of position, if paragraph
1428 : // has formatted itself at least STOP_FLY_FORMAT times and
1429 : // has anchored objects.
1430 : // Thus, the anchored objects get the possibility to format itself
1431 : // and this probably solve the layout loop.
1432 182096 : if ( bFtn &&
1433 182096 : nFormatCount <= STOP_FLY_FORMAT &&
1434 748 : !GetDrawObjs() )
1435 : {
1436 748 : mbValidPos = false;
1437 748 : MakePos();
1438 748 : aOldFrmPos = (Frm().*fnRect->fnGetPos)();
1439 748 : aOldPrtPos = (Prt().*fnRect->fnGetPos)();
1440 : }
1441 : }
1442 :
1443 : // - loop prevention
1444 : {
1445 287887 : if ( aOldFrm_StopFormat == Frm() &&
1446 94079 : aOldPrt_StopFormat == Prt() )
1447 : {
1448 94079 : ++nConsequetiveFormatsWithoutChange;
1449 : }
1450 : else
1451 : {
1452 99729 : nConsequetiveFormatsWithoutChange = 0;
1453 : }
1454 : }
1455 :
1456 : // Yet again an invalid value? Repeat from the start...
1457 193808 : if ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
1458 252461 : continue;
1459 :
1460 : // Done?
1461 : // Attention: because height == 0, it's better to use Top()+Height() instead of
1462 : // Bottom(). This might happen with undersized TextFrms on the lower edge of a
1463 : // multi-column section
1464 132825 : const long nPrtBottom = (GetUpper()->*fnRect->fnGetPrtBottom)();
1465 132825 : const long nBottomDist = (Frm().*fnRect->fnBottomDist)( nPrtBottom );
1466 132825 : if( nBottomDist >= 0 )
1467 : {
1468 129967 : if ( bKeep && bMoveable )
1469 : {
1470 : // We make sure the successor will be formatted the same.
1471 : // This way, we keep control until (almost) everything is stable,
1472 : // allowing us to avoid endless loops caused by ever repeating
1473 : // retries.
1474 :
1475 : // bMoveFwdInvalid is required for #38407#. This was originally solved
1476 : // in flowfrm.cxx rev 1.38, but broke the above schema and
1477 : // preferred to play towers of hanoi (#43669#).
1478 3562 : SwFrm *pNxt = HasFollow() ? NULL : FindNext();
1479 : // For sections we prefer the content, because it can change
1480 : // the page if required.
1481 7126 : while( pNxt && pNxt->IsSctFrm() )
1482 : {
1483 168 : if( ((SwSectionFrm*)pNxt)->GetSection() )
1484 : {
1485 166 : pNxt = ((SwSectionFrm*)pNxt)->ContainsAny();
1486 166 : break;
1487 : }
1488 2 : pNxt = pNxt->FindNext();
1489 : }
1490 3562 : if ( pNxt )
1491 : {
1492 3346 : const bool bMoveFwdInvalid = 0 != GetIndNext();
1493 : const bool bNxtNew =
1494 5274 : ( 0 == (pNxt->Prt().*fnRect->fnGetHeight)() ) &&
1495 5254 : (!pNxt->IsTxtFrm() ||!((SwTxtFrm*)pNxt)->IsHiddenNow());
1496 :
1497 3346 : pNxt->Calc();
1498 :
1499 4362 : if ( !bMovedBwd &&
1500 2570 : ((bMoveFwdInvalid && !GetIndNext()) ||
1501 : bNxtNew) )
1502 : {
1503 1016 : if( bMovedFwd )
1504 78 : pNotify->SetInvaKeep();
1505 1016 : bMovedFwd = false;
1506 : }
1507 : }
1508 : }
1509 129967 : continue;
1510 : }
1511 :
1512 : // I don't fit into my parents, so it's time to make changes
1513 : // as constructively as possible.
1514 :
1515 : //If I'm NOT allowed to leave the parent Frm, I've got a problem.
1516 : // Following Arthur Dent, we do the only thing that you can do with
1517 : // an unsolvable problem: We ignore it with all our power.
1518 2858 : if ( !bMoveable || IsUndersized() )
1519 : {
1520 258 : if( !bMoveable && IsInTab() )
1521 : {
1522 40 : long nDiff = -(Frm().*fnRect->fnBottomDist)(
1523 40 : (GetUpper()->*fnRect->fnGetPrtBottom)() );
1524 40 : long nReal = GetUpper()->Grow( nDiff );
1525 40 : if( nReal )
1526 4 : continue;
1527 : }
1528 508 : break;
1529 : }
1530 :
1531 : // If there's no way I can make myself fit into my Upper, the situation
1532 : // could still probably be mitigated by splitting up.
1533 : // This situation arises with freshly created Follows that had been moved
1534 : // to the next page but is still too big for it - ie. needs to be split
1535 : // as well.
1536 :
1537 : // If I'm unable to split (WouldFit()) and can't be fitted, I'm going
1538 : // to tell my TxtFrm part that, if possible, we still need to split despite
1539 : // the "don't split" attribute.
1540 2600 : bool bMoveOrFit = false;
1541 2600 : bool bDontMoveMe = !GetIndPrev();
1542 2600 : if( bDontMoveMe && IsInSct() )
1543 : {
1544 956 : SwFtnBossFrm* pBoss = FindFtnBossFrm();
1545 2428 : bDontMoveMe = !pBoss->IsInSct() ||
1546 2868 : ( !pBoss->Lower()->GetNext() && !pBoss->GetPrev() );
1547 : }
1548 :
1549 : // Finally, we are able to split table rows. Therefore, bDontMoveMe
1550 : // can be set to false:
1551 2678 : if( bDontMoveMe && IsInTab() &&
1552 78 : 0 != const_cast<SwCntntFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) )
1553 78 : bDontMoveMe = false;
1554 :
1555 3198 : if ( bDontMoveMe && (Frm().*fnRect->fnGetHeight)() >
1556 598 : (GetUpper()->Prt().*fnRect->fnGetHeight)() )
1557 : {
1558 598 : if ( !bFitPromise )
1559 : {
1560 1196 : SwTwips nTmp = (GetUpper()->Prt().*fnRect->fnGetHeight)() -
1561 1196 : (Prt().*fnRect->fnGetTop)();
1562 598 : bool bSplit = !IsFwdMoveAllowed();
1563 598 : if ( nTmp > 0 && WouldFit( nTmp, bSplit, false ) )
1564 : {
1565 0 : Prepare( PREP_WIDOWS_ORPHANS, 0, false );
1566 0 : mbValidSize = false;
1567 0 : bFitPromise = true;
1568 0 : continue;
1569 : }
1570 : /*
1571 : * In earlier days, we never tried to fit TextFrms in
1572 : * frames and sections using bMoveOrFit by ignoring
1573 : * its attributes (Widows, Keep).
1574 : * This should have been done at least for column frames;
1575 : * as it must be tried anyway with linked frames and sections.
1576 : * Exception: If we sit in FormatWidthCols, we must not ignore
1577 : * the attributes.
1578 : */
1579 2392 : else if ( !bFtn && bMoveable &&
1580 2318 : ( !bFly || !FindFlyFrm()->IsColLocked() ) &&
1581 1114 : ( !bSct || !FindSctFrm()->IsColLocked() ) )
1582 524 : bMoveOrFit = true;
1583 : }
1584 : #if OSL_DEBUG_LEVEL > 0
1585 : else
1586 : {
1587 : OSL_FAIL( "+TxtFrm didn't respect WouldFit promise." );
1588 : }
1589 : #endif
1590 : }
1591 :
1592 : // Let's see if I can find some space somewhere...
1593 : // footnotes in the neighbourhood are moved into _MoveFtnCntFwd
1594 2600 : SwFrm *pPre = GetIndPrev();
1595 2600 : SwFrm *pOldUp = GetUpper();
1596 :
1597 : /* MA 13. Oct. 98: What is this supposed to be!?
1598 : * AMA 14. Dec 98: If a column section can't find any space for its first ContentFrm, it should be
1599 : * moved not only to the next column, but probably even to the next page, creating
1600 : * a section-follow there.
1601 : */
1602 7866 : if( IsInSct() && bMovedFwd && bMakePage && pOldUp->IsColBodyFrm() &&
1603 1232 : pOldUp->GetUpper()->GetUpper()->IsSctFrm() &&
1604 3650 : ( pPre || pOldUp->GetUpper()->GetPrev() ) &&
1605 516 : ((SwSectionFrm*)pOldUp->GetUpper()->GetUpper())->MoveAllowed(this) )
1606 : {
1607 516 : bMovedFwd = false;
1608 : }
1609 :
1610 2600 : const bool bCheckForGrownBody = pOldUp->IsBodyFrm();
1611 2600 : const long nOldBodyHeight = (pOldUp->Frm().*fnRect->fnGetHeight)();
1612 :
1613 2600 : if ( !bMovedFwd && !MoveFwd( bMakePage, false ) )
1614 838 : bMakePage = false;
1615 2600 : SWREFRESHFN( this )
1616 :
1617 : // If MoveFwd moves the paragraph to the next page, a following
1618 : // paragraph, which contains footnotes can can cause the old upper
1619 : // frame to grow. In this case we explicitly allow a new check
1620 : // for MoveBwd. Robust: We also check the bMovedBwd flag again.
1621 : // If pOldUp was a footnote frame, it has been deleted inside MoveFwd.
1622 : // Therefore we only check for growing body frames.
1623 3966 : if ( bCheckForGrownBody && ! bMovedBwd && pOldUp != GetUpper() &&
1624 1366 : (pOldUp->Frm().*fnRect->fnGetHeight)() > nOldBodyHeight )
1625 : {
1626 0 : bMovedFwd = false;
1627 : }
1628 : else
1629 : {
1630 2600 : bMovedFwd = true;
1631 : }
1632 :
1633 2600 : bFormatted = sal_False;
1634 2600 : if ( bMoveOrFit && GetUpper() == pOldUp )
1635 : {
1636 : // FME 2007-08-30 #i81146# new loop control
1637 524 : if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
1638 : {
1639 524 : Prepare( PREP_MUST_FIT, 0, false );
1640 524 : mbValidSize = false;
1641 524 : bMustFit = true;
1642 524 : continue;
1643 : }
1644 :
1645 : #if OSL_DEBUG_LEVEL > 0
1646 : OSL_FAIL( "LoopControl in SwCntntFrm::MakeAll" );
1647 : #endif
1648 : }
1649 2076 : if ( bMovedBwd && GetUpper() )
1650 : { // Retire invalidations that have become useless.
1651 538 : GetUpper()->ResetCompletePaint();
1652 538 : if( pPre && !pPre->IsSctFrm() )
1653 496 : ::ValidateSz( pPre );
1654 : }
1655 :
1656 : } //while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
1657 :
1658 : // NEW: Looping Louie (Light). Should not be applied in balanced sections.
1659 : // Should only be applied if there is no better solution!
1660 130215 : LOOPING_LOUIE_LIGHT( bMovedFwd && bMovedBwd && !IsInBalancedSection() &&
1661 : (
1662 :
1663 : // #118572#
1664 226 : ( bFtn && !FindFtnFrm()->GetRef()->IsInSct() ) ||
1665 :
1666 : // #i33887#
1667 236 : ( IsInSct() && bKeep )
1668 :
1669 : // ... add your conditions here ...
1670 :
1671 : ),
1672 130215 : static_cast<SwTxtFrm&>(*this) );
1673 :
1674 130215 : delete pSaveFtn;
1675 :
1676 130215 : UnlockJoin();
1677 130215 : if ( bMovedFwd || bMovedBwd )
1678 15402 : pNotify->SetInvaKeep();
1679 : // OD 2004-02-26 #i25029#
1680 130215 : if ( bMovedFwd )
1681 : {
1682 3350 : pNotify->SetInvalidatePrevPrtArea();
1683 : }
1684 130215 : delete pNotify;
1685 260430 : SetFlyLock( false );
1686 : }
1687 :
1688 808 : void MakeNxt( SwFrm *pFrm, SwFrm *pNxt )
1689 : {
1690 : // fix(25455): Validate, otherwise this leads to a recursion.
1691 : // The first try, cancelling with pFrm = 0 if !Valid, leads to a problem, as
1692 : // the Keep may not be considered properly anymore (27417).
1693 808 : const bool bOldPos = pFrm->GetValidPosFlag();
1694 808 : const bool bOldSz = pFrm->GetValidSizeFlag();
1695 808 : const bool bOldPrt = pFrm->GetValidPrtAreaFlag();
1696 808 : pFrm->mbValidPos = pFrm->mbValidPrtArea = pFrm->mbValidSize = true;
1697 :
1698 : // fix(29272): Don't call MakeAll - there, pFrm might be invalidated again, and
1699 : // we recursively end up in here again.
1700 808 : if ( pNxt->IsCntntFrm() )
1701 : {
1702 808 : SwCntntNotify aNotify( (SwCntntFrm*)pNxt );
1703 1616 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
1704 808 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1705 808 : if ( !pNxt->GetValidSizeFlag() )
1706 : {
1707 804 : if( pNxt->IsVertical() )
1708 0 : pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
1709 : else
1710 804 : pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
1711 : }
1712 808 : ((SwCntntFrm*)pNxt)->MakePrtArea( rAttrs );
1713 1616 : pNxt->Format( &rAttrs );
1714 : }
1715 : else
1716 : {
1717 0 : SwLayNotify aNotify( (SwLayoutFrm*)pNxt );
1718 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
1719 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1720 0 : if ( !pNxt->GetValidSizeFlag() )
1721 : {
1722 0 : if( pNxt->IsVertical() )
1723 0 : pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
1724 : else
1725 0 : pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
1726 : }
1727 0 : pNxt->Format( &rAttrs );
1728 : }
1729 :
1730 808 : pFrm->mbValidPos = bOldPos;
1731 808 : pFrm->mbValidSize = bOldSz;
1732 808 : pFrm->mbValidPrtArea = bOldPrt;
1733 808 : }
1734 :
1735 : /// This routine checks whether there are no other FtnBosses
1736 : /// between the pFrm's FtnBoss and the pNxt's FtnBoss.
1737 0 : static bool lcl_IsNextFtnBoss( const SwFrm *pFrm, const SwFrm* pNxt )
1738 : {
1739 : assert(pFrm && pNxt && "lcl_IsNextFtnBoss: No Frames?");
1740 0 : pFrm = pFrm->FindFtnBossFrm();
1741 0 : pNxt = pNxt->FindFtnBossFrm();
1742 : // If pFrm is a last column, we use the page instead.
1743 0 : while( pFrm && pFrm->IsColumnFrm() && !pFrm->GetNext() )
1744 0 : pFrm = pFrm->GetUpper()->FindFtnBossFrm();
1745 : // If pNxt is a first column, we use the page instead.
1746 0 : while( pNxt && pNxt->IsColumnFrm() && !pNxt->GetPrev() )
1747 0 : pNxt = pNxt->GetUpper()->FindFtnBossFrm();
1748 : // So.. now pFrm and pNxt are either two adjacent pages or columns.
1749 0 : return pFrm && pNxt && pFrm->GetNext() == pNxt;
1750 : }
1751 :
1752 4754 : bool SwCntntFrm::_WouldFit( SwTwips nSpace,
1753 : SwLayoutFrm *pNewUpper,
1754 : bool bTstMove,
1755 : const bool bObjsInNewUpper )
1756 : {
1757 : // To have the footnote select it's place carefully, it needs
1758 : // to be moved in any case if there is at least one page/column
1759 : // between the footnote and the new Upper.
1760 4754 : SwFtnFrm* pFtnFrm = 0;
1761 4754 : if ( IsInFtn() )
1762 : {
1763 0 : if( !lcl_IsNextFtnBoss( pNewUpper, this ) )
1764 0 : return true;
1765 0 : pFtnFrm = FindFtnFrm();
1766 : }
1767 :
1768 : bool bRet;
1769 4754 : bool bSplit = !pNewUpper->Lower();
1770 4754 : SwCntntFrm *pFrm = this;
1771 4754 : const SwFrm *pTmpPrev = pNewUpper->Lower();
1772 4754 : if( pTmpPrev && pTmpPrev->IsFtnFrm() )
1773 0 : pTmpPrev = ((SwFtnFrm*)pTmpPrev)->Lower();
1774 57718 : while ( pTmpPrev && pTmpPrev->GetNext() )
1775 48210 : pTmpPrev = pTmpPrev->GetNext();
1776 5562 : do
1777 : {
1778 : // #i46181#
1779 5562 : SwTwips nSecondCheck = 0;
1780 5562 : SwTwips nOldSpace = nSpace;
1781 5562 : bool bOldSplit = bSplit;
1782 :
1783 6444 : if ( bTstMove || IsInFly() || ( IsInSct() &&
1784 984 : ( pFrm->GetUpper()->IsColBodyFrm() || ( pFtnFrm &&
1785 0 : pFtnFrm->GetUpper()->GetUpper()->IsColumnFrm() ) ) ) )
1786 : {
1787 : // This is going to get a bit insidious now. If you're faint of heart,
1788 : // you'd better look away here. If a Fly contains columns, then the Cntnts
1789 : // are movable, except ones in the last column (see SwFrm::IsMoveable()).
1790 : // Of course they're allowed to float back. WouldFit() only returns a usable
1791 : // value if the Frm is movable. To fool WouldFit() into believing there's
1792 : // a movable Frm, I'm just going to hang it somewhere else for the time.
1793 : // The same procedure applies for column sections to make SwSectionFrm::Growable()
1794 : // return the proper value.
1795 : // Within footnotes, we may even need to put the SwFtnFrm somewhere else, if
1796 : // there's no SwFtnFrm there.
1797 318 : SwFrm* pTmpFrm = pFrm->IsInFtn() && !pNewUpper->FindFtnFrm() ?
1798 318 : (SwFrm*)pFrm->FindFtnFrm() : pFrm;
1799 318 : SwLayoutFrm *pUp = pTmpFrm->GetUpper();
1800 318 : SwFrm *pOldNext = pTmpFrm->GetNext();
1801 318 : pTmpFrm->Remove();
1802 318 : pTmpFrm->InsertBefore( pNewUpper, 0 );
1803 496 : if ( pFrm->IsTxtFrm() &&
1804 144 : ( bTstMove ||
1805 284 : ((SwTxtFrm*)pFrm)->HasFollow() ||
1806 144 : ( !((SwTxtFrm*)pFrm)->HasPara() &&
1807 4 : !((SwTxtFrm*)pFrm)->IsEmpty()
1808 : )
1809 : )
1810 : )
1811 : {
1812 178 : bTstMove = true;
1813 178 : bRet = ((SwTxtFrm*)pFrm)->TestFormat( pTmpPrev, nSpace, bSplit );
1814 : }
1815 : else
1816 140 : bRet = pFrm->WouldFit( nSpace, bSplit, false );
1817 :
1818 318 : pTmpFrm->Remove();
1819 318 : pTmpFrm->InsertBefore( pUp, pOldNext );
1820 : }
1821 : else
1822 : {
1823 5244 : bRet = pFrm->WouldFit( nSpace, bSplit, false );
1824 5244 : nSecondCheck = !bSplit ? 1 : 0;
1825 : }
1826 :
1827 5562 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
1828 5562 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1829 :
1830 : // Sad but true: We need to consider the spacing in our calculation.
1831 : // This already happened in TestFormat.
1832 5562 : if ( bRet && !bTstMove )
1833 : {
1834 : SwTwips nUpper;
1835 :
1836 5312 : if ( pTmpPrev )
1837 : {
1838 4520 : nUpper = CalcUpperSpace( NULL, pTmpPrev );
1839 :
1840 : // in balanced columned section frames we do not want the
1841 : // common border
1842 4520 : bool bCommonBorder = true;
1843 4520 : if ( pFrm->IsInSct() && pFrm->GetUpper()->IsColBodyFrm() )
1844 : {
1845 120 : const SwSectionFrm* pSct = pFrm->FindSctFrm();
1846 120 : bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
1847 : }
1848 :
1849 : // #i46181#
1850 4394 : nSecondCheck = ( 1 == nSecondCheck &&
1851 4312 : pFrm == this &&
1852 8624 : IsTxtFrm() &&
1853 4312 : bCommonBorder &&
1854 4312 : !static_cast<const SwTxtFrm*>(this)->IsEmpty() ) ?
1855 : nUpper :
1856 6074 : 0;
1857 :
1858 : nUpper += bCommonBorder ?
1859 4400 : rAttrs.GetBottomLine( *(pFrm) ) :
1860 8920 : rAttrs.CalcBottomLine();
1861 :
1862 : }
1863 : else
1864 : {
1865 : // #i46181#
1866 792 : nSecondCheck = 0;
1867 :
1868 792 : if( pFrm->IsVertical() )
1869 0 : nUpper = pFrm->Frm().Width() - pFrm->Prt().Width();
1870 : else
1871 792 : nUpper = pFrm->Frm().Height() - pFrm->Prt().Height();
1872 : }
1873 :
1874 5312 : nSpace -= nUpper;
1875 :
1876 5312 : if ( nSpace < 0 )
1877 : {
1878 52 : bRet = false;
1879 :
1880 : // #i46181#
1881 52 : if ( nSecondCheck > 0 )
1882 : {
1883 : // The following code is intended to solve a (rare) problem
1884 : // causing some frames not to move backward:
1885 : // SwTxtFrm::WouldFit() claims that the whole paragraph
1886 : // fits into the given space and subtracts the height of
1887 : // all lines from nSpace. nSpace - nUpper is not a valid
1888 : // indicator if the frame should be allowed to move backward.
1889 : // We do a second check with the original remaining space
1890 : // reduced by the required upper space:
1891 16 : nOldSpace -= nSecondCheck;
1892 16 : const bool bSecondRet = nOldSpace >= 0 && pFrm->WouldFit( nOldSpace, bOldSplit, false );
1893 16 : if ( bSecondRet && bOldSplit && nOldSpace >= 0 )
1894 : {
1895 0 : bRet = true;
1896 0 : bSplit = true;
1897 : }
1898 : }
1899 : }
1900 : }
1901 :
1902 : // OD 2004-03-01 #106629# - also consider lower spacing in table cells
1903 5562 : if ( bRet && IsInTab() &&
1904 0 : pNewUpper->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
1905 : {
1906 0 : nSpace -= rAttrs.GetULSpace().GetLower();
1907 0 : if ( nSpace < 0 )
1908 : {
1909 0 : bRet = false;
1910 : }
1911 : }
1912 :
1913 5562 : if ( bRet && !bSplit && pFrm->IsKeep( rAttrs.GetAttrSet() ) )
1914 : {
1915 822 : if( bTstMove )
1916 : {
1917 0 : while( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
1918 : {
1919 0 : pFrm = ((SwTxtFrm*)pFrm)->GetFollow();
1920 : }
1921 : // OD 11.04.2003 #108824# - If last follow frame of <this> text
1922 : // frame isn't valid, a formatting of the next content frame
1923 : // doesn't makes sense. Thus, return sal_True.
1924 0 : if ( IsAnFollow( pFrm ) && !pFrm->IsValid() )
1925 : {
1926 : OSL_FAIL( "Only a warning for task 108824:/n<SwCntntFrm::_WouldFit(..) - follow not valid!" );
1927 0 : return true;
1928 : }
1929 : }
1930 : SwFrm *pNxt;
1931 1630 : if( 0 != (pNxt = pFrm->FindNext()) && pNxt->IsCntntFrm() &&
1932 0 : ( !pFtnFrm || ( pNxt->IsInFtn() &&
1933 0 : pNxt->FindFtnFrm()->GetAttr() == pFtnFrm->GetAttr() ) ) )
1934 : {
1935 : // TestFormat(?) does not like paragraph- or character anchored objects.
1936 :
1937 : // current solution for the test formatting doesn't work, if
1938 : // objects are present in the remaining area of the new upper
1939 808 : if ( bTstMove &&
1940 0 : ( pNxt->GetDrawObjs() || bObjsInNewUpper ) )
1941 : {
1942 0 : return true;
1943 : }
1944 :
1945 808 : if ( !pNxt->IsValid() )
1946 808 : MakeNxt( pFrm, pNxt );
1947 :
1948 : // Little trick: if the next has a predecessor, then the paragraph
1949 : // spacing has been calculated already, and we don't need to re-calculate
1950 : // it in an expensive way.
1951 808 : if( lcl_NotHiddenPrev( pNxt ) )
1952 726 : pTmpPrev = 0;
1953 : else
1954 : {
1955 82 : if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow() )
1956 0 : pTmpPrev = lcl_NotHiddenPrev( pFrm );
1957 : else
1958 82 : pTmpPrev = pFrm;
1959 : }
1960 808 : pFrm = (SwCntntFrm*)pNxt;
1961 : }
1962 : else
1963 14 : pFrm = 0;
1964 : }
1965 : else
1966 4740 : pFrm = 0;
1967 :
1968 5426 : } while ( bRet && pFrm );
1969 :
1970 4754 : return bRet;
1971 270 : }
1972 :
1973 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|