xref: /aoo41x/main/sw/source/core/layout/sectfrm.cxx (revision 79aad27f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 #include <svl/smplhint.hxx>
28 #include <svl/itemiter.hxx>
29 #include <hints.hxx>
30 #include <txtftn.hxx>
31 #include <fmtftn.hxx>
32 #include <fmtclbl.hxx>
33 #include "sectfrm.hxx"
34 #include "section.hxx"		// SwSection
35 #include "frmtool.hxx"		// StackHack
36 #include "doc.hxx"			// SwDoc
37 #include "cntfrm.hxx"		// SwCntntFrm
38 #include "rootfrm.hxx"		// SwRootFrm
39 #include "pagefrm.hxx"		// SwPageFrm
40 #include "fmtpdsc.hxx"		// SwFmtPageDesc
41 #include "fmtcntnt.hxx"		// SwFmtCntnt
42 #include "ndindex.hxx"		// SwNodeIndex
43 #include "ftnidx.hxx"
44 #include "txtfrm.hxx"		// SwTxtFrm
45 #include "fmtclds.hxx"		// SwFmtCol
46 #include "colfrm.hxx"		// SwColumnFrm
47 #include "tabfrm.hxx"		// SwTabFrm
48 #include "flyfrm.hxx"		// SwFlyFrm
49 #include "ftnfrm.hxx"		// SwFtnFrm
50 #include "layouter.hxx"		// SwLayouter
51 #include "dbg_lay.hxx"
52 #include "viewsh.hxx"
53 #include "viewopt.hxx"
54 #include "viewimp.hxx"
55 #include <editeng/ulspitem.hxx>
56 #include <editeng/lrspitem.hxx>
57 #include <editeng/brshitem.hxx>
58 #include <fmtftntx.hxx>
59 // OD 2004-05-24 #i28701#
60 #include <dflyobj.hxx>
61 #include <flyfrms.hxx>
62 #include <sortedobjs.hxx>
63 
SV_IMPL_PTRARR_SORT(SwDestroyList,SwSectionFrmPtr)64 SV_IMPL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr )
65 
66 /*************************************************************************
67 |*
68 |*	SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
69 |*
70 |*	Ersterstellung		AMA 26. Nov. 97
71 |*	Letzte Aenderung	AMA 26. Nov. 97
72 |*
73 |*************************************************************************/
74 SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib ) :
75 	SwLayoutFrm( rSect.GetFmt(), pSib ),
76 	SwFlowFrm( (SwFrm&)*this ),
77 	pSection( &rSect )
78 {
79     nType = FRMC_SECTION;
80 
81 	CalcFtnAtEndFlag();
82 	CalcEndAtEndFlag();
83 }
84 
SwSectionFrm(SwSectionFrm & rSect,sal_Bool bMaster)85 SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
86 	SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
87 	SwFlowFrm( (SwFrm&)*this ),
88 	pSection( rSect.GetSection() )
89 {
90 	bFtnAtEnd = rSect.IsFtnAtEnd();
91 	bEndnAtEnd = rSect.IsEndnAtEnd();
92 	bLockJoin = sal_False;
93     nType = FRMC_SECTION;
94 
95 	PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
96 
97 	if( bMaster )
98 	{
99 		if( rSect.IsFollow() )
100 		{
101             SwSectionFrm* pMaster = rSect.FindMaster();
102 			pMaster->SetFollow( this );
103 			bIsFollow = sal_True;
104 		}
105 		else
106 			rSect.bIsFollow = sal_True;
107 		SetFollow( &rSect );
108 	}
109 	else
110 	{
111 		bIsFollow = sal_True;
112 		SetFollow( rSect.GetFollow() );
113 		rSect.SetFollow( this );
114 		if( !GetFollow() )
115 			rSect.SimpleFormat();
116 		if( !rSect.IsColLocked() )
117 			rSect.InvalidateSize();
118 	}
119 }
120 
121 // NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
122 //       frame and its insert in the layout.
Init()123 void SwSectionFrm::Init()
124 {
125     ASSERT( GetUpper(), "SwSectionFrm::Init before insertion?!" );
126     SWRECTFN( this )
127     long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
128     (Frm().*fnRect->fnSetWidth)( nWidth );
129     (Frm().*fnRect->fnSetHeight)( 0 );
130 
131     // #109700# LRSpace for sections
132     const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
133     (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
134     (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
135                                  rLRSpace.GetRight() );
136     (Prt().*fnRect->fnSetHeight)( 0 );
137 
138     const SwFmtCol &rCol = GetFmt()->GetCol();
139     if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
140 	{
141         const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
142         ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
143         if( pOld != &rCol )
144             delete pOld;
145 	}
146 }
147 
~SwSectionFrm()148 SwSectionFrm::~SwSectionFrm()
149 {
150 	if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
151 	{
152 		SwRootFrm *pRootFrm = getRootFrm();
153 		if( pRootFrm )
154 			pRootFrm->RemoveFromList( this );	//swmod 071108//swmod 071225
155 		if( IsFollow() )
156 		{
157             SwSectionFrm *pMaster = FindMaster();
158 			if( pMaster )
159 			{
160 				PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
161 				pMaster->SetFollow( GetFollow() );
162 				// Ein Master greift sich immer den Platz bis zur Unterkante seines
163 				// Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
164 				// freigeben, deshalb wird die Size des Masters invalidiert.
165 				if( !GetFollow() )
166 					pMaster->InvalidateSize();
167 			}
168 		}
169 		else if( HasFollow() )
170 		{
171 			PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
172 			GetFollow()->bIsFollow = sal_False;
173 		}
174 	}
175 }
176 
177 
178 /*************************************************************************
179 |*
180 |*	SwSectionFrm::DelEmpty()
181 |*
182 |*	Ersterstellung		AMA 17. Dec. 97
183 |*	Letzte Aenderung	AMA 17. Dec. 97
184 |*
185 |*************************************************************************/
DelEmpty(sal_Bool bRemove)186 void SwSectionFrm::DelEmpty( sal_Bool bRemove )
187 {
188 	if( IsColLocked() )
189 	{
190 		ASSERT( !bRemove, "Don't delete locked SectionFrms" );
191 		return;
192 	}
193 	SwFrm* pUp = GetUpper();
194 	if( pUp )
195     {
196         // --> OD 2005-12-01 #i27138#
197         // notify accessibility paragraphs objects about changed
198         // CONTENT_FLOWS_FROM/_TO relation.
199         // Relation CONTENT_FLOWS_FROM for current next paragraph will change
200         // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
201         {
202             ViewShell* pViewShell( getRootFrm()->GetCurrShell() );
203             if ( pViewShell && pViewShell->GetLayout() &&
204                  pViewShell->GetLayout()->IsAnyShellAccessible() )
205             {
206                 pViewShell->InvalidateAccessibleParaFlowRelation(
207                                 dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
208                                 dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
209             }
210         }
211         // <--
212         _Cut( bRemove );
213     }
214 	if( IsFollow() )
215 	{
216         SwSectionFrm *pMaster = FindMaster();
217 		pMaster->SetFollow( GetFollow() );
218 		// Ein Master greift sich immer den Platz bis zur Unterkante seines
219 		// Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
220 		// freigeben, deshalb wird die Size des Masters invalidiert.
221 		if( !GetFollow() && !pMaster->IsColLocked() )
222 			pMaster->InvalidateSize();
223 		bIsFollow = sal_False;
224 	}
225 	else if( HasFollow() )
226 		GetFollow()->bIsFollow = sal_False;
227 	pFollow = NULL;
228 	if( pUp )
229 	{
230 		Frm().Height( 0 );
231 		// Wenn wir sowieso sofort zerstoert werden, brauchen/duerfen wir
232 		// uns gar nicht erst in die Liste eintragen
233 		if( bRemove )
234 		{   // Wenn wir bereits halbtot waren vor diesem DelEmpty, so
235 			// stehen wir vermutlich auch in der Liste und muessen uns
236 			// dort austragen
237 			if( !pSection && getRootFrm() )
238 				getRootFrm()->RemoveFromList( this );
239 		}
240 		else if( getRootFrm() )
241 			getRootFrm()->InsertEmptySct( this );	//swmod 071108//swmod 071225
242 		pSection = NULL; // damit ist allerdings eine Reanimierung quasi ausgeschlossen
243 	}
244 }
245 
246 /*************************************************************************
247 |*
248 |*	SwSectionFrm::Cut()
249 |*
250 |*	Ersterstellung		AMA 02. Dec. 97
251 |*	Letzte Aenderung	AMA 02. Dec. 97
252 |*
253 |*************************************************************************/
Cut()254 void SwSectionFrm::Cut()
255 {
256 	_Cut( sal_True );
257 }
258 
_Cut(sal_Bool bRemove)259 void SwSectionFrm::_Cut( sal_Bool bRemove )
260 {
261 	ASSERT( GetUpper(), "Cut ohne Upper()." );
262 
263 	PROTOCOL( this, PROT_CUT, 0, GetUpper() )
264 
265 	SwPageFrm *pPage = FindPageFrm();
266 	InvalidatePage( pPage );
267 	SwFrm *pFrm = GetNext();
268 	SwFrm* pPrepFrm = NULL;
269 	while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
270 		pFrm = pFrm->GetNext();
271 	if( pFrm )
272 	{	//Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
273 		//berechnet der ist jetzt wo er der erste wird obsolete
274 		pFrm->_InvalidatePrt();
275 		pFrm->_InvalidatePos();
276 		if( pFrm->IsSctFrm() )
277 			pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
278 		if ( pFrm && pFrm->IsCntntFrm() )
279 		{
280 			pFrm->InvalidatePage( pPage );
281 			if( IsInFtn() && !GetIndPrev() )
282 				pPrepFrm = pFrm;
283 		}
284 	}
285 	else
286 	{
287 		InvalidateNextPos();
288 		//Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
289 		if ( 0 != (pFrm = GetPrev()) )
290 		{	pFrm->SetRetouche();
291 			pFrm->Prepare( PREP_WIDOWS_ORPHANS );
292 			if ( pFrm->IsCntntFrm() )
293 				pFrm->InvalidatePage( pPage );
294 		}
295 		//Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
296 		//er die Retouche uebernehmen.
297 		//Ausserdem kann eine Leerseite entstanden sein.
298 		else
299 		{	SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
300 			pRoot->SetSuperfluous();
301 			GetUpper()->SetCompletePaint();
302 		}
303 	}
304 	//Erst removen, dann Upper Shrinken.
305 	SwLayoutFrm *pUp = GetUpper();
306 	if( bRemove )
307 	{
308 		Remove();
309 		if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
310 			pUp->GetUpper() )
311 		{
312 			pUp->Cut();
313 			delete pUp;
314 			pUp = NULL;
315 		}
316 	}
317 	if( pPrepFrm )
318 		pPrepFrm->Prepare( PREP_FTN );
319 	if ( pUp )
320 	{
321         SWRECTFN( this );
322         SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
323         if( nFrmHeight > 0 )
324 		{
325 			if( !bRemove )
326 			{
327                 (Frm().*fnRect->fnSetHeight)( 0 );
328                 (Prt().*fnRect->fnSetHeight)( 0 );
329 			}
330             pUp->Shrink( nFrmHeight );
331 		}
332 	}
333 }
334 
335 /*************************************************************************
336 |*
337 |*	SwSectionFrm::Paste()
338 |*
339 |*	Ersterstellung		AMA 04. Dec. 97
340 |*	Letzte Aenderung	AMA 04. Dec. 97
341 |*
342 |*************************************************************************/
343 
Paste(SwFrm * pParent,SwFrm * pSibling)344 void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
345 {
346 	ASSERT( pParent, "Kein Parent fuer Paste." );
347 	ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
348 	ASSERT( pParent != this, "Bin selbst der Parent." );
349 	ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
350 	ASSERT( !GetPrev() && !GetUpper(),
351 			"Bin noch irgendwo angemeldet." );
352 
353 	PROTOCOL( this, PROT_PASTE, 0, GetUpper() )
354 
355 	//In den Baum einhaengen.
356 	SwSectionFrm* pSect = pParent->FindSctFrm();
357     // --> OD 2008-06-23 #156927#
358     // Assure that parent is not inside a table frame, which is inside the found section frame.
359     if ( pSect )
360     {
361         SwTabFrm* pTableFrm = pParent->FindTabFrm();
362         if ( pTableFrm &&
363              pSect->IsAnLower( pTableFrm ) )
364         {
365             pSect = 0;
366         }
367     }
368     // <--
369 
370     SWRECTFN( pParent )
371 	if( pSect && HasToBreak( pSect ) )
372 	{
373 		if( pParent->IsColBodyFrm() ) // handelt es sich um einen spaltigen Bereich
374 		{
375 			// Falls wir zufaellig am Ende einer Spalte stehen, muss pSibling
376 			// auf den ersten Frame der naechsten Spalte zeigen, damit
377 			// der Inhalt der naechsten Spalte von InsertGroup richtig in den
378 			// neu angelegten pSect umgehaengt wird.
379 			SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
380 			while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
381 				pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
382 			if( pSibling )
383 			{
384 				// Schlimmer noch: alle folgenden Spalteninhalte muessen
385 				// an die pSibling-Kette angehaengt werden, damit sie
386 				// mitgenommen werden.
387 				SwFrm *pTmp = pSibling;
388 				while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
389 				{
390 					while ( pTmp->GetNext() )
391 						pTmp = pTmp->GetNext();
392 					SwFrm* pSave = ::SaveCntnt( pCol );
393                     ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
394                 }
395 			}
396 		}
397 		pParent = pSect;
398 		pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection(), pParent );
399 		// Wenn pParent in zwei Teile zerlegt wird, so muss sein Follow am
400 		// neuen, zweiten Teil angebracht werden.
401 		pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
402 		((SwSectionFrm*)pParent)->SetFollow( NULL );
403 		if( pSect->GetFollow() )
404 			pParent->_InvalidateSize();
405 
406 		InsertGroupBefore( pParent, pSibling, pSect );
407         pSect->Init();
408         (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True);
409 		if( !((SwLayoutFrm*)pParent)->Lower() )
410 		{
411 			SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False );
412 			pParent = this;
413 		}
414 	}
415 	else
416 		InsertGroupBefore( pParent, pSibling, NULL );
417 
418 	_InvalidateAll();
419 	SwPageFrm *pPage = FindPageFrm();
420 	InvalidatePage( pPage );
421 
422 	if ( pSibling )
423 	{
424 		pSibling->_InvalidatePos();
425 		pSibling->_InvalidatePrt();
426 		if ( pSibling->IsCntntFrm() )
427 			pSibling->InvalidatePage( pPage );
428 	}
429 
430     SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
431     if( nFrmHeight )
432         pParent->Grow( nFrmHeight );
433 
434 	if ( GetPrev() )
435 	{
436 		if ( !IsFollow() )
437 		{
438 			GetPrev()->InvalidateSize();
439 			if ( GetPrev()->IsCntntFrm() )
440 				GetPrev()->InvalidatePage( pPage );
441 		}
442 	}
443 }
444 
445 
446 /*************************************************************************
447 |*
448 |*	SwSectionFrm::HasToBreak()
449 |*
450 |*  Hier wird entschieden, ob der this-SectionFrm den uebergebenen
451 |*  (Section)Frm aufbrechen soll oder nicht.
452 |*  Zunaechst werden uebergeordnete Bereiche immer aufgebrochen,
453 |*  spaeter koennte man es einstellbar machen.
454 |*
455 |*	Ersterstellung		AMA 12. Dec. 97
456 |*	Letzte Aenderung	AMA 12. Dec. 97
457 |*
458 |*************************************************************************/
459 
HasToBreak(const SwFrm * pFrm) const460 sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
461 {
462 	if( !pFrm->IsSctFrm() )
463 		return sal_False;
464 
465 	SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
466 //	if( !pTmp->GetSect().GetValue() )
467 //		return sal_False;
468 
469 	const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
470 	do
471 	{
472 		pTmp = pTmp->GetParent();
473 		if( !pTmp )
474 			return sal_False;
475 		if( pTmp == pOtherFmt )
476 			return sal_True;
477 	} while( sal_True ); //	( pTmp->GetSect().GetValue() );
478 }
479 
480 /*************************************************************************
481 |*
482 |*	SwSectionFrm::MergeNext()
483 |*
484 |*	Ersterstellung		AMA 04. Dec. 97
485 |*	Letzte Aenderung	AMA 04. Dec. 97
486 |*
487 |*  Verschmilzt zwei SectionFrms, falls es sich um den
488 |*  gleichen Bereich handelt.
489 |*  Notwendig kann dies sein, wenn ein (Unter-)Bereich geloescht wird, der
490 |*  einen anderen in zwei Teile zerlegt hatte.
491 |*
492 |*************************************************************************/
493 
MergeNext(SwSectionFrm * pNxt)494 void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
495 {
496 	if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
497 	{
498 		PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
499 
500 		SwFrm* pTmp = ::SaveCntnt( pNxt );
501 		if( pTmp )
502 		{
503 			SwFrm* pLast = Lower();
504 			SwLayoutFrm* pLay = this;
505 			if( pLast )
506 			{
507 				while( pLast->GetNext() )
508 					pLast = pLast->GetNext();
509 				if( pLast->IsColumnFrm() )
510 				{   // Spalten jetzt mit BodyFrm
511 					pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
512 					pLast = pLay->Lower();
513 					if( pLast )
514 						while( pLast->GetNext() )
515 							pLast = pLast->GetNext();
516 				}
517 			}
518             ::RestoreCntnt( pTmp, pLay, pLast, true );
519         }
520 		SetFollow( pNxt->GetFollow() );
521 		pNxt->SetFollow( NULL );
522 		pNxt->bIsFollow = sal_False;
523 		pNxt->Cut();
524 		delete pNxt;
525 		InvalidateSize();
526 	}
527 }
528 
529 /*************************************************************************
530 |*
531 |*	SwSectionFrm::SplitSect()
532 |*
533 |*	Ersterstellung		AMA 29. Apr. 99
534 |*	Letzte Aenderung	AMA 29. Apr. 99
535 |*
536 |*  Zerteilt einen SectionFrm in zwei Teile, der zweite Teil beginnt mit dem
537 |*  uebergebenen Frame.
538 |*  Benoetigt wird dies beim Einfuegen eines inneren Bereichs, weil innerhalb
539 |*  von Rahmen oder Tabellenzellen das MoveFwd nicht den erwuenschten Effekt
540 |*  haben kann.
541 |*
542 |*************************************************************************/
543 
SplitSect(SwFrm * pFrm,sal_Bool bApres)544 sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
545 {
546 	ASSERT( pFrm, "SplitSect: Why?" );
547 	SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
548 	if( !pOther )
549 		return sal_False;
550 	SwSectionFrm* pSect = pOther->FindSctFrm();
551     if( pSect != this )
552 		return sal_False;
553 	// Den Inhalt zur Seite stellen
554 	SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
555 	ASSERT( pSav, "SplitSect: What's on?" );
556 	if( pSav ) // Robust
557 	{	// Einen neuen SctFrm anlegen, nicht als Follow/Master
558         SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
559 		pNew->InsertBehind( pSect->GetUpper(), pSect );
560         pNew->Init();
561         SWRECTFN( this )
562         (pNew->*fnRect->fnMakePos)( NULL, pSect, sal_True );
563         // OD 25.03.2003 #108339# - restore content:
564         // determine layout frame for restoring content after the initialization
565         // of the section frame. In the section initialization the columns are
566         // created.
567         {
568             SwLayoutFrm* pLay = pNew;
569             // Search for last layout frame, e.g. for columned sections.
570             while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
571                 pLay = (SwLayoutFrm*)pLay->Lower();
572             ::RestoreCntnt( pSav, pLay, NULL, true );
573         }
574         _InvalidateSize();
575         if( HasFollow() )
576         {
577             pNew->SetFollow( GetFollow() );
578             SetFollow( NULL );
579         }
580 		return sal_True;
581 	}
582 	return sal_False;
583 }
584 
585 /*************************************************************************
586 |*
587 |*	SwSectionFrm::MoveCntntAndDelete()
588 |*
589 |*	Ersterstellung		AMA 29. Jan 99
590 |*	Letzte Aenderung	AMA 29. Jan 99
591 |*
592 |*  MoveCntnt wird zur Zerstoerung eines SectionFrms wg. Aufhebung oder
593 |*  Verstecken des Bereichs gerufen, um den Inhalt umzuhaengen.
594 |*  Wenn der SectionFrm keinen anderen aufbrach, so wird der Inhalt in
595 |*  den Upper bewegt. Anderfalls wird der Inhalt in den anderen SectionFrm
596 |*  umgehaengt, dieser muss ggf. gemergt werden.
597 |*
598 |*************************************************************************/
599 // Wenn ein mehrspaltiger Bereich aufgehoben wird, muessen die ContentFrms
600 // invalidiert werden
601 
lcl_InvalidateInfFlags(SwFrm * pFrm,sal_Bool bInva)602 void lcl_InvalidateInfFlags( SwFrm* pFrm, sal_Bool bInva )
603 {
604 	while ( pFrm )
605 	{
606 		pFrm->InvalidateInfFlags();
607 		if( bInva )
608 		{
609 			pFrm->_InvalidatePos();
610 			pFrm->_InvalidateSize();
611 			pFrm->_InvalidatePrt();
612 		}
613 		if( pFrm->IsLayoutFrm() )
614 			lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False );
615 		pFrm = pFrm->GetNext();
616 	}
617 }
618 
619 
620 //
621 // Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
622 //
lcl_GetNextCntntFrm(const SwLayoutFrm * pLay,bool bFwd)623 SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
624 {
625     if ( bFwd )
626     {
627         if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
628             return (SwCntntFrm*)pLay->GetNext();
629     }
630     else
631     {
632         if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
633             return (SwCntntFrm*)pLay->GetPrev();
634     }
635 
636     // #100926#
637     const SwFrm* pFrm = pLay;
638     SwCntntFrm *pCntntFrm = 0;
639     sal_Bool bGoingUp = sal_True;
640     do {
641         const SwFrm *p = 0;
642         sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
643 
644         bGoingDown = !bGoingUp && ( 0 !=  ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
645         if ( !bGoingDown )
646         {
647             bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
648                                           ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
649                                           ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
650             if ( !bGoingFwdOrBwd )
651             {
652                 bGoingUp = (0 != (p = pFrm->GetUpper() ) );
653                 if ( !bGoingUp )
654                     return 0;
655             }
656         }
657 
658         bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
659 
660         if( !bFwd && bGoingDown && p )
661             while ( p->GetNext() )
662                 p = p->GetNext();
663 
664         pFrm = p;
665     } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
666 
667     return pCntntFrm;
668 }
669 
670 #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
671 					? pLayFrm->GetNextLayoutLeaf() \
672 					: pLayFrm )
673 
MoveCntntAndDelete(SwSectionFrm * pDel,sal_Bool bSave)674 void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
675 {
676 	sal_Bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
677 	SwFrm* pPrv = pDel->GetPrev();
678 	SwLayoutFrm* pUp = pDel->GetUpper();
679     // OD 27.03.2003 #i12711# - initialize local pointer variables.
680     SwSectionFrm* pPrvSct = NULL;
681     SwSectionFrm* pNxtSct = NULL;
682     SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
683 	if( pDel->IsInTab() && pParent )
684 	{
685 		SwTabFrm *pTab = pDel->FindTabFrm();
686 		// Wenn wir innerhalb einer Tabelle liegen, koennen wir nur Bereiche
687 		// aufgebrochen haben, die ebenfalls innerhalb liegen, nicht etwa
688 		// einen Bereich, der die gesamte Tabelle umfasst.
689 		if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
690 			pParent = NULL;
691 	}
692 	// Wenn unser Format einen Parent besitzt, so haben wir vermutlich
693 	// einen anderen SectionFrm aufgebrochen, dies muss geprueft werden,
694 	// dazu besorgen wir uns zunaechst den vorhergehende und den nach-
695 	// folgenden CntntFrm, mal sehen, ob diese in SectionFrms liegen.
696     // OD 27.03.2003 #i12711# - check, if previous and next section belonging
697     // together and can be joined, *not* only if deleted section contains content.
698     if ( pParent )
699     {
700         SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
701         pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
702         SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
703         pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
704     }
705     else
706     {
707         pParent = NULL;
708         pPrvSct = pNxtSct = NULL;
709     }
710 
711 	// Jetzt wird der Inhalt beseite gestellt und der Frame zerstoert
712 	SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
713 	sal_Bool bOldFtn = sal_True;
714 	if( pSave && pUp->IsFtnFrm() )
715 	{
716 		bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
717 		((SwFtnFrm*)pUp)->ColLock();
718 	}
719 	pDel->DelEmpty( sal_True );
720 	delete pDel;
721 	if( pParent )
722 	{	// Hier wird die geeignete Einfuegeposition gesucht
723 		if( pNxtSct && pNxtSct->GetFmt() == pParent )
724 		{   // Hier koennen wir uns am Anfang einfuegen
725 			pUp = FIRSTLEAF( pNxtSct );
726 			pPrv = NULL;
727 			if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
728 				pPrvSct = NULL; // damit nicht gemergt wird
729 		}
730 		else if( pPrvSct && pPrvSct->GetFmt() == pParent )
731 		{   // Wunderbar, hier koennen wir uns am Ende einfuegen
732 			pUp = pPrvSct;
733 			if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
734 			{
735                 pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
736                 // Der Body der letzten Spalte
737                 pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
738 			}
739             // damit hinter dem letzten eingefuegt wird
740             pPrv = pUp->GetLastLower();
741             pPrvSct = NULL; // damit nicht gemergt wird
742 		}
743 		else
744 		{
745 			if( pSave )
746 			{	// Folgende Situationen: Vor und hinter dem zu loeschenden Bereich
747 				// ist entweder die Bereichsgrenze des umfassenden Bereichs oder
748 				// es schliesst ein anderer (Geschwister-)Bereich direkt an, der
749 				// vom gleichen Parent abgeleitet ist.
750 				// Dann gibt es (noch) keinen Teil unseres Parents, der den Inhalt
751 				// aufnehmen kann,also bauen wir ihn uns.
752                 pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp );
753 				pPrvSct->InsertBehind( pUp, pPrv );
754                 pPrvSct->Init();
755                 SWRECTFN( pUp )
756                 (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True );
757 				pUp = FIRSTLEAF( pPrvSct );
758 				pPrv = NULL;
759 			}
760 			pPrvSct = NULL; // damit nicht gemergt wird
761 		}
762 	}
763 	// Der Inhalt wird eingefuegt..
764 	if( pSave )
765 	{
766 		lcl_InvalidateInfFlags( pSave, bSize );
767         ::RestoreCntnt( pSave, pUp, pPrv, true );
768         pUp->FindPageFrm()->InvalidateCntnt();
769 		if( !bOldFtn )
770 			((SwFtnFrm*)pUp)->ColUnlock();
771 	}
772 	// jetzt koennen eventuell zwei Teile des uebergeordneten Bereich verschmelzen
773 	if( pPrvSct && !pPrvSct->IsJoinLocked() )
774 	{
775 		ASSERT( pNxtSct, "MoveCntnt: No Merge" );
776 		pPrvSct->MergeNext( pNxtSct );
777 	}
778 }
779 
MakeAll()780 void SwSectionFrm::MakeAll()
781 {
782 	if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
783 		return;
784 	if( !pSection ) // Durch DelEmpty
785 	{
786 		ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
787 		if( !bValidPos )
788 		{
789             if( GetUpper() )
790             {
791                 SWRECTFN( GetUpper() )
792                 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
793 			}
794         }
795 		bValidSize = bValidPos = bValidPrtArea = sal_True;
796 		return;
797 	}
798 	LockJoin();	//Ich lass mich nicht unterwegs vernichten.
799 
800 	while( GetNext() && GetNext() == GetFollow() )
801 	{
802 		const SwFrm* pFoll = GetFollow();
803 		MergeNext( (SwSectionFrm*)GetNext() );
804 		if( pFoll == GetFollow() )
805 			break;
806 	}
807 
808     // OD 2004-03-15 #116561# - In online layout join the follows, if section
809     // can grow.
810     const ViewShell *pSh = getRootFrm()->GetCurrShell();
811     if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
812          ( Grow( LONG_MAX, true ) > 0 ) )
813     {
814         while( GetFollow() )
815         {
816             const SwFrm* pFoll = GetFollow();
817             MergeNext( GetFollow() );
818             if( pFoll == GetFollow() )
819                 break;
820         }
821     }
822 
823 	// Ein Bereich mit Follow nimmt allen Platz bis zur Unterkante des Uppers
824 	// in Anspruch. Bewegt er sich, so kann seine Groesse zu- oder abnehmen...
825 	if( !bValidPos && ToMaximize( sal_False ) )
826 		bValidSize = sal_False;
827 
828 #if OSL_DEBUG_LEVEL > 1
829 	const SwFmtCol &rCol = GetFmt()->GetCol();
830     (void)rCol;
831 #endif
832 	SwLayoutFrm::MakeAll();
833 	UnlockJoin();
834 	if( pSection && IsSuperfluous() )
835 		DelEmpty( sal_False );
836 }
837 
ShouldBwdMoved(SwLayoutFrm *,sal_Bool,sal_Bool &)838 sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & )
839 {
840 	ASSERT( sal_False, "Hups, wo ist meine Tarnkappe?" );
841 	return sal_False;
842 }
843 
_GetEndSectFmt() const844 const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
845 {
846 	const SwSectionFmt *pFmt = pSection->GetFmt();
847 	while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
848 	{
849 		if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
850 			pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
851 		else
852 			return NULL;
853 	}
854 	return pFmt;
855 }
856 
lcl_FindCntntFrm(SwCntntFrm * & rpCntntFrm,SwFtnFrm * & rpFtnFrm,SwFrm * pFrm,sal_Bool & rbChkFtn)857 void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
858 	SwFrm* pFrm, sal_Bool &rbChkFtn )
859 {
860 	if( pFrm )
861 	{
862 		while( pFrm->GetNext() )
863 			pFrm = pFrm->GetNext();
864 		while( !rpCntntFrm && pFrm )
865 		{
866 			if( pFrm->IsCntntFrm() )
867 				rpCntntFrm = (SwCntntFrm*)pFrm;
868 			else if( pFrm->IsLayoutFrm() )
869 			{
870 				if( pFrm->IsFtnFrm() )
871 				{
872 					if( rbChkFtn )
873 					{
874 						rpFtnFrm = (SwFtnFrm*)pFrm;
875 						rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
876 					}
877 				}
878 				else
879 					lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
880 						((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
881 			}
882 			pFrm = pFrm->GetPrev();
883 		}
884 	}
885 }
886 
FindLastCntnt(sal_uInt8 nMode)887 SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
888 {
889 	SwCntntFrm *pRet = NULL;
890 	SwFtnFrm *pFtnFrm = NULL;
891 	SwSectionFrm *pSect = this;
892 	if( nMode )
893 	{
894 		const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
895 			  					   pSection->GetFmt();
896 		do {
897 			while( pSect->HasFollow() )
898 				pSect = pSect->GetFollow();
899 			SwFrm* pTmp = pSect->FindNext();
900 			while( pTmp && pTmp->IsSctFrm() &&
901 				   !((SwSectionFrm*)pTmp)->GetSection() )
902 				pTmp = pTmp->FindNext();
903 			if( pTmp && pTmp->IsSctFrm() &&
904 				((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
905 				pSect = (SwSectionFrm*)pTmp;
906 			else
907 				break;
908 		} while( sal_True );
909 	}
910 	sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
911 	do
912 	{
913 		lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
914 		if( pRet || !pSect->IsFollow() || !nMode ||
915 			( FINDMODE_MYLAST == nMode && this == pSect ) )
916 			break;
917         pSect = pSect->FindMaster();
918 	} while( pSect );
919 	if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
920 		pRet = pFtnFrm->ContainsCntnt();
921 	return pRet;
922 }
923 
CalcMinDiff(SwTwips & rMinDiff) const924 sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
925 {
926 	if( ToMaximize( sal_True ) )
927 	{
928         SWRECTFN( this )
929         rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
930         rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
931         return sal_True;
932 	}
933 	return sal_False;
934 }
935 
936 /*************************************************************************
937  *
938  * 	SwSectionFrm::CollectEndnotes(  )
939  *
940  *	Ersterstellung		AMA 03. Nov 99
941  *	Letzte Aenderung	AMA 03. Nov 99
942  *
943  *  CollectEndnotes looks for endnotes in the sectionfrm and his follows,
944  *  the endnotes will cut off the layout and put into the array.
945  *  If the first endnote is not a master-SwFtnFrm, the whole sectionfrm
946  *  contains only endnotes and it is not necessary to collect them.
947  *
948  *************************************************************************/
949 
lcl_FindEndnote(SwSectionFrm * & rpSect,sal_Bool & rbEmpty,SwLayouter * pLayouter)950 SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, sal_Bool &rbEmpty,
951 	SwLayouter *pLayouter )
952 {
953 	// if rEmpty is set, the rpSect is already searched
954 	SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
955 	while( pSect )
956 	{
957        ASSERT( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
958                 "InsertEndnotes: Where's my column?" );
959 
960         // i73332: Columned section in endnote
961         SwColumnFrm* pCol = 0;
962         if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
963             pCol = (SwColumnFrm*)pSect->Lower();
964 
965         while( pCol ) // check all columns
966 		{
967 			SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
968 			if( pFtnCont )
969 			{
970 				SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
971 				while( pRet ) // look for endnotes
972 				{
973 					if( pRet->GetAttr()->GetFtn().IsEndNote() )
974 					{
975 						if( pRet->GetMaster() )
976 						{
977 							if( pLayouter )
978 								pLayouter->CollectEndnote( pRet );
979 							else
980 								return 0;
981 						}
982 						else
983 							return pRet; // Found
984 					}
985 					pRet = (SwFtnFrm*)pRet->GetNext();
986 				}
987 			}
988 			pCol = (SwColumnFrm*)pCol->GetNext();
989         }
990 		rpSect = pSect;
991 		pSect = pLayouter ? pSect->GetFollow() : NULL;
992 		rbEmpty = sal_True;
993 	}
994 	return NULL;
995 }
996 
lcl_ColumnRefresh(SwSectionFrm * pSect,sal_Bool bFollow)997 void lcl_ColumnRefresh( SwSectionFrm* pSect, sal_Bool bFollow )
998 {
999 	while( pSect )
1000 	{
1001 		sal_Bool bOldLock = pSect->IsColLocked();
1002 		pSect->ColLock();
1003 		if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
1004 		{
1005 			SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
1006 			do
1007 			{	pCol->_InvalidateSize();
1008 				pCol->_InvalidatePos();
1009 				((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
1010 				pCol->Calc();   // calculation of column and
1011 				((SwLayoutFrm*)pCol)->Lower()->Calc();  // body
1012 				pCol = (SwColumnFrm*)pCol->GetNext();
1013 			} while ( pCol );
1014 		}
1015 		if( !bOldLock )
1016 			pSect->ColUnlock();
1017 		if( bFollow )
1018 			pSect = pSect->GetFollow();
1019 		else
1020 			pSect = NULL;
1021 	}
1022 }
1023 
CollectEndnotes(SwLayouter * pLayouter)1024 void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
1025 {
1026 	ASSERT( IsColLocked(), "CollectEndnotes: You love the risk?" );
1027     // i73332: Section in footnode does not have columns!
1028     ASSERT( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );
1029 
1030 	SwSectionFrm* pSect = this;
1031 	SwFtnFrm* pFtn;
1032 	sal_Bool bEmpty = sal_False;
1033 	// pSect is the last sectionfrm without endnotes or the this-pointer
1034 	// the first sectionfrm with endnotes may be destroyed, when the endnotes
1035 	// is cutted
1036 	while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
1037 		pLayouter->CollectEndnote( pFtn );
1038 	if( pLayouter->HasEndnotes() )
1039 		lcl_ColumnRefresh( this, sal_True );
1040 }
1041 
1042 /*************************************************************************
1043 |*
1044 |*	SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1045 |*
1046 |*	Beschreibung:		Passt die Groesse an die Umgebung an.
1047 |*  	Wer einen Follow oder Fussnoten besitzt, soll bis zur Unterkante
1048 |*      des Uppers gehen (bMaximize).
1049 |*		Niemand darf ueber den Upper hinausgehen, ggf. darf man versuchen (bGrow)
1050 |*		seinen Upper zu growen.
1051 |*      Wenn die Groesse veraendert werden musste, wird der Inhalt kalkuliert.
1052 |*
1053 |*************************************************************************/
1054 
1055 /// OD 18.09.2002 #100522#
1056 /// perform calculation of content, only if height has changed.
_CheckClipping(sal_Bool bGrow,sal_Bool bMaximize)1057 void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1058 {
1059     SWRECTFN( this )
1060     long nDiff;
1061     SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1062 	if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
1063 				   !FindFlyFrm()->IsLocked() ) )
1064 	{
1065         nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1066         if( !bMaximize )
1067             nDiff += Undersize();
1068         if( nDiff > 0 )
1069         {
1070             long nAdd = GetUpper()->Grow( nDiff );
1071             if( bVert && !bRev )
1072                 nDeadLine -= nAdd;
1073             else
1074                 nDeadLine += nAdd;
1075         }
1076 	}
1077     nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1078     SetUndersized( !bMaximize && nDiff >= 0 );
1079     const bool bCalc = ( IsUndersized() || bMaximize ) &&
1080                        ( nDiff ||
1081                          (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
1082     // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
1083     // that a calculation has to be done beside the value of <bCalc>.
1084     bool bExtraCalc = false;
1085     if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
1086 	{
1087 		SwSectionFrm *pSect = this;
1088 		sal_Bool bEmpty = sal_False;
1089 		SwLayoutFrm* pFtn = IsEndnAtEnd() ?
1090 			lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
1091 		if( pFtn )
1092 		{
1093 			pFtn = pFtn->FindFtnBossFrm();
1094 			SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
1095             // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
1096             if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
1097                 bExtraCalc = true;
1098 		}
1099 		else if( GetFollow() && !GetFollow()->ContainsAny() )
1100             bExtraCalc = true;
1101 	}
1102     if ( bCalc || bExtraCalc )
1103 	{
1104         nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
1105         if( nDiff < 0 )
1106         {
1107             nDiff = 0;
1108             nDeadLine = (Frm().*fnRect->fnGetTop)();
1109         }
1110         const Size aOldSz( Prt().SSize() );
1111         long nTop = (this->*fnRect->fnGetTopMargin)();
1112         (Frm().*fnRect->fnSetBottom)( nDeadLine );
1113         nDiff = (Frm().*fnRect->fnGetHeight)();
1114         if( nTop > nDiff )
1115             nTop = nDiff;
1116         (this->*fnRect->fnSetYMargins)( nTop, 0 );
1117 
1118         // OD 18.09.2002 #100522#
1119         // Determine, if height has changed.
1120         // Note: In vertical layout the height equals the width value.
1121         bool bHeightChanged = bVert ?
1122                             (aOldSz.Width() != Prt().Width()) :
1123                             (aOldSz.Height() != Prt().Height());
1124         // Wir haben zu guter Letzt noch einmal die Hoehe geaendert,
1125 		// dann wird das innere Layout (Columns) kalkuliert und
1126 		// der Inhalt ebenfalls.
1127         // OD 18.09.2002 #100522#
1128         // calculate content, only if height has changed.
1129         // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
1130         // If an endnote has an incorrect position or a follow section contains
1131         // no content except footnotes/endnotes, the content has also been calculated.
1132         if ( ( bHeightChanged || bExtraCalc ) && Lower() )
1133 		{
1134 			if( Lower()->IsColumnFrm() )
1135 			{
1136 				lcl_ColumnRefresh( this, sal_False );
1137                 ::CalcCntnt( this );
1138 			}
1139 			else
1140 			{
1141 				ChgLowersProp( aOldSz );
1142 				if( !bMaximize && !IsCntntLocked() )
1143 					::CalcCntnt( this );
1144 			}
1145 		}
1146 	}
1147 }
1148 
SimpleFormat()1149 void SwSectionFrm::SimpleFormat()
1150 {
1151 	if ( IsJoinLocked() || IsColLocked() )
1152 		return;
1153 	// ASSERT( pFollow, "SimpleFormat: Follow required" );
1154 	LockJoin();
1155     SWRECTFN( this )
1156     if( GetPrev() || GetUpper() )
1157 	{
1158         // --> OD 2009-09-28 #b6882166#
1159         // assure notifications on position changes.
1160         const SwLayNotify aNotify( this );
1161         // <--
1162         (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
1163 		bValidPos = sal_True;
1164 	}
1165     SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1166     // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
1167     // order to get calculated lowers, not only if there space left in its upper.
1168     if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
1169 	{
1170         (Frm().*fnRect->fnSetBottom)( nDeadLine );
1171         long nHeight = (Frm().*fnRect->fnGetHeight)();
1172         long nTop = CalcUpperSpace();
1173         if( nTop > nHeight )
1174             nTop = nHeight;
1175         (this->*fnRect->fnSetYMargins)( nTop, 0 );
1176 	}
1177     lcl_ColumnRefresh( this, sal_False );
1178 	UnlockJoin();
1179 }
1180 
1181 // --> OD 2005-01-11 #i40147# - helper class to perform extra section format
1182 // to position anchored objects and to keep the position of whose objects locked.
1183 class ExtraFormatToPositionObjs
1184 {
1185     private:
1186         SwSectionFrm* mpSectFrm;
1187         bool mbExtraFormatPerformed;
1188 
1189     public:
ExtraFormatToPositionObjs(SwSectionFrm & _rSectFrm)1190         ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
1191             : mpSectFrm( &_rSectFrm ),
1192               mbExtraFormatPerformed( false )
1193         {}
1194 
~ExtraFormatToPositionObjs()1195         ~ExtraFormatToPositionObjs()
1196         {
1197             if ( mbExtraFormatPerformed )
1198             {
1199                 // release keep locked position of lower floating screen objects
1200                 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1201                 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1202                 if ( pObjs )
1203                 {
1204                     sal_uInt32 i = 0;
1205                     for ( i = 0; i < pObjs->Count(); ++i )
1206                     {
1207                         SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1208 
1209                         if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1210                         {
1211                             pAnchoredObj->SetKeepPosLocked( false );
1212                         }
1213                     }
1214                 }
1215             }
1216         }
1217 
1218         // --> OD 2008-06-20 #i81555#
InitObjs(SwFrm & rFrm)1219         void InitObjs( SwFrm& rFrm )
1220         {
1221             SwSortedObjs* pObjs = rFrm.GetDrawObjs();
1222             if ( pObjs )
1223             {
1224                 sal_uInt32 i = 0;
1225                 for ( i = 0; i < pObjs->Count(); ++i )
1226                 {
1227                     SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1228 
1229                     pAnchoredObj->UnlockPosition();
1230                     pAnchoredObj->SetClearedEnvironment( false );
1231                 }
1232             }
1233             SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
1234             if ( pLayoutFrm != 0 )
1235             {
1236                 SwFrm* pLowerFrm = pLayoutFrm->GetLower();
1237                 while ( pLowerFrm != 0 )
1238                 {
1239                     InitObjs( *pLowerFrm );
1240 
1241                     pLowerFrm = pLowerFrm->GetNext();
1242                 }
1243             }
1244         }
1245         // <--
1246 
FormatSectionToPositionObjs()1247         void FormatSectionToPositionObjs()
1248         {
1249             // perform extra format for multi-columned section.
1250             if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
1251                  mpSectFrm->Lower()->GetNext() )
1252             {
1253                 // grow section till bottom of printing area of upper frame
1254                 SWRECTFN( mpSectFrm );
1255                 SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
1256                 Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
1257                 SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
1258                                         (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
1259                 (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
1260                 (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
1261                 // --> OD 2006-05-08 #i59789#
1262                 // suppress formatting, if printing area of section is too narrow
1263                 if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
1264                 {
1265                     return;
1266                 }
1267                 // <--
1268                 mpSectFrm->ChgLowersProp( aOldSectPrtSize );
1269 
1270                 // format column frames and its body and footnote container
1271                 SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
1272                 while ( pColFrm )
1273                 {
1274                     pColFrm->Calc();
1275                     pColFrm->Lower()->Calc();
1276                     if ( pColFrm->Lower()->GetNext() )
1277                     {
1278                         pColFrm->Lower()->GetNext()->Calc();
1279                     }
1280 
1281                     pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
1282                 }
1283 
1284                 // unlock position of lower floating screen objects for the extra format
1285                 // --> OD 2008-06-20 #i81555#
1286                 // Section frame can already have changed the page and its content
1287                 // can still be on the former page.
1288                 // Thus, initialize objects via lower-relationship
1289                 InitObjs( *mpSectFrm );
1290                 // <--
1291 
1292                 // format content - first with collecting its foot-/endnotes before content
1293                 // format, second without collecting its foot-/endnotes.
1294                 ::CalcCntnt( mpSectFrm );
1295                 ::CalcCntnt( mpSectFrm, true );
1296 
1297                 // keep locked position of lower floating screen objects
1298                 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1299                 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1300                 if ( pObjs )
1301                 {
1302                     sal_uInt32 i = 0;
1303                     for ( i = 0; i < pObjs->Count(); ++i )
1304                     {
1305                         SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1306 
1307                         if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1308                         {
1309                             pAnchoredObj->SetKeepPosLocked( true );
1310                         }
1311                     }
1312                 }
1313 
1314                 mbExtraFormatPerformed = true;
1315             }
1316         }
1317 };
1318 
1319 /*************************************************************************
1320 |*
1321 |*	SwSectionFrm::Format()
1322 |*
1323 |*	Beschreibung:		"Formatiert" den Frame; Frm und PrtArea.
1324 |*	Ersterstellung		AMA 03. Dec. 97
1325 |* 	Letzte Aenderung	MA 09. Oct. 98
1326 |*
1327 |*************************************************************************/
1328 
Format(const SwBorderAttrs * pAttr)1329 void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
1330 {
1331 	if( !pSection ) // Durch DelEmpty
1332 	{
1333 		ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
1334 		bValidSize = bValidPos = bValidPrtArea = sal_True;
1335 		return;
1336 	}
1337     SWRECTFN( this )
1338 	if ( !bValidPrtArea )
1339 	{
1340 		PROTOCOL( this, PROT_PRTAREA, 0, 0 )
1341 		bValidPrtArea = sal_True;
1342 		SwTwips nUpper = CalcUpperSpace();
1343 
1344         // #109700# LRSpace for sections
1345         const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1346         (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
1347 
1348         if( nUpper != (this->*fnRect->fnGetTopMargin)() )
1349 		{
1350 			bValidSize = sal_False;
1351 			SwFrm* pOwn = ContainsAny();
1352 			if( pOwn )
1353 				pOwn->_InvalidatePos();
1354 		}
1355         (this->*fnRect->fnSetYMargins)( nUpper, 0 );
1356 	}
1357 
1358 	if ( !bValidSize )
1359 	{
1360 		PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
1361         const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
1362 		sal_Bool bOldLock = IsColLocked();
1363 		ColLock();
1364 
1365 		bValidSize = sal_True;
1366 
1367         //die Groesse wird nur dann vom Inhalt bestimmt, wenn der SectFrm
1368 		//keinen Follow hat. Anderfalls fuellt er immer den Upper bis
1369 		//zur Unterkante aus. Fuer den Textfluss ist nicht er, sondern sein
1370 		//Inhalt selbst verantwortlich.
1371 		sal_Bool bMaximize = ToMaximize( sal_False );
1372 
1373         // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
1374         // on object positioning, an extra formatting has to be performed
1375         // to determine the correct positions the floating screen objects.
1376         // --> OD 2005-01-11 #i40147#
1377         // use new helper class <ExtraFormatToPositionObjs>.
1378         // This class additionally keep the locked position of the objects
1379         // and releases this position lock keeping on destruction.
1380         ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
1381         if ( !bMaximize &&
1382              GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
1383              !GetFmt()->GetBalancedColumns().GetValue() )
1384         {
1385             aExtraFormatToPosObjs.FormatSectionToPositionObjs();
1386         }
1387         // <--
1388 
1389         // Column widths have to be adjusted before calling _CheckClipping.
1390         // _CheckClipping can cause the formatting of the lower frames
1391         // which still have a width of 0.
1392         const sal_Bool bHasColumns = Lower() && Lower()->IsColumnFrm();
1393         if ( bHasColumns && Lower()->GetNext() )
1394             AdjustColumns( 0, sal_False );
1395 
1396 		if( GetUpper() )
1397 		{
1398             long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1399             (aFrm.*fnRect->fnSetWidth)( nWidth );
1400 
1401             // #109700# LRSpace for sections
1402             const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1403             (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
1404                                         rLRSpace.GetRight() );
1405 
1406             // OD 15.10.2002 #103517# - allow grow in online layout
1407             // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
1408             // method <_CheckClipping(..)>.
1409             const ViewShell *pSh = getRootFrm()->GetCurrShell();
1410             _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
1411 			bMaximize = ToMaximize( sal_False );
1412 			bValidSize = sal_True;
1413 		}
1414 
1415         //Breite der Spalten pruefen und ggf. einstellen.
1416         if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
1417             ((SwColumnFrm*)Lower())->Lower()->Calc();
1418 
1419 		if ( !bMaximize )
1420 		{
1421             SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
1422 			SwFrm *pFrm = pLower;
1423 			if( pFrm )
1424 			{
1425 				if( pFrm->IsColumnFrm() && pFrm->GetNext() )
1426 				{
1427                     // --> OD 2006-05-08 #i61435#
1428                     // suppress formatting, if upper frame has height <= 0
1429                     if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
1430                     {
1431                         FormatWidthCols( *pAttr, nRemaining, MINLAY );
1432                     }
1433                     // <--
1434                     // --> OD 2006-01-04 #126020# - adjust check for empty section
1435                     // --> OD 2006-02-01 #130797# - correct fix #126020#
1436                     while( HasFollow() && !GetFollow()->ContainsCntnt() &&
1437                            !GetFollow()->ContainsAny( true ) )
1438                     // <--
1439 					{
1440 						SwFrm* pOld = GetFollow();
1441 						GetFollow()->DelEmpty( sal_False );
1442 						if( pOld == GetFollow() )
1443 							break;
1444 					}
1445 					bMaximize = ToMaximize( sal_False );
1446                     nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
1447 				}
1448 				else
1449 				{
1450 					if( pFrm->IsColumnFrm() )
1451 					{
1452 						pFrm->Calc();
1453 						pFrm = ((SwColumnFrm*)pFrm)->Lower();
1454 						pFrm->Calc();
1455 						pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1456 						CalcFtnCntnt();
1457 					}
1458 					// Wenn wir in einem spaltigen Rahmen stehen und dieser
1459 					// gerade im FormatWidthCols ein CalcCntnt ruft, muss
1460 					// unser Inhalt ggf. kalkuliert werden.
1461 					if( pFrm && !pFrm->IsValid() && IsInFly() &&
1462 						FindFlyFrm()->IsColLocked() )
1463 						::CalcCntnt( this );
1464 					nRemaining += InnerHeight();
1465 					bMaximize = HasFollow();
1466 				}
1467 			}
1468 
1469             SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
1470 			if( nDiff < 0)
1471 			{
1472                 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1473 				{
1474                     long nBottom = (Frm().*fnRect->fnGetBottom)();
1475                     nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
1476                     long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1477                     if( nTmpDiff > 0 )
1478 					{
1479                         nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
1480                         nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
1481                         nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1482                         if( nTmpDiff > 0 )
1483                             nDiff += nTmpDiff;
1484 						if( nDiff > 0 )
1485 							nDiff = 0;
1486 					}
1487 				}
1488 			}
1489 			if( nDiff )
1490 			{
1491                 long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
1492                 long nTop = (this->*fnRect->fnGetTopMargin)();
1493                 (Frm().*fnRect->fnAddBottom)( nTmp );
1494                 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1495 				InvalidateNextPos();
1496 				if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
1497 				{
1498 					// Wenn ein einspaltiger Bereich gerade den Platz geschaffen
1499 					// hat, den sich die "undersized" Absaetze gewuenscht haben,
1500 					// muessen diese invalidiert und kalkuliert werden, damit
1501 					// sie diesen ausfuellen.
1502 					pFrm = pLower;
1503 					if( pFrm->IsColumnFrm() )
1504 					{
1505 						pFrm->_InvalidateSize();
1506 						pFrm->_InvalidatePos();
1507 						pFrm->Calc();
1508 						pFrm = ((SwColumnFrm*)pFrm)->Lower();
1509 						pFrm->Calc();
1510 						pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1511 						CalcFtnCntnt();
1512 					}
1513 					sal_Bool bUnderSz = sal_False;
1514 					while( pFrm )
1515 					{
1516 						if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
1517 						{
1518 							pFrm->Prepare( PREP_ADJUST_FRM );
1519 							bUnderSz = sal_True;
1520 						}
1521 						pFrm = pFrm->GetNext();
1522 					}
1523 					if( bUnderSz && !IsCntntLocked() )
1524 						::CalcCntnt( this );
1525 				}
1526 			}
1527 		}
1528 
1529 		//Unterkante des Uppers nicht ueberschreiten. Fuer Sections mit
1530 		//Follows die Unterkante auch nicht unterschreiten.
1531 		if ( GetUpper() )
1532 			_CheckClipping( sal_True, bMaximize );
1533 		if( !bOldLock )
1534 			ColUnlock();
1535         long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
1536         if( nDiff > 0 )
1537 		{
1538 			if( !GetNext() )
1539 				SetRetouche(); // Dann muessen wir die Retusche selbst uebernehmen
1540             if( GetUpper() && !GetUpper()->IsFooterFrm() )
1541                 GetUpper()->Shrink( nDiff );
1542 		}
1543 		if( IsUndersized() )
1544 			bValidPrtArea = sal_True;
1545     }
1546 }
1547 
1548 /*************************************************************************
1549 |*
1550 |*	SwFrm::GetNextSctLeaf()
1551 |*
1552 |*	Beschreibung		Liefert das naechste Layoutblatt in das der	Frame
1553 |* 		gemoved werden kann.
1554 |* 		Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
1555 |*	Ersterstellung		AMA 07. Jan. 98
1556 |*	Letzte Aenderung	AMA 07. Jan. 98
1557 |*
1558 |*************************************************************************/
1559 
1560 
GetNextSctLeaf(MakePageType eMakePage)1561 SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
1562 {
1563 	//Achtung: Geschachtelte Bereiche werden zur Zeit nicht unterstuetzt.
1564 
1565 	PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )
1566 
1567 	// Abkuerzungen fuer spaltige Bereiche, wenn wir noch nicht in der letzten Spalte sind.
1568 	// Koennen wir in die naechste Spalte des Bereichs rutschen?
1569 	if( IsColBodyFrm() && GetUpper()->GetNext() )
1570 		return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
1571 	if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
1572 		return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
1573 	// Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
1574 	// nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette zuschlagen muessen
1575 	if( GetUpper()->IsInTab() || FindFooterOrHeader() )
1576 		return 0;
1577 
1578 //MA 03. Feb. 99: Warum GetUpper()? Das knallt mit Buch.sgl weil im
1579 //FlyAtCnt::MakeFlyPos ein Orient der SectionFrm ist und auf diesen ein
1580 //GetLeaf gerufen wird.
1581 //	SwSectionFrm *pSect = GetUpper()->FindSctFrm();
1582 	SwSectionFrm *pSect = FindSctFrm();
1583 	sal_Bool bWrongPage = sal_False;
1584 	ASSERT( pSect, "GetNextSctLeaf: Missing SectionFrm" );
1585 
1586 	// Hier eine Abkuerzung fuer Bereiche mit Follows,
1587 	// dieser kann akzeptiert werden, wenn keine Spalten oder Seiten (ausser Dummyseiten)
1588 	// dazwischen liegen.
1589 	// Bei verketteten Rahmen und ind Fussnoten wuerde die Abkuerzung noch aufwendiger
1590 	if( pSect->HasFollow() && pSect->IsInDocBody() )
1591 	{
1592 		if( pSect->GetFollow() == pSect->GetNext() )
1593 		{
1594 			SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
1595 			if( WrongPageDesc( pPg ) )
1596 				bWrongPage = sal_True;
1597 			else
1598 				return FIRSTLEAF( pSect->GetFollow() );
1599 		}
1600 		else
1601 		{
1602 			SwFrm* pTmp;
1603 			if( !pSect->GetUpper()->IsColBodyFrm() ||
1604 				0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
1605 				pTmp = pSect->FindPageFrm()->GetNext();
1606 			if( pTmp ) // ist jetzt die naechste Spalte oder Seite
1607 			{
1608 				SwFrm* pTmpX = pTmp;
1609 				if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
1610 					pTmp = pTmp->GetNext(); // Dummyseiten ueberspringen
1611 				SwFrm *pUp = pSect->GetFollow()->GetUpper();
1612 				// pUp wird die Spalte, wenn der Follow in einer "nicht ersten" Spalte
1613 				// liegt, ansonsten die Seite:
1614 				if( !pUp->IsColBodyFrm() ||
1615 					!( pUp = pUp->GetUpper() )->GetPrev() )
1616 					pUp = pUp->FindPageFrm();
1617 				// Jetzt muessen pUp und pTmp die gleiche Seite/Spalte sein,
1618 				// sonst liegen Seiten oder Spalten zwischen Master und Follow.
1619 				if( pUp == pTmp || pUp->GetNext() == pTmpX )
1620 				{
1621 					SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
1622 										(SwPageFrm*)pUp : pUp->FindPageFrm();
1623 					if( WrongPageDesc( pNxtPg ) )
1624 						bWrongPage = sal_True;
1625 					else
1626 						return FIRSTLEAF( pSect->GetFollow() );
1627 				}
1628 			}
1629 		}
1630 	}
1631 
1632 	// Immer im gleichen Bereich landen: Body wieder in Body etc.
1633 	const sal_Bool bBody = IsInDocBody();
1634 	const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage();
1635 
1636 	SwLayoutFrm *pLayLeaf;
1637 	// Eine Abkuerzung fuer TabFrms, damit nicht alle Zellen abgehuehnert werden
1638 	if( bWrongPage )
1639 		pLayLeaf = 0;
1640 	else if( IsTabFrm() )
1641     {
1642 		SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
1643         pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
1644     }
1645 	else
1646 	{
1647 		pLayLeaf = GetNextLayoutLeaf();
1648 		if( IsColumnFrm() )
1649 		{
1650 			while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
1651 				pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1652 		}
1653 	}
1654 
1655 	SwLayoutFrm *pOldLayLeaf = 0;			//Damit bei neu erzeugten Seiten
1656 											//nicht wieder vom Anfang gesucht
1657 											//wird.
1658 
1659 	while( sal_True )
1660 	{
1661 		if( pLayLeaf )
1662 		{
1663 			// Ein Layoutblatt wurde gefunden, mal sehen, ob er mich aufnehmen kann,
1664 			// ob hier ein weiterer SectionFrm eingefuegt werden kann
1665 			// oder ob wir weitersuchen muessen.
1666 			SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
1667 			if ( !bFtnPage && pNxtPg->IsFtnPage() )
1668 			{	//Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
1669 				pLayLeaf = 0;
1670 				continue;
1671 			}
1672 			// Einmal InBody, immer InBody, nicht in Tabellen hinein
1673 			// und nicht in fremde Bereiche hinein
1674 			if ( (bBody && !pLayLeaf->IsInDocBody()) ||
1675 				 (IsInFtn() != pLayLeaf->IsInFtn() ) ||
1676 				 pLayLeaf->IsInTab() ||
1677 				 ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
1678 				   || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
1679 			{
1680 				//Er will mich nicht; neuer Versuch, neues Glueck
1681 				pOldLayLeaf = pLayLeaf;
1682 				pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1683 				continue;
1684 			}
1685 			if( WrongPageDesc( pNxtPg ) )
1686 			{
1687 				if( bWrongPage )
1688 					break; // there's a column between me and my right page
1689 				pLayLeaf = 0;
1690 				bWrongPage = sal_True;
1691 				pOldLayLeaf = 0;
1692 				continue;
1693 			}
1694 		}
1695 		//Es gibt keinen passenden weiteren LayoutFrm, also muss eine
1696 		//neue Seite her, allerdings nuetzen uns innerhalb eines Rahmens
1697 		//neue Seiten nichts.
1698 		else if( !pSect->IsInFly() &&
1699 			( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
1700 		{
1701 			InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1702 					   sal_False );
1703 			//und nochmal das ganze
1704 			pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1705 			continue;
1706 		}
1707 		break;
1708 	}
1709 
1710 	if( pLayLeaf )
1711 	{
1712 		// Das passende Layoutblatt haben wir gefunden, wenn es dort bereits einen
1713 		// Follow unseres Bereichs gibt, nehmen wir dessen erstes Layoutblatt,
1714 		// andernfalls wird es Zeit, einen Bereichsfollow zu erzeugen
1715 		SwSectionFrm* pNew;
1716 
1717 		//Dies kann entfallen, wenn bei existierenden Follows bereits abgekuerzt wurde
1718 		SwFrm* pFirst = pLayLeaf->Lower();
1719 		// Auch hier muessen zum Loeschen angemeldete SectionFrms ignoriert werden
1720 		while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
1721 			pFirst = pFirst->GetNext();
1722 		if( pFirst && pFirst->IsSctFrm() &&	pSect->GetFollow() == pFirst )
1723 			pNew = pSect->GetFollow();
1724 		else if( MAKEPAGE_NOSECTION == eMakePage )
1725 			return pLayLeaf;
1726 		else
1727 		{
1728             pNew = new SwSectionFrm( *pSect, sal_False );
1729 			pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
1730             pNew->Init();
1731             SWRECTFN( pNew )
1732             (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True );
1733 
1734 			// Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
1735 			// umgehaengt werden hinter den neuen Follow der Bereichsframes.
1736 			SwFrm* pTmp = pSect->GetNext();
1737 			if( pTmp && pTmp != pSect->GetFollow() )
1738 			{
1739 				SwFlowFrm* pNxt;
1740 				SwCntntFrm* pNxtCntnt = NULL;
1741 				if( pTmp->IsCntntFrm() )
1742 				{
1743 					pNxt = (SwCntntFrm*)pTmp;
1744 					pNxtCntnt = (SwCntntFrm*)pTmp;
1745 				}
1746 				else
1747 				{
1748 					pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1749 					if( pTmp->IsSctFrm() )
1750 						pNxt = (SwSectionFrm*)pTmp;
1751 					else
1752 					{
1753 						ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
1754 						pNxt = (SwTabFrm*)pTmp;
1755 					}
1756 					while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
1757 					{
1758 						if( pTmp->IsCntntFrm() )
1759 							pNxtCntnt = (SwCntntFrm*)pTmp;
1760 						else
1761 							pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1762 					}
1763 				}
1764 				if( pNxtCntnt )
1765 				{
1766 					SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
1767 					if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
1768 					{
1769 						SwSaveFtnHeight aHeight( pOldBoss,
1770 							pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
1771 						pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
1772 									pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
1773 					}
1774 				}
1775 				((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
1776 			}
1777 			if( pNew->GetFollow() )
1778 				pNew->SimpleFormat();
1779 		}
1780 		// Das gesuchte Layoutblatt ist jetzt das erste des ermittelten SctFrms:
1781 		pLayLeaf = FIRSTLEAF( pNew );
1782 	}
1783 	return pLayLeaf;
1784 }
1785 
1786 /*************************************************************************
1787 |*
1788 |*	SwFrm::GetPrevSctLeaf()
1789 |*
1790 |*	Beschreibung		Liefert das vorhergehende LayoutBlatt in das der
1791 |* 		Frame gemoved werden kann.
1792 |*	Ersterstellung		AMA 07. Jan. 98
1793 |*	Letzte Aenderung	AMA 07. Jan. 98
1794 |*
1795 |*************************************************************************/
1796 
1797 
GetPrevSctLeaf(MakePageType)1798 SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
1799 {
1800 	PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )
1801 
1802 	SwLayoutFrm* pCol;
1803 	// ColumnFrm beinhalten jetzt stets einen BodyFrm
1804 	if( IsColBodyFrm() )
1805 		pCol = GetUpper();
1806 	else if( GetUpper()->IsColBodyFrm() )
1807 		pCol = GetUpper()->GetUpper();
1808 	else
1809 		pCol = NULL;
1810 	sal_Bool bJump = sal_False;
1811 	if( pCol )
1812 	{
1813 		if( pCol->GetPrev() )
1814 		{
1815 			do
1816 			{
1817 				pCol = (SwLayoutFrm*)pCol->GetPrev();
1818 				// Gibt es dort Inhalt?
1819 				if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
1820 				{
1821 					if( bJump )		// Haben wir eine leere Spalte uebersprungen?
1822 						SwFlowFrm::SetMoveBwdJump( sal_True );
1823 					return (SwLayoutFrm*)pCol->Lower();  // Der Spaltenbody
1824 				}
1825 				bJump = sal_True;
1826 			} while( pCol->GetPrev() );
1827 
1828 			// Hier landen wir, wenn alle Spalten leer sind,
1829 			// pCol ist jetzt die erste Spalte, wir brauchen aber den Body:
1830 			pCol = (SwLayoutFrm*)pCol->Lower();
1831 		}
1832 		else
1833 			pCol = NULL;
1834 	}
1835 
1836 	if( bJump )		// Haben wir eine leere Spalte uebersprungen?
1837 		SwFlowFrm::SetMoveBwdJump( sal_True );
1838 
1839 	// Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
1840 	// nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette
1841 	// zuschlagen muessen, ebenso wenn der Bereich einen pPrev hat.
1842 	// Jetzt ziehen wir sogar eine leere Spalte in Betracht...
1843 	ASSERT( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
1844 	if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
1845 		return pCol;
1846 
1847     // === IMPORTANT ===
1848     // Precondition, which needs to be hold, is that the <this> frame can be
1849     // inside a table, but then the found section frame <pSect> is also inside
1850     // this table.
1851     SwSectionFrm *pSect = FindSctFrm();
1852 
1853     // --> OD 2009-01-16 #i95698#
1854     // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
1855     // Thus, a table inside a section, which is inside another table can only
1856     // flow backward in the columns of its section.
1857     // Note: The table cell, which contains the section, can not have a master table cell.
1858     if ( IsTabFrm() && pSect->IsInTab() )
1859     {
1860         return pCol;
1861     }
1862     // <--
1863 
1864     {
1865         SwFrm *pPrv;
1866         if( 0 != ( pPrv = pSect->GetIndPrev() ) )
1867         {
1868             // Herumlungernde, halbtote SectionFrms sollen uns nicht beirren
1869             while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
1870                 pPrv = pPrv->GetPrev();
1871             if( pPrv )
1872                 return pCol;
1873         }
1874     }
1875 
1876 	const sal_Bool bBody = IsInDocBody();
1877 	const sal_Bool bFly  = IsInFly();
1878 
1879 	SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1880 	SwLayoutFrm *pPrevLeaf = 0;
1881 
1882 	while ( pLayLeaf )
1883     {
1884         //In Tabellen oder Bereiche geht's niemals hinein.
1885         if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
1886         {
1887             pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1888         }
1889 		else if ( bBody && pLayLeaf->IsInDocBody() )
1890 		{
1891             // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
1892             // Exception: pLayLeaf->Lower() is a zombie section frame
1893             const SwFrm* pTmp = pLayLeaf->Lower();
1894             // OD 11.04.2003 #108824# - consider, that the zombie section frame
1895             // can have frame below it in the found layout leaf.
1896             // Thus, skipping zombie section frame, if possible.
1897             while ( pTmp && pTmp->IsSctFrm() &&
1898                     !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
1899                     pTmp->GetNext()
1900                   )
1901             {
1902                 pTmp = pTmp->GetNext();
1903             }
1904             if ( pTmp &&
1905                  ( !pTmp->IsSctFrm() ||
1906                    ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
1907                  )
1908                )
1909             {
1910         	    break;
1911             }
1912 			pPrevLeaf = pLayLeaf;
1913 			pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1914 			if ( pLayLeaf )
1915 				SwFlowFrm::SetMoveBwdJump( sal_True );
1916 		}
1917 		else if ( bFly )
1918 			break;	//Cntnts in Flys sollte jedes Layout-Blatt recht sein. Warum?
1919 		else
1920 			pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1921 	}
1922 	if( !pLayLeaf )
1923 	{
1924 		if( !pPrevLeaf )
1925 			return pCol;
1926 		pLayLeaf = pPrevLeaf;
1927 	}
1928 
1929 	SwSectionFrm* pNew = NULL;
1930 	// Zunaechst einmal an das Ende des Layoutblatts gehen
1931 	SwFrm *pTmp = pLayLeaf->Lower();
1932 	if( pTmp )
1933 	{
1934 		while( pTmp->GetNext() )
1935 			pTmp = pTmp->GetNext();
1936 		if( pTmp->IsSctFrm() )
1937 		{
1938 			// Halbtote stoeren hier nur...
1939 			while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
1940 					pTmp->GetPrev()->IsSctFrm() )
1941 				pTmp = pTmp->GetPrev();
1942 			if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
1943 				pNew = (SwSectionFrm*)pTmp;
1944 		}
1945 	}
1946 	if( !pNew )
1947 	{
1948         pNew = new SwSectionFrm( *pSect, sal_True );
1949 		pNew->InsertBefore( pLayLeaf, NULL );
1950         pNew->Init();
1951         SWRECTFN( pNew )
1952         (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );
1953 
1954 		pLayLeaf = FIRSTLEAF( pNew );
1955 		if( !pNew->Lower() )    // einspaltige Bereiche formatieren
1956 		{
1957 			pNew->MakePos();
1958 			pLayLeaf->Format(); // damit die PrtArea fuers MoveBwd stimmt
1959 		}
1960 		else
1961 			pNew->SimpleFormat();
1962 	}
1963 	else
1964 	{
1965 		pLayLeaf = FIRSTLEAF( pNew );
1966 		if( pLayLeaf->IsColBodyFrm() )
1967         {
1968             // In existent section columns we're looking for the last not empty
1969             // column.
1970             SwLayoutFrm *pTmpLay = pLayLeaf;
1971 			while( pLayLeaf->GetUpper()->GetNext() )
1972             {
1973 				pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
1974                 if( pLayLeaf->Lower() )
1975                     pTmpLay = pLayLeaf;
1976             }
1977             // If we skipped an empty column, we've to set the jump-flag
1978             if( pLayLeaf != pTmpLay )
1979             {
1980                 pLayLeaf = pTmpLay;
1981                 SwFlowFrm::SetMoveBwdJump( sal_True );
1982             }
1983 		}
1984 	}
1985 	return pLayLeaf;
1986 }
1987 
lcl_DeadLine(const SwFrm * pFrm)1988 SwTwips lcl_DeadLine( const SwFrm* pFrm )
1989 {
1990 	const SwLayoutFrm* pUp = pFrm->GetUpper();
1991 	while( pUp && pUp->IsInSct() )
1992 	{
1993 		if( pUp->IsSctFrm() )
1994 			pUp = pUp->GetUpper();
1995 		// Spalten jetzt mit BodyFrm
1996 		else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
1997 			pUp = pUp->GetUpper()->GetUpper();
1998 		else
1999 			break;
2000 	}
2001     SWRECTFN( pFrm )
2002     return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
2003                  (pFrm->Frm().*fnRect->fnGetBottom)();
2004 }
2005 
2006 // SwSectionFrm::Growable(..) prueft, ob der SectionFrm noch wachsen kann,
2007 // ggf. muss die Umgebung gefragt werden
2008 
Growable() const2009 sal_Bool SwSectionFrm::Growable() const
2010 {
2011     SWRECTFN( this )
2012     if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
2013         (Frm().*fnRect->fnGetBottom)() ) > 0 )
2014 		return sal_True;
2015 
2016     return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
2017 }
2018 
2019 /*************************************************************************
2020 |*
2021 |*	SwSectionFrm::_Grow(), _Shrink()
2022 |*
2023 |*	Ersterstellung		AMA 14. Jan. 98
2024 |*	Letzte Aenderung	AMA 14. Jan. 98
2025 |*
2026 |*************************************************************************/
2027 
_Grow(SwTwips nDist,sal_Bool bTst)2028 SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
2029 {
2030     if ( !IsColLocked() && !HasFixSize() )
2031 	{
2032         SWRECTFN( this )
2033         long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2034         if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
2035             nDist = LONG_MAX - nFrmHeight;
2036 
2037 		if ( nDist <= 0L )
2038 			return 0L;
2039 
2040         sal_Bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
2041         // OD 2004-03-15 #116561# - allow grow in online layout
2042         sal_Bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
2043              GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2044         if( !bGrow )
2045         {
2046              const ViewShell *pSh = getRootFrm()->GetCurrShell();
2047              bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
2048         }
2049         if( bGrow )
2050 		{
2051             SwTwips nGrow;
2052             if( IsInFtn() )
2053                 nGrow = 0;
2054             else
2055             {
2056                 nGrow = lcl_DeadLine( this );
2057                 nGrow = (*fnRect->fnYDiff)( nGrow,
2058                                            (Frm().*fnRect->fnGetBottom)() );
2059             }
2060 			SwTwips nSpace = nGrow;
2061             if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
2062                 nGrow += GetUpper()->Grow( LONG_MAX, sal_True );
2063 
2064 			if( nGrow > nDist )
2065 				nGrow = nDist;
2066 			if( nGrow <= 0 )
2067 			{
2068 				nGrow = 0;
2069 				if( nDist && !bTst )
2070 				{
2071 					if( bInCalcCntnt )
2072 						_InvalidateSize();
2073 					else
2074 						InvalidateSize();
2075 				}
2076 			}
2077 			else if( !bTst )
2078 			{
2079 				if( bInCalcCntnt )
2080 					_InvalidateSize();
2081 				else if( nSpace < nGrow &&  nDist != nSpace + GetUpper()->
2082                          Grow( nGrow - nSpace, sal_False ) )
2083 					InvalidateSize();
2084 				else
2085 				{
2086 					const SvxGraphicPosition ePos =
2087 						GetAttrSet()->GetBackground().GetGraphicPos();
2088 					if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2089 					{
2090 						SetCompletePaint();
2091 						InvalidatePage();
2092 					}
2093                     if( GetUpper() && GetUpper()->IsHeaderFrm() )
2094                         GetUpper()->InvalidateSize();
2095 				}
2096                 (Frm().*fnRect->fnAddBottom)( nGrow );
2097                 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
2098                 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2099 
2100                 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2101 				{
2102 					SwFrm* pTmp = Lower();
2103 					do
2104 					{
2105 						pTmp->_InvalidateSize();
2106 						pTmp = pTmp->GetNext();
2107 					} while ( pTmp );
2108 					_InvalidateSize();
2109 				}
2110 				if( GetNext() )
2111 				{
2112 					SwFrm *pFrm = GetNext();
2113 					while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2114 						pFrm = pFrm->GetNext();
2115 					if( pFrm )
2116 					{
2117 						if( bInCalcCntnt )
2118 							pFrm->_InvalidatePos();
2119 						else
2120 							pFrm->InvalidatePos();
2121 					}
2122 				}
2123                 // --> OD 2004-07-05 #i28701# - Due to the new object positioning
2124                 // the frame on the next page/column can flow backward (e.g. it
2125                 // was moved forward due to the positioning of its objects ).
2126                 // Thus, invalivate this next frame, if document compatibility
2127                 // option 'Consider wrapping style influence on object positioning' is ON.
2128                 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2129                 {
2130                     InvalidateNextPos();
2131                 }
2132                 // <--
2133 			}
2134 			return nGrow;
2135 		}
2136 		if ( !bTst )
2137 		{
2138 			if( bInCalcCntnt )
2139 				_InvalidateSize();
2140 			else
2141 				InvalidateSize();
2142 		}
2143 	}
2144 	return 0L;
2145 }
2146 
_Shrink(SwTwips nDist,sal_Bool bTst)2147 SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
2148 {
2149     if ( Lower() && !IsColLocked() && !HasFixSize() )
2150 	{
2151 		if( ToMaximize( sal_False ) )
2152 		{
2153 			if( !bTst )
2154 				InvalidateSize();
2155 		}
2156 		else
2157 		{
2158             SWRECTFN( this )
2159             long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2160             if ( nDist > nFrmHeight )
2161                 nDist = nFrmHeight;
2162 
2163 			if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
2164 				 !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
2165 			{	//Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
2166 				//das Wachstum (wg. des Ausgleichs).
2167 				if ( !bTst )
2168 					InvalidateSize();
2169 				return nDist;
2170 			}
2171 			else if( !bTst )
2172 			{
2173 				const SvxGraphicPosition ePos =
2174 					GetAttrSet()->GetBackground().GetGraphicPos();
2175 				if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2176 				{
2177 					SetCompletePaint();
2178 					InvalidatePage();
2179 				}
2180                 (Frm().*fnRect->fnAddBottom)( -nDist );
2181                 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
2182                 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2183 
2184                 SwTwips nReal = 0;
2185                 // We do not allow a section frame to shrink the its upper
2186                 // footer frame. This is because in the calculation of a
2187                 // footer frame, the content of the section frame is _not_
2188                 // calculated. If there is a fly frame overlapping with the
2189                 // footer frame, the section frame is not affected by this
2190                 // during the calculation of the footer frame size.
2191                 // The footer frame does not grow in its FormatSize function
2192                 // but during the calculation of the content of the section
2193                 // frame. The section frame grows until some of its text is
2194                 // located on top of the fly frame. The next call of CalcCntnt
2195                 // tries to shrink the section and here it would also shrink
2196                 // the footer. This may not happen, because shrinking the footer
2197                 // would cause the top of the section frame to overlap with the
2198                 // fly frame again, this would result in a perfect loop.
2199                 if( GetUpper() && !GetUpper()->IsFooterFrm() )
2200                     nReal = GetUpper()->Shrink( nDist, bTst );
2201 
2202                 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2203 				{
2204 					SwFrm* pTmp = Lower();
2205 					do
2206 					{
2207 						pTmp->_InvalidateSize();
2208 						pTmp = pTmp->GetNext();
2209 					} while ( pTmp );
2210 				}
2211 				if( GetNext() )
2212 				{
2213 					SwFrm* pFrm = GetNext();
2214 					while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2215 						pFrm = pFrm->GetNext();
2216 					if( pFrm )
2217 						pFrm->InvalidatePos();
2218 					else
2219 						SetRetouche();
2220 				}
2221 				else
2222 					SetRetouche();
2223 				return nDist;
2224 			}
2225 		}
2226 	}
2227 	return 0L;
2228 }
2229 
2230 /*************************************************************************
2231 |*
2232 |*	SwSectionFrm::MoveAllowed()
2233 |*
2234 |*	Ersterstellung		MA 08. Oct. 98
2235 |*	Letzte Aenderung	MA 08. Oct. 98
2236 |*
2237 |*	Wann sind Frms innerhalb eines SectionFrms moveable?
2238 |*  Wenn sie noch nicht in der letzten Spalte des SectionFrms sind,
2239 |* 	wenn es einen Follow gibt,
2240 |*  wenn der SectionFrm nicht mehr wachsen kann, wird es komplizierter,
2241 |*  dann kommt es darauf an, ob der SectionFrm ein naechstes Layoutblatt
2242 |*  finden kann. In (spaltigen/verketteten) Flys wird dies via GetNextLayout
2243 |* 	geprueft, in Tabellen und in Kopf/Fusszeilen gibt es keins, im DocBody
2244 |*  und auch im Fussnoten dagegen immer.
2245 |*
2246 |*  Benutzt wird diese Routine im TxtFormatter, um zu entscheiden, ob ein
2247 |* 	(Absatz-)Follow erzeugt werden darf oder ob der Absatz zusammenhalten muss.
2248 |*
2249 |*************************************************************************/
2250 
MoveAllowed(const SwFrm * pFrm) const2251 sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
2252 {
2253 	// Gibt es einen Follow oder ist der Frame nicht in der letzten Spalte?
2254 	if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
2255 		pFrm->GetUpper()->GetUpper()->GetNext() ) )
2256 		return sal_True;
2257 	if( pFrm->IsInFtn() )
2258 	{
2259 		if( IsInFtn() )
2260 		{
2261 			if( GetUpper()->IsInSct() )
2262 			{
2263 				if( Growable() )
2264 					return sal_False;
2265 				return GetUpper()->FindSctFrm()->MoveAllowed( this );
2266 			}
2267 			else
2268 				return sal_True;
2269 		}
2270 		// The content of footnote inside a columned sectionfrm is moveable
2271 		// except in the last column
2272 		const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
2273 		if( pLay->IsColumnFrm() && pLay->GetNext() )
2274 		{
2275 			// The first paragraph in the first footnote in the first column
2276 			// in the sectionfrm at the top of the page is not moveable,
2277 			// if the columnbody is empty.
2278 			sal_Bool bRet = sal_False;
2279 			if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
2280 				pFrm->FindFtnFrm()->GetPrev() )
2281 				bRet = sal_True;
2282 			else
2283 			{
2284 				SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
2285 				if( pBody && pBody->Lower() )
2286 					bRet = sal_True;
2287 			}
2288 			if( bRet && ( IsFtnAtEnd() || !Growable() ) )
2289 				return sal_True;
2290 		}
2291 	}
2292 	// Oder kann der Bereich noch wachsen?
2293 	if(	!IsColLocked() && Growable() )
2294 		return sal_False;
2295 	// Jetzt muss untersucht werden, ob es ein Layoutblatt gibt, in dem
2296 	// ein Bereichsfollow erzeugt werden kann.
2297 	if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
2298 		return sal_False; // In Tabellen/Kopf/Fusszeilen geht es nicht
2299 	if( IsInFly() ) // Bei spaltigen oder verketteten Rahmen
2300 		return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
2301 	return sal_True;
2302 }
2303 
2304 /** Called for a frame inside a section with no direct previous frame (or only
2305     previous empty section frames) the previous frame of the outer section is
2306     returned, if the frame is the first flowing content of this section.
2307 
2308     Note: For a frame inside a table frame, which is inside a section frame,
2309           NULL is returned.
2310 */
_GetIndPrev() const2311 SwFrm* SwFrm::_GetIndPrev() const
2312 {
2313 	SwFrm *pRet = NULL;
2314     // --> OD 2007-09-04 #i79774#, #b659654#
2315     // Do not assert, if the frame has a direct previous frame, because it
2316     // could be an empty section frame. The caller has to assure, that the
2317     // frame has no direct previous frame or only empty section frames as
2318     // previous frames.
2319     ASSERT( /*!pPrev &&*/ IsInSct(), "Why?" );
2320     // <--
2321     const SwFrm* pSct = GetUpper();
2322 	if( !pSct )
2323 		return NULL;
2324 	if( pSct->IsSctFrm() )
2325 		pRet = pSct->GetIndPrev();
2326 	else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2327     {
2328         // Do not return the previous frame of the outer section, if in one
2329         // of the previous columns is content.
2330         const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
2331 		while( pCol )
2332 		{
2333 			ASSERT( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
2334 			ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2335 					"GetIndPrev(): Where's the body?");
2336 			if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2337 				return NULL;
2338 			pCol = pCol->GetPrev();
2339 		}
2340 		pRet = pSct->GetIndPrev();
2341 	}
2342 
2343     // skip empty section frames
2344 	while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
2345 		pRet = pRet->GetIndPrev();
2346 	return pRet;
2347 }
2348 
_GetIndNext()2349 SwFrm* SwFrm::_GetIndNext()
2350 {
2351 	ASSERT( !pNext && IsInSct(), "Why?" );
2352 	SwFrm* pSct = GetUpper();
2353 	if( !pSct )
2354 		return NULL;
2355 	if( pSct->IsSctFrm() )
2356 		return pSct->GetIndNext();
2357 	if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2358 	{	// Wir duerfen nur den Nachfolger des SectionFrms zurueckliefern,
2359 		// wenn in keiner folgenden Spalte mehr Inhalt ist
2360 		SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
2361 		while( pCol )
2362 		{
2363 			ASSERT( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
2364 			ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2365 					"GetIndNext(): Where's the body?");
2366 			if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2367 				return NULL;
2368 			pCol = pCol->GetNext();
2369 		}
2370 		return pSct->GetIndNext();
2371 	}
2372 	return NULL;
2373 }
2374 
IsDescendantFrom(const SwSectionFmt * pFmt) const2375 sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
2376 {
2377 	if( !pSection || !pFmt )
2378 		return sal_False;
2379 	const SwSectionFmt *pMyFmt = pSection->GetFmt();
2380 	while( pFmt != pMyFmt )
2381 	{
2382 		if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2383 			pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
2384 		else
2385 			return sal_False;
2386 	}
2387 	return sal_True;
2388 }
2389 
CalcFtnAtEndFlag()2390 void SwSectionFrm::CalcFtnAtEndFlag()
2391 {
2392 	SwSectionFmt *pFmt = GetSection()->GetFmt();
2393 	sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2394 	bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
2395 	bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2396 				 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2397 	while( !bFtnAtEnd && !bOwnFtnNum )
2398 	{
2399 		if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2400 			pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2401 		else
2402 			break;
2403 		nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2404 		if( FTNEND_ATPGORDOCEND != nVal )
2405 		{
2406 			bFtnAtEnd = sal_True;
2407 			bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2408 						 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2409 		}
2410 	}
2411 }
2412 
IsEndnoteAtMyEnd() const2413 sal_Bool SwSectionFrm::IsEndnoteAtMyEnd() const
2414 {
2415 	return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2416 }
2417 
CalcEndAtEndFlag()2418 void SwSectionFrm::CalcEndAtEndFlag()
2419 {
2420 	SwSectionFmt *pFmt = GetSection()->GetFmt();
2421 	bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2422 	while( !bEndnAtEnd )
2423 	{
2424 		if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2425 			pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2426 		else
2427 			break;
2428 		bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2429 	}
2430 }
2431 
2432 /*************************************************************************
2433 |*
2434 |*	SwSectionFrm::Modify()
2435 |*
2436 |*	Ersterstellung		MA 08. Oct. 98
2437 |*	Letzte Aenderung	MA 08. Oct. 98
2438 |*
2439 |*************************************************************************/
2440 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)2441 void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2442 {
2443 	sal_uInt8 nInvFlags = 0;
2444 
2445 	if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2446 	{
2447 		SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2448 		SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2449 		SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2450 		SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2451 		while( sal_True )
2452 		{
2453 			_UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2454 						 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2455 						 &aOldSet, &aNewSet );
2456 			if( aNIter.IsAtEnd() )
2457 				break;
2458 			aNIter.NextItem();
2459 			aOIter.NextItem();
2460 		}
2461 		if ( aOldSet.Count() || aNewSet.Count() )
2462 			SwLayoutFrm::Modify( &aOldSet, &aNewSet );
2463 	}
2464 	else
2465 		_UpdateAttr( pOld, pNew, nInvFlags );
2466 
2467 	if ( nInvFlags != 0 )
2468 	{
2469 		if ( nInvFlags & 0x01 )
2470 			InvalidateSize();
2471 		if ( nInvFlags & 0x10 )
2472 			SetCompletePaint();
2473 	}
2474 }
2475 
SwClientNotify(const SwModify & rMod,const SfxHint & rHint)2476 void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
2477 {
2478     // --> OD #i117863#
2479     const SwSectionFrmMoveAndDeleteHint* pHint =
2480                     dynamic_cast<const SwSectionFrmMoveAndDeleteHint*>(&rHint);
2481     if ( pHint && pHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
2482     {
2483         SwSectionFrm::MoveCntntAndDelete( this, pHint->IsSaveCntnt() );
2484     }
2485     // <--
2486 }
2487 
_UpdateAttr(const SfxPoolItem * pOld,const SfxPoolItem * pNew,sal_uInt8 & rInvFlags,SwAttrSetChg * pOldSet,SwAttrSetChg * pNewSet)2488 void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
2489 							sal_uInt8 &rInvFlags,
2490 							SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2491 {
2492 	sal_Bool bClear = sal_True;
2493 	const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2494 	switch( nWhich )
2495 	{   // Mehrspaltigkeit in Fussnoten unterdruecken...
2496 		case RES_FMT_CHG:
2497 		{
2498 			const SwFmtCol& rNewCol = GetFmt()->GetCol();
2499 			if( !IsInFtn() )
2500 			{
2501 				//Dummer Fall. Bei der Zuweisung einer Vorlage k?nnen wir uns
2502 				//nicht auf das alte Spaltenattribut verlassen. Da diese
2503 				//wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
2504 				//bleibt uns nur einen temporaeres Attribut zu basteln.
2505 				SwFmtCol aCol;
2506 				if ( Lower() && Lower()->IsColumnFrm() )
2507 				{
2508 					sal_uInt16 nCol = 0;
2509 					SwFrm *pTmp = Lower();
2510 					do
2511 					{	++nCol;
2512 						pTmp = pTmp->GetNext();
2513 					} while ( pTmp );
2514 					aCol.Init( nCol, 0, 1000 );
2515 				}
2516 				sal_Bool bChgFtn = IsFtnAtEnd();
2517 				sal_Bool bChgEndn = IsEndnAtEnd();
2518 				sal_Bool bChgMyEndn = IsEndnoteAtMyEnd();
2519 				CalcFtnAtEndFlag();
2520 				CalcEndAtEndFlag();
2521 				bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
2522 						  ( bChgEndn != IsEndnAtEnd() ) ||
2523 						  ( bChgMyEndn != IsEndnoteAtMyEnd() );
2524 				ChgColumns( aCol, rNewCol, bChgFtn );
2525 				rInvFlags |= 0x10;
2526 			}
2527 			rInvFlags |= 0x01;
2528 			bClear = sal_False;
2529 		}
2530 			break;
2531 
2532 		case RES_COL:
2533 			if( !IsInFtn() )
2534 			{
2535 				ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
2536 				rInvFlags |= 0x11;
2537 			}
2538 			break;
2539 
2540 		case RES_FTN_AT_TXTEND:
2541 			if( !IsInFtn() )
2542 			{
2543 				sal_Bool bOld = IsFtnAtEnd();
2544 				CalcFtnAtEndFlag();
2545 				if( bOld != IsFtnAtEnd() )
2546 				{
2547 					const SwFmtCol& rNewCol = GetFmt()->GetCol();
2548 					ChgColumns( rNewCol, rNewCol, sal_True );
2549 					rInvFlags |= 0x01;
2550 				}
2551 			}
2552 			break;
2553 
2554 		case RES_END_AT_TXTEND:
2555 			if( !IsInFtn() )
2556 			{
2557 				sal_Bool bOld = IsEndnAtEnd();
2558 				sal_Bool bMyOld = IsEndnoteAtMyEnd();
2559 				CalcEndAtEndFlag();
2560 				if( bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
2561 				{
2562 					const SwFmtCol& rNewCol = GetFmt()->GetCol();
2563 					ChgColumns( rNewCol, rNewCol, sal_True );
2564 					rInvFlags |= 0x01;
2565 				}
2566 			}
2567 			break;
2568 		case RES_COLUMNBALANCE:
2569 			rInvFlags |= 0x01;
2570 			break;
2571 
2572         case RES_FRAMEDIR :
2573             SetDerivedR2L( sal_False );
2574             CheckDirChange();
2575             break;
2576 
2577 		case RES_PROTECT:
2578 			{
2579 				ViewShell *pSh = getRootFrm()->GetCurrShell();
2580 				if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
2581 					pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
2582 			}
2583 			break;
2584 
2585 		default:
2586 			bClear = sal_False;
2587 	}
2588 	if ( bClear )
2589 	{
2590 		if ( pOldSet || pNewSet )
2591 		{
2592 			if ( pOldSet )
2593 				pOldSet->ClearItem( nWhich );
2594 			if ( pNewSet )
2595 				pNewSet->ClearItem( nWhich );
2596 		}
2597 		else
2598 			SwLayoutFrm::Modify( pOld, pNew );
2599 	}
2600 }
2601 
2602 /*-----------------09.06.99 14:58-------------------
2603  * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
2604  * page causes a maximal Size of the sectionframe.
2605  * --------------------------------------------------*/
2606 
ToMaximize(sal_Bool bCheckFollow) const2607 sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
2608 {
2609 	if( HasFollow() )
2610 	{
2611 		if( !bCheckFollow ) // Don't check superfluous follows
2612 			return sal_True;
2613 		const SwSectionFrm* pFoll = GetFollow();
2614 		while( pFoll && pFoll->IsSuperfluous() )
2615 			pFoll = pFoll->GetFollow();
2616 		if( pFoll )
2617 			return sal_True;
2618 	}
2619 	if( IsFtnAtEnd() )
2620 		return sal_False;
2621 	const SwFtnContFrm* pCont = ContainsFtnCont();
2622 	if( !IsEndnAtEnd() )
2623 		return 0 != pCont;
2624 	sal_Bool bRet = sal_False;
2625 	while( pCont && !bRet )
2626 	{
2627 		if( pCont->FindFootNote() )
2628 			bRet = sal_True;
2629 		else
2630 			pCont = ContainsFtnCont( pCont );
2631 	}
2632 	return bRet;
2633 }
2634 
2635 /*-----------------09.06.99 15:07-------------------
2636  * sal_Bool SwSectionFrm::ContainsFtnCont()
2637  * checks every Column for FtnContFrms.
2638  * --------------------------------------------------*/
2639 
ContainsFtnCont(const SwFtnContFrm * pCont) const2640 SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
2641 {
2642 	SwFtnContFrm* pRet = NULL;
2643 	const SwLayoutFrm* pLay;
2644 	if( pCont )
2645 	{
2646 		pLay = pCont->FindFtnBossFrm( 0 );
2647 		ASSERT( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
2648 		pLay = (SwLayoutFrm*)pLay->GetNext();
2649 	}
2650 	else if( Lower() && Lower()->IsColumnFrm() )
2651 		pLay = (SwLayoutFrm*)Lower();
2652 	else
2653 		pLay = NULL;
2654 	while ( !pRet && pLay )
2655 	{
2656 		if( pLay->Lower() && pLay->Lower()->GetNext() )
2657 		{
2658 			ASSERT( pLay->Lower()->GetNext()->IsFtnContFrm(),
2659 					"ToMaximize: Unexspected Frame" );
2660 			pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
2661 		}
2662 		ASSERT( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
2663 				"ToMaximize: ColFrm exspected" );
2664 		pLay = (SwLayoutFrm*)pLay->GetNext();
2665 	}
2666 	return pRet;
2667 }
2668 
InvalidateFtnPos()2669 void SwSectionFrm::InvalidateFtnPos()
2670 {
2671 	SwFtnContFrm* pCont = ContainsFtnCont( NULL );
2672 	if( pCont )
2673 	{
2674 		SwFrm *pTmp = pCont->ContainsCntnt();
2675 		if( pTmp )
2676 			pTmp->_InvalidatePos();
2677 	}
2678 }
2679 
2680 /*-----------------18.03.99 10:37-------------------
2681  * SwSectionFrm::Undersize() liefert den Betrag, um den der Bereich gern
2682  * groesser waere, wenn in ihm Undersized TxtFrms liegen, ansonsten Null.
2683  * Das Undersized-Flag wird ggf. korrigiert.
2684  * --------------------------------------------------*/
2685 
Undersize(sal_Bool bOverSize)2686 long SwSectionFrm::Undersize( sal_Bool bOverSize )
2687 {
2688 	bUndersized = sal_False;
2689     SWRECTFN( this )
2690     long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
2691 	if( nRet > 0 )
2692 		bUndersized = sal_True;
2693 	else if( !bOverSize )
2694 		nRet = 0;
2695 	return nRet;
2696 }
2697 
2698 /// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
2699 /// before format of current one, because current one can move backward.
2700 /// After moving backward to a previous page method <FindNext()> will return
2701 /// the text frame presenting the first page footnote, if it exists. Thus, the
2702 /// rest of the footnote/endnote container would not be formatted.
CalcFtnCntnt()2703 void SwSectionFrm::CalcFtnCntnt()
2704 {
2705 	SwFtnContFrm* pCont = ContainsFtnCont();
2706 	if( pCont )
2707 	{
2708 		SwFrm* pFrm = pCont->ContainsAny();
2709 		if( pFrm )
2710 			pCont->Calc();
2711 		while( pFrm && IsAnLower( pFrm ) )
2712 		{
2713 			SwFtnFrm* pFtn = pFrm->FindFtnFrm();
2714 			if( pFtn )
2715 				pFtn->Calc();
2716             // OD 01.04.2003 #108446# - determine next frame before format current frame.
2717             SwFrm* pNextFrm = 0;
2718             {
2719                 if( pFrm->IsSctFrm() )
2720                 {
2721                     pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
2722                 }
2723                 if( !pNextFrm )
2724                 {
2725                     pNextFrm = pFrm->FindNext();
2726                 }
2727             }
2728 			pFrm->Calc();
2729             pFrm = pNextFrm;
2730 		}
2731 	}
2732 }
2733 
2734 /* -----------------09.02.99 14:26-------------------
2735  * Wenn ein SectionFrm leerlaeuft, z.B. weil sein Inhalt die Seite/Spalte wechselt,
2736  * so wird er nicht sofort zerstoert (es koennte noch jemand auf dem Stack einen Pointer
2737  * auf ihn halten), sondern er traegt sich in eine Liste am RootFrm ein, die spaeter
2738  * abgearbeitet wird (in LayAction::Action u.a.). Seine Groesse wird auf Null gesetzt und
2739  * sein Zeiger auf seine Section ebenfalls. Solche zum Loeschen vorgesehene SectionFrms
2740  * muessen vom Layout/beim Formatieren ignoriert werden.
2741  *
2742  * Mit InsertEmptySct nimmt der RootFrm einen SectionFrm in die Liste auf,
2743  * mit RemoveFromList kann ein SectionFrm wieder aus der Liste entfernt werden (Dtor),
2744  * mit DeleteEmptySct wird die Liste abgearbeitet und die SectionFrms zerstoert
2745  * --------------------------------------------------*/
2746 
InsertEmptySct(SwSectionFrm * pDel)2747 void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
2748 {
2749 	if( !pDestroy )
2750 		pDestroy = new SwDestroyList;
2751 	sal_uInt16 nPos;
2752 	if( !pDestroy->Seek_Entry( pDel, &nPos ) )
2753 		pDestroy->Insert( pDel );
2754 }
2755 
_DeleteEmptySct()2756 void SwRootFrm::_DeleteEmptySct()
2757 {
2758 	ASSERT( pDestroy, "Keine Liste, keine Kekse" );
2759 	while( pDestroy->Count() )
2760 	{
2761 		SwSectionFrm* pSect = (*pDestroy)[0];
2762 		pDestroy->Remove( sal_uInt16(0) );
2763 		ASSERT( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
2764 				"DeleteEmptySct: Locked SectionFrm" );
2765 		if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
2766 		{
2767 			SwLayoutFrm* pUp = pSect->GetUpper();
2768 			pSect->Remove();
2769 			delete pSect;
2770 			if( pUp && !pUp->Lower() )
2771 			{
2772 				if( pUp->IsPageBodyFrm() )
2773 					pUp->getRootFrm()->SetSuperfluous();
2774 				else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
2775 					pUp->GetUpper() )
2776 				{
2777 					pUp->Cut();
2778 					delete pUp;
2779 				}
2780 			}
2781 		}
2782 		else {
2783 			ASSERT( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
2784         }
2785 	}
2786 }
2787 
_RemoveFromList(SwSectionFrm * pSct)2788 void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
2789 {
2790 	ASSERT( pDestroy, "Where's my list?" );
2791 	sal_uInt16 nPos;
2792 	if( pDestroy->Seek_Entry( pSct, &nPos ) )
2793 		pDestroy->Remove( nPos );
2794 }
2795 
2796 #ifdef DBG_UTIL
2797 
IsInDelList(SwSectionFrm * pSct) const2798 sal_Bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
2799 {
2800 	sal_uInt16 nPos;
2801 	return ( pDestroy && pDestroy->Seek_Entry( pSct, &nPos ) );
2802 }
2803 
2804 #endif
2805 
IsBalancedSection() const2806 bool SwSectionFrm::IsBalancedSection() const
2807 {
2808     bool bRet = false;
2809     if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2810     {
2811         bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2812     }
2813     return bRet;
2814 }
2815 
2816