Update ooo320-m1
[ooovba.git] / sw / source / core / layout / sectfrm.cxx
blob5dcb6040d76f35610d691611986d5b5b8dc2bd93
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sectfrm.cxx,v $
10 * $Revision: 1.55 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <svtools/itemiter.hxx>
36 #include <hints.hxx>
37 #include <txtftn.hxx>
38 #include <fmtftn.hxx>
39 #include <fmtclbl.hxx>
40 #include "sectfrm.hxx"
41 #include "section.hxx" // SwSection
42 #include "frmtool.hxx" // StackHack
43 #include "doc.hxx" // SwDoc
44 #include "cntfrm.hxx" // SwCntntFrm
45 #include "rootfrm.hxx" // SwRootFrm
46 #include "pagefrm.hxx" // SwPageFrm
47 #include "fmtpdsc.hxx" // SwFmtPageDesc
48 #include "fmtcntnt.hxx" // SwFmtCntnt
49 #include "ndindex.hxx" // SwNodeIndex
50 #include "ftnidx.hxx"
51 #include "txtfrm.hxx" // SwTxtFrm
52 #include "fmtclds.hxx" // SwFmtCol
53 #include "colfrm.hxx" // SwColumnFrm
54 #include "tabfrm.hxx" // SwTabFrm
55 #include "flyfrm.hxx" // SwFlyFrm
56 #include "ftnfrm.hxx" // SwFtnFrm
57 #include "layouter.hxx" // SwLayouter
58 #include "dbg_lay.hxx"
59 #include "viewsh.hxx"
60 #include "viewimp.hxx"
61 #include <svx/ulspitem.hxx>
62 #include <svx/lrspitem.hxx>
63 #include <svx/brshitem.hxx>
64 #include <fmtftntx.hxx>
65 // OD 2004-05-24 #i28701#
66 #include <dflyobj.hxx>
67 #include <flyfrms.hxx>
68 #include <sortedobjs.hxx>
70 SV_IMPL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr )
72 /*************************************************************************
74 |* SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
76 |* Ersterstellung AMA 26. Nov. 97
77 |* Letzte Aenderung AMA 26. Nov. 97
79 |*************************************************************************/
80 SwSectionFrm::SwSectionFrm( SwSection &rSect ) :
81 SwLayoutFrm( rSect.GetFmt() ),
82 SwFlowFrm( (SwFrm&)*this ),
83 pSection( &rSect )
85 nType = FRMC_SECTION;
87 CalcFtnAtEndFlag();
88 CalcEndAtEndFlag();
91 SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, BOOL bMaster ) :
92 SwLayoutFrm( rSect.GetFmt() ),
93 SwFlowFrm( (SwFrm&)*this ),
94 pSection( rSect.GetSection() )
96 bFtnAtEnd = rSect.IsFtnAtEnd();
97 bEndnAtEnd = rSect.IsEndnAtEnd();
98 bLockJoin = FALSE;
99 nType = FRMC_SECTION;
101 PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
103 if( bMaster )
105 if( rSect.IsFollow() )
107 SwSectionFrm* pMaster = rSect.FindMaster();
108 pMaster->SetFollow( this );
109 bIsFollow = TRUE;
111 else
112 rSect.bIsFollow = TRUE;
113 SetFollow( &rSect );
115 else
117 bIsFollow = TRUE;
118 SetFollow( rSect.GetFollow() );
119 rSect.SetFollow( this );
120 if( !GetFollow() )
121 rSect.SimpleFormat();
122 if( !rSect.IsColLocked() )
123 rSect.InvalidateSize();
127 // NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
128 // frame and its insert in the layout.
129 void SwSectionFrm::Init()
131 ASSERT( GetUpper(), "SwSectionFrm::Init before insertion?!" );
132 SWRECTFN( this )
133 long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
134 (Frm().*fnRect->fnSetWidth)( nWidth );
135 (Frm().*fnRect->fnSetHeight)( 0 );
137 // #109700# LRSpace for sections
138 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
139 (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
140 (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
141 rLRSpace.GetRight() );
142 (Prt().*fnRect->fnSetHeight)( 0 );
144 const SwFmtCol &rCol = GetFmt()->GetCol();
145 if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
147 const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
148 ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
149 if( pOld != &rCol )
150 delete pOld;
154 SwSectionFrm::~SwSectionFrm()
156 if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
158 SwRootFrm *pRootFrm = GetFmt()->GetDoc()->GetRootFrm();
159 if( pRootFrm )
160 pRootFrm->RemoveFromList( this );
161 if( IsFollow() )
163 SwSectionFrm *pMaster = FindMaster();
164 if( pMaster )
166 PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
167 pMaster->SetFollow( GetFollow() );
168 // Ein Master greift sich immer den Platz bis zur Unterkante seines
169 // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
170 // freigeben, deshalb wird die Size des Masters invalidiert.
171 if( !GetFollow() )
172 pMaster->InvalidateSize();
175 else if( HasFollow() )
177 PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
178 GetFollow()->bIsFollow = FALSE;
184 /*************************************************************************
186 |* SwSectionFrm::DelEmpty()
188 |* Ersterstellung AMA 17. Dec. 97
189 |* Letzte Aenderung AMA 17. Dec. 97
191 |*************************************************************************/
192 void SwSectionFrm::DelEmpty( BOOL bRemove )
194 if( IsColLocked() )
196 ASSERT( !bRemove, "Don't delete locked SectionFrms" );
197 return;
199 SwFrm* pUp = GetUpper();
200 if( pUp )
202 // --> OD 2005-12-01 #i27138#
203 // notify accessibility paragraphs objects about changed
204 // CONTENT_FLOWS_FROM/_TO relation.
205 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
206 // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
208 ViewShell* pViewShell( GetShell() );
209 if ( pViewShell && pViewShell->GetLayout() &&
210 pViewShell->GetLayout()->IsAnyShellAccessible() )
212 pViewShell->InvalidateAccessibleParaFlowRelation(
213 dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
214 dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
217 // <--
218 _Cut( bRemove );
220 if( IsFollow() )
222 SwSectionFrm *pMaster = FindMaster();
223 pMaster->SetFollow( GetFollow() );
224 // Ein Master greift sich immer den Platz bis zur Unterkante seines
225 // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
226 // freigeben, deshalb wird die Size des Masters invalidiert.
227 if( !GetFollow() && !pMaster->IsColLocked() )
228 pMaster->InvalidateSize();
229 bIsFollow = FALSE;
231 else if( HasFollow() )
232 GetFollow()->bIsFollow = FALSE;
233 pFollow = NULL;
234 if( pUp )
236 Frm().Height( 0 );
237 // Wenn wir sowieso sofort zerstoert werden, brauchen/duerfen wir
238 // uns gar nicht erst in die Liste eintragen
239 if( bRemove )
240 { // Wenn wir bereits halbtot waren vor diesem DelEmpty, so
241 // stehen wir vermutlich auch in der Liste und muessen uns
242 // dort austragen
243 if( !pSection )
244 GetFmt()->GetDoc()->GetRootFrm()->RemoveFromList( this );
246 else
247 GetFmt()->GetDoc()->GetRootFrm()->InsertEmptySct( this );
248 pSection = NULL; // damit ist allerdings eine Reanimierung quasi ausgeschlossen
252 /*************************************************************************
254 |* SwSectionFrm::Cut()
256 |* Ersterstellung AMA 02. Dec. 97
257 |* Letzte Aenderung AMA 02. Dec. 97
259 |*************************************************************************/
260 void SwSectionFrm::Cut()
262 _Cut( TRUE );
265 void SwSectionFrm::_Cut( BOOL bRemove )
267 ASSERT( GetUpper(), "Cut ohne Upper()." );
269 PROTOCOL( this, PROT_CUT, 0, GetUpper() )
271 SwPageFrm *pPage = FindPageFrm();
272 InvalidatePage( pPage );
273 SwFrm *pFrm = GetNext();
274 SwFrm* pPrepFrm = NULL;
275 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
276 pFrm = pFrm->GetNext();
277 if( pFrm )
278 { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
279 //berechnet der ist jetzt wo er der erste wird obsolete
280 pFrm->_InvalidatePrt();
281 pFrm->_InvalidatePos();
282 if( pFrm->IsSctFrm() )
283 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
284 if ( pFrm && pFrm->IsCntntFrm() )
286 pFrm->InvalidatePage( pPage );
287 if( IsInFtn() && !GetIndPrev() )
288 pPrepFrm = pFrm;
291 else
293 InvalidateNextPos();
294 //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
295 if ( 0 != (pFrm = GetPrev()) )
296 { pFrm->SetRetouche();
297 pFrm->Prepare( PREP_WIDOWS_ORPHANS );
298 if ( pFrm->IsCntntFrm() )
299 pFrm->InvalidatePage( pPage );
301 //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
302 //er die Retouche uebernehmen.
303 //Ausserdem kann eine Leerseite entstanden sein.
304 else
305 { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
306 pRoot->SetSuperfluous();
307 GetUpper()->SetCompletePaint();
310 //Erst removen, dann Upper Shrinken.
311 SwLayoutFrm *pUp = GetUpper();
312 if( bRemove )
314 Remove();
315 if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
316 pUp->GetUpper() )
318 pUp->Cut();
319 delete pUp;
320 pUp = NULL;
323 if( pPrepFrm )
324 pPrepFrm->Prepare( PREP_FTN );
325 if ( pUp )
327 SWRECTFN( this );
328 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
329 if( nFrmHeight > 0 )
331 if( !bRemove )
333 (Frm().*fnRect->fnSetHeight)( 0 );
334 (Prt().*fnRect->fnSetHeight)( 0 );
336 pUp->Shrink( nFrmHeight );
341 /*************************************************************************
343 |* SwSectionFrm::Paste()
345 |* Ersterstellung AMA 04. Dec. 97
346 |* Letzte Aenderung AMA 04. Dec. 97
348 |*************************************************************************/
350 void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
352 ASSERT( pParent, "Kein Parent fuer Paste." );
353 ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
354 ASSERT( pParent != this, "Bin selbst der Parent." );
355 ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
356 ASSERT( !GetPrev() && !GetUpper(),
357 "Bin noch irgendwo angemeldet." );
359 PROTOCOL( this, PROT_PASTE, 0, GetUpper() )
361 //In den Baum einhaengen.
362 SwSectionFrm* pSect = pParent->FindSctFrm();
363 // --> OD 2008-06-23 #156927#
364 // Assure that parent is not inside a table frame, which is inside the found section frame.
365 if ( pSect )
367 SwTabFrm* pTableFrm = pParent->FindTabFrm();
368 if ( pTableFrm &&
369 pSect->IsAnLower( pTableFrm ) )
371 pSect = 0;
374 // <--
376 SWRECTFN( pParent )
377 if( pSect && HasToBreak( pSect ) )
379 if( pParent->IsColBodyFrm() ) // handelt es sich um einen spaltigen Bereich
381 // Falls wir zufaellig am Ende einer Spalte stehen, muss pSibling
382 // auf den ersten Frame der naechsten Spalte zeigen, damit
383 // der Inhalt der naechsten Spalte von InsertGroup richtig in den
384 // neu angelegten pSect umgehaengt wird.
385 SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
386 while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
387 pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
388 if( pSibling )
390 // Schlimmer noch: alle folgenden Spalteninhalte muessen
391 // an die pSibling-Kette angehaengt werden, damit sie
392 // mitgenommen werden.
393 SwFrm *pTmp = pSibling;
394 while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
396 while ( pTmp->GetNext() )
397 pTmp = pTmp->GetNext();
398 SwFrm* pSave = ::SaveCntnt( pCol );
399 ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
403 pParent = pSect;
404 pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection() );
405 // Wenn pParent in zwei Teile zerlegt wird, so muss sein Follow am
406 // neuen, zweiten Teil angebracht werden.
407 pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
408 ((SwSectionFrm*)pParent)->SetFollow( NULL );
409 if( pSect->GetFollow() )
410 pParent->_InvalidateSize();
412 InsertGroupBefore( pParent, pSibling, pSect );
413 pSect->Init();
414 (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), TRUE);
415 if( !((SwLayoutFrm*)pParent)->Lower() )
417 SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, FALSE );
418 pParent = this;
421 else
422 InsertGroupBefore( pParent, pSibling, NULL );
424 _InvalidateAll();
425 SwPageFrm *pPage = FindPageFrm();
426 InvalidatePage( pPage );
428 if ( pSibling )
430 pSibling->_InvalidatePos();
431 pSibling->_InvalidatePrt();
432 if ( pSibling->IsCntntFrm() )
433 pSibling->InvalidatePage( pPage );
436 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
437 if( nFrmHeight )
438 pParent->Grow( nFrmHeight );
440 if ( GetPrev() )
442 if ( !IsFollow() )
444 GetPrev()->InvalidateSize();
445 if ( GetPrev()->IsCntntFrm() )
446 GetPrev()->InvalidatePage( pPage );
452 /*************************************************************************
454 |* SwSectionFrm::HasToBreak()
456 |* Hier wird entschieden, ob der this-SectionFrm den uebergebenen
457 |* (Section)Frm aufbrechen soll oder nicht.
458 |* Zunaechst werden uebergeordnete Bereiche immer aufgebrochen,
459 |* spaeter koennte man es einstellbar machen.
461 |* Ersterstellung AMA 12. Dec. 97
462 |* Letzte Aenderung AMA 12. Dec. 97
464 |*************************************************************************/
466 BOOL SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
468 if( !pFrm->IsSctFrm() )
469 return FALSE;
471 SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
472 // if( !pTmp->GetSect().GetValue() )
473 // return FALSE;
475 const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
478 pTmp = pTmp->GetParent();
479 if( !pTmp )
480 return FALSE;
481 if( pTmp == pOtherFmt )
482 return TRUE;
483 } while( TRUE ); // ( pTmp->GetSect().GetValue() );
486 /*************************************************************************
488 |* SwSectionFrm::MergeNext()
490 |* Ersterstellung AMA 04. Dec. 97
491 |* Letzte Aenderung AMA 04. Dec. 97
493 |* Verschmilzt zwei SectionFrms, falls es sich um den
494 |* gleichen Bereich handelt.
495 |* Notwendig kann dies sein, wenn ein (Unter-)Bereich geloescht wird, der
496 |* einen anderen in zwei Teile zerlegt hatte.
498 |*************************************************************************/
500 void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
502 if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
504 PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
506 SwFrm* pTmp = ::SaveCntnt( pNxt );
507 if( pTmp )
509 SwFrm* pLast = Lower();
510 SwLayoutFrm* pLay = this;
511 if( pLast )
513 while( pLast->GetNext() )
514 pLast = pLast->GetNext();
515 if( pLast->IsColumnFrm() )
516 { // Spalten jetzt mit BodyFrm
517 pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
518 pLast = pLay->Lower();
519 if( pLast )
520 while( pLast->GetNext() )
521 pLast = pLast->GetNext();
524 ::RestoreCntnt( pTmp, pLay, pLast, true );
526 SetFollow( pNxt->GetFollow() );
527 pNxt->SetFollow( NULL );
528 pNxt->bIsFollow = FALSE;
529 pNxt->Cut();
530 delete pNxt;
531 InvalidateSize();
535 /*************************************************************************
537 |* SwSectionFrm::SplitSect()
539 |* Ersterstellung AMA 29. Apr. 99
540 |* Letzte Aenderung AMA 29. Apr. 99
542 |* Zerteilt einen SectionFrm in zwei Teile, der zweite Teil beginnt mit dem
543 |* uebergebenen Frame.
544 |* Benoetigt wird dies beim Einfuegen eines inneren Bereichs, weil innerhalb
545 |* von Rahmen oder Tabellenzellen das MoveFwd nicht den erwuenschten Effekt
546 |* haben kann.
548 |*************************************************************************/
550 BOOL SwSectionFrm::SplitSect( SwFrm* pFrm, BOOL bApres )
552 ASSERT( pFrm, "SplitSect: Why?" );
553 SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
554 if( !pOther )
555 return FALSE;
556 SwSectionFrm* pSect = pOther->FindSctFrm();
557 if( pSect != this )
558 return FALSE;
559 // Den Inhalt zur Seite stellen
560 SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
561 ASSERT( pSav, "SplitSect: What's on?" );
562 if( pSav ) // Robust
563 { // Einen neuen SctFrm anlegen, nicht als Follow/Master
564 SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection() );
565 pNew->InsertBehind( pSect->GetUpper(), pSect );
566 pNew->Init();
567 SWRECTFN( this )
568 (pNew->*fnRect->fnMakePos)( NULL, pSect, TRUE );
569 // OD 25.03.2003 #108339# - restore content:
570 // determine layout frame for restoring content after the initialization
571 // of the section frame. In the section initialization the columns are
572 // created.
574 SwLayoutFrm* pLay = pNew;
575 // Search for last layout frame, e.g. for columned sections.
576 while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
577 pLay = (SwLayoutFrm*)pLay->Lower();
578 ::RestoreCntnt( pSav, pLay, NULL, true );
580 _InvalidateSize();
581 if( HasFollow() )
583 pNew->SetFollow( GetFollow() );
584 SetFollow( NULL );
586 return TRUE;
588 return FALSE;
591 /*************************************************************************
593 |* SwSectionFrm::MoveCntntAndDelete()
595 |* Ersterstellung AMA 29. Jan 99
596 |* Letzte Aenderung AMA 29. Jan 99
598 |* MoveCntnt wird zur Zerstoerung eines SectionFrms wg. Aufhebung oder
599 |* Verstecken des Bereichs gerufen, um den Inhalt umzuhaengen.
600 |* Wenn der SectionFrm keinen anderen aufbrach, so wird der Inhalt in
601 |* den Upper bewegt. Anderfalls wird der Inhalt in den anderen SectionFrm
602 |* umgehaengt, dieser muss ggf. gemergt werden.
604 |*************************************************************************/
605 // Wenn ein mehrspaltiger Bereich aufgehoben wird, muessen die ContentFrms
606 // invalidiert werden
608 void lcl_InvalidateInfFlags( SwFrm* pFrm, BOOL bInva )
610 while ( pFrm )
612 pFrm->InvalidateInfFlags();
613 if( bInva )
615 pFrm->_InvalidatePos();
616 pFrm->_InvalidateSize();
617 pFrm->_InvalidatePrt();
619 if( pFrm->IsLayoutFrm() )
620 lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), FALSE );
621 pFrm = pFrm->GetNext();
627 // Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
629 SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
631 if ( bFwd )
633 if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
634 return (SwCntntFrm*)pLay->GetNext();
636 else
638 if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
639 return (SwCntntFrm*)pLay->GetPrev();
642 // #100926#
643 const SwFrm* pFrm = pLay;
644 SwCntntFrm *pCntntFrm = 0;
645 BOOL bGoingUp = TRUE;
646 do {
647 const SwFrm *p = 0;
648 BOOL bGoingFwdOrBwd = FALSE, bGoingDown = FALSE;
650 bGoingDown = !bGoingUp && ( 0 != ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
651 if ( !bGoingDown )
653 bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
654 ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
655 ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
656 if ( !bGoingFwdOrBwd )
658 bGoingUp = (0 != (p = pFrm->GetUpper() ) );
659 if ( !bGoingUp )
660 return 0;
664 bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
666 if( !bFwd && bGoingDown && p )
667 while ( p->GetNext() )
668 p = p->GetNext();
670 pFrm = p;
671 } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
673 return pCntntFrm;
676 #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
677 ? pLayFrm->GetNextLayoutLeaf() \
678 : pLayFrm )
680 void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, BOOL bSave )
682 BOOL bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
683 SwFrm* pPrv = pDel->GetPrev();
684 SwLayoutFrm* pUp = pDel->GetUpper();
685 // OD 27.03.2003 #i12711# - initialize local pointer variables.
686 SwSectionFrm* pPrvSct = NULL;
687 SwSectionFrm* pNxtSct = NULL;
688 SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
689 if( pDel->IsInTab() && pParent )
691 SwTabFrm *pTab = pDel->FindTabFrm();
692 // Wenn wir innerhalb einer Tabelle liegen, koennen wir nur Bereiche
693 // aufgebrochen haben, die ebenfalls innerhalb liegen, nicht etwa
694 // einen Bereich, der die gesamte Tabelle umfasst.
695 if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
696 pParent = NULL;
698 // Wenn unser Format einen Parent besitzt, so haben wir vermutlich
699 // einen anderen SectionFrm aufgebrochen, dies muss geprueft werden,
700 // dazu besorgen wir uns zunaechst den vorhergehende und den nach-
701 // folgenden CntntFrm, mal sehen, ob diese in SectionFrms liegen.
702 // OD 27.03.2003 #i12711# - check, if previous and next section belonging
703 // together and can be joined, *not* only if deleted section contains content.
704 if ( pParent )
706 SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
707 pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
708 SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
709 pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
711 else
713 pParent = NULL;
714 pPrvSct = pNxtSct = NULL;
717 // Jetzt wird der Inhalt beseite gestellt und der Frame zerstoert
718 SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
719 BOOL bOldFtn = TRUE;
720 if( pSave && pUp->IsFtnFrm() )
722 bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
723 ((SwFtnFrm*)pUp)->ColLock();
725 pDel->DelEmpty( TRUE );
726 delete pDel;
727 if( pParent )
728 { // Hier wird die geeignete Einfuegeposition gesucht
729 if( pNxtSct && pNxtSct->GetFmt() == pParent )
730 { // Hier koennen wir uns am Anfang einfuegen
731 pUp = FIRSTLEAF( pNxtSct );
732 pPrv = NULL;
733 if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
734 pPrvSct = NULL; // damit nicht gemergt wird
736 else if( pPrvSct && pPrvSct->GetFmt() == pParent )
737 { // Wunderbar, hier koennen wir uns am Ende einfuegen
738 pUp = pPrvSct;
739 if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
741 pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
742 // Der Body der letzten Spalte
743 pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
745 // damit hinter dem letzten eingefuegt wird
746 pPrv = pUp->GetLastLower();
747 pPrvSct = NULL; // damit nicht gemergt wird
749 else
751 if( pSave )
752 { // Folgende Situationen: Vor und hinter dem zu loeschenden Bereich
753 // ist entweder die Bereichsgrenze des umfassenden Bereichs oder
754 // es schliesst ein anderer (Geschwister-)Bereich direkt an, der
755 // vom gleichen Parent abgeleitet ist.
756 // Dann gibt es (noch) keinen Teil unseres Parents, der den Inhalt
757 // aufnehmen kann,also bauen wir ihn uns.
758 pPrvSct = new SwSectionFrm( *pParent->GetSection() );
759 pPrvSct->InsertBehind( pUp, pPrv );
760 pPrvSct->Init();
761 SWRECTFN( pUp )
762 (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, TRUE );
763 pUp = FIRSTLEAF( pPrvSct );
764 pPrv = NULL;
766 pPrvSct = NULL; // damit nicht gemergt wird
769 // Der Inhalt wird eingefuegt..
770 if( pSave )
772 lcl_InvalidateInfFlags( pSave, bSize );
773 ::RestoreCntnt( pSave, pUp, pPrv, true );
774 pUp->FindPageFrm()->InvalidateCntnt();
775 if( !bOldFtn )
776 ((SwFtnFrm*)pUp)->ColUnlock();
778 // jetzt koennen eventuell zwei Teile des uebergeordneten Bereich verschmelzen
779 if( pPrvSct && !pPrvSct->IsJoinLocked() )
781 ASSERT( pNxtSct, "MoveCntnt: No Merge" );
782 pPrvSct->MergeNext( pNxtSct );
786 void SwSectionFrm::MakeAll()
788 if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
789 return;
790 if( !pSection ) // Durch DelEmpty
792 ASSERT( GetFmt()->GetDoc()->GetRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
793 if( !bValidPos )
795 if( GetUpper() )
797 SWRECTFN( GetUpper() )
798 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), FALSE );
801 bValidSize = bValidPos = bValidPrtArea = TRUE;
802 return;
804 LockJoin(); //Ich lass mich nicht unterwegs vernichten.
806 while( GetNext() && GetNext() == GetFollow() )
808 const SwFrm* pFoll = GetFollow();
809 MergeNext( (SwSectionFrm*)GetNext() );
810 if( pFoll == GetFollow() )
811 break;
814 // OD 2004-03-15 #116561# - In online layout join the follows, if section
815 // can grow.
816 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
817 ( Grow( LONG_MAX, true ) > 0 ) )
819 while( GetFollow() )
821 const SwFrm* pFoll = GetFollow();
822 MergeNext( GetFollow() );
823 if( pFoll == GetFollow() )
824 break;
828 // Ein Bereich mit Follow nimmt allen Platz bis zur Unterkante des Uppers
829 // in Anspruch. Bewegt er sich, so kann seine Groesse zu- oder abnehmen...
830 if( !bValidPos && ToMaximize( FALSE ) )
831 bValidSize = FALSE;
833 #if OSL_DEBUG_LEVEL > 1
834 const SwFmtCol &rCol = GetFmt()->GetCol();
835 (void)rCol;
836 #endif
837 SwLayoutFrm::MakeAll();
838 UnlockJoin();
839 if( pSection && IsSuperfluous() )
840 DelEmpty( FALSE );
843 BOOL SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, BOOL , BOOL & )
845 ASSERT( FALSE, "Hups, wo ist meine Tarnkappe?" );
846 return FALSE;
849 const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
851 const SwSectionFmt *pFmt = pSection->GetFmt();
852 while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
854 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
855 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
856 else
857 return NULL;
859 return pFmt;
862 void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
863 SwFrm* pFrm, BOOL &rbChkFtn )
865 if( pFrm )
867 while( pFrm->GetNext() )
868 pFrm = pFrm->GetNext();
869 while( !rpCntntFrm && pFrm )
871 if( pFrm->IsCntntFrm() )
872 rpCntntFrm = (SwCntntFrm*)pFrm;
873 else if( pFrm->IsLayoutFrm() )
875 if( pFrm->IsFtnFrm() )
877 if( rbChkFtn )
879 rpFtnFrm = (SwFtnFrm*)pFrm;
880 rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
883 else
884 lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
885 ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
887 pFrm = pFrm->GetPrev();
892 SwCntntFrm *SwSectionFrm::FindLastCntnt( BYTE nMode )
894 SwCntntFrm *pRet = NULL;
895 SwFtnFrm *pFtnFrm = NULL;
896 SwSectionFrm *pSect = this;
897 if( nMode )
899 const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
900 pSection->GetFmt();
901 do {
902 while( pSect->HasFollow() )
903 pSect = pSect->GetFollow();
904 SwFrm* pTmp = pSect->FindNext();
905 while( pTmp && pTmp->IsSctFrm() &&
906 !((SwSectionFrm*)pTmp)->GetSection() )
907 pTmp = pTmp->FindNext();
908 if( pTmp && pTmp->IsSctFrm() &&
909 ((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
910 pSect = (SwSectionFrm*)pTmp;
911 else
912 break;
913 } while( TRUE );
915 BOOL bFtnFound = nMode == FINDMODE_ENDNOTE;
918 lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
919 if( pRet || !pSect->IsFollow() || !nMode ||
920 ( FINDMODE_MYLAST == nMode && this == pSect ) )
921 break;
922 pSect = pSect->FindMaster();
923 } while( pSect );
924 if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
925 pRet = pFtnFrm->ContainsCntnt();
926 return pRet;
929 BOOL SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
931 if( ToMaximize( TRUE ) )
933 SWRECTFN( this )
934 rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
935 rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
936 return TRUE;
938 return FALSE;
941 /*************************************************************************
943 * SwSectionFrm::CollectEndnotes( )
945 * Ersterstellung AMA 03. Nov 99
946 * Letzte Aenderung AMA 03. Nov 99
948 * CollectEndnotes looks for endnotes in the sectionfrm and his follows,
949 * the endnotes will cut off the layout and put into the array.
950 * If the first endnote is not a master-SwFtnFrm, the whole sectionfrm
951 * contains only endnotes and it is not necessary to collect them.
953 *************************************************************************/
955 SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, BOOL &rbEmpty,
956 SwLayouter *pLayouter )
958 // if rEmpty is set, the rpSect is already searched
959 SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
960 while( pSect )
962 ASSERT( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
963 "InsertEndnotes: Where's my column?" );
965 // i73332: Columned section in endnote
966 SwColumnFrm* pCol = 0;
967 if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
968 pCol = (SwColumnFrm*)pSect->Lower();
970 while( pCol ) // check all columns
972 SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
973 if( pFtnCont )
975 SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
976 while( pRet ) // look for endnotes
978 if( pRet->GetAttr()->GetFtn().IsEndNote() )
980 if( pRet->GetMaster() )
982 if( pLayouter )
983 pLayouter->CollectEndnote( pRet );
984 else
985 return 0;
987 else
988 return pRet; // Found
990 pRet = (SwFtnFrm*)pRet->GetNext();
993 pCol = (SwColumnFrm*)pCol->GetNext();
995 rpSect = pSect;
996 pSect = pLayouter ? pSect->GetFollow() : NULL;
997 rbEmpty = TRUE;
999 return NULL;
1002 void lcl_ColumnRefresh( SwSectionFrm* pSect, BOOL bFollow )
1004 while( pSect )
1006 BOOL bOldLock = pSect->IsColLocked();
1007 pSect->ColLock();
1008 if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
1010 SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
1012 { pCol->_InvalidateSize();
1013 pCol->_InvalidatePos();
1014 ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
1015 pCol->Calc(); // calculation of column and
1016 ((SwLayoutFrm*)pCol)->Lower()->Calc(); // body
1017 pCol = (SwColumnFrm*)pCol->GetNext();
1018 } while ( pCol );
1020 if( !bOldLock )
1021 pSect->ColUnlock();
1022 if( bFollow )
1023 pSect = pSect->GetFollow();
1024 else
1025 pSect = NULL;
1029 void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
1031 ASSERT( IsColLocked(), "CollectEndnotes: You love the risk?" );
1032 // i73332: Section in footnode does not have columns!
1033 ASSERT( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );
1035 SwSectionFrm* pSect = this;
1036 SwFtnFrm* pFtn;
1037 BOOL bEmpty = FALSE;
1038 // pSect is the last sectionfrm without endnotes or the this-pointer
1039 // the first sectionfrm with endnotes may be destroyed, when the endnotes
1040 // is cutted
1041 while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
1042 pLayouter->CollectEndnote( pFtn );
1043 if( pLayouter->HasEndnotes() )
1044 lcl_ColumnRefresh( this, TRUE );
1047 /*************************************************************************
1049 |* SwSectionFrm::_CheckClipping( BOOL bGrow, BOOL bMaximize )
1051 |* Beschreibung: Passt die Groesse an die Umgebung an.
1052 |* Wer einen Follow oder Fussnoten besitzt, soll bis zur Unterkante
1053 |* des Uppers gehen (bMaximize).
1054 |* Niemand darf ueber den Upper hinausgehen, ggf. darf man versuchen (bGrow)
1055 |* seinen Upper zu growen.
1056 |* Wenn die Groesse veraendert werden musste, wird der Inhalt kalkuliert.
1058 |*************************************************************************/
1060 /// OD 18.09.2002 #100522#
1061 /// perform calculation of content, only if height has changed.
1062 void SwSectionFrm::_CheckClipping( BOOL bGrow, BOOL bMaximize )
1064 SWRECTFN( this )
1065 long nDiff;
1066 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1067 if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
1068 !FindFlyFrm()->IsLocked() ) )
1070 nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1071 if( !bMaximize )
1072 nDiff += Undersize();
1073 if( nDiff > 0 )
1075 long nAdd = GetUpper()->Grow( nDiff );
1076 if( bVert && !bRev )
1077 nDeadLine -= nAdd;
1078 else
1079 nDeadLine += nAdd;
1082 nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1083 SetUndersized( !bMaximize && nDiff >= 0 );
1084 const bool bCalc = ( IsUndersized() || bMaximize ) &&
1085 ( nDiff ||
1086 (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
1087 // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
1088 // that a calculation has to be done beside the value of <bCalc>.
1089 bool bExtraCalc = false;
1090 if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
1092 SwSectionFrm *pSect = this;
1093 BOOL bEmpty = FALSE;
1094 SwLayoutFrm* pFtn = IsEndnAtEnd() ?
1095 lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
1096 if( pFtn )
1098 pFtn = pFtn->FindFtnBossFrm();
1099 SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
1100 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
1101 if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
1102 bExtraCalc = true;
1104 else if( GetFollow() && !GetFollow()->ContainsAny() )
1105 bExtraCalc = true;
1107 if ( bCalc || bExtraCalc )
1109 nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
1110 if( nDiff < 0 )
1112 nDiff = 0;
1113 nDeadLine = (Frm().*fnRect->fnGetTop)();
1115 const Size aOldSz( Prt().SSize() );
1116 long nTop = (this->*fnRect->fnGetTopMargin)();
1117 (Frm().*fnRect->fnSetBottom)( nDeadLine );
1118 nDiff = (Frm().*fnRect->fnGetHeight)();
1119 if( nTop > nDiff )
1120 nTop = nDiff;
1121 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1123 // OD 18.09.2002 #100522#
1124 // Determine, if height has changed.
1125 // Note: In vertical layout the height equals the width value.
1126 bool bHeightChanged = bVert ?
1127 (aOldSz.Width() != Prt().Width()) :
1128 (aOldSz.Height() != Prt().Height());
1129 // Wir haben zu guter Letzt noch einmal die Hoehe geaendert,
1130 // dann wird das innere Layout (Columns) kalkuliert und
1131 // der Inhalt ebenfalls.
1132 // OD 18.09.2002 #100522#
1133 // calculate content, only if height has changed.
1134 // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
1135 // If an endnote has an incorrect position or a follow section contains
1136 // no content except footnotes/endnotes, the content has also been calculated.
1137 if ( ( bHeightChanged || bExtraCalc ) && Lower() )
1139 if( Lower()->IsColumnFrm() )
1141 lcl_ColumnRefresh( this, FALSE );
1142 ::CalcCntnt( this );
1144 else
1146 ChgLowersProp( aOldSz );
1147 if( !bMaximize && !IsCntntLocked() )
1148 ::CalcCntnt( this );
1154 void SwSectionFrm::SimpleFormat()
1156 if ( IsJoinLocked() || IsColLocked() )
1157 return;
1158 // ASSERT( pFollow, "SimpleFormat: Follow required" );
1159 LockJoin();
1160 SWRECTFN( this )
1161 if( GetPrev() || GetUpper() )
1163 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), FALSE );
1164 bValidPos = TRUE;
1166 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1167 // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
1168 // order to get calculated lowers, not only if there space left in its upper.
1169 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
1171 (Frm().*fnRect->fnSetBottom)( nDeadLine );
1172 long nHeight = (Frm().*fnRect->fnGetHeight)();
1173 long nTop = CalcUpperSpace();
1174 if( nTop > nHeight )
1175 nTop = nHeight;
1176 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1178 lcl_ColumnRefresh( this, FALSE );
1179 UnlockJoin();
1182 // --> OD 2005-01-11 #i40147# - helper class to perform extra section format
1183 // to position anchored objects and to keep the position of whose objects locked.
1184 class ExtraFormatToPositionObjs
1186 private:
1187 SwSectionFrm* mpSectFrm;
1188 bool mbExtraFormatPerformed;
1190 public:
1191 ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
1192 : mpSectFrm( &_rSectFrm ),
1193 mbExtraFormatPerformed( false )
1196 ~ExtraFormatToPositionObjs()
1198 if ( mbExtraFormatPerformed )
1200 // release keep locked position of lower floating screen objects
1201 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1202 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1203 if ( pObjs )
1205 sal_uInt32 i = 0;
1206 for ( i = 0; i < pObjs->Count(); ++i )
1208 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1210 if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1212 pAnchoredObj->SetKeepPosLocked( false );
1219 // --> OD 2008-06-20 #i81555#
1220 void InitObjs( SwFrm& rFrm )
1222 SwSortedObjs* pObjs = rFrm.GetDrawObjs();
1223 if ( pObjs )
1225 sal_uInt32 i = 0;
1226 for ( i = 0; i < pObjs->Count(); ++i )
1228 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1230 pAnchoredObj->UnlockPosition();
1231 pAnchoredObj->SetClearedEnvironment( false );
1234 SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
1235 if ( pLayoutFrm != 0 )
1237 SwFrm* pLowerFrm = pLayoutFrm->GetLower();
1238 while ( pLowerFrm != 0 )
1240 InitObjs( *pLowerFrm );
1242 pLowerFrm = pLowerFrm->GetNext();
1246 // <--
1248 void FormatSectionToPositionObjs()
1250 // perform extra format for multi-columned section.
1251 if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
1252 mpSectFrm->Lower()->GetNext() )
1254 // grow section till bottom of printing area of upper frame
1255 SWRECTFN( mpSectFrm );
1256 SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
1257 Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
1258 SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
1259 (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
1260 (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
1261 (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
1262 // --> OD 2006-05-08 #i59789#
1263 // suppress formatting, if printing area of section is too narrow
1264 if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
1266 return;
1268 // <--
1269 mpSectFrm->ChgLowersProp( aOldSectPrtSize );
1271 // format column frames and its body and footnote container
1272 SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
1273 while ( pColFrm )
1275 pColFrm->Calc();
1276 pColFrm->Lower()->Calc();
1277 if ( pColFrm->Lower()->GetNext() )
1279 pColFrm->Lower()->GetNext()->Calc();
1282 pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
1285 // unlock position of lower floating screen objects for the extra format
1286 // --> OD 2008-06-20 #i81555#
1287 // Section frame can already have changed the page and its content
1288 // can still be on the former page.
1289 // Thus, initialize objects via lower-relationship
1290 InitObjs( *mpSectFrm );
1291 // <--
1293 // format content - first with collecting its foot-/endnotes before content
1294 // format, second without collecting its foot-/endnotes.
1295 ::CalcCntnt( mpSectFrm );
1296 ::CalcCntnt( mpSectFrm, true );
1298 // keep locked position of lower floating screen objects
1299 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1300 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1301 if ( pObjs )
1303 sal_uInt32 i = 0;
1304 for ( i = 0; i < pObjs->Count(); ++i )
1306 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1308 if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1310 pAnchoredObj->SetKeepPosLocked( true );
1315 mbExtraFormatPerformed = true;
1320 /*************************************************************************
1322 |* SwSectionFrm::Format()
1324 |* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
1325 |* Ersterstellung AMA 03. Dec. 97
1326 |* Letzte Aenderung MA 09. Oct. 98
1328 |*************************************************************************/
1330 void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
1332 if( !pSection ) // Durch DelEmpty
1334 ASSERT( GetFmt()->GetDoc()->GetRootFrm()->IsInDelList( this ),
1335 "SectionFrm without Section" );
1336 bValidSize = bValidPos = bValidPrtArea = TRUE;
1337 return;
1339 SWRECTFN( this )
1340 if ( !bValidPrtArea )
1342 PROTOCOL( this, PROT_PRTAREA, 0, 0 )
1343 bValidPrtArea = TRUE;
1344 SwTwips nUpper = CalcUpperSpace();
1346 // #109700# LRSpace for sections
1347 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1348 (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
1350 if( nUpper != (this->*fnRect->fnGetTopMargin)() )
1352 bValidSize = FALSE;
1353 SwFrm* pOwn = ContainsAny();
1354 if( pOwn )
1355 pOwn->_InvalidatePos();
1357 (this->*fnRect->fnSetYMargins)( nUpper, 0 );
1360 if ( !bValidSize )
1362 PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
1363 const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
1364 BOOL bOldLock = IsColLocked();
1365 ColLock();
1367 bValidSize = TRUE;
1369 //die Groesse wird nur dann vom Inhalt bestimmt, wenn der SectFrm
1370 //keinen Follow hat. Anderfalls fuellt er immer den Upper bis
1371 //zur Unterkante aus. Fuer den Textfluss ist nicht er, sondern sein
1372 //Inhalt selbst verantwortlich.
1373 BOOL bMaximize = ToMaximize( FALSE );
1375 // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
1376 // on object positioning, an extra formatting has to be performed
1377 // to determine the correct positions the floating screen objects.
1378 // --> OD 2005-01-11 #i40147#
1379 // use new helper class <ExtraFormatToPositionObjs>.
1380 // This class additionally keep the locked position of the objects
1381 // and releases this position lock keeping on destruction.
1382 ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
1383 if ( !bMaximize &&
1384 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
1385 !GetFmt()->GetBalancedColumns().GetValue() )
1387 aExtraFormatToPosObjs.FormatSectionToPositionObjs();
1389 // <--
1391 // Column widths have to be adjusted before calling _CheckClipping.
1392 // _CheckClipping can cause the formatting of the lower frames
1393 // which still have a width of 0.
1394 const sal_Bool bHasColumns = Lower() && Lower()->IsColumnFrm();
1395 if ( bHasColumns && Lower()->GetNext() )
1396 AdjustColumns( 0, FALSE );
1398 if( GetUpper() )
1400 long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1401 (aFrm.*fnRect->fnSetWidth)( nWidth );
1403 // #109700# LRSpace for sections
1404 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1405 (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
1406 rLRSpace.GetRight() );
1408 // OD 15.10.2002 #103517# - allow grow in online layout
1409 // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
1410 // method <_CheckClipping(..)>.
1411 _CheckClipping( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE), bMaximize );
1412 bMaximize = ToMaximize( FALSE );
1413 bValidSize = TRUE;
1416 //Breite der Spalten pruefen und ggf. einstellen.
1417 if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
1418 ((SwColumnFrm*)Lower())->Lower()->Calc();
1420 if ( !bMaximize )
1422 SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
1423 SwFrm *pFrm = pLower;
1424 if( pFrm )
1426 if( pFrm->IsColumnFrm() && pFrm->GetNext() )
1428 // --> OD 2006-05-08 #i61435#
1429 // suppress formatting, if upper frame has height <= 0
1430 if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
1432 FormatWidthCols( *pAttr, nRemaining, MINLAY );
1434 // <--
1435 // --> OD 2006-01-04 #126020# - adjust check for empty section
1436 // --> OD 2006-02-01 #130797# - correct fix #126020#
1437 while( HasFollow() && !GetFollow()->ContainsCntnt() &&
1438 !GetFollow()->ContainsAny( true ) )
1439 // <--
1441 SwFrm* pOld = GetFollow();
1442 GetFollow()->DelEmpty( FALSE );
1443 if( pOld == GetFollow() )
1444 break;
1446 bMaximize = ToMaximize( FALSE );
1447 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
1449 else
1451 if( pFrm->IsColumnFrm() )
1453 pFrm->Calc();
1454 pFrm = ((SwColumnFrm*)pFrm)->Lower();
1455 pFrm->Calc();
1456 pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1457 CalcFtnCntnt();
1459 // Wenn wir in einem spaltigen Rahmen stehen und dieser
1460 // gerade im FormatWidthCols ein CalcCntnt ruft, muss
1461 // unser Inhalt ggf. kalkuliert werden.
1462 if( pFrm && !pFrm->IsValid() && IsInFly() &&
1463 FindFlyFrm()->IsColLocked() )
1464 ::CalcCntnt( this );
1465 nRemaining += InnerHeight();
1466 bMaximize = HasFollow();
1470 SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
1471 if( nDiff < 0)
1473 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1475 long nBottom = (Frm().*fnRect->fnGetBottom)();
1476 nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
1477 long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1478 if( nTmpDiff > 0 )
1480 nTmpDiff = GetUpper()->Grow( nTmpDiff, TRUE );
1481 nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
1482 nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1483 if( nTmpDiff > 0 )
1484 nDiff += nTmpDiff;
1485 if( nDiff > 0 )
1486 nDiff = 0;
1490 if( nDiff )
1492 long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
1493 long nTop = (this->*fnRect->fnGetTopMargin)();
1494 (Frm().*fnRect->fnAddBottom)( nTmp );
1495 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1496 InvalidateNextPos();
1497 if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
1499 // Wenn ein einspaltiger Bereich gerade den Platz geschaffen
1500 // hat, den sich die "undersized" Absaetze gewuenscht haben,
1501 // muessen diese invalidiert und kalkuliert werden, damit
1502 // sie diesen ausfuellen.
1503 pFrm = pLower;
1504 if( pFrm->IsColumnFrm() )
1506 pFrm->_InvalidateSize();
1507 pFrm->_InvalidatePos();
1508 pFrm->Calc();
1509 pFrm = ((SwColumnFrm*)pFrm)->Lower();
1510 pFrm->Calc();
1511 pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1512 CalcFtnCntnt();
1514 BOOL bUnderSz = FALSE;
1515 while( pFrm )
1517 if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
1519 pFrm->Prepare( PREP_ADJUST_FRM );
1520 bUnderSz = TRUE;
1522 pFrm = pFrm->GetNext();
1524 if( bUnderSz && !IsCntntLocked() )
1525 ::CalcCntnt( this );
1530 //Unterkante des Uppers nicht ueberschreiten. Fuer Sections mit
1531 //Follows die Unterkante auch nicht unterschreiten.
1532 if ( GetUpper() )
1533 _CheckClipping( TRUE, bMaximize );
1534 if( !bOldLock )
1535 ColUnlock();
1536 long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
1537 if( nDiff > 0 )
1539 if( !GetNext() )
1540 SetRetouche(); // Dann muessen wir die Retusche selbst uebernehmen
1541 if( GetUpper() && !GetUpper()->IsFooterFrm() )
1542 GetUpper()->Shrink( nDiff );
1544 if( IsUndersized() )
1545 bValidPrtArea = TRUE;
1549 /*************************************************************************
1551 |* SwFrm::GetNextSctLeaf()
1553 |* Beschreibung Liefert das naechste Layoutblatt in das der Frame
1554 |* gemoved werden kann.
1555 |* Neue Seiten werden nur dann erzeugt, wenn der Parameter TRUE ist.
1556 |* Ersterstellung AMA 07. Jan. 98
1557 |* Letzte Aenderung AMA 07. Jan. 98
1559 |*************************************************************************/
1562 SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
1564 //Achtung: Geschachtelte Bereiche werden zur Zeit nicht unterstuetzt.
1566 PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )
1568 // Abkuerzungen fuer spaltige Bereiche, wenn wir noch nicht in der letzten Spalte sind.
1569 // Koennen wir in die naechste Spalte des Bereichs rutschen?
1570 if( IsColBodyFrm() && GetUpper()->GetNext() )
1571 return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
1572 if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
1573 return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
1574 // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
1575 // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette zuschlagen muessen
1576 if( GetUpper()->IsInTab() || FindFooterOrHeader() )
1577 return 0;
1579 //MA 03. Feb. 99: Warum GetUpper()? Das knallt mit Buch.sgl weil im
1580 //FlyAtCnt::MakeFlyPos ein Orient der SectionFrm ist und auf diesen ein
1581 //GetLeaf gerufen wird.
1582 // SwSectionFrm *pSect = GetUpper()->FindSctFrm();
1583 SwSectionFrm *pSect = FindSctFrm();
1584 BOOL bWrongPage = FALSE;
1585 ASSERT( pSect, "GetNextSctLeaf: Missing SectionFrm" );
1587 // Hier eine Abkuerzung fuer Bereiche mit Follows,
1588 // dieser kann akzeptiert werden, wenn keine Spalten oder Seiten (ausser Dummyseiten)
1589 // dazwischen liegen.
1590 // Bei verketteten Rahmen und ind Fussnoten wuerde die Abkuerzung noch aufwendiger
1591 if( pSect->HasFollow() && pSect->IsInDocBody() )
1593 if( pSect->GetFollow() == pSect->GetNext() )
1595 SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
1596 if( WrongPageDesc( pPg ) )
1597 bWrongPage = TRUE;
1598 else
1599 return FIRSTLEAF( pSect->GetFollow() );
1601 else
1603 SwFrm* pTmp;
1604 if( !pSect->GetUpper()->IsColBodyFrm() ||
1605 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
1606 pTmp = pSect->FindPageFrm()->GetNext();
1607 if( pTmp ) // ist jetzt die naechste Spalte oder Seite
1609 SwFrm* pTmpX = pTmp;
1610 if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
1611 pTmp = pTmp->GetNext(); // Dummyseiten ueberspringen
1612 SwFrm *pUp = pSect->GetFollow()->GetUpper();
1613 // pUp wird die Spalte, wenn der Follow in einer "nicht ersten" Spalte
1614 // liegt, ansonsten die Seite:
1615 if( !pUp->IsColBodyFrm() ||
1616 !( pUp = pUp->GetUpper() )->GetPrev() )
1617 pUp = pUp->FindPageFrm();
1618 // Jetzt muessen pUp und pTmp die gleiche Seite/Spalte sein,
1619 // sonst liegen Seiten oder Spalten zwischen Master und Follow.
1620 if( pUp == pTmp || pUp->GetNext() == pTmpX )
1622 SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
1623 (SwPageFrm*)pUp : pUp->FindPageFrm();
1624 if( WrongPageDesc( pNxtPg ) )
1625 bWrongPage = TRUE;
1626 else
1627 return FIRSTLEAF( pSect->GetFollow() );
1633 // Immer im gleichen Bereich landen: Body wieder in Body etc.
1634 const BOOL bBody = IsInDocBody();
1635 const BOOL bFtnPage = FindPageFrm()->IsFtnPage();
1637 SwLayoutFrm *pLayLeaf;
1638 // Eine Abkuerzung fuer TabFrms, damit nicht alle Zellen abgehuehnert werden
1639 if( bWrongPage )
1640 pLayLeaf = 0;
1641 else if( IsTabFrm() )
1643 SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
1644 pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
1646 else
1648 pLayLeaf = GetNextLayoutLeaf();
1649 if( IsColumnFrm() )
1651 while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
1652 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1656 SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten
1657 //nicht wieder vom Anfang gesucht
1658 //wird.
1660 while( TRUE )
1662 if( pLayLeaf )
1664 // Ein Layoutblatt wurde gefunden, mal sehen, ob er mich aufnehmen kann,
1665 // ob hier ein weiterer SectionFrm eingefuegt werden kann
1666 // oder ob wir weitersuchen muessen.
1667 SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
1668 if ( !bFtnPage && pNxtPg->IsFtnPage() )
1669 { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
1670 pLayLeaf = 0;
1671 continue;
1673 // Einmal InBody, immer InBody, nicht in Tabellen hinein
1674 // und nicht in fremde Bereiche hinein
1675 if ( (bBody && !pLayLeaf->IsInDocBody()) ||
1676 (IsInFtn() != pLayLeaf->IsInFtn() ) ||
1677 pLayLeaf->IsInTab() ||
1678 ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
1679 || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
1681 //Er will mich nicht; neuer Versuch, neues Glueck
1682 pOldLayLeaf = pLayLeaf;
1683 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1684 continue;
1686 if( WrongPageDesc( pNxtPg ) )
1688 if( bWrongPage )
1689 break; // there's a column between me and my right page
1690 pLayLeaf = 0;
1691 bWrongPage = TRUE;
1692 pOldLayLeaf = 0;
1693 continue;
1696 //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
1697 //neue Seite her, allerdings nuetzen uns innerhalb eines Rahmens
1698 //neue Seiten nichts.
1699 else if( !pSect->IsInFly() &&
1700 ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
1702 InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1703 FALSE );
1704 //und nochmal das ganze
1705 pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1706 continue;
1708 break;
1711 if( pLayLeaf )
1713 // Das passende Layoutblatt haben wir gefunden, wenn es dort bereits einen
1714 // Follow unseres Bereichs gibt, nehmen wir dessen erstes Layoutblatt,
1715 // andernfalls wird es Zeit, einen Bereichsfollow zu erzeugen
1716 SwSectionFrm* pNew;
1718 //Dies kann entfallen, wenn bei existierenden Follows bereits abgekuerzt wurde
1719 SwFrm* pFirst = pLayLeaf->Lower();
1720 // Auch hier muessen zum Loeschen angemeldete SectionFrms ignoriert werden
1721 while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
1722 pFirst = pFirst->GetNext();
1723 if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst )
1724 pNew = pSect->GetFollow();
1725 else if( MAKEPAGE_NOSECTION == eMakePage )
1726 return pLayLeaf;
1727 else
1729 pNew = new SwSectionFrm( *pSect, FALSE );
1730 pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
1731 pNew->Init();
1732 SWRECTFN( pNew )
1733 (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, TRUE );
1735 // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
1736 // umgehaengt werden hinter den neuen Follow der Bereichsframes.
1737 SwFrm* pTmp = pSect->GetNext();
1738 if( pTmp && pTmp != pSect->GetFollow() )
1740 SwFlowFrm* pNxt;
1741 SwCntntFrm* pNxtCntnt = NULL;
1742 if( pTmp->IsCntntFrm() )
1744 pNxt = (SwCntntFrm*)pTmp;
1745 pNxtCntnt = (SwCntntFrm*)pTmp;
1747 else
1749 pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1750 if( pTmp->IsSctFrm() )
1751 pNxt = (SwSectionFrm*)pTmp;
1752 else
1754 ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
1755 pNxt = (SwTabFrm*)pTmp;
1757 while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
1759 if( pTmp->IsCntntFrm() )
1760 pNxtCntnt = (SwCntntFrm*)pTmp;
1761 else
1762 pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1765 if( pNxtCntnt )
1767 SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( TRUE );
1768 if( pOldBoss == pNxtCntnt->FindFtnBossFrm( TRUE ) )
1770 SwSaveFtnHeight aHeight( pOldBoss,
1771 pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
1772 pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
1773 pLayLeaf->FindFtnBossFrm( TRUE ), FALSE );
1776 ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
1778 if( pNew->GetFollow() )
1779 pNew->SimpleFormat();
1781 // Das gesuchte Layoutblatt ist jetzt das erste des ermittelten SctFrms:
1782 pLayLeaf = FIRSTLEAF( pNew );
1784 return pLayLeaf;
1787 /*************************************************************************
1789 |* SwFrm::GetPrevSctLeaf()
1791 |* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
1792 |* Frame gemoved werden kann.
1793 |* Ersterstellung AMA 07. Jan. 98
1794 |* Letzte Aenderung AMA 07. Jan. 98
1796 |*************************************************************************/
1799 SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
1801 PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )
1803 SwLayoutFrm* pCol;
1804 // ColumnFrm beinhalten jetzt stets einen BodyFrm
1805 if( IsColBodyFrm() )
1806 pCol = GetUpper();
1807 else if( GetUpper()->IsColBodyFrm() )
1808 pCol = GetUpper()->GetUpper();
1809 else
1810 pCol = NULL;
1811 BOOL bJump = FALSE;
1812 if( pCol )
1814 if( pCol->GetPrev() )
1818 pCol = (SwLayoutFrm*)pCol->GetPrev();
1819 // Gibt es dort Inhalt?
1820 if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
1822 if( bJump ) // Haben wir eine leere Spalte uebersprungen?
1823 SwFlowFrm::SetMoveBwdJump( TRUE );
1824 return (SwLayoutFrm*)pCol->Lower(); // Der Spaltenbody
1826 bJump = TRUE;
1827 } while( pCol->GetPrev() );
1829 // Hier landen wir, wenn alle Spalten leer sind,
1830 // pCol ist jetzt die erste Spalte, wir brauchen aber den Body:
1831 pCol = (SwLayoutFrm*)pCol->Lower();
1833 else
1834 pCol = NULL;
1837 if( bJump ) // Haben wir eine leere Spalte uebersprungen?
1838 SwFlowFrm::SetMoveBwdJump( TRUE );
1840 // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
1841 // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette
1842 // zuschlagen muessen, ebenso wenn der Bereich einen pPrev hat.
1843 // Jetzt ziehen wir sogar eine leere Spalte in Betracht...
1844 ASSERT( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
1845 if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
1846 return pCol;
1848 // === IMPORTANT ===
1849 // Precondition, which needs to be hold, is that the <this> frame can be
1850 // inside a table, but then the found section frame <pSect> is also inside
1851 // this table.
1852 SwSectionFrm *pSect = FindSctFrm();
1854 // --> OD 2009-01-16 #i95698#
1855 // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
1856 // Thus, a table inside a section, which is inside another table can only
1857 // flow backward in the columns of its section.
1858 // Note: The table cell, which contains the section, can not have a master table cell.
1859 if ( IsTabFrm() && pSect->IsInTab() )
1861 return pCol;
1863 // <--
1866 SwFrm *pPrv;
1867 if( 0 != ( pPrv = pSect->GetIndPrev() ) )
1869 // Herumlungernde, halbtote SectionFrms sollen uns nicht beirren
1870 while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
1871 pPrv = pPrv->GetPrev();
1872 if( pPrv )
1873 return pCol;
1877 const BOOL bBody = IsInDocBody();
1878 const BOOL bFly = IsInFly();
1880 SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1881 SwLayoutFrm *pPrevLeaf = 0;
1883 while ( pLayLeaf )
1885 //In Tabellen oder Bereiche geht's niemals hinein.
1886 if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
1888 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1890 else if ( bBody && pLayLeaf->IsInDocBody() )
1892 // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
1893 // Exception: pLayLeaf->Lower() is a zombie section frame
1894 const SwFrm* pTmp = pLayLeaf->Lower();
1895 // OD 11.04.2003 #108824# - consider, that the zombie section frame
1896 // can have frame below it in the found layout leaf.
1897 // Thus, skipping zombie section frame, if possible.
1898 while ( pTmp && pTmp->IsSctFrm() &&
1899 !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
1900 pTmp->GetNext()
1903 pTmp = pTmp->GetNext();
1905 if ( pTmp &&
1906 ( !pTmp->IsSctFrm() ||
1907 ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
1911 break;
1913 pPrevLeaf = pLayLeaf;
1914 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1915 if ( pLayLeaf )
1916 SwFlowFrm::SetMoveBwdJump( TRUE );
1918 else if ( bFly )
1919 break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein. Warum?
1920 else
1921 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1923 if( !pLayLeaf )
1925 if( !pPrevLeaf )
1926 return pCol;
1927 pLayLeaf = pPrevLeaf;
1930 SwSectionFrm* pNew = NULL;
1931 // Zunaechst einmal an das Ende des Layoutblatts gehen
1932 SwFrm *pTmp = pLayLeaf->Lower();
1933 if( pTmp )
1935 while( pTmp->GetNext() )
1936 pTmp = pTmp->GetNext();
1937 if( pTmp->IsSctFrm() )
1939 // Halbtote stoeren hier nur...
1940 while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
1941 pTmp->GetPrev()->IsSctFrm() )
1942 pTmp = pTmp->GetPrev();
1943 if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
1944 pNew = (SwSectionFrm*)pTmp;
1947 if( !pNew )
1949 pNew = new SwSectionFrm( *pSect, TRUE );
1950 pNew->InsertBefore( pLayLeaf, NULL );
1951 pNew->Init();
1952 SWRECTFN( pNew )
1953 (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), TRUE );
1955 pLayLeaf = FIRSTLEAF( pNew );
1956 if( !pNew->Lower() ) // einspaltige Bereiche formatieren
1958 pNew->MakePos();
1959 pLayLeaf->Format(); // damit die PrtArea fuers MoveBwd stimmt
1961 else
1962 pNew->SimpleFormat();
1964 else
1966 pLayLeaf = FIRSTLEAF( pNew );
1967 if( pLayLeaf->IsColBodyFrm() )
1969 // In existent section columns we're looking for the last not empty
1970 // column.
1971 SwLayoutFrm *pTmpLay = pLayLeaf;
1972 while( pLayLeaf->GetUpper()->GetNext() )
1974 pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
1975 if( pLayLeaf->Lower() )
1976 pTmpLay = pLayLeaf;
1978 // If we skipped an empty column, we've to set the jump-flag
1979 if( pLayLeaf != pTmpLay )
1981 pLayLeaf = pTmpLay;
1982 SwFlowFrm::SetMoveBwdJump( TRUE );
1986 return pLayLeaf;
1989 SwTwips lcl_DeadLine( const SwFrm* pFrm )
1991 const SwLayoutFrm* pUp = pFrm->GetUpper();
1992 while( pUp && pUp->IsInSct() )
1994 if( pUp->IsSctFrm() )
1995 pUp = pUp->GetUpper();
1996 // Spalten jetzt mit BodyFrm
1997 else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
1998 pUp = pUp->GetUpper()->GetUpper();
1999 else
2000 break;
2002 SWRECTFN( pFrm )
2003 return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
2004 (pFrm->Frm().*fnRect->fnGetBottom)();
2007 // SwSectionFrm::Growable(..) prueft, ob der SectionFrm noch wachsen kann,
2008 // ggf. muss die Umgebung gefragt werden
2010 BOOL SwSectionFrm::Growable() const
2012 SWRECTFN( this )
2013 if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
2014 (Frm().*fnRect->fnGetBottom)() ) > 0 )
2015 return TRUE;
2017 return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, TRUE ) );
2020 /*************************************************************************
2022 |* SwSectionFrm::_Grow(), _Shrink()
2024 |* Ersterstellung AMA 14. Jan. 98
2025 |* Letzte Aenderung AMA 14. Jan. 98
2027 |*************************************************************************/
2029 SwTwips SwSectionFrm::_Grow( SwTwips nDist, BOOL bTst )
2031 if ( !IsColLocked() && !HasFixSize() )
2033 SWRECTFN( this )
2034 long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2035 if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
2036 nDist = LONG_MAX - nFrmHeight;
2038 if ( nDist <= 0L )
2039 return 0L;
2041 BOOL bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
2042 // OD 2004-03-15 #116561# - allow grow in online layout
2043 if ( !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
2044 GetSection()->GetFmt()->GetBalancedColumns().GetValue() ||
2045 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
2047 SwTwips nGrow;
2048 if( IsInFtn() )
2049 nGrow = 0;
2050 else
2052 nGrow = lcl_DeadLine( this );
2053 nGrow = (*fnRect->fnYDiff)( nGrow,
2054 (Frm().*fnRect->fnGetBottom)() );
2056 SwTwips nSpace = nGrow;
2057 if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
2058 nGrow += GetUpper()->Grow( LONG_MAX, TRUE );
2060 if( nGrow > nDist )
2061 nGrow = nDist;
2062 if( nGrow <= 0 )
2064 nGrow = 0;
2065 if( nDist && !bTst )
2067 if( bInCalcCntnt )
2068 _InvalidateSize();
2069 else
2070 InvalidateSize();
2073 else if( !bTst )
2075 if( bInCalcCntnt )
2076 _InvalidateSize();
2077 else if( nSpace < nGrow && nDist != nSpace + GetUpper()->
2078 Grow( nGrow - nSpace, FALSE ) )
2079 InvalidateSize();
2080 else
2082 const SvxGraphicPosition ePos =
2083 GetAttrSet()->GetBackground().GetGraphicPos();
2084 if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2086 SetCompletePaint();
2087 InvalidatePage();
2089 if( GetUpper() && GetUpper()->IsHeaderFrm() )
2090 GetUpper()->InvalidateSize();
2092 (Frm().*fnRect->fnAddBottom)( nGrow );
2093 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
2094 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2096 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2098 SwFrm* pTmp = Lower();
2101 pTmp->_InvalidateSize();
2102 pTmp = pTmp->GetNext();
2103 } while ( pTmp );
2104 _InvalidateSize();
2106 if( GetNext() )
2108 SwFrm *pFrm = GetNext();
2109 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2110 pFrm = pFrm->GetNext();
2111 if( pFrm )
2113 if( bInCalcCntnt )
2114 pFrm->_InvalidatePos();
2115 else
2116 pFrm->InvalidatePos();
2119 // --> OD 2004-07-05 #i28701# - Due to the new object positioning
2120 // the frame on the next page/column can flow backward (e.g. it
2121 // was moved forward due to the positioning of its objects ).
2122 // Thus, invalivate this next frame, if document compatibility
2123 // option 'Consider wrapping style influence on object positioning' is ON.
2124 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2126 InvalidateNextPos();
2128 // <--
2130 return nGrow;
2132 if ( !bTst )
2134 if( bInCalcCntnt )
2135 _InvalidateSize();
2136 else
2137 InvalidateSize();
2140 return 0L;
2143 SwTwips SwSectionFrm::_Shrink( SwTwips nDist, BOOL bTst )
2145 if ( Lower() && !IsColLocked() && !HasFixSize() )
2147 if( ToMaximize( FALSE ) )
2149 if( !bTst )
2150 InvalidateSize();
2152 else
2154 SWRECTFN( this )
2155 long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2156 if ( nDist > nFrmHeight )
2157 nDist = nFrmHeight;
2159 if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
2160 !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
2161 { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
2162 //das Wachstum (wg. des Ausgleichs).
2163 if ( !bTst )
2164 InvalidateSize();
2165 return nDist;
2167 else if( !bTst )
2169 const SvxGraphicPosition ePos =
2170 GetAttrSet()->GetBackground().GetGraphicPos();
2171 if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2173 SetCompletePaint();
2174 InvalidatePage();
2176 (Frm().*fnRect->fnAddBottom)( -nDist );
2177 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
2178 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2180 SwTwips nReal = 0;
2181 // We do not allow a section frame to shrink the its upper
2182 // footer frame. This is because in the calculation of a
2183 // footer frame, the content of the section frame is _not_
2184 // calculated. If there is a fly frame overlapping with the
2185 // footer frame, the section frame is not affected by this
2186 // during the calculation of the footer frame size.
2187 // The footer frame does not grow in its FormatSize function
2188 // but during the calculation of the content of the section
2189 // frame. The section frame grows until some of its text is
2190 // located on top of the fly frame. The next call of CalcCntnt
2191 // tries to shrink the section and here it would also shrink
2192 // the footer. This may not happen, because shrinking the footer
2193 // would cause the top of the section frame to overlap with the
2194 // fly frame again, this would result in a perfect loop.
2195 if( GetUpper() && !GetUpper()->IsFooterFrm() )
2196 nReal = GetUpper()->Shrink( nDist, bTst );
2198 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2200 SwFrm* pTmp = Lower();
2203 pTmp->_InvalidateSize();
2204 pTmp = pTmp->GetNext();
2205 } while ( pTmp );
2207 if( GetNext() )
2209 SwFrm* pFrm = GetNext();
2210 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2211 pFrm = pFrm->GetNext();
2212 if( pFrm )
2213 pFrm->InvalidatePos();
2214 else
2215 SetRetouche();
2217 else
2218 SetRetouche();
2219 return nDist;
2223 return 0L;
2226 /*************************************************************************
2228 |* SwSectionFrm::MoveAllowed()
2230 |* Ersterstellung MA 08. Oct. 98
2231 |* Letzte Aenderung MA 08. Oct. 98
2233 |* Wann sind Frms innerhalb eines SectionFrms moveable?
2234 |* Wenn sie noch nicht in der letzten Spalte des SectionFrms sind,
2235 |* wenn es einen Follow gibt,
2236 |* wenn der SectionFrm nicht mehr wachsen kann, wird es komplizierter,
2237 |* dann kommt es darauf an, ob der SectionFrm ein naechstes Layoutblatt
2238 |* finden kann. In (spaltigen/verketteten) Flys wird dies via GetNextLayout
2239 |* geprueft, in Tabellen und in Kopf/Fusszeilen gibt es keins, im DocBody
2240 |* und auch im Fussnoten dagegen immer.
2242 |* Benutzt wird diese Routine im TxtFormatter, um zu entscheiden, ob ein
2243 |* (Absatz-)Follow erzeugt werden darf oder ob der Absatz zusammenhalten muss.
2245 |*************************************************************************/
2247 BOOL SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
2249 // Gibt es einen Follow oder ist der Frame nicht in der letzten Spalte?
2250 if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
2251 pFrm->GetUpper()->GetUpper()->GetNext() ) )
2252 return TRUE;
2253 if( pFrm->IsInFtn() )
2255 if( IsInFtn() )
2257 if( GetUpper()->IsInSct() )
2259 if( Growable() )
2260 return FALSE;
2261 return GetUpper()->FindSctFrm()->MoveAllowed( this );
2263 else
2264 return TRUE;
2266 // The content of footnote inside a columned sectionfrm is moveable
2267 // except in the last column
2268 const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
2269 if( pLay->IsColumnFrm() && pLay->GetNext() )
2271 // The first paragraph in the first footnote in the first column
2272 // in the sectionfrm at the top of the page is not moveable,
2273 // if the columnbody is empty.
2274 BOOL bRet = FALSE;
2275 if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
2276 pFrm->FindFtnFrm()->GetPrev() )
2277 bRet = TRUE;
2278 else
2280 SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
2281 if( pBody && pBody->Lower() )
2282 bRet = TRUE;
2284 if( bRet && ( IsFtnAtEnd() || !Growable() ) )
2285 return TRUE;
2288 // Oder kann der Bereich noch wachsen?
2289 if( !IsColLocked() && Growable() )
2290 return FALSE;
2291 // Jetzt muss untersucht werden, ob es ein Layoutblatt gibt, in dem
2292 // ein Bereichsfollow erzeugt werden kann.
2293 if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
2294 return FALSE; // In Tabellen/Kopf/Fusszeilen geht es nicht
2295 if( IsInFly() ) // Bei spaltigen oder verketteten Rahmen
2296 return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
2297 return TRUE;
2300 /** Called for a frame inside a section with no direct previous frame (or only
2301 previous empty section frames) the previous frame of the outer section is
2302 returned, if the frame is the first flowing content of this section.
2304 Note: For a frame inside a table frame, which is inside a section frame,
2305 NULL is returned.
2307 SwFrm* SwFrm::_GetIndPrev() const
2309 SwFrm *pRet = NULL;
2310 // --> OD 2007-09-04 #i79774#, #b659654#
2311 // Do not assert, if the frame has a direct previous frame, because it
2312 // could be an empty section frame. The caller has to assure, that the
2313 // frame has no direct previous frame or only empty section frames as
2314 // previous frames.
2315 ASSERT( /*!pPrev &&*/ IsInSct(), "Why?" );
2316 // <--
2317 const SwFrm* pSct = GetUpper();
2318 if( !pSct )
2319 return NULL;
2320 if( pSct->IsSctFrm() )
2321 pRet = pSct->GetIndPrev();
2322 else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2324 // Do not return the previous frame of the outer section, if in one
2325 // of the previous columns is content.
2326 const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
2327 while( pCol )
2329 ASSERT( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
2330 ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2331 "GetIndPrev(): Where's the body?");
2332 if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2333 return NULL;
2334 pCol = pCol->GetPrev();
2336 pRet = pSct->GetIndPrev();
2339 // skip empty section frames
2340 while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
2341 pRet = pRet->GetIndPrev();
2342 return pRet;
2345 SwFrm* SwFrm::_GetIndNext()
2347 ASSERT( !pNext && IsInSct(), "Why?" );
2348 SwFrm* pSct = GetUpper();
2349 if( !pSct )
2350 return NULL;
2351 if( pSct->IsSctFrm() )
2352 return pSct->GetIndNext();
2353 if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2354 { // Wir duerfen nur den Nachfolger des SectionFrms zurueckliefern,
2355 // wenn in keiner folgenden Spalte mehr Inhalt ist
2356 SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
2357 while( pCol )
2359 ASSERT( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
2360 ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2361 "GetIndNext(): Where's the body?");
2362 if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2363 return NULL;
2364 pCol = pCol->GetNext();
2366 return pSct->GetIndNext();
2368 return NULL;
2371 BOOL SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
2373 if( !pSection || !pFmt )
2374 return FALSE;
2375 const SwSectionFmt *pMyFmt = pSection->GetFmt();
2376 while( pFmt != pMyFmt )
2378 if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2379 pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
2380 else
2381 return FALSE;
2383 return TRUE;
2386 void SwSectionFrm::CalcFtnAtEndFlag()
2388 SwSectionFmt *pFmt = GetSection()->GetFmt();
2389 USHORT nVal = pFmt->GetFtnAtTxtEnd( FALSE ).GetValue();
2390 bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
2391 bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2392 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2393 while( !bFtnAtEnd && !bOwnFtnNum )
2395 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2396 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2397 else
2398 break;
2399 nVal = pFmt->GetFtnAtTxtEnd( FALSE ).GetValue();
2400 if( FTNEND_ATPGORDOCEND != nVal )
2402 bFtnAtEnd = TRUE;
2403 bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2404 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2409 BOOL SwSectionFrm::IsEndnoteAtMyEnd() const
2411 return pSection->GetFmt()->GetEndAtTxtEnd( FALSE ).IsAtEnd();
2414 void SwSectionFrm::CalcEndAtEndFlag()
2416 SwSectionFmt *pFmt = GetSection()->GetFmt();
2417 bEndnAtEnd = pFmt->GetEndAtTxtEnd( FALSE ).IsAtEnd();
2418 while( !bEndnAtEnd )
2420 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2421 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2422 else
2423 break;
2424 bEndnAtEnd = pFmt->GetEndAtTxtEnd( FALSE ).IsAtEnd();
2428 /*************************************************************************
2430 |* SwSectionFrm::Modify()
2432 |* Ersterstellung MA 08. Oct. 98
2433 |* Letzte Aenderung MA 08. Oct. 98
2435 |*************************************************************************/
2437 void SwSectionFrm::Modify( SfxPoolItem * pOld, SfxPoolItem * pNew )
2439 BYTE nInvFlags = 0;
2441 if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2443 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2444 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2445 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2446 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2447 while( TRUE )
2449 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2450 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2451 &aOldSet, &aNewSet );
2452 if( aNIter.IsAtEnd() )
2453 break;
2454 aNIter.NextItem();
2455 aOIter.NextItem();
2457 if ( aOldSet.Count() || aNewSet.Count() )
2458 SwLayoutFrm::Modify( &aOldSet, &aNewSet );
2460 else
2461 _UpdateAttr( pOld, pNew, nInvFlags );
2463 if ( nInvFlags != 0 )
2465 if ( nInvFlags & 0x01 )
2466 InvalidateSize();
2467 if ( nInvFlags & 0x10 )
2468 SetCompletePaint();
2472 void SwSectionFrm::_UpdateAttr( SfxPoolItem *pOld, SfxPoolItem *pNew,
2473 BYTE &rInvFlags,
2474 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2476 BOOL bClear = TRUE;
2477 const USHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2478 switch( nWhich )
2479 { // Mehrspaltigkeit in Fussnoten unterdruecken...
2480 case RES_FMT_CHG:
2482 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2483 if( !IsInFtn() )
2485 //Dummer Fall. Bei der Zuweisung einer Vorlage k?nnen wir uns
2486 //nicht auf das alte Spaltenattribut verlassen. Da diese
2487 //wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
2488 //bleibt uns nur einen temporaeres Attribut zu basteln.
2489 SwFmtCol aCol;
2490 if ( Lower() && Lower()->IsColumnFrm() )
2492 USHORT nCol = 0;
2493 SwFrm *pTmp = Lower();
2495 { ++nCol;
2496 pTmp = pTmp->GetNext();
2497 } while ( pTmp );
2498 aCol.Init( nCol, 0, 1000 );
2500 BOOL bChgFtn = IsFtnAtEnd();
2501 BOOL bChgEndn = IsEndnAtEnd();
2502 BOOL bChgMyEndn = IsEndnoteAtMyEnd();
2503 CalcFtnAtEndFlag();
2504 CalcEndAtEndFlag();
2505 bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
2506 ( bChgEndn != IsEndnAtEnd() ) ||
2507 ( bChgMyEndn != IsEndnoteAtMyEnd() );
2508 ChgColumns( aCol, rNewCol, bChgFtn );
2509 rInvFlags |= 0x10;
2511 rInvFlags |= 0x01;
2512 bClear = FALSE;
2514 break;
2516 case RES_COL:
2517 if( !IsInFtn() )
2519 ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
2520 rInvFlags |= 0x11;
2522 break;
2524 case RES_FTN_AT_TXTEND:
2525 if( !IsInFtn() )
2527 BOOL bOld = IsFtnAtEnd();
2528 CalcFtnAtEndFlag();
2529 if( bOld != IsFtnAtEnd() )
2531 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2532 ChgColumns( rNewCol, rNewCol, TRUE );
2533 rInvFlags |= 0x01;
2536 break;
2538 case RES_END_AT_TXTEND:
2539 if( !IsInFtn() )
2541 BOOL bOld = IsEndnAtEnd();
2542 BOOL bMyOld = IsEndnoteAtMyEnd();
2543 CalcEndAtEndFlag();
2544 if( bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
2546 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2547 ChgColumns( rNewCol, rNewCol, TRUE );
2548 rInvFlags |= 0x01;
2551 break;
2552 case RES_COLUMNBALANCE:
2553 rInvFlags |= 0x01;
2554 break;
2556 case RES_FRAMEDIR :
2557 SetDerivedR2L( sal_False );
2558 CheckDirChange();
2559 break;
2561 case RES_PROTECT:
2563 ViewShell *pSh = GetShell();
2564 if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
2565 pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
2567 break;
2569 default:
2570 bClear = FALSE;
2572 if ( bClear )
2574 if ( pOldSet || pNewSet )
2576 if ( pOldSet )
2577 pOldSet->ClearItem( nWhich );
2578 if ( pNewSet )
2579 pNewSet->ClearItem( nWhich );
2581 else
2582 SwLayoutFrm::Modify( pOld, pNew );
2586 /*-----------------09.06.99 14:58-------------------
2587 * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
2588 * page causes a maximal Size of the sectionframe.
2589 * --------------------------------------------------*/
2591 BOOL SwSectionFrm::ToMaximize( BOOL bCheckFollow ) const
2593 if( HasFollow() )
2595 if( !bCheckFollow ) // Don't check superfluous follows
2596 return TRUE;
2597 const SwSectionFrm* pFoll = GetFollow();
2598 while( pFoll && pFoll->IsSuperfluous() )
2599 pFoll = pFoll->GetFollow();
2600 if( pFoll )
2601 return TRUE;
2603 if( IsFtnAtEnd() )
2604 return FALSE;
2605 const SwFtnContFrm* pCont = ContainsFtnCont();
2606 if( !IsEndnAtEnd() )
2607 return 0 != pCont;
2608 BOOL bRet = FALSE;
2609 while( pCont && !bRet )
2611 if( pCont->FindFootNote() )
2612 bRet = TRUE;
2613 else
2614 pCont = ContainsFtnCont( pCont );
2616 return bRet;
2619 /*-----------------09.06.99 15:07-------------------
2620 * BOOL SwSectionFrm::ContainsFtnCont()
2621 * checks every Column for FtnContFrms.
2622 * --------------------------------------------------*/
2624 SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
2626 SwFtnContFrm* pRet = NULL;
2627 const SwLayoutFrm* pLay;
2628 if( pCont )
2630 pLay = pCont->FindFtnBossFrm( 0 );
2631 ASSERT( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
2632 pLay = (SwLayoutFrm*)pLay->GetNext();
2634 else if( Lower() && Lower()->IsColumnFrm() )
2635 pLay = (SwLayoutFrm*)Lower();
2636 else
2637 pLay = NULL;
2638 while ( !pRet && pLay )
2640 if( pLay->Lower() && pLay->Lower()->GetNext() )
2642 ASSERT( pLay->Lower()->GetNext()->IsFtnContFrm(),
2643 "ToMaximize: Unexspected Frame" );
2644 pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
2646 ASSERT( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
2647 "ToMaximize: ColFrm exspected" );
2648 pLay = (SwLayoutFrm*)pLay->GetNext();
2650 return pRet;
2653 void SwSectionFrm::InvalidateFtnPos()
2655 SwFtnContFrm* pCont = ContainsFtnCont( NULL );
2656 if( pCont )
2658 SwFrm *pTmp = pCont->ContainsCntnt();
2659 if( pTmp )
2660 pTmp->_InvalidatePos();
2664 /*-----------------18.03.99 10:37-------------------
2665 * SwSectionFrm::Undersize() liefert den Betrag, um den der Bereich gern
2666 * groesser waere, wenn in ihm Undersized TxtFrms liegen, ansonsten Null.
2667 * Das Undersized-Flag wird ggf. korrigiert.
2668 * --------------------------------------------------*/
2670 long SwSectionFrm::Undersize( BOOL bOverSize )
2672 bUndersized = FALSE;
2673 SWRECTFN( this )
2674 long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
2675 if( nRet > 0 )
2676 bUndersized = TRUE;
2677 else if( !bOverSize )
2678 nRet = 0;
2679 return nRet;
2682 /// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
2683 /// before format of current one, because current one can move backward.
2684 /// After moving backward to a previous page method <FindNext()> will return
2685 /// the text frame presenting the first page footnote, if it exists. Thus, the
2686 /// rest of the footnote/endnote container would not be formatted.
2687 void SwSectionFrm::CalcFtnCntnt()
2689 SwFtnContFrm* pCont = ContainsFtnCont();
2690 if( pCont )
2692 SwFrm* pFrm = pCont->ContainsAny();
2693 if( pFrm )
2694 pCont->Calc();
2695 while( pFrm && IsAnLower( pFrm ) )
2697 SwFtnFrm* pFtn = pFrm->FindFtnFrm();
2698 if( pFtn )
2699 pFtn->Calc();
2700 // OD 01.04.2003 #108446# - determine next frame before format current frame.
2701 SwFrm* pNextFrm = 0;
2703 if( pFrm->IsSctFrm() )
2705 pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
2707 if( !pNextFrm )
2709 pNextFrm = pFrm->FindNext();
2712 pFrm->Calc();
2713 pFrm = pNextFrm;
2718 /* -----------------09.02.99 14:26-------------------
2719 * Wenn ein SectionFrm leerlaeuft, z.B. weil sein Inhalt die Seite/Spalte wechselt,
2720 * so wird er nicht sofort zerstoert (es koennte noch jemand auf dem Stack einen Pointer
2721 * auf ihn halten), sondern er traegt sich in eine Liste am RootFrm ein, die spaeter
2722 * abgearbeitet wird (in LayAction::Action u.a.). Seine Groesse wird auf Null gesetzt und
2723 * sein Zeiger auf seine Section ebenfalls. Solche zum Loeschen vorgesehene SectionFrms
2724 * muessen vom Layout/beim Formatieren ignoriert werden.
2726 * Mit InsertEmptySct nimmt der RootFrm einen SectionFrm in die Liste auf,
2727 * mit RemoveFromList kann ein SectionFrm wieder aus der Liste entfernt werden (Dtor),
2728 * mit DeleteEmptySct wird die Liste abgearbeitet und die SectionFrms zerstoert
2729 * --------------------------------------------------*/
2731 void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
2733 if( !pDestroy )
2734 pDestroy = new SwDestroyList;
2735 USHORT nPos;
2736 if( !pDestroy->Seek_Entry( pDel, &nPos ) )
2737 pDestroy->Insert( pDel );
2740 void SwRootFrm::_DeleteEmptySct()
2742 ASSERT( pDestroy, "Keine Liste, keine Kekse" );
2743 while( pDestroy->Count() )
2745 SwSectionFrm* pSect = (*pDestroy)[0];
2746 pDestroy->Remove( USHORT(0) );
2747 ASSERT( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
2748 "DeleteEmptySct: Locked SectionFrm" );
2749 if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
2751 SwLayoutFrm* pUp = pSect->GetUpper();
2752 pSect->Remove();
2753 delete pSect;
2754 if( pUp && !pUp->Lower() )
2756 if( pUp->IsPageBodyFrm() )
2757 pUp->FindRootFrm()->SetSuperfluous();
2758 else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
2759 pUp->GetUpper() )
2761 pUp->Cut();
2762 delete pUp;
2766 else {
2767 ASSERT( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
2772 void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
2774 ASSERT( pDestroy, "Where's my list?" );
2775 USHORT nPos;
2776 if( pDestroy->Seek_Entry( pSct, &nPos ) )
2777 pDestroy->Remove( nPos );
2780 #ifndef PRODUCT
2782 BOOL SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
2784 USHORT nPos;
2785 return ( pDestroy && pDestroy->Seek_Entry( pSct, &nPos ) );
2788 #endif
2790 bool SwSectionFrm::IsBalancedSection() const
2792 bool bRet = false;
2793 if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2795 bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2797 return bRet;