update dev300-m58
[ooovba.git] / sw / source / core / layout / pagechg.cxx
blobcf45cba30717a3f2633cf1601aa9212810918646
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: pagechg.cxx,v $
10 * $Revision: 1.57 $
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"
34 #include <com/sun/star/embed/EmbedStates.hpp>
35 #include <ndole.hxx>
36 #include <docary.hxx>
37 #include <svtools/itemiter.hxx>
38 #include <fmtfsize.hxx>
39 #include <fmthdft.hxx>
40 #include <fmtclds.hxx>
41 #include <fmtanchr.hxx>
42 #include <fmtpdsc.hxx>
43 #include <fmtfordr.hxx>
44 #include <fmtfld.hxx>
45 #include <fmtornt.hxx>
46 #include <ftninfo.hxx>
47 #include <tgrditem.hxx>
48 #include <viewopt.hxx>
49 #ifndef _DOCSH_HXX
50 #include <docsh.hxx>
51 #endif
53 #include "viewimp.hxx"
54 #include "pagefrm.hxx"
55 #include "rootfrm.hxx"
56 #include "cntfrm.hxx"
57 #include "flyfrm.hxx"
58 #include "doc.hxx"
59 #include "fesh.hxx"
60 #include "dview.hxx"
61 #include "dflyobj.hxx"
62 #include "dcontact.hxx"
63 #include "frmtool.hxx"
64 #include "fldbas.hxx"
65 #include "hints.hxx"
66 #include "errhdl.hxx"
67 #include "swtable.hxx"
69 #include "ftnidx.hxx"
70 #include "bodyfrm.hxx"
71 #include "ftnfrm.hxx"
72 #include "tabfrm.hxx"
73 #include "txtfrm.hxx"
74 #include "layact.hxx"
75 #include "flyfrms.hxx"
76 #include "htmltbl.hxx"
77 #include "pagedesc.hxx"
78 #include "poolfmt.hxx"
79 #include <svx/frmdiritem.hxx>
80 #include <swfntcch.hxx> // SwFontAccess
81 // OD 2004-05-24 #i28701#
82 #include <sortedobjs.hxx>
84 #include <vcl/svapp.hxx>
86 using namespace ::com::sun::star;
89 /*************************************************************************
91 |* SwBodyFrm::SwBodyFrm()
93 |* Ersterstellung MA ??
94 |* Letzte Aenderung MA 01. Aug. 93
96 |*************************************************************************/
97 SwBodyFrm::SwBodyFrm( SwFrmFmt *pFmt ):
98 SwLayoutFrm( pFmt )
100 nType = FRMC_BODY;
103 /*************************************************************************
105 |* SwBodyFrm::Format()
107 |* Ersterstellung MA 30. May. 94
108 |* Letzte Aenderung MA 20. Jan. 99
110 |*************************************************************************/
111 void SwBodyFrm::Format( const SwBorderAttrs * )
113 //Formatieren des Body ist zu einfach, deshalb bekommt er ein eigenes
114 //Format; Umrandungen und dergl. sind hier nicht zu beruecksichtigen.
115 //Breite ist die der PrtArea des Uppers, Hoehe ist die Hoehe der PrtArea
116 //des Uppers abzueglich der Nachbarn (Wird eigentlich eingestellt aber
117 //Vorsicht ist die Mutter der Robustheit).
118 //Die PrtArea ist stets so gross wie der Frm itself.
120 if ( !bValidSize )
122 SwTwips nHeight = GetUpper()->Prt().Height();
123 SwTwips nWidth = GetUpper()->Prt().Width();
124 const SwFrm *pFrm = GetUpper()->Lower();
127 if ( pFrm != this )
129 if( pFrm->IsVertical() )
130 nWidth -= pFrm->Frm().Width();
131 else
132 nHeight -= pFrm->Frm().Height();
134 pFrm = pFrm->GetNext();
135 } while ( pFrm );
136 if ( nHeight < 0 )
137 nHeight = 0;
138 Frm().Height( nHeight );
139 if( IsVertical() && !IsReverse() && nWidth != Frm().Width() )
140 Frm().Pos().X() += Frm().Width() - nWidth;
141 Frm().Width( nWidth );
144 BOOL bNoGrid = TRUE;
145 if( GetUpper()->IsPageFrm() && ((SwPageFrm*)GetUpper())->HasGrid() )
147 GETGRID( ((SwPageFrm*)GetUpper()) )
148 if( pGrid )
150 bNoGrid = FALSE;
151 long nSum = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
152 SWRECTFN( this )
153 long nSize = (Frm().*fnRect->fnGetWidth)();
154 long nBorder = 0;
155 if( GRID_LINES_CHARS == pGrid->GetGridType() )
157 //for textgrid refactor
158 SwDoc *pDoc = GetFmt()->GetDoc();
159 nBorder = nSize % (GETGRIDWIDTH(pGrid, pDoc));
160 nSize -= nBorder;
161 nBorder /= 2;
163 (Prt().*fnRect->fnSetPosX)( nBorder );
164 (Prt().*fnRect->fnSetWidth)( nSize );
166 // Height of body frame:
167 nBorder = (Frm().*fnRect->fnGetHeight)();
169 // Number of possible lines in area of body frame:
170 long nNumberOfLines = nBorder / nSum;
171 if( nNumberOfLines > pGrid->GetLines() )
172 nNumberOfLines = pGrid->GetLines();
174 // Space required for nNumberOfLines lines:
175 nSize = nNumberOfLines * nSum;
176 nBorder -= nSize;
177 nBorder /= 2;
179 // #i21774# Footnotes and centering the grid does not work together:
180 const bool bAdjust = 0 == ((SwPageFrm*)GetUpper())->GetFmt()->GetDoc()->
181 GetFtnIdxs().Count();
183 (Prt().*fnRect->fnSetPosY)( bAdjust ? nBorder : 0 );
184 (Prt().*fnRect->fnSetHeight)( nSize );
187 if( bNoGrid )
189 Prt().Pos().X() = Prt().Pos().Y() = 0;
190 Prt().Height( Frm().Height() );
191 Prt().Width( Frm().Width() );
193 bValidSize = bValidPrtArea = TRUE;
196 /*************************************************************************
198 |* SwPageFrm::SwPageFrm(), ~SwPageFrm()
200 |* Ersterstellung MA 20. Oct. 92
201 |* Letzte Aenderung MA 08. Dec. 97
203 |*************************************************************************/
204 SwPageFrm::SwPageFrm( SwFrmFmt *pFmt, SwPageDesc *pPgDsc ) :
205 SwFtnBossFrm( pFmt ),
206 pSortedObjs( 0 ),
207 pDesc( pPgDsc ),
208 nPhyPageNum( 0 ),
209 // OD 2004-05-17 #i28701#
210 mbLayoutInProgress( false )
212 SetDerivedVert( FALSE );
213 SetDerivedR2L( FALSE );
214 if( pDesc )
216 bHasGrid = TRUE;
217 GETGRID( this )
218 if( !pGrid )
219 bHasGrid = FALSE;
221 else
222 bHasGrid = FALSE;
223 SetMaxFtnHeight( pPgDsc->GetFtnInfo().GetHeight() ?
224 pPgDsc->GetFtnInfo().GetHeight() : LONG_MAX ),
225 nType = FRMC_PAGE;
226 bInvalidLayout = bInvalidCntnt = bInvalidSpelling = bInvalidSmartTags = bInvalidAutoCmplWrds = bInvalidWordCount = TRUE;
227 bInvalidFlyLayout = bInvalidFlyCntnt = bInvalidFlyInCnt = bFtnPage = bEndNotePage = FALSE;
229 const bool bBrowseMode = pFmt->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE);
230 if ( bBrowseMode )
232 Frm().Height( 0 );
233 ViewShell *pSh = GetShell();
234 long nWidth = pSh ? pSh->VisArea().Width():0;
235 if ( !nWidth )
236 nWidth = 5000L; //aendert sich sowieso
237 Frm().Width ( nWidth );
239 else
240 Frm().SSize( pFmt->GetFrmSize().GetSize() );
242 //Body-Bereich erzeugen und einsetzen, aber nur wenn ich nicht gerade
243 //eine Leerseite bin.
244 SwDoc *pDoc = pFmt->GetDoc();
245 if ( FALSE == (bEmptyPage = pFmt == pDoc->GetEmptyPageFmt()) )
247 bEmptyPage = FALSE;
248 Calc(); //Damit die PrtArea stimmt.
249 SwBodyFrm *pBodyFrm = new SwBodyFrm( pDoc->GetDfltFrmFmt() );
250 pBodyFrm->ChgSize( Prt().SSize() );
251 pBodyFrm->Paste( this );
252 pBodyFrm->Calc(); //Damit die Spalten korrekt
253 //eingesetzt werden koennen.
254 pBodyFrm->InvalidatePos();
256 if ( bBrowseMode )
257 _InvalidateSize(); //Alles nur gelogen
259 //Header/Footer einsetzen, nur rufen wenn aktiv.
260 if ( pFmt->GetHeader().IsActive() )
261 PrepareHeader();
262 if ( pFmt->GetFooter().IsActive() )
263 PrepareFooter();
265 const SwFmtCol &rCol = pFmt->GetCol();
266 if ( rCol.GetNumCols() > 1 )
268 const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass ein
269 //Old-Wert hereingereicht wird.
270 pBodyFrm->ChgColumns( aOld, rCol );
275 SwPageFrm::~SwPageFrm()
277 //FlyContainer entleeren, delete der Flys uebernimmt der Anchor
278 //(Basisklasse SwFrm)
279 if ( pSortedObjs )
281 //Objekte koennen (warum auch immer) auch an Seiten verankert sein,
282 //die vor Ihren Ankern stehen. Dann wuerde auf bereits freigegebenen
283 //Speicher zugegriffen.
284 for ( USHORT i = 0; i < pSortedObjs->Count(); ++i )
286 SwAnchoredObject* pAnchoredObj = (*pSortedObjs)[i];
287 pAnchoredObj->SetPageFrm( 0L );
289 delete pSortedObjs;
290 pSortedObjs = 0; //Auf 0 setzen, sonst rauchts beim Abmdelden von Flys!
293 //Damit der Zugriff auf zerstoerte Seiten verhindert werden kann.
294 if ( !IsEmptyPage() ) //#59184# sollte fuer Leerseiten unnoetig sein.
296 SwDoc *pDoc = GetFmt()->GetDoc();
297 if( pDoc && !pDoc->IsInDtor() )
299 ViewShell *pSh = GetShell();
300 if ( pSh )
302 SwViewImp *pImp = pSh->Imp();
303 pImp->SetFirstVisPageInvalid();
304 if ( pImp->IsAction() )
305 pImp->GetLayAction().SetAgain();
306 // OD 12.02.2003 #i9719#, #105645# - retouche area of page
307 // including border and shadow area.
308 const bool bRightSidebar = !MarginSide();
309 SwRect aRetoucheRect;
310 SwPageFrm::GetBorderAndShadowBoundRect( Frm(), pSh, aRetoucheRect, bRightSidebar );
311 pSh->AddPaintRect( aRetoucheRect );
318 void SwPageFrm::CheckGrid( BOOL bInvalidate )
320 BOOL bOld = bHasGrid;
321 bHasGrid = TRUE;
322 GETGRID( this )
323 bHasGrid = 0 != pGrid;
324 if( bInvalidate || bOld != bHasGrid )
326 SwLayoutFrm* pBody = FindBodyCont();
327 if( pBody )
329 pBody->InvalidatePrt();
330 SwCntntFrm* pFrm = pBody->ContainsCntnt();
331 while( pBody->IsAnLower( pFrm ) )
333 ((SwTxtFrm*)pFrm)->Prepare( PREP_CLEAR );
334 pFrm = pFrm->GetNextCntntFrm();
337 SetCompletePaint();
342 void SwPageFrm::CheckDirection( BOOL bVert )
344 UINT16 nDir =
345 ((SvxFrameDirectionItem&)GetFmt()->GetFmtAttr( RES_FRAMEDIR )).GetValue();
346 if( bVert )
348 if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir ||
349 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
350 bVertical = 0;
351 else
352 bVertical = 1;
354 if( pDesc && pDesc->GetName().GetChar(0)=='x')
355 bReverse = 1;
356 else
358 bReverse = 0;
359 bInvalidVert = 0;
361 else
363 if( FRMDIR_HORI_RIGHT_TOP == nDir )
364 bRightToLeft = 1;
365 else
366 bRightToLeft = 0;
367 bInvalidR2L = 0;
371 /*************************************************************************
373 |* SwPageFrm::PreparePage()
375 |* Beschreibung Erzeugt die Spezifischen Flys zur Seite und formatiert
376 |* generischen Cntnt
377 |* Ersterstellung MA 20. Oct. 92
378 |* Letzte Aenderung MA 09. Nov. 95
380 |*************************************************************************/
381 void MA_FASTCALL lcl_FormatLay( SwLayoutFrm *pLay )
383 //Alle LayoutFrms - nicht aber Tables, Flys o.ae. - formatieren.
385 SwFrm *pTmp = pLay->Lower();
386 //Erst die untergeordneten
387 while ( pTmp )
389 if ( pTmp->GetType() & 0x00FF )
390 ::lcl_FormatLay( (SwLayoutFrm*)pTmp );
391 pTmp = pTmp->GetNext();
393 pLay->Calc();
396 void MA_FASTCALL lcl_MakeObjs( const SwSpzFrmFmts &rTbl, SwPageFrm *pPage )
398 //Anlegen bzw. registrieren von Flys und Drawobjekten.
399 //Die Formate stehen in der SpzTbl (vom Dokument).
400 //Flys werden angelegt, DrawObjekte werden bei der Seite angemeldet.
402 for ( USHORT i = 0; i < rTbl.Count(); ++i )
404 SdrObject *pSdrObj;
405 SwFrmFmt *pFmt = rTbl[i];
406 const SwFmtAnchor &rAnch = pFmt->GetAnchor();
407 if ( rAnch.GetPageNum() == pPage->GetPhyPageNum() )
409 if( rAnch.GetCntntAnchor() )
411 if( FLY_PAGE == rAnch.GetAnchorId() )
413 SwFmtAnchor aAnch( rAnch );
414 aAnch.SetAnchor( 0 );
415 pFmt->SetFmtAttr( aAnch );
417 else
418 continue;
421 //Wird ein Rahmen oder ein SdrObject beschrieben?
422 BOOL bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
423 pSdrObj = 0;
424 if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
426 ASSERT( FALSE, "DrawObject not found." );
427 pFmt->GetDoc()->DelFrmFmt( pFmt );
428 --i;
429 continue;
431 //Das Objekt kann noch an einer anderen Seite verankert sein.
432 //Z.B. beim Einfuegen einer neuen Seite aufgrund eines
433 //Pagedescriptor-Wechsels. Das Objekt muss dann umgehaengt
434 //werden.
435 //Fuer bestimmte Faelle ist das Objekt bereits an der richtigen
436 //Seite verankert. Das wird hier automatisch erledigt und braucht
437 //- wenngleich performater machbar - nicht extra codiert werden.
438 SwPageFrm *pPg = pPage->IsEmptyPage() ? (SwPageFrm*)pPage->GetNext() : pPage;
439 if ( bSdrObj )
441 // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
442 SwDrawContact *pContact =
443 static_cast<SwDrawContact*>(::GetUserCall(pSdrObj));
444 if ( pSdrObj->ISA(SwDrawVirtObj) )
446 SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pSdrObj);
447 if ( pContact )
449 pDrawVirtObj->RemoveFromWriterLayout();
450 pDrawVirtObj->RemoveFromDrawingPage();
451 pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pDrawVirtObj )) );
454 else
456 if ( pContact->GetAnchorFrm() )
457 pContact->DisconnectFromLayout( false );
458 pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pSdrObj )) );
461 else
463 SwClientIter aIter( *pFmt );
464 SwClient *pTmp = aIter.First( TYPE(SwFrm) );
465 SwFlyFrm *pFly;
466 if ( pTmp )
468 pFly = (SwFlyFrm*)pTmp;
469 if( pFly->GetAnchorFrm() )
470 pFly->AnchorFrm()->RemoveFly( pFly );
472 else
473 pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pPg );
474 pPg->AppendFly( pFly );
475 ::RegistFlys( pPg, pFly );
481 void SwPageFrm::PreparePage( BOOL bFtn )
483 SetFtnPage( bFtn );
485 // --> OD 2008-01-30 #i82258#
486 // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has
487 // the side effect, that the content of page header and footer are formatted.
488 // For this formatting it is needed that the anchored objects are registered
489 // at the <SwPageFrm> instance.
490 // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)>
491 ::RegistFlys( this, this );
493 if ( Lower() )
495 ::lcl_FormatLay( this );
497 // <--
499 //Flys und DrawObjekte die noch am Dokument bereitstehen.
500 //Fussnotenseiten tragen keine Seitengebundenen Flys!
501 //Es kann Flys und Objekte geben, die auf Leerseiten (Seitennummernmaessig)
502 //stehen wollen, diese werden jedoch von den Leerseiten ignoriert;
503 //sie werden von den Folgeseiten aufgenommen.
504 if ( !bFtn && !IsEmptyPage() )
506 SwDoc *pDoc = GetFmt()->GetDoc();
508 if ( GetPrev() && ((SwPageFrm*)GetPrev())->IsEmptyPage() )
509 lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), (SwPageFrm*)GetPrev() );
510 lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), this );
512 //Kopf-/Fusszeilen) formatieren.
513 SwLayoutFrm *pLow = (SwLayoutFrm*)Lower();
514 while ( pLow )
516 if ( pLow->GetType() & (FRMTYPE_HEADER|FRMTYPE_FOOTER) )
518 SwCntntFrm *pCntnt = pLow->ContainsCntnt();
519 while ( pCntnt && pLow->IsAnLower( pCntnt ) )
521 pCntnt->OptCalc(); //Nicht die Vorgaenger
522 pCntnt = pCntnt->GetNextCntntFrm();
525 pLow = (SwLayoutFrm*)pLow->GetNext();
530 /*************************************************************************
532 |* SwPageFrm::Modify()
534 |* Ersterstellung MA 20. Oct. 92
535 |* Letzte Aenderung MA 03. Mar. 96
537 |*************************************************************************/
538 void SwPageFrm::Modify( SfxPoolItem * pOld, SfxPoolItem * pNew )
540 ViewShell *pSh = GetShell();
541 if ( pSh )
542 pSh->SetFirstVisPageInvalid();
543 BYTE nInvFlags = 0;
545 if( pNew && RES_ATTRSET_CHG == pNew->Which() )
547 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
548 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
549 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
550 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
551 while( TRUE )
553 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
554 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
555 &aOldSet, &aNewSet );
556 if( aNIter.IsAtEnd() )
557 break;
558 aNIter.NextItem();
559 aOIter.NextItem();
561 if ( aOldSet.Count() || aNewSet.Count() )
562 SwLayoutFrm::Modify( &aOldSet, &aNewSet );
564 else
565 _UpdateAttr( pOld, pNew, nInvFlags );
567 if ( nInvFlags != 0 )
569 InvalidatePage( this );
570 if ( nInvFlags & 0x01 )
571 _InvalidatePrt();
572 if ( nInvFlags & 0x02 )
573 SetCompletePaint();
574 if ( nInvFlags & 0x04 && GetNext() )
575 GetNext()->InvalidatePos();
576 if ( nInvFlags & 0x08 )
577 PrepareHeader();
578 if ( nInvFlags & 0x10 )
579 PrepareFooter();
580 if ( nInvFlags & 0x20 )
581 CheckGrid( nInvFlags & 0x40 );
585 void SwPageFrm::_UpdateAttr( SfxPoolItem *pOld, SfxPoolItem *pNew,
586 BYTE &rInvFlags,
587 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
589 BOOL bClear = TRUE;
590 const USHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
591 switch( nWhich )
593 case RES_FMT_CHG:
595 //Wenn sich das FrmFmt aendert kann hier einiges passieren.
596 //Abgesehen von den Grossenverhaeltnissen sind noch andere
597 //Dinge betroffen.
598 //1. Spaltigkeit.
599 ASSERT( pOld && pNew, "FMT_CHG Missing Format." );
600 const SwFmt* pOldFmt = ((SwFmtChg*)pOld)->pChangedFmt;
601 const SwFmt* pNewFmt = ((SwFmtChg*)pNew)->pChangedFmt;
602 ASSERT( pOldFmt && pNewFmt, "FMT_CHG Missing Format." );
604 const SwFmtCol &rOldCol = pOldFmt->GetCol();
605 const SwFmtCol &rNewCol = pNewFmt->GetCol();
606 if( rOldCol != rNewCol )
608 SwLayoutFrm *pB = FindBodyCont();
609 ASSERT( pB, "Seite ohne Body." );
610 pB->ChgColumns( rOldCol, rNewCol );
611 rInvFlags |= 0x20;
614 //2. Kopf- und Fusszeilen.
615 const SwFmtHeader &rOldH = pOldFmt->GetHeader();
616 const SwFmtHeader &rNewH = pNewFmt->GetHeader();
617 if( rOldH != rNewH )
618 rInvFlags |= 0x08;
620 const SwFmtFooter &rOldF = pOldFmt->GetFooter();
621 const SwFmtFooter &rNewF = pNewFmt->GetFooter();
622 if( rOldF != rNewF )
623 rInvFlags |= 0x10;
624 CheckDirChange();
626 /* kein break hier */
627 case RES_FRM_SIZE:
629 const SwRect aOldPageFrmRect( Frm() );
630 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
632 bValidSize = FALSE;
633 // OD 28.10.2002 #97265# - Don't call <SwPageFrm::MakeAll()>
634 // Calculation of the page is not necessary, because its size is
635 // is invalidated here and further invalidation is done in the
636 // calling method <SwPageFrm::Modify(..)> and probably by calling
637 // <SwLayoutFrm::Modify(..)> at the end.
638 // It can also causes inconsistences, because the lowers are
639 // adjusted, but not calculated, and a <SwPageFrm::MakeAll()> of
640 // a next page is called. This is performed on the switch to the
641 // online layout.
642 //MakeAll();
644 else
646 const SwFmtFrmSize &rSz = nWhich == RES_FMT_CHG ?
647 ((SwFmtChg*)pNew)->pChangedFmt->GetFrmSize() :
648 (const SwFmtFrmSize&)*pNew;
650 Frm().Height( Max( rSz.GetHeight(), long(MINLAY) ) );
651 Frm().Width ( Max( rSz.GetWidth(), long(MINLAY) ) );
653 // PAGES01
654 if ( GetUpper() )
655 static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
657 //Window aufraeumen.
658 ViewShell *pSh;
659 if ( 0 != (pSh = GetShell()) && pSh->GetWin() && aOldPageFrmRect.HasArea() )
661 // OD 12.02.2003 #i9719#, #105645# - consider border and shadow of
662 // page frame for determine 'old' rectangle - it's used for invalidating.
663 const bool bRightSidebar = !MarginSide();
664 SwRect aOldRectWithBorderAndShadow;
665 SwPageFrm::GetBorderAndShadowBoundRect( aOldPageFrmRect, pSh, aOldRectWithBorderAndShadow, bRightSidebar );
666 pSh->InvalidateWindows( aOldRectWithBorderAndShadow );
668 rInvFlags |= 0x03;
669 if ( aOldPageFrmRect.Height() != Frm().Height() )
670 rInvFlags |= 0x04;
672 break;
674 case RES_COL:
676 SwLayoutFrm *pB = FindBodyCont();
677 ASSERT( pB, "Seite ohne Body." );
678 pB->ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
679 rInvFlags |= 0x22;
681 break;
683 case RES_HEADER:
684 rInvFlags |= 0x08;
685 break;
687 case RES_FOOTER:
688 rInvFlags |= 0x10;
689 break;
690 case RES_TEXTGRID:
691 rInvFlags |= 0x60;
692 break;
694 case RES_PAGEDESC_FTNINFO:
695 //Die derzeit einzig sichere Methode:
696 ((SwRootFrm*)GetUpper())->SetSuperfluous();
697 SetMaxFtnHeight( pDesc->GetFtnInfo().GetHeight() );
698 if ( !GetMaxFtnHeight() )
699 SetMaxFtnHeight( LONG_MAX );
700 SetColMaxFtnHeight();
701 //Hier wird die Seite ggf. zerstoert!
702 ((SwRootFrm*)GetUpper())->RemoveFtns( 0, FALSE, TRUE );
703 break;
704 case RES_FRAMEDIR :
705 CheckDirChange();
706 break;
708 default:
709 bClear = FALSE;
711 if ( bClear )
713 if ( pOldSet || pNewSet )
715 if ( pOldSet )
716 pOldSet->ClearItem( nWhich );
717 if ( pNewSet )
718 pNewSet->ClearItem( nWhich );
720 else
721 SwLayoutFrm::Modify( pOld, pNew );
725 /*************************************************************************
727 |* SwPageFrm::GetInfo()
729 |* Beschreibung erfragt Informationen
730 |* Ersterstellung JP 31.03.94
731 |* Letzte Aenderung JP 31.03.94
733 *************************************************************************/
734 // erfrage vom Modify Informationen
735 BOOL SwPageFrm::GetInfo( SfxPoolItem & rInfo ) const
737 if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
739 // es gibt einen PageFrm also wird er benutzt
740 return FALSE;
742 return TRUE; // weiter suchen
745 /*************************************************************************
747 |* SwPageFrm::SetPageDesc()
749 |* Ersterstellung MA 02. Nov. 94
750 |* Letzte Aenderung MA 02. Nov. 94
752 |*************************************************************************/
753 void SwPageFrm::SetPageDesc( SwPageDesc *pNew, SwFrmFmt *pFmt )
755 pDesc = pNew;
756 if ( pFmt )
757 SetFrmFmt( pFmt );
760 /*************************************************************************
762 |* SwPageFrm::FindPageDesc()
764 |* Beschreibung Der richtige PageDesc wird bestimmt:
765 |* 0. Vom Dokument bei Fussnotenseiten und Endnotenseiten
766 |* 1. vom ersten BodyCntnt unterhalb der Seite.
767 |* 2. vom PageDesc der vorstehenden Seite.
768 |* 3. bei Leerseiten vom PageDesc der vorigen Seite.
769 |* 3.1 vom PageDesc der folgenden Seite wenn es keinen Vorgaenger gibt.
770 |* 4. es ist der Default-PageDesc sonst.
771 |* 5. Im BrowseMode ist der Pagedesc immer der vom ersten Absatz im
772 |* Dokument oder Standard (der 0-te) wenn der erste Absatz keinen
773 |* wuenscht.
774 |* (6. Im HTML-Mode ist der Pagedesc immer die HTML-Seitenvorlage.)
775 |* Ersterstellung MA 15. Feb. 93
776 |* Letzte Aenderung MA 17. Jun. 99
778 |*************************************************************************/
779 SwPageDesc *SwPageFrm::FindPageDesc()
781 //0.
782 if ( IsFtnPage() )
784 SwDoc *pDoc = GetFmt()->GetDoc();
785 if ( IsEndNotePage() )
786 return pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
787 else
788 return pDoc->GetFtnInfo().GetPageDesc( *pDoc );
791 //6.
792 //if ( GetFmt()->GetDoc()->IsHTMLMode() )
793 // return GetFmt()->GetDoc()->GetPageDescFromPool( RES_POOLPAGE_HTML );
795 SwPageDesc *pRet = 0;
797 //5.
798 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
800 SwCntntFrm *pFrm = GetUpper()->ContainsCntnt();
801 while ( !pFrm->IsInDocBody() )
802 pFrm = pFrm->GetNextCntntFrm();
803 SwFrm *pFlow = pFrm;
804 if ( pFlow->IsInTab() )
805 pFlow = pFlow->FindTabFrm();
806 pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
807 if ( !pRet )
808 pRet = &GetFmt()->GetDoc()->_GetPageDesc( 0 );
809 return pRet;
812 SwFrm *pFlow = FindFirstBodyCntnt();
813 if ( pFlow && pFlow->IsInTab() )
814 pFlow = pFlow->FindTabFrm();
816 //1.
817 if ( pFlow )
819 SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
820 if ( !pTmp->IsFollow() )
821 pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
824 //3. und 3.1
825 if ( !pRet && IsEmptyPage() )
826 // FME 2008-03-03 #i81544# lijian/fme: an empty page should have
827 // the same page description as its prev, just like after construction
828 // of the empty page.
829 pRet = GetPrev() ? ((SwPageFrm*)GetPrev())->GetPageDesc() :
830 GetNext() ? ((SwPageFrm*)GetNext())->GetPageDesc() : 0;
832 //2.
833 if ( !pRet )
834 pRet = GetPrev() ?
835 ((SwPageFrm*)GetPrev())->GetPageDesc()->GetFollow() : 0;
837 //4.
838 if ( !pRet )
839 pRet = (SwPageDesc*)&(const_cast<const SwDoc *>(GetFmt()->GetDoc())
840 ->GetPageDesc( 0 ));
843 ASSERT( pRet, "Kein Descriptor gefunden." );
844 return pRet;
847 //Wenn der RootFrm seine Groesse aendert muss benachrichtigt werden.
848 void AdjustSizeChgNotify( SwRootFrm *pRoot )
850 const BOOL bOld = pRoot->IsSuperfluous();
851 pRoot->bCheckSuperfluous = FALSE;
852 ViewShell *pSh = pRoot->GetCurrShell();
853 if ( pSh )
855 pSh->Imp()->NotifySizeChg( pRoot->Frm().SSize() );//Einmal fuer das Drawing.
858 pSh->SizeChgNotify(); //Einmal fuer jede Sicht.
859 pSh = (ViewShell*)pSh->GetNext();
860 } while ( pSh != pRoot->GetCurrShell() );
862 pRoot->bCheckSuperfluous = bOld;
866 inline void SetLastPage( SwPageFrm *pPage )
868 ((SwRootFrm*)pPage->GetUpper())->pLastPage = pPage;
871 /*************************************************************************
873 |* SwPageFrm::Cut()
875 |* Ersterstellung MA 23. Feb. 94
876 |* Letzte Aenderung MA 22. Jun. 95
878 |*************************************************************************/
879 void SwPageFrm::Cut()
881 // PAGES01
882 //AdjustRootSize( CHG_CUTPAGE, 0 );
884 ViewShell *pSh = GetShell();
885 if ( !IsEmptyPage() )
887 if ( GetNext() )
888 GetNext()->InvalidatePos();
890 //Flys deren Anker auf anderen Seiten stehen umhaengen.
891 //DrawObjecte spielen hier keine Rolle.
892 if ( GetSortedObjs() )
894 for ( int i = 0; GetSortedObjs() &&
895 (USHORT)i < GetSortedObjs()->Count(); ++i )
897 // --> OD 2004-06-29 #i28701#
898 SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
900 if ( pAnchoredObj->ISA(SwFlyAtCntFrm) )
902 SwFlyFrm* pFly = static_cast<SwFlyAtCntFrm*>(pAnchoredObj);
903 SwPageFrm *pAnchPage = pFly->GetAnchorFrm() ?
904 pFly->AnchorFrm()->FindPageFrm() : 0;
905 if ( pAnchPage && (pAnchPage != this) )
907 MoveFly( pFly, pAnchPage );
908 --i;
909 pFly->InvalidateSize();
910 pFly->_InvalidatePos();
913 // <--
916 //Window aufraeumen
917 if ( pSh && pSh->GetWin() )
918 pSh->InvalidateWindows( Frm() );
921 // die Seitennummer der Root runterzaehlen.
922 ((SwRootFrm*)GetUpper())->DecrPhyPageNums();
923 SwPageFrm *pPg = (SwPageFrm*)GetNext();
924 if ( pPg )
926 while ( pPg )
928 pPg->DecrPhyPageNum(); //inline --nPhyPageNum
929 pPg = (SwPageFrm*)pPg->GetNext();
932 else
933 ::SetLastPage( (SwPageFrm*)GetPrev() );
935 SwFrm* pRootFrm = GetUpper();
937 // Alle Verbindungen kappen.
938 Remove();
940 // PAGES01
941 if ( pRootFrm )
942 static_cast<SwRootFrm*>(pRootFrm)->CheckViewLayout( 0, 0 );
945 /*************************************************************************
947 |* SwPageFrm::Paste()
949 |* Ersterstellung MA 23. Feb. 94
950 |* Letzte Aenderung MA 07. Dec. 94
952 |*************************************************************************/
953 void SwPageFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
955 ASSERT( pParent->IsRootFrm(), "Parent ist keine Root." );
956 ASSERT( pParent, "Kein Parent fuer Paste." );
957 ASSERT( pParent != this, "Bin selbst der Parent." );
958 ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
959 ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
960 "Bin noch irgendwo angemeldet." );
962 //In den Baum einhaengen.
963 InsertBefore( (SwLayoutFrm*)pParent, pSibling );
965 // die Seitennummer am Root hochzaehlen.
966 ((SwRootFrm*)GetUpper())->IncrPhyPageNums();
967 if( GetPrev() )
968 SetPhyPageNum( ((SwPageFrm*)GetPrev())->GetPhyPageNum() + 1 );
969 else
970 SetPhyPageNum( 1 );
971 SwPageFrm *pPg = (SwPageFrm*)GetNext();
972 if ( pPg )
974 while ( pPg )
976 pPg->IncrPhyPageNum(); //inline ++nPhyPageNum
977 pPg->_InvalidatePos();
978 pPg->InvalidateLayout();
979 pPg = (SwPageFrm*)pPg->GetNext();
982 else
983 ::SetLastPage( this );
985 if( Frm().Width() != pParent->Prt().Width() )
986 _InvalidateSize();
988 InvalidatePos();
990 // PAGES01
991 if ( GetUpper() )
992 static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
995 /*************************************************************************
997 |* SwPageFrm::PrepareRegisterChg()
999 |* Ersterstellung AMA 22. Jul. 96
1000 |* Letzte Aenderung AMA 22. Jul. 96
1002 |*************************************************************************/
1003 void lcl_PrepFlyInCntRegister( SwCntntFrm *pFrm )
1005 pFrm->Prepare( PREP_REGISTER );
1006 if( pFrm->GetDrawObjs() )
1008 for( USHORT i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
1010 // --> OD 2004-06-29 #i28701#
1011 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
1012 if ( pAnchoredObj->ISA(SwFlyInCntFrm) )
1014 SwFlyFrm* pFly = static_cast<SwFlyInCntFrm*>(pAnchoredObj);
1015 SwCntntFrm *pCnt = pFly->ContainsCntnt();
1016 while ( pCnt )
1018 lcl_PrepFlyInCntRegister( pCnt );
1019 pCnt = pCnt->GetNextCntntFrm();
1022 // <--
1027 void SwPageFrm::PrepareRegisterChg()
1029 SwCntntFrm *pFrm = FindFirstBodyCntnt();
1030 while( pFrm )
1032 lcl_PrepFlyInCntRegister( pFrm );
1033 pFrm = pFrm->GetNextCntntFrm();
1034 if( !IsAnLower( pFrm ) )
1035 break;
1037 if( GetSortedObjs() )
1039 for( USHORT i = 0; i < GetSortedObjs()->Count(); ++i )
1041 // --> OD 2004-06-29 #i28701#
1042 SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
1043 if ( pAnchoredObj->ISA(SwFlyFrm) )
1045 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
1046 pFrm = pFly->ContainsCntnt();
1047 while ( pFrm )
1049 ::lcl_PrepFlyInCntRegister( pFrm );
1050 pFrm = pFrm->GetNextCntntFrm();
1057 /*************************************************************************
1059 |* SwFrm::CheckPageDescs()
1061 |* Beschreibung Prueft alle Seiten ab der uebergebenen, daraufhin,
1062 |* ob sie das richtige FrmFmt verwenden. Wenn 'falsche' Seiten
1063 |* aufgespuehrt werden, so wird versucht die Situation moeglichst
1064 |* einfache zu bereinigen.
1066 |* Ersterstellung MA 10. Feb. 93
1067 |* Letzte Aenderung MA 18. Apr. 96
1069 |*************************************************************************/
1070 void SwFrm::CheckPageDescs( SwPageFrm *pStart, BOOL bNotifyFields )
1072 ASSERT( pStart, "Keine Startpage." );
1074 ViewShell *pSh = pStart->GetShell();
1075 SwViewImp *pImp = pSh ? pSh->Imp() : 0;
1077 if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
1079 pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() );
1080 return;
1083 //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
1084 //die Seitenposition an, _ab_ der invalidiert werden soll.
1085 SwTwips nDocPos = LONG_MAX;
1087 SwRootFrm *pRoot = (SwRootFrm*)pStart->GetUpper();
1088 SwDoc* pDoc = pStart->GetFmt()->GetDoc();
1089 const BOOL bFtns = 0 != pDoc->GetFtnIdxs().Count();
1091 SwPageFrm *pPage = pStart;
1092 if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
1093 pPage = (SwPageFrm*)pPage->GetPrev();
1094 while ( pPage )
1096 //gewuenschten PageDesc und FrmFmt festellen.
1097 SwPageDesc *pDesc = pPage->FindPageDesc();
1098 BOOL bCheckEmpty = pPage->IsEmptyPage();
1099 BOOL bActOdd = pPage->OnRightPage();
1100 BOOL bOdd = pPage->WannaRightPage();
1101 SwFrmFmt *pFmtWish = bOdd ? pDesc->GetRightFmt()
1102 : pDesc->GetLeftFmt();
1104 if ( bActOdd != bOdd ||
1105 pDesc != pPage->GetPageDesc() || //falscher Desc
1106 ( pFmtWish != pPage->GetFmt() && //falsches Format und
1107 ( !pPage->IsEmptyPage() || pFmtWish ) //nicht Leerseite
1111 //Wenn wir schon ein Seite veraendern muessen kann das eine
1112 //Weile dauern, deshalb hier den WaitCrsr pruefen.
1113 if( pImp )
1114 pImp->CheckWaitCrsr();
1116 //Ab hier muessen die Felder invalidiert werden!
1117 if ( nDocPos == LONG_MAX )
1118 nDocPos = pPage->GetPrev() ?
1119 pPage->GetPrev()->Frm().Top() : pPage->Frm().Top();
1121 //Faelle:
1122 //1. Wir haben eine EmptyPage und wollen eine "Normalseite".
1123 // ->EmptyPage wegwerfen und weiter mit der naechsten.
1124 //2. Wir haben eine EmptyPage und wollen eine EmptyPage mit
1125 // anderem Descriptor.
1126 // ->Descriptor austauschen.
1127 //3. Wir haben eine "Normalseite" und wollen eine EmptyPage.
1128 // ->Emptypage einfuegen, nicht aber wenn die Vorseite
1129 // bereits eine EmptyPage ist -> 6.
1130 //4. Wir haben eine "Normalseite" und wollen eine "Normalseite"
1131 // mit anderem Descriptor
1132 // ->Descriptor und Format austauschen
1133 //5. Wir haben eine "Normalseite" und wollen eine "Normalseite"
1134 // mit anderem Format
1135 // ->Format austauschen.
1136 //6. Wir haben kein Wunschformat erhalten, also nehmen wir das
1137 // 'andere' Format (rechts/links) des PageDesc.
1139 if ( pPage->IsEmptyPage() && ( pFmtWish || //1.
1140 ( !bOdd && !pPage->GetPrev() ) ) )
1142 SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
1143 pPage->Cut();
1144 delete pPage;
1145 if ( pStart == pPage )
1146 pStart = pTmp;
1147 pPage = pTmp;
1148 continue;
1150 else if ( pPage->IsEmptyPage() && !pFmtWish && //2.
1151 pDesc != pPage->GetPageDesc() )
1153 pPage->SetPageDesc( pDesc, 0 );
1155 else if ( !pPage->IsEmptyPage() && //3.
1156 bActOdd != bOdd &&
1157 ( ( !pPage->GetPrev() && !bOdd ) ||
1158 ( pPage->GetPrev() &&
1159 !((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
1163 if ( pPage->GetPrev() )
1164 pDesc = ((SwPageFrm*)pPage->GetPrev())->GetPageDesc();
1165 SwPageFrm *pTmp = new SwPageFrm( pDoc->GetEmptyPageFmt(),pDesc);
1166 pTmp->Paste( pRoot, pPage );
1167 pTmp->PreparePage( FALSE );
1168 pPage = pTmp;
1170 else if ( pPage->GetPageDesc() != pDesc ) //4.
1172 SwPageDesc *pOld = pPage->GetPageDesc();
1173 pPage->SetPageDesc( pDesc, pFmtWish );
1174 if ( bFtns )
1176 //Wenn sich bestimmte Werte der FtnInfo veraendert haben
1177 //muss etwas passieren. Wir versuchen den Schaden zu
1178 //begrenzen.
1179 //Wenn die Seiten keinen FtnCont hat, ist zwar theoretisches
1180 //ein Problem denkbar, aber das ignorieren wir mit aller Kraft.
1181 //Bei Aenderungen hoffen wir mal, dass eine Invalidierung
1182 //ausreicht, denn alles andere wuerde viel Kraft kosten.
1183 SwFtnContFrm *pCont = pPage->FindFtnCont();
1184 if ( pCont && !(pOld->GetFtnInfo() == pDesc->GetFtnInfo()) )
1185 pCont->_InvalidateAll();
1188 else if ( pFmtWish && pPage->GetFmt() != pFmtWish ) //5.
1190 pPage->SetFrmFmt( pFmtWish );
1192 else if ( !pFmtWish ) //6.
1194 //Format mit verdrehter Logic besorgen.
1195 pFmtWish = bOdd ? pDesc->GetLeftFmt() : pDesc->GetRightFmt();
1196 if ( pPage->GetFmt() != pFmtWish )
1197 pPage->SetFrmFmt( pFmtWish );
1199 #ifndef PRODUCT
1200 else
1202 ASSERT( FALSE, "CheckPageDescs, missing solution" );
1204 #endif
1206 if ( bCheckEmpty )
1208 //Es kann noch sein, dass die Leerseite schlicht ueberflussig ist.
1209 //Obiger Algorithmus kann dies leider nicht feststellen.
1210 //Eigentlich muesste die Leerseite einfach praeventiv entfernt
1211 //werden; sie wuerde ja ggf. wieder eingefuegt.
1212 //Die EmptyPage ist genau dann ueberfluessig, wenn die Folgeseite
1213 //auch ohne sie auskommt. Dazu muessen wir uns die Verhaeltnisse
1214 //genauer ansehen. Wir bestimmen den PageDesc und die virtuelle
1215 //Seitennummer manuell.
1216 SwPageFrm *pPg = (SwPageFrm*)pPage->GetNext();
1217 if( !pPg || pPage->OnRightPage() == pPg->WannaRightPage() )
1219 //Die Folgeseite hat kein Problem ein FrmFmt zu finden oder keinen
1220 //Nachfolger, also ist die Leerseite ueberfluessig.
1221 SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
1222 pPage->Cut();
1223 delete pPage;
1224 if ( pStart == pPage )
1225 pStart = pTmp;
1226 pPage = pTmp;
1227 continue;
1230 pPage = (SwPageFrm*)pPage->GetNext();
1233 pRoot->SetAssertFlyPages();
1234 pRoot->AssertPageFlys( pStart );
1236 if ( bNotifyFields && (!pImp || !pImp->IsUpdateExpFlds()) )
1238 SwDocPosUpdate aMsgHnt( nDocPos );
1239 pDoc->UpdatePageFlds( &aMsgHnt );
1242 #ifndef PRODUCT
1243 //Ein paar Pruefungen muessen schon erlaubt sein.
1245 //1. Keine zwei EmptyPages hintereinander.
1246 //2. Alle PageDescs richtig?
1247 BOOL bEmpty = FALSE;
1248 SwPageFrm *pPg = pStart;
1249 while ( pPg )
1251 if ( pPg->IsEmptyPage() )
1253 if ( bEmpty )
1255 ASSERT( FALSE, "Doppelte Leerseiten." );
1256 break; //Einmal reicht.
1258 bEmpty = TRUE;
1260 else
1261 bEmpty = FALSE;
1263 //MA 21. Jun. 95: Kann zu testzwecken 'rein, ist aber bei zyklen durchaus
1264 //moeglich: Ein paar Seiten, auf der ersten 'erste Seite' anwenden,
1265 //rechte als folge der ersten, linke als folge der rechten, rechte als
1266 //folge der linken.
1267 // ASSERT( pPg->GetPageDesc() == pPg->FindPageDesc(),
1268 // "Seite mit falschem Descriptor." );
1270 pPg = (SwPageFrm*)pPg->GetNext();
1272 #endif
1275 /*************************************************************************
1277 |* SwFrm::InsertPage()
1279 |* Beschreibung
1280 |* Ersterstellung MA 10. Feb. 93
1281 |* Letzte Aenderung MA 27. Jul. 93
1283 |*************************************************************************/
1284 SwPageFrm *SwFrm::InsertPage( SwPageFrm *pPrevPage, BOOL bFtn )
1286 SwRootFrm *pRoot = (SwRootFrm*)pPrevPage->GetUpper();
1287 SwPageFrm *pSibling = (SwPageFrm*)pRoot->GetLower();
1288 SwPageDesc *pDesc = pSibling->GetPageDesc();
1290 pSibling = (SwPageFrm*)pPrevPage->GetNext();
1291 //Rechte (ungerade) oder linke (gerade) Seite einfuegen?
1292 BOOL bNextOdd = !pPrevPage->OnRightPage();
1293 BOOL bWishedOdd = bNextOdd;
1295 //Welcher PageDesc gilt?
1296 //Bei CntntFrm der aus dem Format wenn einer angegeben ist,
1297 //der Follow vom bereits in der PrevPage gueltigen sonst.
1298 pDesc = 0;
1299 if ( IsFlowFrm() && !SwFlowFrm::CastFlowFrm( this )->IsFollow() )
1300 { SwFmtPageDesc &rDesc = (SwFmtPageDesc&)GetAttrSet()->GetPageDesc();
1301 pDesc = rDesc.GetPageDesc();
1302 if ( rDesc.GetNumOffset() )
1304 bWishedOdd = rDesc.GetNumOffset() % 2 ? TRUE : FALSE;
1305 //Die Gelegenheit nutzen wir um das Flag an der Root zu pflegen.
1306 pRoot->SetVirtPageNum( TRUE );
1309 if ( !pDesc )
1310 pDesc = pPrevPage->GetPageDesc()->GetFollow();
1312 ASSERT( pDesc, "Missing PageDesc" );
1313 if( !(bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
1314 bWishedOdd = !bWishedOdd;
1316 SwDoc *pDoc = pPrevPage->GetFmt()->GetDoc();
1317 SwFrmFmt *pFmt;
1318 BOOL bCheckPages = FALSE;
1319 //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben eine
1320 //Leerseite einfuegen.
1321 if( bWishedOdd != bNextOdd )
1322 { pFmt = pDoc->GetEmptyPageFmt();
1323 SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc();
1324 SwPageFrm *pPage = new SwPageFrm( pFmt, pTmpDesc );
1325 pPage->Paste( pRoot, pSibling );
1326 pPage->PreparePage( bFtn );
1327 //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
1328 //Es sei denn, es ist eine Fussnotenseite
1329 if ( pSibling && !pSibling->IsFtnPage() &&
1330 !pSibling->FindFirstBodyCntnt() )
1332 SwPageFrm *pDel = pSibling;
1333 pSibling = (SwPageFrm*)pSibling->GetNext();
1334 if ( pDoc->GetFtnIdxs().Count() )
1335 pRoot->RemoveFtns( pDel, TRUE );
1336 pDel->Cut();
1337 delete pDel;
1339 else
1340 bCheckPages = TRUE;
1342 pFmt = bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt();
1343 ASSERT( pFmt, "Descriptor without format." );
1344 SwPageFrm *pPage = new SwPageFrm( pFmt, pDesc );
1345 pPage->Paste( pRoot, pSibling );
1346 pPage->PreparePage( bFtn );
1347 //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
1348 //Es sei denn es ist eine Fussnotenseite.
1349 if ( pSibling && !pSibling->IsFtnPage() &&
1350 !pSibling->FindFirstBodyCntnt() )
1352 SwPageFrm *pDel = pSibling;
1353 pSibling = (SwPageFrm*)pSibling->GetNext();
1354 if ( pDoc->GetFtnIdxs().Count() )
1355 pRoot->RemoveFtns( pDel, TRUE );
1356 pDel->Cut();
1357 delete pDel;
1359 else
1360 bCheckPages = TRUE;
1362 if ( pSibling )
1364 if ( bCheckPages )
1366 CheckPageDescs( pSibling, FALSE );
1367 ViewShell *pSh = GetShell();
1368 SwViewImp *pImp = pSh ? pSh->Imp() : 0;
1369 if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
1371 const USHORT nNum = pImp->GetLayAction().GetCheckPageNum();
1372 if ( nNum == pPrevPage->GetPhyPageNum() + 1 )
1373 pImp->GetLayAction().SetCheckPageNumDirect(
1374 pSibling->GetPhyPageNum() );
1375 return pPage;
1378 else
1379 pRoot->AssertPageFlys( pSibling );
1382 //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
1383 //die Seitenposition an, _ab_ der invalidiert werden soll.
1384 ViewShell *pSh = GetShell();
1385 if ( !pSh || !pSh->Imp()->IsUpdateExpFlds() )
1387 SwDocPosUpdate aMsgHnt( pPrevPage->Frm().Top() );
1388 pDoc->UpdatePageFlds( &aMsgHnt );
1390 return pPage;
1393 // false = right, true = left
1394 bool SwPageFrm::MarginSide() const
1396 if (!GetShell() || GetShell()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE))
1397 return false;
1398 else
1400 const bool bLTR = GetUpper() ? static_cast<const SwRootFrm*>(GetUpper())->IsLeftToRightViewLayout() : true;
1401 const bool bBookMode = GetShell()->GetViewOptions()->IsViewLayoutBookMode();
1402 const bool bRightSidebar = bLTR ? (!bBookMode || OnRightPage()) : (bBookMode && !OnRightPage());
1404 return !bRightSidebar;
1408 /*************************************************************************
1410 |* SwRootFrm::GrowFrm()
1412 |* Ersterstellung MA 30. Jul. 92
1413 |* Letzte Aenderung MA 05. May. 94
1415 |*************************************************************************/
1417 SwTwips SwRootFrm::GrowFrm( SwTwips nDist, BOOL bTst, BOOL )
1419 if ( !bTst )
1420 Frm().SSize().Height() += nDist;
1421 return nDist;
1423 /*************************************************************************
1425 |* SwRootFrm::ShrinkFrm()
1427 |* Ersterstellung MA 30. Jul. 92
1428 |* Letzte Aenderung MA 05. May. 94
1430 |*************************************************************************/
1431 SwTwips SwRootFrm::ShrinkFrm( SwTwips nDist, BOOL bTst, BOOL )
1433 ASSERT( nDist >= 0, "nDist < 0." );
1434 ASSERT( nDist <= Frm().Height(), "nDist > als aktuelle Groesse." );
1436 if ( !bTst )
1437 Frm().SSize().Height() -= nDist;
1438 return nDist;
1441 /*************************************************************************
1443 |* SwRootFrm::RemoveSuperfluous()
1445 |* Beschreibung: Entfernung von ueberfluessigen Seiten.
1446 |* Arbeitet nur wenn das Flag bCheckSuperfluous gesetzt ist.
1447 |* Definition: Eine Seite ist genau dann leer, wenn der
1448 |* Body-Textbereich keinen CntntFrm enthaelt, aber nicht, wenn noch
1449 |* mindestens ein Fly an der Seite klebt.
1450 |* Die Seite ist auch dann nicht leer, wenn sie noch eine
1451 |* Fussnote enthaelt.
1452 |* Es muss zweimal angesetzt werden um leeren Seiten aufzuspueren:
1453 |* - einmal fuer die Endnotenseiten.
1454 |* - und einmal fuer die Seiten des Bodytextes.
1456 |* Ersterstellung MA 20. May. 92
1457 |* Letzte Aenderung MA 10. Jan. 95
1459 |*************************************************************************/
1460 void SwRootFrm::RemoveSuperfluous()
1462 if ( !IsSuperfluous() )
1463 return;
1464 bCheckSuperfluous = FALSE;
1466 SwPageFrm *pPage = GetLastPage();
1467 long nDocPos = LONG_MAX;
1469 //Jetzt wird fuer die jeweils letzte Seite geprueft ob sie leer ist
1470 //bei der ersten nicht leeren Seite wird die Schleife beendet.
1473 bool bExistEssentialObjs = ( 0 != pPage->GetSortedObjs() );
1474 if ( bExistEssentialObjs )
1476 //Nur weil die Seite Flys hat sind wir noch lange nicht fertig,
1477 //denn wenn alle Flys an generischem Inhalt haengen, so ist sie
1478 //trotzdem ueberfluessig (Ueberpruefung auf DocBody sollte reichen).
1479 // OD 19.06.2003 #108784# - consider that drawing objects in
1480 // header/footer are supported now.
1481 bool bOnlySuperfluosObjs = true;
1482 SwSortedObjs &rObjs = *pPage->GetSortedObjs();
1483 for ( USHORT i = 0; bOnlySuperfluosObjs && i < rObjs.Count(); ++i )
1485 // --> OD 2004-06-29 #i28701#
1486 SwAnchoredObject* pAnchoredObj = rObjs[i];
1487 // OD 2004-01-19 #110582# - do not consider hidden objects
1488 if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
1489 pAnchoredObj->GetDrawObj()->GetLayer() ) &&
1490 !pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() )
1492 bOnlySuperfluosObjs = false;
1494 // <--
1496 bExistEssentialObjs = !bOnlySuperfluosObjs;
1499 // OD 19.06.2003 #108784# - optimization: check first, if essential objects
1500 // exists.
1501 const SwLayoutFrm* pBody = 0;
1502 if ( bExistEssentialObjs ||
1503 pPage->FindFtnCont() ||
1504 ( 0 != ( pBody = pPage->FindBodyCont() ) &&
1505 ( pBody->ContainsCntnt() ||
1506 // --> FME 2005-05-18 #i47580#
1507 // Do not delete page if there's an empty tabframe
1508 // left. I think it might be correct to use ContainsAny()
1509 // instead of ContainsCntnt() to cover the empty-table-case,
1510 // but I'm not fully sure, since ContainsAny() also returns
1511 // SectionFrames. Therefore I prefer to do it the safe way:
1512 ( pBody->Lower() && pBody->Lower()->IsTabFrm() ) ) ) )
1513 // <--
1515 if ( pPage->IsFtnPage() )
1517 while ( pPage->IsFtnPage() )
1519 pPage = (SwPageFrm*)pPage->GetPrev();
1520 ASSERT( pPage, "Nur noch Endnotenseiten uebrig." );
1522 continue;
1524 else
1525 pPage = 0;
1528 if ( pPage )
1530 SwPageFrm *pEmpty = pPage;
1531 pPage = (SwPageFrm*)pPage->GetPrev();
1532 if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
1533 RemoveFtns( pEmpty, TRUE );
1534 pEmpty->Cut();
1535 delete pEmpty;
1536 nDocPos = pPage ? pPage->Frm().Top() : 0;
1538 } while ( pPage );
1540 ViewShell *pSh = GetShell();
1541 if ( nDocPos != LONG_MAX &&
1542 (!pSh || !pSh->Imp()->IsUpdateExpFlds()) )
1544 SwDocPosUpdate aMsgHnt( nDocPos );
1545 GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
1549 /*************************************************************************
1551 |* SwRootFrm::AssertFlyPages()
1553 |* Beschreibung Stellt sicher, dass genuegend Seiten vorhanden
1554 |* sind, damit alle Seitengebundenen Rahmen und DrawObject
1555 |* untergebracht sind.
1557 |* Ersterstellung MA 27. Jul. 93
1558 |* Letzte Aenderung MA 24. Apr. 97
1560 |*************************************************************************/
1561 void SwRootFrm::AssertFlyPages()
1563 if ( !IsAssertFlyPages() )
1564 return;
1565 bAssertFlyPages = FALSE;
1567 SwDoc *pDoc = GetFmt()->GetDoc();
1568 const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1570 //Auf welche Seite will der 'letzte' Fly?
1571 USHORT nMaxPg = 0;
1572 USHORT i;
1574 for ( i = 0; i < pTbl->Count(); ++i )
1576 const SwFmtAnchor &rAnch = (*pTbl)[i]->GetAnchor();
1577 if ( !rAnch.GetCntntAnchor() && nMaxPg < rAnch.GetPageNum() )
1578 nMaxPg = rAnch.GetPageNum();
1580 //Wieviele Seiten haben wir derzeit?
1581 SwPageFrm *pPage = (SwPageFrm*)Lower();
1582 while ( pPage && pPage->GetNext() &&
1583 !((SwPageFrm*)pPage->GetNext())->IsFtnPage() )
1585 pPage = (SwPageFrm*)pPage->GetNext();
1588 if ( nMaxPg > pPage->GetPhyPageNum() )
1590 //Die Seiten werden ausgehend von der letzten Seite konsequent
1591 //nach den Regeln der PageDescs weitergefuehrt.
1592 BOOL bOdd = pPage->GetPhyPageNum() % 2 ? TRUE : FALSE;
1593 SwPageDesc *pDesc = pPage->GetPageDesc();
1594 SwFrm *pSibling = pPage->GetNext();
1595 for ( i = pPage->GetPhyPageNum(); i < nMaxPg; ++i )
1597 if ( !(bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
1599 //Leerseite einfuegen, die Flys werden aber erst von
1600 //der naechsten Seite aufgenommen!
1601 pPage = new SwPageFrm( pDoc->GetEmptyPageFmt(), pDesc );
1602 pPage->Paste( this, pSibling );
1603 pPage->PreparePage( FALSE );
1604 bOdd = bOdd ? FALSE : TRUE;
1605 ++i;
1607 pPage = new
1608 SwPageFrm( (bOdd ? pDesc->GetRightFmt() :
1609 pDesc->GetLeftFmt()), pDesc );
1610 pPage->Paste( this, pSibling );
1611 pPage->PreparePage( FALSE );
1612 bOdd = bOdd ? FALSE : TRUE;
1613 pDesc = pDesc->GetFollow();
1615 //Jetzt koennen die Endnotenseiten natuerlich wieder krumm sein;
1616 //in diesem Fall werden sie vernichtet.
1617 if ( pDoc->GetFtnIdxs().Count() )
1619 pPage = (SwPageFrm*)Lower();
1620 while ( pPage && !pPage->IsFtnPage() )
1621 pPage = (SwPageFrm*)pPage->GetNext();
1623 if ( pPage )
1625 SwPageDesc *pTmpDesc = pPage->FindPageDesc();
1626 bOdd = pPage->OnRightPage();
1627 if ( pPage->GetFmt() !=
1628 (bOdd ? pTmpDesc->GetRightFmt() : pTmpDesc->GetLeftFmt()) )
1629 RemoveFtns( pPage, FALSE, TRUE );
1635 /*************************************************************************
1637 |* SwRootFrm::AssertPageFlys()
1639 |* Beschreibung Stellt sicher, dass ab der uebergebenen Seite
1640 |* auf allen Seiten die Seitengebunden Objecte auf der richtigen
1641 |* Seite (Seitennummer stehen).
1643 |* Ersterstellung MA 02. Nov. 94
1644 |* Letzte Aenderung MA 10. Aug. 95
1646 |*************************************************************************/
1647 void SwRootFrm::AssertPageFlys( SwPageFrm *pPage )
1649 while ( pPage )
1651 if ( pPage->GetSortedObjs() )
1653 pPage->GetSortedObjs();
1654 for ( int i = 0;
1655 pPage->GetSortedObjs() && USHORT(i) < pPage->GetSortedObjs()->Count();
1656 ++i)
1658 // --> OD 2004-06-29 #i28701#
1659 SwFrmFmt& rFmt = (*pPage->GetSortedObjs())[i]->GetFrmFmt();
1660 const SwFmtAnchor &rAnch = rFmt.GetAnchor();
1661 const USHORT nPg = rAnch.GetPageNum();
1662 if ( rAnch.GetAnchorId() == FLY_PAGE &&
1663 nPg != pPage->GetPhyPageNum() )
1665 //Das er auf der falschen Seite steht muss noch nichts
1666 //heissen, wenn er eigentlich auf der Vorseite
1667 //stehen will und diese eine EmptyPage ist.
1668 if( nPg && !(pPage->GetPhyPageNum()-1 == nPg &&
1669 ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage()) )
1671 //Umhaengen kann er sich selbst, indem wir ihm
1672 //einfach ein Modify mit seinem AnkerAttr schicken.
1673 #ifdef PRODUCT
1674 rFmt.SwModify::Modify( 0, (SwFmtAnchor*)&rAnch );
1675 #else
1676 const sal_uInt32 nCnt = pPage->GetSortedObjs()->Count();
1677 rFmt.SwModify::Modify( 0, (SwFmtAnchor*)&rAnch );
1678 ASSERT( !pPage->GetSortedObjs() ||
1679 nCnt != pPage->GetSortedObjs()->Count(),
1680 "Kann das Obj nicht umhaengen." );
1681 #endif
1682 --i;
1687 pPage = (SwPageFrm*)pPage->GetNext();
1691 /*************************************************************************
1693 |* SwRootFrm::ChgSize()
1695 |* Ersterstellung MA 24. Jul. 92
1696 |* Letzte Aenderung MA 13. Aug. 93
1698 |*************************************************************************/
1699 Size SwRootFrm::ChgSize( const Size& aNewSize )
1701 Frm().SSize() = aNewSize;
1702 _InvalidatePrt();
1703 bFixSize = FALSE;
1704 return Frm().SSize();
1707 /*************************************************************************
1709 |* SwRootFrm::MakeAll()
1711 |* Ersterstellung MA 17. Nov. 92
1712 |* Letzte Aenderung MA 19. Apr. 93
1714 |*************************************************************************/
1715 void SwRootFrm::MakeAll()
1717 if ( !bValidPos )
1718 { bValidPos = TRUE;
1719 aFrm.Pos().X() = aFrm.Pos().Y() = DOCUMENTBORDER;
1721 if ( !bValidPrtArea )
1722 { bValidPrtArea = TRUE;
1723 aPrt.Pos().X() = aPrt.Pos().Y() = 0;
1724 aPrt.SSize( aFrm.SSize() );
1726 if ( !bValidSize )
1727 //SSize wird von den Seiten (Cut/Paste) eingestellt.
1728 bValidSize = TRUE;
1731 /*************************************************************************
1733 |* SwRootFrm::ImplInvalidateBrowseWidth()
1735 |* Ersterstellung MA 08. Jun. 96
1736 |* Letzte Aenderung MA 08. Jun. 96
1738 |*************************************************************************/
1739 void SwRootFrm::ImplInvalidateBrowseWidth()
1741 bBrowseWidthValid = FALSE;
1742 SwFrm *pPg = Lower();
1743 while ( pPg )
1745 pPg->InvalidateSize();
1746 pPg = pPg->GetNext();
1750 /*************************************************************************
1752 |* SwRootFrm::ImplCalcBrowseWidth()
1754 |* Ersterstellung MA 07. Jun. 96
1755 |* Letzte Aenderung MA 13. Jun. 96
1757 |*************************************************************************/
1758 void SwRootFrm::ImplCalcBrowseWidth()
1760 ASSERT( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE),
1761 "CalcBrowseWidth and not in BrowseView" );
1763 //Die (minimale) Breite wird von Rahmen, Tabellen und Zeichenobjekten
1764 //bestimmt. Die Breite wird nicht anhand ihrer aktuellen Groessen bestimmt,
1765 //sondern anhand der Attribute. Es interessiert also nicht wie breit sie
1766 //sind, sondern wie breit sie sein wollen.
1767 //Rahmen und Zeichenobjekte innerhalb ander Objekte (Rahmen, Tabellen)
1768 //Zaehlen nicht.
1769 //Seitenraender und Spalten werden hier nicht beruecksichtigt.
1771 SwFrm *pFrm = ContainsCntnt();
1772 while ( pFrm && !pFrm->IsInDocBody() )
1773 pFrm = ((SwCntntFrm*)pFrm)->GetNextCntntFrm();
1774 if ( !pFrm )
1775 return;
1777 bBrowseWidthValid = TRUE;
1778 ViewShell *pSh = GetShell();
1779 nBrowseWidth = pSh
1780 ? MINLAY + 2 * pSh->GetOut()->
1781 PixelToLogic( pSh->GetBrowseBorder() ).Width()
1782 : 5000;
1785 if ( pFrm->IsInTab() )
1786 pFrm = pFrm->FindTabFrm();
1788 if ( pFrm->IsTabFrm() &&
1789 !((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize().GetWidthPercent() )
1791 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
1792 const SwBorderAttrs &rAttrs = *aAccess.Get();
1793 const SwFmtHoriOrient &rHori = rAttrs.GetAttrSet().GetHoriOrient();
1794 long nWidth = rAttrs.GetSize().Width();
1795 if ( nWidth < USHRT_MAX-2000 && //-2000, weil bei Randeinstellung per
1796 //Zuppeln das USHRT_MAX verlorengeht!
1797 text::HoriOrientation::FULL != rHori.GetHoriOrient() )
1799 const SwHTMLTableLayout *pLayoutInfo =
1800 ((const SwTabFrm *)pFrm)->GetTable()
1801 ->GetHTMLTableLayout();
1802 if ( pLayoutInfo )
1803 nWidth = Min( nWidth, pLayoutInfo->GetBrowseWidthMin() );
1805 switch ( rHori.GetHoriOrient() )
1807 case text::HoriOrientation::NONE:
1808 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
1809 nWidth += rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm );
1810 break;
1811 case text::HoriOrientation::LEFT_AND_WIDTH:
1812 nWidth += rAttrs.CalcLeft( pFrm );
1813 break;
1814 default:
1815 break;
1818 nBrowseWidth = Max( nBrowseWidth, nWidth );
1821 else if ( pFrm->GetDrawObjs() )
1823 for ( USHORT i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
1825 // --> OD 2004-06-29 #i28701#
1826 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
1827 const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
1828 const BOOL bFly = pAnchoredObj->ISA(SwFlyFrm);
1829 if ( bFly &&
1830 WEIT_WECH == pAnchoredObj->GetObjRect().Width()||
1831 rFmt.GetFrmSize().GetWidthPercent() )
1832 continue;
1834 long nWidth = 0;
1835 switch ( rFmt.GetAnchor().GetAnchorId() )
1837 case FLY_IN_CNTNT:
1838 nWidth = bFly ? rFmt.GetFrmSize().GetWidth() :
1839 pAnchoredObj->GetObjRect().Width();
1840 break;
1841 case FLY_AT_CNTNT:
1843 // --> FME 2004-09-13 #i33170#
1844 // Reactivated old code because
1845 // nWidth = pAnchoredObj->GetObjRect().Right()
1846 // gives wrong results for objects that are still
1847 // at position WEIT_WECH.
1848 if ( bFly )
1850 nWidth = rFmt.GetFrmSize().GetWidth();
1851 const SwFmtHoriOrient &rHori = rFmt.GetHoriOrient();
1852 switch ( rHori.GetHoriOrient() )
1854 case text::HoriOrientation::NONE:
1855 nWidth += rHori.GetPos();
1856 break;
1857 case text::HoriOrientation::INSIDE:
1858 case text::HoriOrientation::LEFT:
1859 if ( text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() )
1860 nWidth += pFrm->Prt().Left();
1861 break;
1862 default:
1863 break;
1866 else
1867 //Fuer Zeichenobjekte ist die Auswahl sehr klein,
1868 //weil sie keine Attribute haben, also durch ihre
1869 //aktuelle Groesse bestimmt werden.
1870 nWidth = pAnchoredObj->GetObjRect().Right() -
1871 pAnchoredObj->GetDrawObj()->GetAnchorPos().X();
1872 // <--
1874 break;
1875 default: /* do nothing */;
1877 nBrowseWidth = Max( nBrowseWidth, nWidth );
1880 pFrm = pFrm->FindNextCnt();
1881 } while ( pFrm );
1884 /*************************************************************************
1886 |* SwRootFrm::StartAllAction()
1888 |* Ersterstellung MA 08. Mar. 98
1889 |* Letzte Aenderung MA 08. Mar. 98
1891 |*************************************************************************/
1893 void SwRootFrm::StartAllAction()
1895 ViewShell *pSh = GetCurrShell();
1896 if ( pSh )
1898 { if ( pSh->ISA( SwCrsrShell ) )
1899 ((SwCrsrShell*)pSh)->StartAction();
1900 else
1901 pSh->StartAction();
1902 pSh = (ViewShell*)pSh->GetNext();
1904 } while ( pSh != GetCurrShell() );
1907 void SwRootFrm::EndAllAction( BOOL bVirDev )
1909 ViewShell *pSh = GetCurrShell();
1910 if ( pSh )
1913 const BOOL bOldEndActionByVirDev = pSh->IsEndActionByVirDev();
1914 pSh->SetEndActionByVirDev( bVirDev );
1915 if ( pSh->ISA( SwCrsrShell ) )
1917 ((SwCrsrShell*)pSh)->EndAction();
1918 ((SwCrsrShell*)pSh)->CallChgLnk();
1919 if ( pSh->ISA( SwFEShell ) )
1920 ((SwFEShell*)pSh)->SetChainMarker();
1922 else
1923 pSh->EndAction();
1924 pSh->SetEndActionByVirDev( bOldEndActionByVirDev );
1925 pSh = (ViewShell*)pSh->GetNext();
1927 } while ( pSh != GetCurrShell() );
1930 void SwRootFrm::UnoRemoveAllActions()
1932 ViewShell *pSh = GetCurrShell();
1933 if ( pSh )
1936 // --> OD 2008-05-16 #i84729#
1937 // No end action, if <ViewShell> instance is currently in its end action.
1938 // Recursives calls to <::EndAction()> are not allowed.
1939 if ( !pSh->IsInEndAction() )
1941 DBG_ASSERT(!pSh->GetRestoreActions(), "Restore action count is already set!");
1942 BOOL bCrsr = pSh->ISA( SwCrsrShell );
1943 BOOL bFE = pSh->ISA( SwFEShell );
1944 USHORT nRestore = 0;
1945 while( pSh->ActionCount() )
1947 if( bCrsr )
1949 ((SwCrsrShell*)pSh)->EndAction();
1950 ((SwCrsrShell*)pSh)->CallChgLnk();
1951 if ( bFE )
1952 ((SwFEShell*)pSh)->SetChainMarker();
1954 else
1955 pSh->EndAction();
1956 nRestore++;
1958 pSh->SetRestoreActions(nRestore);
1960 // <--
1961 pSh->LockView(TRUE);
1962 pSh = (ViewShell*)pSh->GetNext();
1964 } while ( pSh != GetCurrShell() );
1967 void SwRootFrm::UnoRestoreAllActions()
1969 ViewShell *pSh = GetCurrShell();
1970 if ( pSh )
1973 USHORT nActions = pSh->GetRestoreActions();
1974 while( nActions-- )
1976 if ( pSh->ISA( SwCrsrShell ) )
1977 ((SwCrsrShell*)pSh)->StartAction();
1978 else
1979 pSh->StartAction();
1981 pSh->SetRestoreActions(0);
1982 pSh->LockView(FALSE);
1983 pSh = (ViewShell*)pSh->GetNext();
1985 } while ( pSh != GetCurrShell() );
1988 // PAGES01: Helper functions for SwRootFrm::CheckViewLayout
1989 void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset );
1991 void lcl_MoveAllLowerObjs( SwFrm* pFrm, const Point& rOffset )
1993 SwSortedObjs* pSortedObj = 0;
1994 const bool bPage = pFrm->IsPageFrm();
1996 if ( bPage )
1997 pSortedObj = static_cast<SwPageFrm*>(pFrm)->GetSortedObjs();
1998 else
1999 pSortedObj = pFrm->GetDrawObjs();
2001 for ( USHORT i = 0; pSortedObj && i < pSortedObj->Count(); ++i)
2003 SwAnchoredObject* pAnchoredObj = (*pSortedObj)[i];
2005 const SwFrmFmt& rObjFmt = pAnchoredObj->GetFrmFmt();
2006 const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor();
2008 // all except from the as character anchored objects are moved
2009 // when processing the page frame:
2010 const bool bAsChar = rAnchor.GetAnchorId() == FLY_IN_CNTNT;
2011 if ( !bPage && !bAsChar )
2012 continue;
2014 SwObjPositioningInProgress aPosInProgress( *pAnchoredObj );
2016 if ( pAnchoredObj->ISA(SwFlyFrm) )
2018 SwFlyFrm* pFlyFrm( static_cast<SwFlyFrm*>(pAnchoredObj) );
2019 lcl_MoveAllLowers( pFlyFrm, rOffset );
2020 pFlyFrm->NotifyDrawObj();
2021 // --> let the active embedded object be moved
2022 if ( pFlyFrm->Lower() )
2024 if ( pFlyFrm->Lower()->IsNoTxtFrm() )
2026 SwCntntFrm* pCntntFrm = static_cast<SwCntntFrm*>(pFlyFrm->Lower());
2027 ViewShell *pSh = pFlyFrm->Lower()->GetShell();
2028 if ( pSh )
2030 SwOLENode* pNode = pCntntFrm->GetNode()->GetOLENode();
2031 if ( pNode )
2033 svt::EmbeddedObjectRef& xObj = pNode->GetOLEObj().GetObject();
2034 if ( xObj.is() )
2036 ViewShell* pTmp = pSh;
2039 SwFEShell* pFEShell = dynamic_cast< SwFEShell* >( pTmp );
2040 if ( pFEShell )
2041 pFEShell->MoveObjectIfActive( xObj, rOffset );
2042 pTmp = static_cast<ViewShell*>( pTmp->GetNext() );
2043 } while( pTmp != pSh );
2049 // <--
2051 else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
2053 SwAnchoredDrawObject* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject*>(pAnchoredObj) );
2055 // don't touch objects that are not yet positioned:
2056 const bool bNotYetPositioned = pAnchoredDrawObj->NotYetPositioned();
2057 if ( bNotYetPositioned )
2058 continue;
2060 const Point aCurrAnchorPos = pAnchoredDrawObj->GetDrawObj()->GetAnchorPos();
2061 const Point aNewAnchorPos( ( aCurrAnchorPos + rOffset ) );
2062 pAnchoredDrawObj->DrawObj()->SetAnchorPos( aNewAnchorPos );
2063 pAnchoredDrawObj->SetLastObjRect( pAnchoredDrawObj->GetObjRect().SVRect() );
2065 // --> OD 2009-08-20 #i92511#
2066 // cache for object rectangle inclusive spaces has to be invalidated.
2067 pAnchoredObj->InvalidateObjRectWithSpaces();
2068 // <--
2072 void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset )
2074 const SwRect aFrm( pFrm->Frm() );
2076 // first move the current frame
2077 pFrm->Frm().Pos() += rOffset;
2079 // Don't forget accessibility:
2080 if( pFrm->IsAccessibleFrm() )
2082 SwRootFrm *pRootFrm = pFrm->FindRootFrm();
2083 if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
2084 pRootFrm->GetCurrShell() )
2086 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
2090 // the move any objects
2091 lcl_MoveAllLowerObjs( pFrm, rOffset );
2093 // finally, for layout frames we have to call this function recursively:
2094 if ( pFrm->ISA(SwLayoutFrm) )
2096 SwFrm* pLowerFrm = pFrm->GetLower();
2097 while ( pLowerFrm )
2099 lcl_MoveAllLowers( pLowerFrm, rOffset );
2100 pLowerFrm = pLowerFrm->GetNext();
2105 // PAGES01: Calculate how the pages have to be positioned
2106 void SwRootFrm::CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea )
2108 // --> OD 2008-07-07 #i91432#
2109 // No calculation of page positions, if only an empty page is present.
2110 // This situation occurs when <SwRootFrm> instance is in construction
2111 // and the document contains only left pages.
2112 if ( Lower()->GetNext() == 0 &&
2113 static_cast<SwPageFrm*>(Lower())->IsEmptyPage() )
2115 return;
2117 // <--
2119 if ( !pVisArea )
2121 // no early return for bNewPage
2122 if ( mnViewWidth < 0 )
2123 mnViewWidth = 0;
2125 else
2127 ASSERT( pViewOpt, "CheckViewLayout required ViewOptions" )
2129 const USHORT nColumns = pViewOpt->GetViewLayoutColumns();
2130 const bool bBookMode = pViewOpt->IsViewLayoutBookMode();
2132 if ( nColumns == mnColumns && bBookMode == mbBookMode && pVisArea->Width() == mnViewWidth && !mbSidebarChanged )
2133 return;
2135 mnColumns = nColumns;
2136 mbBookMode = bBookMode;
2137 mnViewWidth = pVisArea->Width();
2138 mbSidebarChanged = false;
2141 if( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE ) )
2143 mnColumns = 1;
2144 mbBookMode = false;
2147 Calc();
2149 const BOOL bOldCallbackActionEnabled = IsCallbackActionEnabled();
2150 SetCallbackActionEnabled( FALSE );
2152 maPageRects.clear();
2154 const long nBorder = Frm().Pos().X();
2155 const long nVisWidth = mnViewWidth - 2 * nBorder;
2156 const long nGapBetweenPages = GAPBETWEENPAGES;
2158 // check how many pages fit into the first page layout row:
2159 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(Lower());
2161 // will contain the number of pages per row. 0 means that
2162 // the page does not fit.
2163 long nWidthRemain = nVisWidth;
2165 // after one row has been processed, these variables contain
2166 // the width of the row and the maxium of the page heights
2167 long nCurrentRowHeight = 0;
2168 long nCurrentRowWidth = 0;
2170 // these variables are used to finally set the size of the
2171 // root frame
2172 long nSumRowHeight = 0;
2173 SwTwips nMinPageLeft = TWIPS_MAX;
2174 SwTwips nMaxPageRight = 0;
2175 SwPageFrm* pStartOfRow = pPageFrm;
2176 USHORT nNumberOfPagesInRow = mbBookMode ? 1 : 0; // in book view, start with right page
2177 bool bFirstRow = true;
2179 bool bPageChanged = false;
2180 const bool bRTL = !IsLeftToRightViewLayout();
2181 const SwTwips nSidebarWidth = SwPageFrm::GetSidebarBorderWidth( GetShell() );
2183 while ( pPageFrm )
2185 // we consider the current page to be "start of row" if
2186 // 1. it is the first page in the current row or
2187 // 2. it is the second page in the row and the first page is an empty page in non-book view:
2188 const bool bStartOfRow = pPageFrm == pStartOfRow ||
2189 ( pStartOfRow->IsEmptyPage() && pPageFrm == pStartOfRow->GetNext() && !mbBookMode );
2191 const bool bEmptyPage = pPageFrm->IsEmptyPage() && !mbBookMode;
2193 // no half doc border space for first page in each row and
2194 long nPageWidth = 0;
2195 long nPageHeight = 0;
2197 if ( mbBookMode )
2199 const SwFrm& rFormatPage = pPageFrm->GetFormatPage();
2201 nPageWidth = rFormatPage.Frm().Width() + nSidebarWidth + ((bStartOfRow || 1 == (pPageFrm->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages);
2202 nPageHeight = rFormatPage.Frm().Height() + nGapBetweenPages;
2204 else
2206 SwRect aPageFrm;
2207 if ( !pPageFrm->IsEmptyPage() )
2209 nPageWidth = pPageFrm->Frm().Width() + nSidebarWidth + (bStartOfRow ? 0 : nGapBetweenPages);
2210 nPageHeight = pPageFrm->Frm().Height() + nGapBetweenPages;
2214 if ( !bEmptyPage )
2215 ++nNumberOfPagesInRow;
2217 // finish current row if
2218 // 1. in dynamic mode the current page does not fit anymore or
2219 // 2. the current page exceeds the maximum number of columns
2220 bool bRowFinished = (0 == mnColumns && nWidthRemain < nPageWidth ) ||
2221 (0 != mnColumns && mnColumns < nNumberOfPagesInRow);
2223 // make sure that at least one page goes to the current row:
2224 if ( !bRowFinished || bStartOfRow )
2226 // current page is allowed to be in current row
2227 nWidthRemain = nWidthRemain - nPageWidth;
2229 nCurrentRowWidth = nCurrentRowWidth + nPageWidth;
2230 nCurrentRowHeight = Max( nCurrentRowHeight, nPageHeight );
2232 pPageFrm = static_cast<SwPageFrm*>(pPageFrm->GetNext());
2234 if ( !pPageFrm )
2235 bRowFinished = true;
2238 if ( bRowFinished )
2240 // pPageFrm now points to the first page in the new row or null
2241 // pStartOfRow points to the first page in the current row
2243 // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
2244 if ( !pPageFrm && nWidthRemain > 0 )
2246 // find last page in current row:
2247 const SwPageFrm* pLastPageInCurrentRow = pStartOfRow;
2248 while( pLastPageInCurrentRow->GetNext() )
2249 pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetNext());
2251 if ( pLastPageInCurrentRow->IsEmptyPage() )
2252 pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetPrev());
2254 // check how many times the last page would still fit into the remaining space:
2255 USHORT nNumberOfVirtualPages = 0;
2256 const USHORT nMaxNumberOfVirtualPages = mnColumns > 0 ? mnColumns - nNumberOfPagesInRow : USHRT_MAX;
2257 SwTwips nRemain = nWidthRemain;
2258 SwTwips nVirtualPagesWidth = 0;
2259 SwTwips nLastPageWidth = pLastPageInCurrentRow->Frm().Width() + nSidebarWidth;
2261 while ( ( mnColumns > 0 || nRemain > 0 ) && nNumberOfVirtualPages < nMaxNumberOfVirtualPages )
2263 SwTwips nLastPageWidthWithGap = nLastPageWidth;
2264 if ( !mbBookMode || ( 0 == (nNumberOfVirtualPages + nNumberOfPagesInRow) %2) )
2265 nLastPageWidthWithGap += nGapBetweenPages;
2267 if ( mnColumns > 0 || nLastPageWidthWithGap < nRemain )
2269 ++nNumberOfVirtualPages;
2270 nVirtualPagesWidth += nLastPageWidthWithGap;
2272 nRemain = nRemain - nLastPageWidthWithGap;
2275 nCurrentRowWidth = nCurrentRowWidth + nVirtualPagesWidth;
2278 // first page in book mode is always special:
2279 if ( bFirstRow && mbBookMode )
2281 // --> OD 2008-04-08 #i88036#
2282 // nCurrentRowWidth += pStartOfRow->Frm().Width() + nSidebarWidth;
2283 nCurrentRowWidth +=
2284 pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
2285 // <--
2288 // center page if possible
2289 const long nSizeDiff = nVisWidth > nCurrentRowWidth ?
2290 ( nVisWidth - nCurrentRowWidth ) / 2 :
2293 // adjust positions of pages in current row
2294 long nX = nSizeDiff;
2296 const long nRowStart = nBorder + nSizeDiff;
2297 const long nRowEnd = nRowStart + nCurrentRowWidth;
2299 if ( bFirstRow && mbBookMode )
2301 // --> OD 2008-04-08 #i88036#
2302 // nX += pStartOfRow->Frm().Width() + nSidebarWidth;
2303 nX += pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
2304 // <--
2307 SwPageFrm* pEndOfRow = pPageFrm;
2308 SwPageFrm* pPageToAdjust = pStartOfRow;
2312 const SwPageFrm* pFormatPage = pPageToAdjust;
2313 if ( mbBookMode )
2314 pFormatPage = &pPageToAdjust->GetFormatPage();
2316 const SwTwips nCurrentPageWidth = pFormatPage->Frm().Width() + (pFormatPage->IsEmptyPage() ? 0 : nSidebarWidth);
2317 const Point aOldPagePos = pPageToAdjust->Frm().Pos();
2318 const bool bLeftSidebar = pPageToAdjust->MarginSide();
2319 const SwTwips nLeftPageAddOffset = bLeftSidebar ?
2320 nSidebarWidth :
2323 Point aNewPagePos( nBorder + nX, nBorder + nSumRowHeight );
2324 Point aNewPagePosWithLeftOffset( nBorder + nX + nLeftPageAddOffset, nBorder + nSumRowHeight );
2326 // RTL view layout: Calculate mirrored page position
2327 if ( bRTL )
2329 const long nXOffsetInRow = aNewPagePos.X() - nRowStart;
2330 aNewPagePos.X() = nRowEnd - nXOffsetInRow - nCurrentPageWidth;
2331 aNewPagePosWithLeftOffset = aNewPagePos;
2332 aNewPagePosWithLeftOffset.X() += nLeftPageAddOffset;
2335 if ( aNewPagePosWithLeftOffset != aOldPagePos )
2337 lcl_MoveAllLowers( pPageToAdjust, aNewPagePosWithLeftOffset - aOldPagePos );
2338 pPageToAdjust->SetCompletePaint();
2339 bPageChanged = true;
2342 // calculate area covered by the current page and store to
2343 // maPageRects. This is used e.g., for cursor setting
2344 const bool bFirstColumn = pPageToAdjust == pStartOfRow;
2345 const bool bLastColumn = pPageToAdjust->GetNext() == pEndOfRow;
2346 const bool bLastRow = !pEndOfRow;
2348 nMinPageLeft = Min( nMinPageLeft, aNewPagePos.X() );
2349 nMaxPageRight = Max( nMaxPageRight, aNewPagePos.X() + nCurrentPageWidth);
2351 // border of nGapBetweenPages around the current page:
2352 SwRect aPageRectWithBorders( aNewPagePos.X() - nGapBetweenPages,
2353 aNewPagePos.Y(),
2354 pPageToAdjust->Frm().SSize().Width() + nGapBetweenPages + nSidebarWidth,
2355 nCurrentRowHeight );
2357 static const long nOuterClickDiff = 1000000;
2359 // adjust borders for these special cases:
2360 if ( bFirstColumn && !bRTL || bLastColumn && bRTL )
2361 aPageRectWithBorders.SubLeft( nOuterClickDiff );
2362 if ( bLastColumn && !bRTL || bFirstColumn && bRTL )
2363 aPageRectWithBorders.AddRight( nOuterClickDiff );
2364 if ( bFirstRow )
2365 aPageRectWithBorders.SubTop( nOuterClickDiff );
2366 if ( bLastRow )
2367 aPageRectWithBorders.AddBottom( nOuterClickDiff );
2369 maPageRects.push_back( aPageRectWithBorders );
2371 nX = nX + nCurrentPageWidth;
2372 pPageToAdjust = static_cast<SwPageFrm*>(pPageToAdjust->GetNext());
2374 // distance to next page
2375 if ( pPageToAdjust && pPageToAdjust != pEndOfRow )
2377 // in book view, we add the x gap before left (even) pages:
2378 if ( mbBookMode )
2380 if ( 0 == (pPageToAdjust->GetPhyPageNum()%2) )
2381 nX = nX + nGapBetweenPages;
2383 else
2385 // in non-book view, dont add x gap before
2386 // 1. the last empty page in a row
2387 // 2. after an empty page
2388 const bool bDontAddGap = ( pPageToAdjust->IsEmptyPage() && pPageToAdjust->GetNext() == pEndOfRow ) ||
2389 ( static_cast<SwPageFrm*>(pPageToAdjust->GetPrev())->IsEmptyPage() );
2391 if ( !bDontAddGap )
2392 nX = nX + nGapBetweenPages;
2396 while ( pPageToAdjust != pEndOfRow );
2398 // adjust values for root frame size
2399 nSumRowHeight = nSumRowHeight + nCurrentRowHeight;
2401 // start new row:
2402 nCurrentRowHeight = 0;
2403 nCurrentRowWidth = 0;
2404 pStartOfRow = pEndOfRow;
2405 nWidthRemain = nVisWidth;
2406 nNumberOfPagesInRow = 0;
2407 bFirstRow = false;
2408 } // end row finished
2409 } // end while
2411 // set size of root frame:
2412 const Size aOldSize( Frm().SSize() );
2413 const Size aNewSize( nMaxPageRight - nBorder, nSumRowHeight - nGapBetweenPages );
2415 if ( bPageChanged || aNewSize != aOldSize )
2417 ChgSize( aNewSize );
2418 ::AdjustSizeChgNotify( this );
2419 Calc();
2421 ViewShell* pSh = GetShell();
2423 if ( pSh && pSh->GetDoc()->GetDocShell() )
2425 pSh->SetFirstVisPageInvalid();
2426 if (bOldCallbackActionEnabled)
2428 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
2429 pSh->GetDoc()->GetDocShell()->Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED));
2434 maPagesArea.Pos( Frm().Pos() );
2435 maPagesArea.SSize( aNewSize );
2436 if ( TWIPS_MAX != nMinPageLeft )
2437 maPagesArea._Left( nMinPageLeft );
2439 SetCallbackActionEnabled( bOldCallbackActionEnabled );
2442 bool SwRootFrm::IsLeftToRightViewLayout() const
2444 // Layout direction determined by layout direction of the first page.
2445 // --> OD 2008-04-08 #i88036#
2446 // Only ask a non-empty page frame for its layout direction
2447 // const SwPageFrm* pPage = dynamic_cast<const SwPageFrm*>(Lower());
2448 // return !pPage->IsRightToLeft() && !pPage->IsVertical();
2449 const SwPageFrm& rPage =
2450 dynamic_cast<const SwPageFrm*>(Lower())->GetFormatPage();
2451 return !rPage.IsRightToLeft() && !rPage.IsVertical();
2452 // <--
2455 /*const SwRect SwRootFrm::GetExtendedPageArea( USHORT nPageNumber ) const
2457 SwRect aRet;
2458 ASSERT( nPageNumber < maPageRects.size(), "No extended page area available" )
2459 if ( nPageNumber < maPageRects.size() )
2460 aRet = maPageRects[ nPageNumber ];
2461 return aRet;
2465 const SwPageFrm& SwPageFrm::GetFormatPage() const
2467 const SwPageFrm* pRet = this;
2468 if ( IsEmptyPage() )
2470 pRet = static_cast<const SwPageFrm*>( OnRightPage() ? GetNext() : GetPrev() );
2471 // --> OD 2008-04-08 #i88035#
2472 // Typically a right empty page frame has a next non-empty page frame and
2473 // a left empty page frame has a previous non-empty page frame.
2474 // But under certain cirsumstances this assumption is not true -
2475 // e.g. during insertion of a left page at the end of the document right
2476 // after a left page in an intermediate state a right empty page does not
2477 // have a next page frame.
2478 if ( pRet == 0 )
2480 if ( OnRightPage() )
2482 pRet = static_cast<const SwPageFrm*>( GetPrev() );
2484 else
2486 pRet = static_cast<const SwPageFrm*>( GetNext() );
2489 ASSERT( pRet,
2490 "<SwPageFrm::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash." );
2491 // <--
2493 return *pRet;