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