xref: /trunk/main/sw/source/core/layout/pagechg.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <com/sun/star/embed/EmbedStates.hpp>
32 #include <ndole.hxx>
33 #include <docary.hxx>
34 #include <svl/itemiter.hxx>
35 #include <fmtfsize.hxx>
36 #include <fmthdft.hxx>
37 #include <fmtclds.hxx>
38 #include <fmtanchr.hxx>
39 #include <fmtpdsc.hxx>
40 #include <fmtfordr.hxx>
41 #include <fmtfld.hxx>
42 #include <fmtornt.hxx>
43 #include <ftninfo.hxx>
44 #include <tgrditem.hxx>
45 #include <viewopt.hxx>
46 #include <docsh.hxx>
47 
48 #include "viewimp.hxx"
49 #include "viewopt.hxx"
50 #include "pagefrm.hxx"
51 #include "rootfrm.hxx"
52 #include "cntfrm.hxx"
53 #include "flyfrm.hxx"
54 #include "doc.hxx"
55 #include "fesh.hxx"
56 #include "dview.hxx"
57 #include "dflyobj.hxx"
58 #include "dcontact.hxx"
59 #include "frmtool.hxx"
60 #include "fldbas.hxx"
61 #include "hints.hxx"
62 #include "errhdl.hxx"
63 #include "swtable.hxx"
64 
65 #include "ftnidx.hxx"
66 #include "bodyfrm.hxx"
67 #include "ftnfrm.hxx"
68 #include "tabfrm.hxx"
69 #include "txtfrm.hxx"
70 #include "layact.hxx"
71 #include "flyfrms.hxx"
72 #include "htmltbl.hxx"
73 #include "pagedesc.hxx"
74 #include "poolfmt.hxx"
75 #include <editeng/frmdiritem.hxx>
76 #include <swfntcch.hxx> // SwFontAccess
77 #include <sortedobjs.hxx>
78 #include <switerator.hxx>
79 #include <vcl/svapp.hxx>
80 
81 using namespace ::com::sun::star;
82 
83 
84 /*************************************************************************
85 |*
86 |*  SwBodyFrm::SwBodyFrm()
87 |*
88 |*  Ersterstellung      MA ??
89 |*  Letzte Aenderung    MA 01. Aug. 93
90 |*
91 |*************************************************************************/
92 SwBodyFrm::SwBodyFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
93     SwLayoutFrm( pFmt, pSib )
94 {
95     nType = FRMC_BODY;
96 }
97 
98 /*************************************************************************
99 |*
100 |*  SwBodyFrm::Format()
101 |*
102 |*  Ersterstellung      MA 30. May. 94
103 |*  Letzte Aenderung    MA 20. Jan. 99
104 |*
105 |*************************************************************************/
106 void SwBodyFrm::Format( const SwBorderAttrs * )
107 {
108     //Formatieren des Body ist zu einfach, deshalb bekommt er ein eigenes
109     //Format; Umrandungen und dergl. sind hier nicht zu beruecksichtigen.
110     //Breite ist die der PrtArea des Uppers, Hoehe ist die Hoehe der PrtArea
111     //des Uppers abzueglich der Nachbarn (Wird eigentlich eingestellt aber
112     //Vorsicht ist die Mutter der Robustheit).
113     //Die PrtArea ist stets so gross wie der Frm itself.
114 
115     if ( !bValidSize )
116     {
117         SwTwips nHeight = GetUpper()->Prt().Height();
118         SwTwips nWidth = GetUpper()->Prt().Width();
119         const SwFrm *pFrm = GetUpper()->Lower();
120         do
121         {
122             if ( pFrm != this )
123             {
124                 if( pFrm->IsVertical() )
125                     nWidth -= pFrm->Frm().Width();
126                 else
127                     nHeight -= pFrm->Frm().Height();
128             }
129             pFrm = pFrm->GetNext();
130         } while ( pFrm );
131         if ( nHeight < 0 )
132             nHeight = 0;
133         Frm().Height( nHeight );
134         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
135         if( IsVertical() && !IsVertLR() && !IsReverse() && nWidth != Frm().Width() )
136             Frm().Pos().X() += Frm().Width() - nWidth;
137         Frm().Width( nWidth );
138     }
139 
140     sal_Bool bNoGrid = sal_True;
141     if( GetUpper()->IsPageFrm() && ((SwPageFrm*)GetUpper())->HasGrid() )
142     {
143         GETGRID( ((SwPageFrm*)GetUpper()) )
144         if( pGrid )
145         {
146             bNoGrid = sal_False;
147             long nSum = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
148             SWRECTFN( this )
149             long nSize = (Frm().*fnRect->fnGetWidth)();
150             long nBorder = 0;
151             if( GRID_LINES_CHARS == pGrid->GetGridType() )
152             {
153                 //for textgrid refactor
154                 SwDoc *pDoc = GetFmt()->GetDoc();
155                 nBorder = nSize % (GETGRIDWIDTH(pGrid, pDoc));
156                 nSize -= nBorder;
157                 nBorder /= 2;
158             }
159             (Prt().*fnRect->fnSetPosX)( nBorder );
160             (Prt().*fnRect->fnSetWidth)( nSize );
161 
162             // Height of body frame:
163             nBorder = (Frm().*fnRect->fnGetHeight)();
164 
165             // Number of possible lines in area of body frame:
166             long nNumberOfLines = nBorder / nSum;
167             if( nNumberOfLines > pGrid->GetLines() )
168                 nNumberOfLines = pGrid->GetLines();
169 
170             // Space required for nNumberOfLines lines:
171             nSize = nNumberOfLines * nSum;
172             nBorder -= nSize;
173             nBorder /= 2;
174 
175             // #i21774# Footnotes and centering the grid does not work together:
176             const bool bAdjust = 0 == ((SwPageFrm*)GetUpper())->GetFmt()->GetDoc()->
177                                         GetFtnIdxs().Count();
178 
179             (Prt().*fnRect->fnSetPosY)( bAdjust ? nBorder : 0 );
180             (Prt().*fnRect->fnSetHeight)( nSize );
181         }
182     }
183     if( bNoGrid )
184     {
185         Prt().Pos().X() = Prt().Pos().Y() = 0;
186         Prt().Height( Frm().Height() );
187         Prt().Width( Frm().Width() );
188     }
189     bValidSize = bValidPrtArea = sal_True;
190 }
191 
192 /*************************************************************************
193 |*
194 |*  SwPageFrm::SwPageFrm(), ~SwPageFrm()
195 |*
196 |*  Ersterstellung      MA 20. Oct. 92
197 |*  Letzte Aenderung    MA 08. Dec. 97
198 |*
199 |*************************************************************************/
200 SwPageFrm::SwPageFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwPageDesc *pPgDsc ) :
201     SwFtnBossFrm( pFmt, pSib ),
202     pSortedObjs( 0 ),
203     pDesc( pPgDsc ),
204     nPhyPageNum( 0 ),
205     // OD 2004-05-17 #i28701#
206     mbLayoutInProgress( false )
207 {
208     SetDerivedVert( sal_False );
209     SetDerivedR2L( sal_False );
210     if( pDesc )
211     {
212         bHasGrid = sal_True;
213         GETGRID( this )
214         if( !pGrid )
215             bHasGrid = sal_False;
216     }
217     else
218         bHasGrid = sal_False;
219     SetMaxFtnHeight( pPgDsc->GetFtnInfo().GetHeight() ?
220                      pPgDsc->GetFtnInfo().GetHeight() : LONG_MAX ),
221     nType = FRMC_PAGE;
222     bInvalidLayout = bInvalidCntnt = bInvalidSpelling = bInvalidSmartTags = bInvalidAutoCmplWrds = bInvalidWordCount = sal_True;
223     bInvalidFlyLayout = bInvalidFlyCntnt = bInvalidFlyInCnt = bFtnPage = bEndNotePage = sal_False;
224 
225     ViewShell *pSh = getRootFrm()->GetCurrShell();
226     const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
227     if ( bBrowseMode )
228     {
229         Frm().Height( 0 );
230         long nWidth = pSh->VisArea().Width();
231         if ( !nWidth )
232             nWidth = 5000L;     //aendert sich sowieso
233         Frm().Width ( nWidth );
234     }
235     else
236         Frm().SSize( pFmt->GetFrmSize().GetSize() );
237 
238     //Body-Bereich erzeugen und einsetzen, aber nur wenn ich nicht gerade
239     //eine Leerseite bin.
240     SwDoc *pDoc = pFmt->GetDoc();
241     if ( sal_False == (bEmptyPage = pFmt == pDoc->GetEmptyPageFmt()) )
242     {
243         bEmptyPage = sal_False;
244         Calc();                             //Damit die PrtArea stimmt.
245         SwBodyFrm *pBodyFrm = new SwBodyFrm( pDoc->GetDfltFrmFmt(), this );
246         pBodyFrm->ChgSize( Prt().SSize() );
247         pBodyFrm->Paste( this );
248         pBodyFrm->Calc();                   //Damit die Spalten korrekt
249                                             //eingesetzt werden koennen.
250         pBodyFrm->InvalidatePos();
251 
252         if ( bBrowseMode )
253             _InvalidateSize();      //Alles nur gelogen
254 
255         //Header/Footer einsetzen, nur rufen wenn aktiv.
256         if ( pFmt->GetHeader().IsActive() )
257             PrepareHeader();
258         if ( pFmt->GetFooter().IsActive() )
259             PrepareFooter();
260 
261         const SwFmtCol &rCol = pFmt->GetCol();
262         if ( rCol.GetNumCols() > 1 )
263         {
264             const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass ein
265                                  //Old-Wert hereingereicht wird.
266             pBodyFrm->ChgColumns( aOld, rCol );
267         }
268     }
269 }
270 
271 SwPageFrm::~SwPageFrm()
272 {
273     //FlyContainer entleeren, delete der Flys uebernimmt der Anchor
274     //(Basisklasse SwFrm)
275     if ( pSortedObjs )
276     {
277         //Objekte koennen (warum auch immer) auch an Seiten verankert sein,
278         //die vor Ihren Ankern stehen. Dann wuerde auf bereits freigegebenen
279         //Speicher zugegriffen.
280         for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
281         {
282             SwAnchoredObject* pAnchoredObj = (*pSortedObjs)[i];
283             pAnchoredObj->SetPageFrm( 0L );
284         }
285         delete pSortedObjs;
286         pSortedObjs = 0;        //Auf 0 setzen, sonst rauchts beim Abmdelden von Flys!
287     }
288 
289     //Damit der Zugriff auf zerstoerte Seiten verhindert werden kann.
290     if ( !IsEmptyPage() ) //#59184# sollte fuer Leerseiten unnoetig sein.
291     {
292         SwDoc *pDoc = GetFmt()->GetDoc();
293         if( pDoc && !pDoc->IsInDtor() )
294         {
295             ViewShell *pSh = getRootFrm()->GetCurrShell();
296             if ( pSh )
297             {
298                 SwViewImp *pImp = pSh->Imp();
299                 pImp->SetFirstVisPageInvalid();
300                 if ( pImp->IsAction() )
301                     pImp->GetLayAction().SetAgain();
302                 // OD 12.02.2003 #i9719#, #105645# - retouche area of page
303                 // including border and shadow area.
304                 const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
305                 SwRect aRetoucheRect;
306                 SwPageFrm::GetBorderAndShadowBoundRect( Frm(), pSh, aRetoucheRect, bRightSidebar );
307                 pSh->AddPaintRect( aRetoucheRect );
308             }
309         }
310     }
311 }
312 
313 
314 void SwPageFrm::CheckGrid( sal_Bool bInvalidate )
315 {
316     sal_Bool bOld = bHasGrid;
317     bHasGrid = sal_True;
318     GETGRID( this )
319     bHasGrid = 0 != pGrid;
320     if( bInvalidate || bOld != bHasGrid )
321     {
322         SwLayoutFrm* pBody = FindBodyCont();
323         if( pBody )
324         {
325             pBody->InvalidatePrt();
326             SwCntntFrm* pFrm = pBody->ContainsCntnt();
327             while( pBody->IsAnLower( pFrm ) )
328             {
329                 ((SwTxtFrm*)pFrm)->Prepare( PREP_CLEAR );
330                 pFrm = pFrm->GetNextCntntFrm();
331             }
332         }
333         SetCompletePaint();
334     }
335 }
336 
337 
338 void SwPageFrm::CheckDirection( sal_Bool bVert )
339 {
340     sal_uInt16 nDir =
341             ((SvxFrameDirectionItem&)GetFmt()->GetFmtAttr( RES_FRAMEDIR )).GetValue();
342     if( bVert )
343     {
344         if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir )
345         {
346             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
347             bVertLR = 0;
348             bVertical = 0;
349         }
350         else
351         {
352             const ViewShell *pSh = getRootFrm()->GetCurrShell();
353             if( pSh && pSh->GetViewOptions()->getBrowseMode() )
354             {
355                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
356                 bVertLR = 0;
357                 bVertical = 0;
358             }
359             else
360             {
361                 bVertical = 1;
362                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
363                 if(FRMDIR_VERT_TOP_RIGHT == nDir)
364                     bVertLR = 0;
365                 else if(FRMDIR_VERT_TOP_LEFT==nDir)
366                     bVertLR = 1;
367             }
368         }
369 
370         bReverse = 0;
371         bInvalidVert = 0;
372     }
373     else
374     {
375         if( FRMDIR_HORI_RIGHT_TOP == nDir )
376             bRightToLeft = 1;
377         else
378             bRightToLeft = 0;
379         bInvalidR2L = 0;
380     }
381 }
382 
383 /*************************************************************************
384 |*
385 |*  SwPageFrm::PreparePage()
386 |*
387 |*  Beschreibung        Erzeugt die Spezifischen Flys zur Seite und formatiert
388 |*      generischen Cntnt
389 |*  Ersterstellung      MA 20. Oct. 92
390 |*  Letzte Aenderung    MA 09. Nov. 95
391 |*
392 |*************************************************************************/
393 void MA_FASTCALL lcl_FormatLay( SwLayoutFrm *pLay )
394 {
395     //Alle LayoutFrms - nicht aber Tables, Flys o.ae. - formatieren.
396 
397     SwFrm *pTmp = pLay->Lower();
398     //Erst die untergeordneten
399     while ( pTmp )
400     {
401         if ( pTmp->GetType() & 0x00FF )
402             ::lcl_FormatLay( (SwLayoutFrm*)pTmp );
403         pTmp = pTmp->GetNext();
404     }
405     pLay->Calc();
406 }
407 
408 void MA_FASTCALL lcl_MakeObjs( const SwSpzFrmFmts &rTbl, SwPageFrm *pPage )
409 {
410     //Anlegen bzw. registrieren von Flys und Drawobjekten.
411     //Die Formate stehen in der SpzTbl (vom Dokument).
412     //Flys werden angelegt, DrawObjekte werden bei der Seite angemeldet.
413 
414     for ( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
415     {
416         SdrObject *pSdrObj;
417         SwFrmFmt *pFmt = rTbl[i];
418         const SwFmtAnchor &rAnch = pFmt->GetAnchor();
419         if ( rAnch.GetPageNum() == pPage->GetPhyPageNum() )
420         {
421             if( rAnch.GetCntntAnchor() )
422             {
423                 if (FLY_AT_PAGE == rAnch.GetAnchorId())
424                 {
425                     SwFmtAnchor aAnch( rAnch );
426                     aAnch.SetAnchor( 0 );
427                     pFmt->SetFmtAttr( aAnch );
428                 }
429                 else
430                     continue;
431             }
432 
433             //Wird ein Rahmen oder ein SdrObject beschrieben?
434             sal_Bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
435             pSdrObj = 0;
436             if ( bSdrObj  && 0 == (pSdrObj = pFmt->FindSdrObject()) )
437             {
438                 ASSERT( sal_False, "DrawObject not found." );
439                 pFmt->GetDoc()->DelFrmFmt( pFmt );
440                 --i;
441                 continue;
442             }
443             //Das Objekt kann noch an einer anderen Seite verankert sein.
444             //Z.B. beim Einfuegen einer neuen Seite aufgrund eines
445             //Pagedescriptor-Wechsels. Das Objekt muss dann umgehaengt
446             //werden.
447             //Fuer bestimmte Faelle ist das Objekt bereits an der richtigen
448             //Seite verankert. Das wird hier automatisch erledigt und braucht
449             //- wenngleich performater machbar - nicht extra codiert werden.
450             SwPageFrm *pPg = pPage->IsEmptyPage() ? (SwPageFrm*)pPage->GetNext() : pPage;
451             if ( bSdrObj )
452             {
453                 // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
454                 SwDrawContact *pContact =
455                             static_cast<SwDrawContact*>(::GetUserCall(pSdrObj));
456                 if ( pSdrObj->ISA(SwDrawVirtObj) )
457                 {
458                     SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pSdrObj);
459                     if ( pContact )
460                     {
461                         pDrawVirtObj->RemoveFromWriterLayout();
462                         pDrawVirtObj->RemoveFromDrawingPage();
463                         pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pDrawVirtObj )) );
464                     }
465                 }
466                 else
467                 {
468                     if ( pContact->GetAnchorFrm() )
469                         pContact->DisconnectFromLayout( false );
470                     pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pSdrObj )) );
471                 }
472             }
473             else
474             {
475                 SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
476                 SwFlyFrm *pFly = aIter.First();
477                 if ( pFly)
478                 {
479                     if( pFly->GetAnchorFrm() )
480                         pFly->AnchorFrm()->RemoveFly( pFly );
481                 }
482                 else
483                     pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pPg, pPg );
484                 pPg->AppendFly( pFly );
485                 ::RegistFlys( pPg, pFly );
486             }
487         }
488     }
489 }
490 
491 void SwPageFrm::PreparePage( sal_Bool bFtn )
492 {
493     SetFtnPage( bFtn );
494 
495     // --> OD 2008-01-30 #i82258#
496     // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has
497     // the side effect, that the content of page header and footer are formatted.
498     // For this formatting it is needed that the anchored objects are registered
499     // at the <SwPageFrm> instance.
500     // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)>
501     ::RegistFlys( this, this );
502 
503         if ( Lower() )
504     {
505                 ::lcl_FormatLay( this );
506     }
507     // <--
508 
509     //Flys und DrawObjekte die noch am Dokument bereitstehen.
510     //Fussnotenseiten tragen keine Seitengebundenen Flys!
511     //Es kann Flys und Objekte geben, die auf Leerseiten (Seitennummernmaessig)
512     //stehen wollen, diese werden jedoch von den Leerseiten ignoriert;
513     //sie werden von den Folgeseiten aufgenommen.
514     if ( !bFtn && !IsEmptyPage() )
515     {
516         SwDoc *pDoc = GetFmt()->GetDoc();
517 
518         if ( GetPrev() && ((SwPageFrm*)GetPrev())->IsEmptyPage() )
519             lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), (SwPageFrm*)GetPrev() );
520         lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), this );
521 
522         //Kopf-/Fusszeilen) formatieren.
523         SwLayoutFrm *pLow = (SwLayoutFrm*)Lower();
524         while ( pLow )
525         {
526             if ( pLow->GetType() & (FRMTYPE_HEADER|FRMTYPE_FOOTER) )
527             {
528                 SwCntntFrm *pCntnt = pLow->ContainsCntnt();
529                 while ( pCntnt && pLow->IsAnLower( pCntnt ) )
530                 {
531                     pCntnt->OptCalc();  //Nicht die Vorgaenger
532                     pCntnt = pCntnt->GetNextCntntFrm();
533                 }
534             }
535             pLow = (SwLayoutFrm*)pLow->GetNext();
536         }
537     }
538 }
539 
540 /*************************************************************************
541 |*
542 |*  SwPageFrm::Modify()
543 |*
544 |*  Ersterstellung      MA 20. Oct. 92
545 |*  Letzte Aenderung    MA 03. Mar. 96
546 |*
547 |*************************************************************************/
548 void SwPageFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
549 {
550     ViewShell *pSh = getRootFrm()->GetCurrShell();
551     if ( pSh )
552         pSh->SetFirstVisPageInvalid();
553     sal_uInt8 nInvFlags = 0;
554 
555     if( pNew && RES_ATTRSET_CHG == pNew->Which() )
556     {
557         SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
558         SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
559         SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
560         SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
561         while( sal_True )
562         {
563             _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
564                          (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
565                          &aOldSet, &aNewSet );
566             if( aNIter.IsAtEnd() )
567                 break;
568             aNIter.NextItem();
569             aOIter.NextItem();
570         }
571         if ( aOldSet.Count() || aNewSet.Count() )
572             SwLayoutFrm::Modify( &aOldSet, &aNewSet );
573     }
574     else
575         _UpdateAttr( pOld, pNew, nInvFlags );
576 
577     if ( nInvFlags != 0 )
578     {
579         InvalidatePage( this );
580         if ( nInvFlags & 0x01 )
581             _InvalidatePrt();
582         if ( nInvFlags & 0x02 )
583             SetCompletePaint();
584         if ( nInvFlags & 0x04 && GetNext() )
585             GetNext()->InvalidatePos();
586         if ( nInvFlags & 0x08 )
587             PrepareHeader();
588         if ( nInvFlags & 0x10 )
589             PrepareFooter();
590         if ( nInvFlags & 0x20 )
591             CheckGrid( nInvFlags & 0x40 );
592     }
593 }
594 
595 void SwPageFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
596                              sal_uInt8 &rInvFlags,
597                              SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
598 {
599     sal_Bool bClear = sal_True;
600     const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
601     switch( nWhich )
602     {
603         case RES_FMT_CHG:
604         {
605             //Wenn sich das FrmFmt aendert kann hier einiges passieren.
606             //Abgesehen von den Grossenverhaeltnissen sind noch andere
607             //Dinge betroffen.
608             //1. Spaltigkeit.
609             ASSERT( pOld && pNew, "FMT_CHG Missing Format." );
610             const SwFmt* pOldFmt = ((SwFmtChg*)pOld)->pChangedFmt;
611             const SwFmt* pNewFmt = ((SwFmtChg*)pNew)->pChangedFmt;
612             ASSERT( pOldFmt && pNewFmt, "FMT_CHG Missing Format." );
613 
614             const SwFmtCol &rOldCol = pOldFmt->GetCol();
615             const SwFmtCol &rNewCol = pNewFmt->GetCol();
616             if( rOldCol != rNewCol )
617             {
618                 SwLayoutFrm *pB = FindBodyCont();
619                 ASSERT( pB, "Seite ohne Body." );
620                 pB->ChgColumns( rOldCol, rNewCol );
621                 rInvFlags |= 0x20;
622             }
623 
624             //2. Kopf- und Fusszeilen.
625             const SwFmtHeader &rOldH = pOldFmt->GetHeader();
626             const SwFmtHeader &rNewH = pNewFmt->GetHeader();
627             if( rOldH != rNewH )
628                 rInvFlags |= 0x08;
629 
630             const SwFmtFooter &rOldF = pOldFmt->GetFooter();
631             const SwFmtFooter &rNewF = pNewFmt->GetFooter();
632             if( rOldF != rNewF )
633                 rInvFlags |= 0x10;
634             CheckDirChange();
635         }
636             /* kein break hier */
637         case RES_FRM_SIZE:
638         {
639             const SwRect aOldPageFrmRect( Frm() );
640             ViewShell *pSh = getRootFrm()->GetCurrShell();
641             if( pSh && pSh->GetViewOptions()->getBrowseMode() )
642             {
643                 bValidSize = sal_False;
644                 // OD 28.10.2002 #97265# - Don't call <SwPageFrm::MakeAll()>
645                 // Calculation of the page is not necessary, because its size is
646                 // is invalidated here and further invalidation is done in the
647                 // calling method <SwPageFrm::Modify(..)> and probably by calling
648                 // <SwLayoutFrm::Modify(..)> at the end.
649                 // It can also causes inconsistences, because the lowers are
650                 // adjusted, but not calculated, and a <SwPageFrm::MakeAll()> of
651                 // a next page is called. This is performed on the switch to the
652                 // online layout.
653                 //MakeAll();
654             }
655             else
656             {
657                 const SwFmtFrmSize &rSz = nWhich == RES_FMT_CHG ?
658                         ((SwFmtChg*)pNew)->pChangedFmt->GetFrmSize() :
659                         (const SwFmtFrmSize&)*pNew;
660 
661                 Frm().Height( Max( rSz.GetHeight(), long(MINLAY) ) );
662                 Frm().Width ( Max( rSz.GetWidth(),  long(MINLAY) ) );
663 
664                 // PAGES01
665                 if ( GetUpper() )
666                     static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
667             }
668             //Window aufraeumen.
669             if( pSh && pSh->GetWin() && aOldPageFrmRect.HasArea() )
670             {
671                 // OD 12.02.2003 #i9719#, #105645# - consider border and shadow of
672                 // page frame for determine 'old' rectangle - it's used for invalidating.
673                 const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
674                 SwRect aOldRectWithBorderAndShadow;
675                 SwPageFrm::GetBorderAndShadowBoundRect( aOldPageFrmRect, pSh, aOldRectWithBorderAndShadow, bRightSidebar );
676                 pSh->InvalidateWindows( aOldRectWithBorderAndShadow );
677             }
678             rInvFlags |= 0x03;
679             if ( aOldPageFrmRect.Height() != Frm().Height() )
680                 rInvFlags |= 0x04;
681         }
682         break;
683 
684         case RES_COL:
685         {
686             SwLayoutFrm *pB = FindBodyCont();
687             ASSERT( pB, "Seite ohne Body." );
688             pB->ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
689             rInvFlags |= 0x22;
690         }
691         break;
692 
693         case RES_HEADER:
694             rInvFlags |= 0x08;
695             break;
696 
697         case RES_FOOTER:
698             rInvFlags |= 0x10;
699             break;
700         case RES_TEXTGRID:
701             rInvFlags |= 0x60;
702             break;
703 
704         case RES_PAGEDESC_FTNINFO:
705             //Die derzeit einzig sichere Methode:
706             ((SwRootFrm*)GetUpper())->SetSuperfluous();
707             SetMaxFtnHeight( pDesc->GetFtnInfo().GetHeight() );
708             if ( !GetMaxFtnHeight() )
709                 SetMaxFtnHeight( LONG_MAX );
710             SetColMaxFtnHeight();
711             //Hier wird die Seite ggf. zerstoert!
712             ((SwRootFrm*)GetUpper())->RemoveFtns( 0, sal_False, sal_True );
713             break;
714         case RES_FRAMEDIR :
715             CheckDirChange();
716             break;
717 
718         default:
719             bClear = sal_False;
720     }
721     if ( bClear )
722     {
723         if ( pOldSet || pNewSet )
724         {
725             if ( pOldSet )
726                 pOldSet->ClearItem( nWhich );
727             if ( pNewSet )
728                 pNewSet->ClearItem( nWhich );
729         }
730         else
731             SwLayoutFrm::Modify( pOld, pNew );
732     }
733 }
734 
735 /*************************************************************************
736 |*
737 |*                SwPageFrm::GetInfo()
738 |*
739 |*    Beschreibung      erfragt Informationen
740 |*    Ersterstellung    JP 31.03.94
741 |*    Letzte Aenderung  JP 31.03.94
742 |*
743 *************************************************************************/
744     // erfrage vom Modify Informationen
745 sal_Bool SwPageFrm::GetInfo( SfxPoolItem & rInfo ) const
746 {
747     if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
748     {
749         // es gibt einen PageFrm also wird er benutzt
750         return sal_False;
751     }
752     return sal_True;        // weiter suchen
753 }
754 
755 /*************************************************************************
756 |*
757 |*  SwPageFrm::SetPageDesc()
758 |*
759 |*  Ersterstellung      MA 02. Nov. 94
760 |*  Letzte Aenderung    MA 02. Nov. 94
761 |*
762 |*************************************************************************/
763 void  SwPageFrm::SetPageDesc( SwPageDesc *pNew, SwFrmFmt *pFmt )
764 {
765     pDesc = pNew;
766     if ( pFmt )
767         SetFrmFmt( pFmt );
768 }
769 
770 /*************************************************************************
771 |*
772 |*  SwPageFrm::FindPageDesc()
773 |*
774 |*  Beschreibung        Der richtige PageDesc wird bestimmt:
775 |*      0.  Vom Dokument bei Fussnotenseiten und Endnotenseiten
776 |*      1.  vom ersten BodyCntnt unterhalb der Seite.
777 |*      2.  vom PageDesc der vorstehenden Seite.
778 |*      3.  bei Leerseiten vom PageDesc der vorigen Seite.
779 |*      3.1 vom PageDesc der folgenden Seite wenn es keinen Vorgaenger gibt.
780 |*      4.  es ist der Default-PageDesc sonst.
781 |*      5.  Im BrowseMode ist der Pagedesc immer der vom ersten Absatz im
782 |*          Dokument oder Standard (der 0-te) wenn der erste Absatz keinen
783 |*          wuenscht.
784 |*     (6.  Im HTML-Mode ist der Pagedesc immer die HTML-Seitenvorlage.)
785 |*  Ersterstellung      MA 15. Feb. 93
786 |*  Letzte Aenderung    MA 17. Jun. 99
787 |*
788 |*************************************************************************/
789 SwPageDesc *SwPageFrm::FindPageDesc()
790 {
791     //0.
792     if ( IsFtnPage() )
793     {
794         SwDoc *pDoc = GetFmt()->GetDoc();
795         if ( IsEndNotePage() )
796             return pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
797         else
798             return pDoc->GetFtnInfo().GetPageDesc( *pDoc );
799     }
800 
801     //6.
802     //if ( GetFmt()->GetDoc()->IsHTMLMode() )
803     //  return GetFmt()->GetDoc()->GetPageDescFromPool( RES_POOLPAGE_HTML );
804 
805     SwPageDesc *pRet = 0;
806 
807     //5.
808     const ViewShell *pSh = getRootFrm()->GetCurrShell();
809     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
810     {
811         SwCntntFrm *pFrm = GetUpper()->ContainsCntnt();
812         while ( !pFrm->IsInDocBody() )
813             pFrm = pFrm->GetNextCntntFrm();
814         SwFrm *pFlow = pFrm;
815         if ( pFlow->IsInTab() )
816             pFlow = pFlow->FindTabFrm();
817         pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
818         if ( !pRet )
819             pRet = &GetFmt()->GetDoc()->_GetPageDesc( 0 );
820         return pRet;
821     }
822 
823     SwFrm *pFlow = FindFirstBodyCntnt();
824     if ( pFlow && pFlow->IsInTab() )
825         pFlow = pFlow->FindTabFrm();
826 
827     //1.
828     if ( pFlow )
829     {
830         SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
831         if ( !pTmp->IsFollow() )
832             pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
833     }
834 
835     //3. und 3.1
836     if ( !pRet && IsEmptyPage() )
837             // FME 2008-03-03 #i81544# lijian/fme: an empty page should have
838             // the same page description as its prev, just like after construction
839             // of the empty page.
840         pRet = GetPrev() ? ((SwPageFrm*)GetPrev())->GetPageDesc() :
841                GetNext() ? ((SwPageFrm*)GetNext())->GetPageDesc() : 0;
842 
843     //2.
844     if ( !pRet )
845         pRet = GetPrev() ?
846                     ((SwPageFrm*)GetPrev())->GetPageDesc()->GetFollow() : 0;
847 
848     //4.
849     if ( !pRet )
850         pRet = (SwPageDesc*)&(const_cast<const SwDoc *>(GetFmt()->GetDoc())
851                               ->GetPageDesc( 0 ));
852 
853 
854     ASSERT( pRet, "Kein Descriptor gefunden." );
855     return pRet;
856 }
857 
858 //Wenn der RootFrm seine Groesse aendert muss benachrichtigt werden.
859 void AdjustSizeChgNotify( SwRootFrm *pRoot )
860 {
861     const sal_Bool bOld = pRoot->IsSuperfluous();
862     pRoot->bCheckSuperfluous = sal_False;
863     ViewShell *pSh = pRoot->GetCurrShell();
864     if ( pSh )
865     {
866         do
867         {
868             if( pRoot == pSh->GetLayout() )
869             {
870                 pSh->SizeChgNotify();
871                 pSh->Imp()->NotifySizeChg( pRoot->Frm().SSize() );
872             }
873             pSh = (ViewShell*)pSh->GetNext();
874         } while ( pSh != pRoot->GetCurrShell() );
875     }
876     pRoot->bCheckSuperfluous = bOld;
877 }
878 
879 
880 inline void SetLastPage( SwPageFrm *pPage )
881 {
882     ((SwRootFrm*)pPage->GetUpper())->pLastPage = pPage;
883 }
884 
885 /*************************************************************************
886 |*
887 |*  SwPageFrm::Cut()
888 |*
889 |*  Ersterstellung      MA 23. Feb. 94
890 |*  Letzte Aenderung    MA 22. Jun. 95
891 |*
892 |*************************************************************************/
893 void SwPageFrm::Cut()
894 {
895     // PAGES01
896     //AdjustRootSize( CHG_CUTPAGE, 0 );
897 
898     ViewShell *pSh = getRootFrm()->GetCurrShell();
899     if ( !IsEmptyPage() )
900     {
901         if ( GetNext() )
902             GetNext()->InvalidatePos();
903 
904         //Flys deren Anker auf anderen Seiten stehen umhaengen.
905         //DrawObjecte spielen hier keine Rolle.
906         if ( GetSortedObjs() )
907         {
908             for ( int i = 0; GetSortedObjs() &&
909                              (sal_uInt16)i < GetSortedObjs()->Count(); ++i )
910             {
911                 // --> OD 2004-06-29 #i28701#
912                 SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
913 
914                 if ( pAnchoredObj->ISA(SwFlyAtCntFrm) )
915                 {
916                     SwFlyFrm* pFly = static_cast<SwFlyAtCntFrm*>(pAnchoredObj);
917                     SwPageFrm *pAnchPage = pFly->GetAnchorFrm() ?
918                                 pFly->AnchorFrm()->FindPageFrm() : 0;
919                     if ( pAnchPage && (pAnchPage != this) )
920                     {
921                         MoveFly( pFly, pAnchPage );
922                         --i;
923                         pFly->InvalidateSize();
924                         pFly->_InvalidatePos();
925                     }
926                 }
927                 // <--
928             }
929         }
930         //Window aufraeumen
931         if ( pSh && pSh->GetWin() )
932             pSh->InvalidateWindows( Frm() );
933     }
934 
935     // die Seitennummer der Root runterzaehlen.
936     ((SwRootFrm*)GetUpper())->DecrPhyPageNums();
937     SwPageFrm *pPg = (SwPageFrm*)GetNext();
938     if ( pPg )
939     {
940         while ( pPg )
941         {
942             pPg->DecrPhyPageNum();  //inline --nPhyPageNum
943             pPg = (SwPageFrm*)pPg->GetNext();
944         }
945     }
946     else
947         ::SetLastPage( (SwPageFrm*)GetPrev() );
948 
949     SwFrm* pRootFrm = GetUpper();
950 
951     // Alle Verbindungen kappen.
952     Remove();
953 
954     // PAGES01
955     if ( pRootFrm )
956         static_cast<SwRootFrm*>(pRootFrm)->CheckViewLayout( 0, 0 );
957 }
958 
959 /*************************************************************************
960 |*
961 |*  SwPageFrm::Paste()
962 |*
963 |*  Ersterstellung      MA 23. Feb. 94
964 |*  Letzte Aenderung    MA 07. Dec. 94
965 |*
966 |*************************************************************************/
967 void SwPageFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
968 {
969     ASSERT( pParent->IsRootFrm(), "Parent ist keine Root." );
970     ASSERT( pParent, "Kein Parent fuer Paste." );
971     ASSERT( pParent != this, "Bin selbst der Parent." );
972     ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
973     ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
974             "Bin noch irgendwo angemeldet." );
975 
976     //In den Baum einhaengen.
977     InsertBefore( (SwLayoutFrm*)pParent, pSibling );
978 
979     // die Seitennummer am Root hochzaehlen.
980     ((SwRootFrm*)GetUpper())->IncrPhyPageNums();
981     if( GetPrev() )
982         SetPhyPageNum( ((SwPageFrm*)GetPrev())->GetPhyPageNum() + 1 );
983     else
984         SetPhyPageNum( 1 );
985     SwPageFrm *pPg = (SwPageFrm*)GetNext();
986     if ( pPg )
987     {
988         while ( pPg )
989         {
990             pPg->IncrPhyPageNum();  //inline ++nPhyPageNum
991             pPg->_InvalidatePos();
992             pPg->InvalidateLayout();
993             pPg = (SwPageFrm*)pPg->GetNext();
994         }
995     }
996     else
997         ::SetLastPage( this );
998 
999     if( Frm().Width() != pParent->Prt().Width() )
1000         _InvalidateSize();
1001 
1002     InvalidatePos();
1003 
1004     ViewShell *pSh = getRootFrm()->GetCurrShell();
1005     if ( pSh )
1006         pSh->SetFirstVisPageInvalid();
1007     // PAGES01
1008     getRootFrm()->CheckViewLayout( 0, 0 );
1009 }
1010 
1011 /*************************************************************************
1012 |*
1013 |*  SwPageFrm::PrepareRegisterChg()
1014 |*
1015 |*  Ersterstellung      AMA 22. Jul. 96
1016 |*  Letzte Aenderung    AMA 22. Jul. 96
1017 |*
1018 |*************************************************************************/
1019 void lcl_PrepFlyInCntRegister( SwCntntFrm *pFrm )
1020 {
1021     pFrm->Prepare( PREP_REGISTER );
1022     if( pFrm->GetDrawObjs() )
1023     {
1024         for( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
1025         {
1026             // --> OD 2004-06-29 #i28701#
1027             SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
1028             if ( pAnchoredObj->ISA(SwFlyInCntFrm) )
1029             {
1030                 SwFlyFrm* pFly = static_cast<SwFlyInCntFrm*>(pAnchoredObj);
1031                 SwCntntFrm *pCnt = pFly->ContainsCntnt();
1032                 while ( pCnt )
1033                 {
1034                     lcl_PrepFlyInCntRegister( pCnt );
1035                     pCnt = pCnt->GetNextCntntFrm();
1036                 }
1037             }
1038             // <--
1039         }
1040     }
1041 }
1042 
1043 void SwPageFrm::PrepareRegisterChg()
1044 {
1045     SwCntntFrm *pFrm = FindFirstBodyCntnt();
1046     while( pFrm )
1047     {
1048         lcl_PrepFlyInCntRegister( pFrm );
1049         pFrm = pFrm->GetNextCntntFrm();
1050         if( !IsAnLower( pFrm ) )
1051             break;
1052     }
1053     if( GetSortedObjs() )
1054     {
1055         for( sal_uInt16 i = 0; i < GetSortedObjs()->Count(); ++i )
1056         {
1057             // --> OD 2004-06-29 #i28701#
1058             SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
1059             if ( pAnchoredObj->ISA(SwFlyFrm) )
1060             {
1061                 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
1062                 pFrm = pFly->ContainsCntnt();
1063                 while ( pFrm )
1064                 {
1065                     ::lcl_PrepFlyInCntRegister( pFrm );
1066                     pFrm = pFrm->GetNextCntntFrm();
1067                 }
1068             }
1069         }
1070     }
1071 }
1072 
1073 /*************************************************************************
1074 |*
1075 |*  SwFrm::CheckPageDescs()
1076 |*
1077 |*  Beschreibung        Prueft alle Seiten ab der uebergebenen, daraufhin,
1078 |*      ob sie das richtige FrmFmt verwenden. Wenn 'falsche' Seiten
1079 |*      aufgespuehrt werden, so wird versucht die Situation moeglichst
1080 |*      einfache zu bereinigen.
1081 |*
1082 |*  Ersterstellung      MA 10. Feb. 93
1083 |*  Letzte Aenderung    MA 18. Apr. 96
1084 |*
1085 |*************************************************************************/
1086 void SwFrm::CheckPageDescs( SwPageFrm *pStart, sal_Bool bNotifyFields )
1087 {
1088     ASSERT( pStart, "Keine Startpage." );
1089 
1090     ViewShell *pSh   = pStart->getRootFrm()->GetCurrShell();
1091     SwViewImp *pImp  = pSh ? pSh->Imp() : 0;
1092 
1093     if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
1094     {
1095         pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() );
1096         return;
1097     }
1098 
1099     //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
1100     //die Seitenposition an, _ab_ der invalidiert werden soll.
1101     SwTwips nDocPos  = LONG_MAX;
1102 
1103     SwRootFrm *pRoot = (SwRootFrm*)pStart->GetUpper();
1104     SwDoc* pDoc      = pStart->GetFmt()->GetDoc();
1105     const sal_Bool bFtns = 0 != pDoc->GetFtnIdxs().Count();
1106 
1107     SwPageFrm *pPage = pStart;
1108     if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
1109         pPage = (SwPageFrm*)pPage->GetPrev();
1110     while ( pPage )
1111     {
1112         //gewuenschten PageDesc und FrmFmt festellen.
1113         SwPageDesc *pDesc = pPage->FindPageDesc();
1114         sal_Bool bCheckEmpty = pPage->IsEmptyPage();
1115         sal_Bool bActOdd = pPage->OnRightPage();
1116         sal_Bool bOdd = pPage->WannaRightPage();
1117         SwFrmFmt *pFmtWish = bOdd ? pDesc->GetRightFmt()
1118                                   : pDesc->GetLeftFmt();
1119 
1120         if ( bActOdd != bOdd ||
1121              pDesc != pPage->GetPageDesc() ||       //falscher Desc
1122              ( pFmtWish != pPage->GetFmt()  &&      //falsches Format und
1123                ( !pPage->IsEmptyPage() || pFmtWish ) //nicht Leerseite
1124              )
1125            )
1126         {
1127             //Wenn wir schon ein Seite veraendern muessen kann das eine
1128             //Weile dauern, deshalb hier den WaitCrsr pruefen.
1129             if( pImp )
1130                 pImp->CheckWaitCrsr();
1131 
1132             //Ab hier muessen die Felder invalidiert werden!
1133             if ( nDocPos == LONG_MAX )
1134                 nDocPos = pPage->GetPrev() ?
1135                             pPage->GetPrev()->Frm().Top() : pPage->Frm().Top();
1136 
1137             //Faelle:
1138             //1. Wir haben eine EmptyPage und wollen eine "Normalseite".
1139             //      ->EmptyPage wegwerfen und weiter mit der naechsten.
1140             //2. Wir haben eine EmptyPage und wollen eine EmptyPage mit
1141             //   anderem Descriptor.
1142             //      ->Descriptor austauschen.
1143             //3. Wir haben eine "Normalseite" und wollen eine EmptyPage.
1144             //      ->Emptypage einfuegen, nicht aber wenn die Vorseite
1145             //                             bereits eine EmptyPage ist -> 6.
1146             //4. Wir haben eine "Normalseite" und wollen eine "Normalseite"
1147             //   mit anderem Descriptor
1148             //      ->Descriptor und Format austauschen
1149             //5. Wir haben eine "Normalseite" und wollen eine "Normalseite"
1150             //   mit anderem Format
1151             //      ->Format austauschen.
1152             //6. Wir haben kein Wunschformat erhalten, also nehmen wir das
1153             //   'andere' Format (rechts/links) des PageDesc.
1154 
1155             if ( pPage->IsEmptyPage() && ( pFmtWish ||          //1.
1156                  ( !bOdd && !pPage->GetPrev() ) ) )
1157             {
1158                 SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
1159                 pPage->Cut();
1160                 delete pPage;
1161                 if ( pStart == pPage )
1162                     pStart = pTmp;
1163                 pPage = pTmp;
1164                 continue;
1165             }
1166             else if ( pPage->IsEmptyPage() && !pFmtWish &&  //2.
1167                       pDesc != pPage->GetPageDesc() )
1168             {
1169                 pPage->SetPageDesc( pDesc, 0 );
1170             }
1171             else if ( !pPage->IsEmptyPage() &&      //3.
1172                       bActOdd != bOdd &&
1173                       ( ( !pPage->GetPrev() && !bOdd ) ||
1174                         ( pPage->GetPrev() &&
1175                           !((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
1176                       )
1177                     )
1178             {
1179                 if ( pPage->GetPrev() )
1180                     pDesc = ((SwPageFrm*)pPage->GetPrev())->GetPageDesc();
1181                 SwPageFrm *pTmp = new SwPageFrm( pDoc->GetEmptyPageFmt(),pRoot,pDesc);
1182                 pTmp->Paste( pRoot, pPage );
1183                 pTmp->PreparePage( sal_False );
1184                 pPage = pTmp;
1185             }
1186             else if ( pPage->GetPageDesc() != pDesc )           //4.
1187             {
1188                 SwPageDesc *pOld = pPage->GetPageDesc();
1189                 pPage->SetPageDesc( pDesc, pFmtWish );
1190                 if ( bFtns )
1191                 {
1192                     //Wenn sich bestimmte Werte der FtnInfo veraendert haben
1193                     //muss etwas passieren. Wir versuchen den Schaden zu
1194                     //begrenzen.
1195                     //Wenn die Seiten keinen FtnCont hat, ist zwar theoretisches
1196                     //ein Problem denkbar, aber das ignorieren wir mit aller Kraft.
1197                     //Bei Aenderungen hoffen wir mal, dass eine Invalidierung
1198                     //ausreicht, denn alles andere wuerde viel Kraft kosten.
1199                     SwFtnContFrm *pCont = pPage->FindFtnCont();
1200                     if ( pCont && !(pOld->GetFtnInfo() == pDesc->GetFtnInfo()) )
1201                         pCont->_InvalidateAll();
1202                 }
1203             }
1204             else if ( pFmtWish && pPage->GetFmt() != pFmtWish )         //5.
1205             {
1206                 pPage->SetFrmFmt( pFmtWish );
1207             }
1208             else if ( !pFmtWish )                                       //6.
1209             {
1210                 //Format mit verdrehter Logic besorgen.
1211                 pFmtWish = bOdd ? pDesc->GetLeftFmt() : pDesc->GetRightFmt();
1212                 if ( pPage->GetFmt() != pFmtWish )
1213                     pPage->SetFrmFmt( pFmtWish );
1214             }
1215 #ifdef DBG_UTIL
1216             else
1217             {
1218                 ASSERT( sal_False, "CheckPageDescs, missing solution" );
1219             }
1220 #endif
1221         }
1222         if ( bCheckEmpty )
1223         {
1224             //Es kann noch sein, dass die Leerseite schlicht  ueberflussig ist.
1225             //Obiger Algorithmus kann dies leider nicht feststellen.
1226             //Eigentlich muesste die Leerseite einfach praeventiv entfernt
1227             //werden; sie wuerde ja ggf. wieder eingefuegt.
1228             //Die EmptyPage ist genau dann ueberfluessig, wenn die Folgeseite
1229             //auch ohne sie auskommt. Dazu muessen wir uns die Verhaeltnisse
1230             //genauer ansehen. Wir bestimmen den PageDesc und die virtuelle
1231             //Seitennummer manuell.
1232             SwPageFrm *pPg = (SwPageFrm*)pPage->GetNext();
1233             if( !pPg || pPage->OnRightPage() == pPg->WannaRightPage() )
1234             {
1235                 //Die Folgeseite hat kein Problem ein FrmFmt zu finden oder keinen
1236                 //Nachfolger, also ist die Leerseite ueberfluessig.
1237                 SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
1238                 pPage->Cut();
1239                 delete pPage;
1240                 if ( pStart == pPage )
1241                     pStart = pTmp;
1242                 pPage = pTmp;
1243                 continue;
1244             }
1245         }
1246         pPage = (SwPageFrm*)pPage->GetNext();
1247     }
1248 
1249     pRoot->SetAssertFlyPages();
1250     pRoot->AssertPageFlys( pStart );
1251 
1252     if ( bNotifyFields && (!pImp || !pImp->IsUpdateExpFlds()) )
1253     {
1254         SwDocPosUpdate aMsgHnt( nDocPos );
1255         pDoc->UpdatePageFlds( &aMsgHnt );
1256     }
1257 
1258 #ifdef DBG_UTIL
1259     //Ein paar Pruefungen muessen schon erlaubt sein.
1260 
1261     //1. Keine zwei EmptyPages hintereinander.
1262     //2. Alle PageDescs richtig?
1263     sal_Bool bEmpty = sal_False;
1264     SwPageFrm *pPg = pStart;
1265     while ( pPg )
1266     {
1267         if ( pPg->IsEmptyPage() )
1268         {
1269             if ( bEmpty )
1270             {
1271                 ASSERT( sal_False, "Doppelte Leerseiten." );
1272                 break;  //Einmal reicht.
1273             }
1274             bEmpty = sal_True;
1275         }
1276         else
1277             bEmpty = sal_False;
1278 
1279 //MA 21. Jun. 95: Kann zu testzwecken 'rein, ist aber bei zyklen durchaus
1280 //moeglich: Ein paar Seiten, auf der ersten 'erste Seite' anwenden,
1281 //rechte als folge der ersten, linke als folge der rechten, rechte als
1282 //folge der linken.
1283 //      ASSERT( pPg->GetPageDesc() == pPg->FindPageDesc(),
1284 //              "Seite mit falschem Descriptor." );
1285 
1286         pPg = (SwPageFrm*)pPg->GetNext();
1287     }
1288 #endif
1289 }
1290 
1291 /*************************************************************************
1292 |*
1293 |*  SwFrm::InsertPage()
1294 |*
1295 |*  Beschreibung
1296 |*  Ersterstellung      MA 10. Feb. 93
1297 |*  Letzte Aenderung    MA 27. Jul. 93
1298 |*
1299 |*************************************************************************/
1300 SwPageFrm *SwFrm::InsertPage( SwPageFrm *pPrevPage, sal_Bool bFtn )
1301 {
1302     SwRootFrm *pRoot = (SwRootFrm*)pPrevPage->GetUpper();
1303     SwPageFrm *pSibling = (SwPageFrm*)pRoot->GetLower();
1304     SwPageDesc *pDesc = pSibling->GetPageDesc();
1305 
1306     pSibling = (SwPageFrm*)pPrevPage->GetNext();
1307         //Rechte (ungerade) oder linke (gerade) Seite einfuegen?
1308     sal_Bool bNextOdd = !pPrevPage->OnRightPage();
1309     sal_Bool bWishedOdd = bNextOdd;
1310 
1311     //Welcher PageDesc gilt?
1312     //Bei CntntFrm der aus dem Format wenn einer angegeben ist,
1313     //der Follow vom bereits in der PrevPage gueltigen sonst.
1314     pDesc = 0;
1315     if ( IsFlowFrm() && !SwFlowFrm::CastFlowFrm( this )->IsFollow() )
1316     {   SwFmtPageDesc &rDesc = (SwFmtPageDesc&)GetAttrSet()->GetPageDesc();
1317         pDesc = rDesc.GetPageDesc();
1318         if ( rDesc.GetNumOffset() )
1319         {
1320             bWishedOdd = rDesc.GetNumOffset() % 2 ? sal_True : sal_False;
1321             //Die Gelegenheit nutzen wir um das Flag an der Root zu pflegen.
1322             pRoot->SetVirtPageNum( sal_True );
1323         }
1324     }
1325     if ( !pDesc )
1326         pDesc = pPrevPage->GetPageDesc()->GetFollow();
1327 
1328     ASSERT( pDesc, "Missing PageDesc" );
1329     if( !(bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
1330         bWishedOdd = !bWishedOdd;
1331 
1332     SwDoc *pDoc = pPrevPage->GetFmt()->GetDoc();
1333     SwFrmFmt *pFmt;
1334     sal_Bool bCheckPages = sal_False;
1335     //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben eine
1336     //Leerseite einfuegen.
1337     if( bWishedOdd != bNextOdd )
1338     {   pFmt = pDoc->GetEmptyPageFmt();
1339         SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc();
1340         SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pTmpDesc );
1341         pPage->Paste( pRoot, pSibling );
1342         pPage->PreparePage( bFtn );
1343         //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
1344         //Es sei denn, es ist eine Fussnotenseite
1345         if ( pSibling && !pSibling->IsFtnPage() &&
1346              !pSibling->FindFirstBodyCntnt() )
1347         {
1348             SwPageFrm *pDel = pSibling;
1349             pSibling = (SwPageFrm*)pSibling->GetNext();
1350             if ( pDoc->GetFtnIdxs().Count() )
1351                 pRoot->RemoveFtns( pDel, sal_True );
1352             pDel->Cut();
1353             delete pDel;
1354         }
1355         else
1356             bCheckPages = sal_True;
1357     }
1358     pFmt = bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt();
1359     ASSERT( pFmt, "Descriptor without format." );
1360     SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pDesc );
1361     pPage->Paste( pRoot, pSibling );
1362     pPage->PreparePage( bFtn );
1363     //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
1364     //Es sei denn es ist eine Fussnotenseite.
1365     if ( pSibling && !pSibling->IsFtnPage() &&
1366          !pSibling->FindFirstBodyCntnt() )
1367     {
1368         SwPageFrm *pDel = pSibling;
1369         pSibling = (SwPageFrm*)pSibling->GetNext();
1370         if ( pDoc->GetFtnIdxs().Count() )
1371             pRoot->RemoveFtns( pDel, sal_True );
1372         pDel->Cut();
1373         delete pDel;
1374     }
1375     else
1376         bCheckPages = sal_True;
1377 
1378     if ( pSibling )
1379     {
1380         if ( bCheckPages )
1381         {
1382             CheckPageDescs( pSibling, sal_False );
1383             ViewShell *pSh = getRootFrm()->GetCurrShell();
1384             SwViewImp *pImp = pSh ? pSh->Imp() : 0;
1385             if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
1386             {
1387                 const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum();
1388                 if ( nNum == pPrevPage->GetPhyPageNum() + 1 )
1389                     pImp->GetLayAction().SetCheckPageNumDirect(
1390                                                     pSibling->GetPhyPageNum() );
1391                 return pPage;
1392             }
1393         }
1394         else
1395             pRoot->AssertPageFlys( pSibling );
1396     }
1397 
1398     //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
1399     //die Seitenposition an, _ab_ der invalidiert werden soll.
1400     ViewShell *pSh = getRootFrm()->GetCurrShell();
1401     if ( !pSh || !pSh->Imp()->IsUpdateExpFlds() )
1402     {
1403         SwDocPosUpdate aMsgHnt( pPrevPage->Frm().Top() );
1404         pDoc->UpdatePageFlds( &aMsgHnt );
1405     }
1406     return pPage;
1407 }
1408 
1409 sw::sidebarwindows::SidebarPosition SwPageFrm::SidebarPosition() const
1410 {
1411     ViewShell *pSh = getRootFrm()->GetCurrShell();
1412     if( !pSh || pSh->GetViewOptions()->getBrowseMode() )
1413     {
1414         return sw::sidebarwindows::SIDEBAR_RIGHT;
1415     }
1416     else
1417     {
1418         const bool bLTR = getRootFrm()->IsLeftToRightViewLayout();
1419         const bool bBookMode = pSh->GetViewOptions()->IsViewLayoutBookMode();
1420         const bool bRightSidebar = bLTR ? (!bBookMode || OnRightPage()) : (bBookMode && !OnRightPage());
1421 
1422         return bRightSidebar
1423                ? sw::sidebarwindows::SIDEBAR_RIGHT
1424                : sw::sidebarwindows::SIDEBAR_LEFT;
1425     }
1426 }
1427 
1428 /*************************************************************************
1429 |*
1430 |*  SwRootFrm::GrowFrm()
1431 |*
1432 |*  Ersterstellung      MA 30. Jul. 92
1433 |*  Letzte Aenderung    MA 05. May. 94
1434 |*
1435 |*************************************************************************/
1436 
1437 SwTwips SwRootFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
1438 {
1439     if ( !bTst )
1440         Frm().SSize().Height() += nDist;
1441     return nDist;
1442 }
1443 /*************************************************************************
1444 |*
1445 |*  SwRootFrm::ShrinkFrm()
1446 |*
1447 |*  Ersterstellung      MA 30. Jul. 92
1448 |*  Letzte Aenderung    MA 05. May. 94
1449 |*
1450 |*************************************************************************/
1451 SwTwips SwRootFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
1452 {
1453     ASSERT( nDist >= 0, "nDist < 0." );
1454     ASSERT( nDist <= Frm().Height(), "nDist > als aktuelle Groesse." );
1455 
1456     if ( !bTst )
1457         Frm().SSize().Height() -= nDist;
1458     return nDist;
1459 }
1460 
1461 /*************************************************************************
1462 |*
1463 |*  SwRootFrm::RemoveSuperfluous()
1464 |*
1465 |*  Beschreibung:       Entfernung von ueberfluessigen Seiten.
1466 |*          Arbeitet nur wenn das Flag bCheckSuperfluous gesetzt ist.
1467 |*          Definition: Eine Seite ist genau dann leer, wenn der
1468 |*          Body-Textbereich keinen CntntFrm enthaelt, aber nicht, wenn noch
1469 |*          mindestens ein Fly an der Seite klebt.
1470 |*          Die Seite ist auch dann nicht leer, wenn sie noch eine
1471 |*          Fussnote enthaelt.
1472 |*          Es muss zweimal angesetzt werden um leeren Seiten aufzuspueren:
1473 |*              - einmal fuer die Endnotenseiten.
1474 |*              - und einmal fuer die Seiten des Bodytextes.
1475 |*
1476 |*  Ersterstellung      MA 20. May. 92
1477 |*  Letzte Aenderung    MA 10. Jan. 95
1478 |*
1479 |*************************************************************************/
1480 void SwRootFrm::RemoveSuperfluous()
1481 {
1482     if ( !IsSuperfluous() )
1483         return;
1484     bCheckSuperfluous = sal_False;
1485 
1486     SwPageFrm *pPage = GetLastPage();
1487     long nDocPos = LONG_MAX;
1488 
1489     //Jetzt wird fuer die jeweils letzte Seite geprueft ob sie leer ist
1490     //bei der ersten nicht leeren Seite wird die Schleife beendet.
1491     do
1492     {
1493         bool bExistEssentialObjs = ( 0 != pPage->GetSortedObjs() );
1494         if ( bExistEssentialObjs )
1495         {
1496             //Nur weil die Seite Flys hat sind wir noch lange nicht fertig,
1497             //denn wenn alle Flys an generischem Inhalt haengen, so ist sie
1498             //trotzdem ueberfluessig (Ueberpruefung auf DocBody sollte reichen).
1499             // OD 19.06.2003 #108784# - consider that drawing objects in
1500             // header/footer are supported now.
1501             bool bOnlySuperfluosObjs = true;
1502             SwSortedObjs &rObjs = *pPage->GetSortedObjs();
1503             for ( sal_uInt16 i = 0; bOnlySuperfluosObjs && i < rObjs.Count(); ++i )
1504             {
1505                 // --> OD 2004-06-29 #i28701#
1506                 SwAnchoredObject* pAnchoredObj = rObjs[i];
1507                 // OD 2004-01-19 #110582# - do not consider hidden objects
1508                 if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
1509                                     pAnchoredObj->GetDrawObj()->GetLayer() ) &&
1510                      !pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() )
1511                 {
1512                     bOnlySuperfluosObjs = false;
1513                 }
1514                 // <--
1515             }
1516             bExistEssentialObjs = !bOnlySuperfluosObjs;
1517         }
1518 
1519         // OD 19.06.2003 #108784# - optimization: check first, if essential objects
1520         // exists.
1521         const SwLayoutFrm* pBody = 0;
1522         if ( bExistEssentialObjs ||
1523              pPage->FindFtnCont() ||
1524              ( 0 != ( pBody = pPage->FindBodyCont() ) &&
1525                 ( pBody->ContainsCntnt() ||
1526                     // --> FME 2005-05-18 #i47580#
1527                     // Do not delete page if there's an empty tabframe
1528                     // left. I think it might be correct to use ContainsAny()
1529                     // instead of ContainsCntnt() to cover the empty-table-case,
1530                     // but I'm not fully sure, since ContainsAny() also returns
1531                     // SectionFrames. Therefore I prefer to do it the safe way:
1532                   ( pBody->Lower() && pBody->Lower()->IsTabFrm() ) ) ) )
1533                     // <--
1534         {
1535             if ( pPage->IsFtnPage() )
1536             {
1537                 while ( pPage->IsFtnPage() )
1538                 {
1539                     pPage = (SwPageFrm*)pPage->GetPrev();
1540                     ASSERT( pPage, "Nur noch Endnotenseiten uebrig." );
1541                 }
1542                 continue;
1543             }
1544             else
1545                 pPage = 0;
1546         }
1547 
1548         if ( pPage )
1549         {
1550             SwPageFrm *pEmpty = pPage;
1551             pPage = (SwPageFrm*)pPage->GetPrev();
1552             if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
1553                 RemoveFtns( pEmpty, sal_True );
1554             pEmpty->Cut();
1555             delete pEmpty;
1556             nDocPos = pPage ? pPage->Frm().Top() : 0;
1557         }
1558     } while ( pPage );
1559 
1560     ViewShell *pSh = getRootFrm()->GetCurrShell();
1561     if ( nDocPos != LONG_MAX &&
1562          (!pSh || !pSh->Imp()->IsUpdateExpFlds()) )
1563     {
1564         SwDocPosUpdate aMsgHnt( nDocPos );
1565         GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
1566     }
1567 }
1568 
1569 /*************************************************************************
1570 |*
1571 |*  SwRootFrm::AssertFlyPages()
1572 |*
1573 |*  Beschreibung        Stellt sicher, dass genuegend Seiten vorhanden
1574 |*      sind, damit alle Seitengebundenen Rahmen und DrawObject
1575 |*      untergebracht sind.
1576 |*
1577 |*  Ersterstellung      MA 27. Jul. 93
1578 |*  Letzte Aenderung    MA 24. Apr. 97
1579 |*
1580 |*************************************************************************/
1581 void SwRootFrm::AssertFlyPages()
1582 {
1583     if ( !IsAssertFlyPages() )
1584         return;
1585     bAssertFlyPages = sal_False;
1586 
1587     SwDoc *pDoc = GetFmt()->GetDoc();
1588     const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1589 
1590     //Auf welche Seite will der 'letzte' Fly?
1591     sal_uInt16 nMaxPg = 0;
1592     sal_uInt16 i;
1593 
1594     for ( i = 0; i < pTbl->Count(); ++i )
1595     {
1596         const SwFmtAnchor &rAnch = (*pTbl)[i]->GetAnchor();
1597         if ( !rAnch.GetCntntAnchor() && nMaxPg < rAnch.GetPageNum() )
1598             nMaxPg = rAnch.GetPageNum();
1599     }
1600     //Wieviele Seiten haben wir derzeit?
1601     SwPageFrm *pPage = (SwPageFrm*)Lower();
1602     while ( pPage && pPage->GetNext() &&
1603             !((SwPageFrm*)pPage->GetNext())->IsFtnPage() )
1604     {
1605         pPage = (SwPageFrm*)pPage->GetNext();
1606     }
1607 
1608     if ( nMaxPg > pPage->GetPhyPageNum() )
1609     {
1610         //Die Seiten werden ausgehend von der letzten Seite konsequent
1611         //nach den Regeln der PageDescs weitergefuehrt.
1612         sal_Bool bOdd = pPage->GetPhyPageNum() % 2 ? sal_True : sal_False;
1613         SwPageDesc *pDesc = pPage->GetPageDesc();
1614         SwFrm *pSibling = pPage->GetNext();
1615         for ( i = pPage->GetPhyPageNum(); i < nMaxPg; ++i  )
1616         {
1617             if ( !(bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
1618             {
1619                 //Leerseite einfuegen, die Flys werden aber erst von
1620                 //der naechsten Seite aufgenommen!
1621                 pPage = new SwPageFrm( pDoc->GetEmptyPageFmt(), this, pDesc );
1622                 pPage->Paste( this, pSibling );
1623                 pPage->PreparePage( sal_False );
1624                 bOdd = bOdd ? sal_False : sal_True;
1625                 ++i;
1626             }
1627             pPage = new
1628                     SwPageFrm( (bOdd ? pDesc->GetRightFmt() :
1629                                        pDesc->GetLeftFmt()), this, pDesc );
1630             pPage->Paste( this, pSibling );
1631             pPage->PreparePage( sal_False );
1632             bOdd = bOdd ? sal_False : sal_True;
1633             pDesc = pDesc->GetFollow();
1634         }
1635         //Jetzt koennen die Endnotenseiten natuerlich wieder krumm sein;
1636         //in diesem Fall werden sie vernichtet.
1637         if ( pDoc->GetFtnIdxs().Count() )
1638         {
1639             pPage = (SwPageFrm*)Lower();
1640             while ( pPage && !pPage->IsFtnPage() )
1641                 pPage = (SwPageFrm*)pPage->GetNext();
1642 
1643             if ( pPage )
1644             {
1645                 SwPageDesc *pTmpDesc = pPage->FindPageDesc();
1646                 bOdd = pPage->OnRightPage();
1647                 if ( pPage->GetFmt() !=
1648                      (bOdd ? pTmpDesc->GetRightFmt() : pTmpDesc->GetLeftFmt()) )
1649                     RemoveFtns( pPage, sal_False, sal_True );
1650             }
1651         }
1652     }
1653 }
1654 
1655 /*************************************************************************
1656 |*
1657 |*  SwRootFrm::AssertPageFlys()
1658 |*
1659 |*  Beschreibung        Stellt sicher, dass ab der uebergebenen Seite
1660 |*      auf allen Seiten die Seitengebunden Objecte auf der richtigen
1661 |*      Seite (Seitennummer stehen).
1662 |*
1663 |*  Ersterstellung      MA 02. Nov. 94
1664 |*  Letzte Aenderung    MA 10. Aug. 95
1665 |*
1666 |*************************************************************************/
1667 void SwRootFrm::AssertPageFlys( SwPageFrm *pPage )
1668 {
1669     while ( pPage )
1670     {
1671         if ( pPage->GetSortedObjs() )
1672         {
1673             pPage->GetSortedObjs();
1674             for ( int i = 0;
1675                   pPage->GetSortedObjs() && sal_uInt16(i) < pPage->GetSortedObjs()->Count();
1676                   ++i)
1677             {
1678                 // --> OD 2004-06-29 #i28701#
1679                 SwFrmFmt& rFmt = (*pPage->GetSortedObjs())[i]->GetFrmFmt();
1680                 const SwFmtAnchor &rAnch = rFmt.GetAnchor();
1681                 const sal_uInt16 nPg = rAnch.GetPageNum();
1682                 if ((rAnch.GetAnchorId() == FLY_AT_PAGE) &&
1683                      nPg != pPage->GetPhyPageNum() )
1684                 {
1685                     //Das er auf der falschen Seite steht muss noch nichts
1686                     //heissen, wenn er eigentlich auf der Vorseite
1687                     //stehen will und diese eine EmptyPage ist.
1688                     if( nPg && !(pPage->GetPhyPageNum()-1 == nPg &&
1689                         ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage()) )
1690                     {
1691                         //Umhaengen kann er sich selbst, indem wir ihm
1692                         //einfach ein Modify mit seinem AnkerAttr schicken.
1693 #ifndef DBG_UTIL
1694                         rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
1695 #else
1696                         const sal_uInt32 nCnt = pPage->GetSortedObjs()->Count();
1697                         rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
1698                         ASSERT( !pPage->GetSortedObjs() ||
1699                                 nCnt != pPage->GetSortedObjs()->Count(),
1700                                 "Object couldn't be reattached!" );
1701 #endif
1702                         --i;
1703                     }
1704                 }
1705             }
1706         }
1707         pPage = (SwPageFrm*)pPage->GetNext();
1708     }
1709 }
1710 
1711 /*************************************************************************
1712 |*
1713 |*  SwRootFrm::ChgSize()
1714 |*
1715 |*  Ersterstellung      MA 24. Jul. 92
1716 |*  Letzte Aenderung    MA 13. Aug. 93
1717 |*
1718 |*************************************************************************/
1719 Size SwRootFrm::ChgSize( const Size& aNewSize )
1720 {
1721     Frm().SSize() = aNewSize;
1722     _InvalidatePrt();
1723     bFixSize = sal_False;
1724     return Frm().SSize();
1725 }
1726 
1727 /*************************************************************************
1728 |*
1729 |*  SwRootFrm::MakeAll()
1730 |*
1731 |*  Ersterstellung      MA 17. Nov. 92
1732 |*  Letzte Aenderung    MA 19. Apr. 93
1733 |*
1734 |*************************************************************************/
1735 void SwRootFrm::MakeAll()
1736 {
1737     if ( !bValidPos )
1738     {   bValidPos = sal_True;
1739         aFrm.Pos().X() = aFrm.Pos().Y() = DOCUMENTBORDER;
1740     }
1741     if ( !bValidPrtArea )
1742     {   bValidPrtArea = sal_True;
1743         aPrt.Pos().X() = aPrt.Pos().Y() = 0;
1744         aPrt.SSize( aFrm.SSize() );
1745     }
1746     if ( !bValidSize )
1747         //SSize wird von den Seiten (Cut/Paste) eingestellt.
1748         bValidSize = sal_True;
1749 }
1750 
1751 /*************************************************************************
1752 |*
1753 |*  SwRootFrm::ImplInvalidateBrowseWidth()
1754 |*
1755 |*  Ersterstellung      MA 08. Jun. 96
1756 |*  Letzte Aenderung    MA 08. Jun. 96
1757 |*
1758 |*************************************************************************/
1759 void SwRootFrm::ImplInvalidateBrowseWidth()
1760 {
1761     bBrowseWidthValid = sal_False;
1762     SwFrm *pPg = Lower();
1763     while ( pPg )
1764     {
1765         pPg->InvalidateSize();
1766         pPg = pPg->GetNext();
1767     }
1768 }
1769 
1770 /*************************************************************************
1771 |*
1772 |*  SwRootFrm::ImplCalcBrowseWidth()
1773 |*
1774 |*  Ersterstellung      MA 07. Jun. 96
1775 |*  Letzte Aenderung    MA 13. Jun. 96
1776 |*
1777 |*************************************************************************/
1778 void SwRootFrm::ImplCalcBrowseWidth()
1779 {
1780     ASSERT( GetCurrShell() && GetCurrShell()->GetViewOptions()->getBrowseMode(),
1781             "CalcBrowseWidth and not in BrowseView" )
1782 
1783     //Die (minimale) Breite wird von Rahmen, Tabellen und Zeichenobjekten
1784     //bestimmt. Die Breite wird nicht anhand ihrer aktuellen Groessen bestimmt,
1785     //sondern anhand der Attribute. Es interessiert also nicht wie breit sie
1786     //sind, sondern wie breit sie sein wollen.
1787     //Rahmen und Zeichenobjekte innerhalb ander Objekte (Rahmen, Tabellen)
1788     //Zaehlen nicht.
1789     //Seitenraender und Spalten werden hier nicht beruecksichtigt.
1790 
1791     SwFrm *pFrm = ContainsCntnt();
1792     while ( pFrm && !pFrm->IsInDocBody() )
1793         pFrm = ((SwCntntFrm*)pFrm)->GetNextCntntFrm();
1794     if ( !pFrm )
1795         return;
1796 
1797     bBrowseWidthValid = sal_True;
1798     ViewShell *pSh = getRootFrm()->GetCurrShell();
1799     nBrowseWidth = pSh
1800                     ? MINLAY + 2 * pSh->GetOut()->
1801                                 PixelToLogic( pSh->GetBrowseBorder() ).Width()
1802                     : 5000;
1803     do
1804     {
1805         if ( pFrm->IsInTab() )
1806             pFrm = pFrm->FindTabFrm();
1807 
1808         if ( pFrm->IsTabFrm() &&
1809              !((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize().GetWidthPercent() )
1810         {
1811             SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
1812             const SwBorderAttrs &rAttrs = *aAccess.Get();
1813             const SwFmtHoriOrient &rHori = rAttrs.GetAttrSet().GetHoriOrient();
1814             long nWidth = rAttrs.GetSize().Width();
1815             if ( nWidth < USHRT_MAX-2000 && //-2000, weil bei Randeinstellung per
1816                                             //Zuppeln das USHRT_MAX verlorengeht!
1817                  text::HoriOrientation::FULL != rHori.GetHoriOrient() )
1818             {
1819                 const SwHTMLTableLayout *pLayoutInfo =
1820                     ((const SwTabFrm *)pFrm)->GetTable()
1821                                             ->GetHTMLTableLayout();
1822                 if ( pLayoutInfo )
1823                     nWidth = Min( nWidth, pLayoutInfo->GetBrowseWidthMin() );
1824 
1825                 switch ( rHori.GetHoriOrient() )
1826                 {
1827                     case text::HoriOrientation::NONE:
1828                         // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
1829                         nWidth += rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm );
1830                         break;
1831                     case text::HoriOrientation::LEFT_AND_WIDTH:
1832                         nWidth += rAttrs.CalcLeft( pFrm );
1833                         break;
1834                     default:
1835                         break;
1836 
1837                 }
1838                 nBrowseWidth = Max( nBrowseWidth, nWidth );
1839             }
1840         }
1841         else if ( pFrm->GetDrawObjs() )
1842         {
1843             for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
1844             {
1845                 // --> OD 2004-06-29 #i28701#
1846                 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
1847                 const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
1848                 const sal_Bool bFly = pAnchoredObj->ISA(SwFlyFrm);
1849                 if ((bFly && (WEIT_WECH == pAnchoredObj->GetObjRect().Width()))
1850                     || rFmt.GetFrmSize().GetWidthPercent())
1851                 {
1852                     continue;
1853                 }
1854 
1855                 long nWidth = 0;
1856                 switch ( rFmt.GetAnchor().GetAnchorId() )
1857                 {
1858                     case FLY_AS_CHAR:
1859                         nWidth = bFly ? rFmt.GetFrmSize().GetWidth() :
1860                                         pAnchoredObj->GetObjRect().Width();
1861                         break;
1862                     case FLY_AT_PARA:
1863                         {
1864                             // --> FME 2004-09-13 #i33170#
1865                             // Reactivated old code because
1866                             // nWidth = pAnchoredObj->GetObjRect().Right()
1867                             // gives wrong results for objects that are still
1868                             // at position WEIT_WECH.
1869                             if ( bFly )
1870                             {
1871                                 nWidth = rFmt.GetFrmSize().GetWidth();
1872                                 const SwFmtHoriOrient &rHori = rFmt.GetHoriOrient();
1873                                 switch ( rHori.GetHoriOrient() )
1874                                 {
1875                                     case text::HoriOrientation::NONE:
1876                                         nWidth += rHori.GetPos();
1877                                         break;
1878                                     case text::HoriOrientation::INSIDE:
1879                                     case text::HoriOrientation::LEFT:
1880                                         if ( text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() )
1881                                             nWidth += pFrm->Prt().Left();
1882                                         break;
1883                                     default:
1884                                         break;
1885                                 }
1886                             }
1887                             else
1888                                 //Fuer Zeichenobjekte ist die Auswahl sehr klein,
1889                                 //weil sie keine Attribute haben, also durch ihre
1890                                 //aktuelle Groesse bestimmt werden.
1891                                 nWidth = pAnchoredObj->GetObjRect().Right() -
1892                                          pAnchoredObj->GetDrawObj()->GetAnchorPos().X();
1893                             // <--
1894                         }
1895                         break;
1896                     default:    /* do nothing */;
1897                 }
1898                 nBrowseWidth = Max( nBrowseWidth, nWidth );
1899             }
1900         }
1901         pFrm = pFrm->FindNextCnt();
1902     } while ( pFrm );
1903 }
1904 
1905 /*************************************************************************
1906 |*
1907 |*  SwRootFrm::StartAllAction()
1908 |*
1909 |*  Ersterstellung      MA 08. Mar. 98
1910 |*  Letzte Aenderung    MA 08. Mar. 98
1911 |*
1912 |*************************************************************************/
1913 
1914 void SwRootFrm::StartAllAction()
1915 {
1916     ViewShell *pSh = GetCurrShell();
1917     if ( pSh )
1918         do
1919         {   if ( pSh->ISA( SwCrsrShell ) )
1920                 ((SwCrsrShell*)pSh)->StartAction();
1921             else
1922                 pSh->StartAction();
1923             pSh = (ViewShell*)pSh->GetNext();
1924 
1925         } while ( pSh != GetCurrShell() );
1926 }
1927 
1928 void SwRootFrm::EndAllAction( sal_Bool bVirDev )
1929 {
1930     ViewShell *pSh = GetCurrShell();
1931     if ( pSh )
1932         do
1933         {
1934             const sal_Bool bOldEndActionByVirDev = pSh->IsEndActionByVirDev();
1935             pSh->SetEndActionByVirDev( bVirDev );
1936             if ( pSh->ISA( SwCrsrShell ) )
1937             {
1938                 ((SwCrsrShell*)pSh)->EndAction();
1939                 ((SwCrsrShell*)pSh)->CallChgLnk();
1940                 if ( pSh->ISA( SwFEShell ) )
1941                     ((SwFEShell*)pSh)->SetChainMarker();
1942             }
1943             else
1944                 pSh->EndAction();
1945             pSh->SetEndActionByVirDev( bOldEndActionByVirDev );
1946             pSh = (ViewShell*)pSh->GetNext();
1947 
1948         } while ( pSh != GetCurrShell() );
1949 }
1950 
1951 void SwRootFrm::UnoRemoveAllActions()
1952 {
1953     ViewShell *pSh = GetCurrShell();
1954     if ( pSh )
1955         do
1956         {
1957             // --> OD 2008-05-16 #i84729#
1958             // No end action, if <ViewShell> instance is currently in its end action.
1959             // Recursives calls to <::EndAction()> are not allowed.
1960             if ( !pSh->IsInEndAction() )
1961             {
1962                 DBG_ASSERT(!pSh->GetRestoreActions(), "Restore action count is already set!");
1963                 sal_Bool bCrsr = pSh->ISA( SwCrsrShell );
1964                 sal_Bool bFE = pSh->ISA( SwFEShell );
1965                 sal_uInt16 nRestore = 0;
1966                 while( pSh->ActionCount() )
1967                 {
1968                     if( bCrsr )
1969                     {
1970                         ((SwCrsrShell*)pSh)->EndAction();
1971                         ((SwCrsrShell*)pSh)->CallChgLnk();
1972                         if ( bFE )
1973                             ((SwFEShell*)pSh)->SetChainMarker();
1974                     }
1975                     else
1976                         pSh->EndAction();
1977                     nRestore++;
1978                 }
1979                 pSh->SetRestoreActions(nRestore);
1980             }
1981             // <--
1982             pSh->LockView(sal_True);
1983             pSh = (ViewShell*)pSh->GetNext();
1984 
1985         } while ( pSh != GetCurrShell() );
1986 }
1987 
1988 void SwRootFrm::UnoRestoreAllActions()
1989 {
1990     ViewShell *pSh = GetCurrShell();
1991     if ( pSh )
1992         do
1993         {
1994             sal_uInt16 nActions = pSh->GetRestoreActions();
1995             while( nActions-- )
1996             {
1997                 if ( pSh->ISA( SwCrsrShell ) )
1998                     ((SwCrsrShell*)pSh)->StartAction();
1999                 else
2000                     pSh->StartAction();
2001             }
2002             pSh->SetRestoreActions(0);
2003             pSh->LockView(sal_False);
2004             pSh = (ViewShell*)pSh->GetNext();
2005 
2006         } while ( pSh != GetCurrShell() );
2007 }
2008 
2009 // PAGES01: Helper functions for SwRootFrm::CheckViewLayout
2010 void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset );
2011 
2012 void lcl_MoveAllLowerObjs( SwFrm* pFrm, const Point& rOffset )
2013 {
2014     SwSortedObjs* pSortedObj = 0;
2015     const bool bPage = pFrm->IsPageFrm();
2016 
2017     if ( bPage )
2018         pSortedObj = static_cast<SwPageFrm*>(pFrm)->GetSortedObjs();
2019     else
2020         pSortedObj = pFrm->GetDrawObjs();
2021 
2022     for ( sal_uInt16 i = 0; pSortedObj && i < pSortedObj->Count(); ++i)
2023     {
2024         SwAnchoredObject* pAnchoredObj = (*pSortedObj)[i];
2025 
2026         const SwFrmFmt& rObjFmt = pAnchoredObj->GetFrmFmt();
2027         const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor();
2028 
2029         // all except from the as character anchored objects are moved
2030         // when processing the page frame:
2031         const bool bAsChar = (rAnchor.GetAnchorId() == FLY_AS_CHAR);
2032         if ( !bPage && !bAsChar )
2033             continue;
2034 
2035         SwObjPositioningInProgress aPosInProgress( *pAnchoredObj );
2036 
2037         if ( pAnchoredObj->ISA(SwFlyFrm) )
2038         {
2039             SwFlyFrm* pFlyFrm( static_cast<SwFlyFrm*>(pAnchoredObj) );
2040             lcl_MoveAllLowers( pFlyFrm, rOffset );
2041             pFlyFrm->NotifyDrawObj();
2042             // --> let the active embedded object be moved
2043             if ( pFlyFrm->Lower() )
2044             {
2045                 if ( pFlyFrm->Lower()->IsNoTxtFrm() )
2046                 {
2047                     SwCntntFrm* pCntntFrm = static_cast<SwCntntFrm*>(pFlyFrm->Lower());
2048                     SwRootFrm* pRoot = pFlyFrm->Lower()->getRootFrm();
2049                     ViewShell *pSh = pRoot ? pRoot->GetCurrShell() : 0;
2050                     if ( pSh )
2051                     {
2052                         SwOLENode* pNode = pCntntFrm->GetNode()->GetOLENode();
2053                         if ( pNode )
2054                         {
2055                             svt::EmbeddedObjectRef& xObj = pNode->GetOLEObj().GetObject();
2056                             if ( xObj.is() )
2057                             {
2058                                 ViewShell* pTmp = pSh;
2059                                 do
2060                                 {
2061                                     SwFEShell* pFEShell = dynamic_cast< SwFEShell* >( pTmp );
2062                                     if ( pFEShell )
2063                                         pFEShell->MoveObjectIfActive( xObj, rOffset );
2064                                     pTmp = static_cast<ViewShell*>( pTmp->GetNext() );
2065                                 } while( pTmp != pSh );
2066                             }
2067                         }
2068                     }
2069                 }
2070             }
2071             // <--
2072         }
2073         else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
2074         {
2075             SwAnchoredDrawObject* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject*>(pAnchoredObj) );
2076 
2077             // don't touch objects that are not yet positioned:
2078             const bool bNotYetPositioned = pAnchoredDrawObj->NotYetPositioned();
2079             if ( bNotYetPositioned )
2080                 continue;
2081 
2082             const Point aCurrAnchorPos = pAnchoredDrawObj->GetDrawObj()->GetAnchorPos();
2083             const Point aNewAnchorPos( ( aCurrAnchorPos + rOffset ) );
2084             pAnchoredDrawObj->DrawObj()->SetAnchorPos( aNewAnchorPos );
2085             pAnchoredDrawObj->SetLastObjRect( pAnchoredDrawObj->GetObjRect().SVRect() );
2086         }
2087         // --> OD 2009-08-20 #i92511#
2088         // cache for object rectangle inclusive spaces has to be invalidated.
2089         pAnchoredObj->InvalidateObjRectWithSpaces();
2090         // <--
2091     }
2092 }
2093 
2094 void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset )
2095 {
2096     const SwRect aFrm( pFrm->Frm() );
2097 
2098     // first move the current frame
2099     pFrm->Frm().Pos() += rOffset;
2100 
2101     // Don't forget accessibility:
2102     if( pFrm->IsAccessibleFrm() )
2103     {
2104         SwRootFrm *pRootFrm = pFrm->getRootFrm();
2105         if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
2106             pRootFrm->GetCurrShell() )
2107         {
2108             pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
2109         }
2110     }
2111 
2112     // the move any objects
2113     lcl_MoveAllLowerObjs( pFrm, rOffset );
2114 
2115     // finally, for layout frames we have to call this function recursively:
2116     if ( pFrm->ISA(SwLayoutFrm) )
2117     {
2118         SwFrm* pLowerFrm = pFrm->GetLower();
2119         while ( pLowerFrm )
2120         {
2121             lcl_MoveAllLowers( pLowerFrm, rOffset );
2122             pLowerFrm = pLowerFrm->GetNext();
2123         }
2124     }
2125 }
2126 
2127 // PAGES01: Calculate how the pages have to be positioned
2128 void SwRootFrm::CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea )
2129 {
2130     // --> OD 2008-07-07 #i91432#
2131     // No calculation of page positions, if only an empty page is present.
2132     // This situation occurs when <SwRootFrm> instance is in construction
2133     // and the document contains only left pages.
2134     if ( Lower()->GetNext() == 0 &&
2135          static_cast<SwPageFrm*>(Lower())->IsEmptyPage() )
2136     {
2137         return;
2138     }
2139     // <--
2140 
2141     if ( !pVisArea )
2142     {
2143         // no early return for bNewPage
2144         if ( mnViewWidth < 0 )
2145             mnViewWidth = 0;
2146     }
2147     else
2148     {
2149         ASSERT( pViewOpt, "CheckViewLayout required ViewOptions" )
2150 
2151         const sal_uInt16 nColumns =  pViewOpt->GetViewLayoutColumns();
2152         const bool   bBookMode = pViewOpt->IsViewLayoutBookMode();
2153 
2154         if ( nColumns == mnColumns && bBookMode == mbBookMode && pVisArea->Width() == mnViewWidth && !mbSidebarChanged )
2155             return;
2156 
2157         mnColumns = nColumns;
2158         mbBookMode = bBookMode;
2159         mnViewWidth = pVisArea->Width();
2160         mbSidebarChanged = false;
2161     }
2162 
2163     if( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE ) )
2164     {
2165         mnColumns = 1;
2166         mbBookMode = false;
2167     }
2168 
2169     Calc();
2170 
2171     const sal_Bool bOldCallbackActionEnabled = IsCallbackActionEnabled();
2172     SetCallbackActionEnabled( sal_False );
2173 
2174     maPageRects.clear();
2175 
2176     const long nBorder = Frm().Pos().X();
2177     const long nVisWidth = mnViewWidth - 2 * nBorder;
2178     const long nGapBetweenPages = GAPBETWEENPAGES;
2179 
2180     // check how many pages fit into the first page layout row:
2181     SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(Lower());
2182 
2183     // will contain the number of pages per row. 0 means that
2184     // the page does not fit.
2185     long nWidthRemain = nVisWidth;
2186 
2187     // after one row has been processed, these variables contain
2188     // the width of the row and the maxium of the page heights
2189     long nCurrentRowHeight = 0;
2190     long nCurrentRowWidth = 0;
2191 
2192     // these variables are used to finally set the size of the
2193     // root frame
2194     long nSumRowHeight = 0;
2195     SwTwips nMinPageLeft = TWIPS_MAX;
2196     SwTwips nMaxPageRight = 0;
2197     SwPageFrm* pStartOfRow = pPageFrm;
2198     sal_uInt16 nNumberOfPagesInRow = mbBookMode ? 1 : 0; // in book view, start with right page
2199     bool bFirstRow = true;
2200 
2201     bool bPageChanged = false;
2202     const bool bRTL = !IsLeftToRightViewLayout();
2203     const SwTwips nSidebarWidth = SwPageFrm::GetSidebarBorderWidth( GetCurrShell() );
2204 
2205     while ( pPageFrm )
2206     {
2207         // we consider the current page to be "start of row" if
2208         // 1. it is the first page in the current row or
2209         // 2. it is the second page in the row and the first page is an empty page in non-book view:
2210         const bool bStartOfRow = pPageFrm == pStartOfRow ||
2211                                              ( pStartOfRow->IsEmptyPage() && pPageFrm == pStartOfRow->GetNext() && !mbBookMode );
2212 
2213         const bool bEmptyPage = pPageFrm->IsEmptyPage() && !mbBookMode;
2214 
2215         // no half doc border space for first page in each row and
2216         long nPageWidth = 0;
2217         long nPageHeight = 0;
2218 
2219         if ( mbBookMode )
2220         {
2221             const SwFrm& rFormatPage = pPageFrm->GetFormatPage();
2222 
2223             nPageWidth  = rFormatPage.Frm().Width()  + nSidebarWidth + ((bStartOfRow || 1 == (pPageFrm->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages);
2224             nPageHeight = rFormatPage.Frm().Height() + nGapBetweenPages;
2225         }
2226         else
2227         {
2228             SwRect aPageFrm;
2229             if ( !pPageFrm->IsEmptyPage() )
2230             {
2231                 nPageWidth  = pPageFrm->Frm().Width() + nSidebarWidth + (bStartOfRow ? 0 : nGapBetweenPages);
2232                 nPageHeight = pPageFrm->Frm().Height() + nGapBetweenPages;
2233             }
2234         }
2235 
2236         if ( !bEmptyPage )
2237             ++nNumberOfPagesInRow;
2238 
2239         // finish current row if
2240         // 1. in dynamic mode the current page does not fit anymore or
2241         // 2. the current page exceeds the maximum number of columns
2242         bool bRowFinished = (0 == mnColumns && nWidthRemain < nPageWidth ) ||
2243                             (0 != mnColumns && mnColumns < nNumberOfPagesInRow);
2244 
2245         // make sure that at least one page goes to the current row:
2246         if ( !bRowFinished || bStartOfRow )
2247         {
2248             // current page is allowed to be in current row
2249             nWidthRemain = nWidthRemain - nPageWidth;
2250 
2251             nCurrentRowWidth = nCurrentRowWidth + nPageWidth;
2252             nCurrentRowHeight = Max( nCurrentRowHeight, nPageHeight );
2253 
2254             pPageFrm = static_cast<SwPageFrm*>(pPageFrm->GetNext());
2255 
2256             if ( !pPageFrm )
2257                 bRowFinished = true;
2258         }
2259 
2260         if ( bRowFinished )
2261         {
2262             // pPageFrm now points to the first page in the new row or null
2263             // pStartOfRow points to the first page in the current row
2264 
2265             // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
2266             if ( !pPageFrm && nWidthRemain > 0 )
2267             {
2268                 // find last page in current row:
2269                 const SwPageFrm* pLastPageInCurrentRow = pStartOfRow;
2270                 while( pLastPageInCurrentRow->GetNext() )
2271                     pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetNext());
2272 
2273                 if ( pLastPageInCurrentRow->IsEmptyPage() )
2274                     pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetPrev());
2275 
2276                 // check how many times the last page would still fit into the remaining space:
2277                 sal_uInt16 nNumberOfVirtualPages = 0;
2278                 const sal_uInt16 nMaxNumberOfVirtualPages = mnColumns > 0 ? mnColumns - nNumberOfPagesInRow : USHRT_MAX;
2279                 SwTwips nRemain = nWidthRemain;
2280                 SwTwips nVirtualPagesWidth = 0;
2281                 SwTwips nLastPageWidth = pLastPageInCurrentRow->Frm().Width() + nSidebarWidth;
2282 
2283                 while ( ( mnColumns > 0 || nRemain > 0 ) && nNumberOfVirtualPages < nMaxNumberOfVirtualPages )
2284                 {
2285                     SwTwips nLastPageWidthWithGap = nLastPageWidth;
2286                     if ( !mbBookMode || ( 0 == (nNumberOfVirtualPages + nNumberOfPagesInRow) %2) )
2287                         nLastPageWidthWithGap += nGapBetweenPages;
2288 
2289                     if ( mnColumns > 0 || nLastPageWidthWithGap < nRemain )
2290                     {
2291                         ++nNumberOfVirtualPages;
2292                         nVirtualPagesWidth += nLastPageWidthWithGap;
2293                     }
2294                     nRemain = nRemain - nLastPageWidthWithGap;
2295                 }
2296 
2297                 nCurrentRowWidth = nCurrentRowWidth + nVirtualPagesWidth;
2298             }
2299 
2300             // first page in book mode is always special:
2301             if ( bFirstRow && mbBookMode )
2302             {
2303                 // --> OD 2008-04-08 #i88036#
2304 //                nCurrentRowWidth += pStartOfRow->Frm().Width() + nSidebarWidth;
2305                 nCurrentRowWidth +=
2306                     pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
2307                 // <--
2308             }
2309 
2310             // center page if possible
2311             const long nSizeDiff = nVisWidth > nCurrentRowWidth ?
2312                                    ( nVisWidth - nCurrentRowWidth ) / 2 :
2313                                    0;
2314 
2315             // adjust positions of pages in current row
2316             long nX = nSizeDiff;
2317 
2318             const long nRowStart = nBorder + nSizeDiff;
2319             const long nRowEnd   = nRowStart + nCurrentRowWidth;
2320 
2321             if ( bFirstRow && mbBookMode )
2322             {
2323                 // --> OD 2008-04-08 #i88036#
2324 //                nX += pStartOfRow->Frm().Width() + nSidebarWidth;
2325                 nX += pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
2326                 // <--
2327             }
2328 
2329             SwPageFrm* pEndOfRow = pPageFrm;
2330             SwPageFrm* pPageToAdjust = pStartOfRow;
2331 
2332             do
2333             {
2334                 const SwPageFrm* pFormatPage = pPageToAdjust;
2335                 if ( mbBookMode )
2336                     pFormatPage = &pPageToAdjust->GetFormatPage();
2337 
2338                 const SwTwips nCurrentPageWidth = pFormatPage->Frm().Width() + (pFormatPage->IsEmptyPage() ? 0 : nSidebarWidth);
2339                 const Point aOldPagePos = pPageToAdjust->Frm().Pos();
2340                 const bool bLeftSidebar = pPageToAdjust->SidebarPosition() == sw::sidebarwindows::SIDEBAR_LEFT;
2341                 const SwTwips nLeftPageAddOffset = bLeftSidebar ?
2342                                                    nSidebarWidth :
2343                                                    0;
2344 
2345                 Point aNewPagePos( nBorder + nX, nBorder + nSumRowHeight );
2346                 Point aNewPagePosWithLeftOffset( nBorder + nX + nLeftPageAddOffset, nBorder + nSumRowHeight );
2347 
2348                 // RTL view layout: Calculate mirrored page position
2349                 if ( bRTL )
2350                 {
2351                     const long nXOffsetInRow = aNewPagePos.X() - nRowStart;
2352                     aNewPagePos.X() = nRowEnd - nXOffsetInRow - nCurrentPageWidth;
2353                     aNewPagePosWithLeftOffset = aNewPagePos;
2354                     aNewPagePosWithLeftOffset.X() += nLeftPageAddOffset;
2355                 }
2356 
2357                 if ( aNewPagePosWithLeftOffset != aOldPagePos )
2358                 {
2359                     lcl_MoveAllLowers( pPageToAdjust, aNewPagePosWithLeftOffset - aOldPagePos );
2360                     pPageToAdjust->SetCompletePaint();
2361                     bPageChanged = true;
2362                 }
2363 
2364                 // calculate area covered by the current page and store to
2365                 // maPageRects. This is used e.g., for cursor setting
2366                 const bool bFirstColumn = pPageToAdjust == pStartOfRow;
2367                 const bool bLastColumn = pPageToAdjust->GetNext() == pEndOfRow;
2368                 const bool bLastRow = !pEndOfRow;
2369 
2370                 nMinPageLeft  = Min( nMinPageLeft, aNewPagePos.X() );
2371                 nMaxPageRight = Max( nMaxPageRight, aNewPagePos.X() + nCurrentPageWidth);
2372 
2373                 // border of nGapBetweenPages around the current page:
2374                 SwRect aPageRectWithBorders( aNewPagePos.X() - nGapBetweenPages,
2375                                              aNewPagePos.Y(),
2376                                              pPageToAdjust->Frm().SSize().Width() + nGapBetweenPages + nSidebarWidth,
2377                                              nCurrentRowHeight );
2378 
2379                 static const long nOuterClickDiff = 1000000;
2380 
2381                 // adjust borders for these special cases:
2382                 if ( (bFirstColumn && !bRTL) || (bLastColumn && bRTL) )
2383                     aPageRectWithBorders.SubLeft( nOuterClickDiff );
2384                 if ( (bLastColumn && !bRTL) || (bFirstColumn && bRTL) )
2385                     aPageRectWithBorders.AddRight( nOuterClickDiff );
2386                 if ( bFirstRow )
2387                     aPageRectWithBorders.SubTop( nOuterClickDiff );
2388                 if ( bLastRow )
2389                     aPageRectWithBorders.AddBottom( nOuterClickDiff );
2390 
2391                 maPageRects.push_back( aPageRectWithBorders );
2392 
2393                 nX = nX + nCurrentPageWidth;
2394                 pPageToAdjust = static_cast<SwPageFrm*>(pPageToAdjust->GetNext());
2395 
2396                 // distance to next page
2397                 if ( pPageToAdjust && pPageToAdjust != pEndOfRow )
2398                 {
2399                     // in book view, we add the x gap before left (even) pages:
2400                     if ( mbBookMode )
2401                     {
2402                         if ( 0 == (pPageToAdjust->GetPhyPageNum()%2) )
2403                             nX = nX + nGapBetweenPages;
2404                     }
2405                     else
2406                     {
2407                         // in non-book view, dont add x gap before
2408                         // 1. the last empty page in a row
2409                         // 2. after an empty page
2410                         const bool bDontAddGap = ( pPageToAdjust->IsEmptyPage() && pPageToAdjust->GetNext() == pEndOfRow ) ||
2411                                                  ( static_cast<SwPageFrm*>(pPageToAdjust->GetPrev())->IsEmptyPage() );
2412 
2413                         if  ( !bDontAddGap )
2414                             nX = nX + nGapBetweenPages;
2415                     }
2416                 }
2417             }
2418             while ( pPageToAdjust != pEndOfRow );
2419 
2420             // adjust values for root frame size
2421             nSumRowHeight = nSumRowHeight + nCurrentRowHeight;
2422 
2423             // start new row:
2424             nCurrentRowHeight = 0;
2425             nCurrentRowWidth = 0;
2426             pStartOfRow = pEndOfRow;
2427             nWidthRemain = nVisWidth;
2428             nNumberOfPagesInRow = 0;
2429             bFirstRow = false;
2430         } // end row finished
2431     } // end while
2432 
2433     // set size of root frame:
2434     const Size aOldSize( Frm().SSize() );
2435     const Size aNewSize( nMaxPageRight - nBorder, nSumRowHeight - nGapBetweenPages );
2436 
2437     if ( bPageChanged || aNewSize != aOldSize )
2438     {
2439         ChgSize( aNewSize );
2440         ::AdjustSizeChgNotify( this );
2441         Calc();
2442 
2443         ViewShell* pSh = GetCurrShell();
2444 
2445         if ( pSh && pSh->GetDoc()->GetDocShell() )
2446         {
2447             pSh->SetFirstVisPageInvalid();
2448             if (bOldCallbackActionEnabled)
2449             {
2450                 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
2451                 pSh->GetDoc()->GetDocShell()->Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED));
2452             }
2453         }
2454     }
2455 
2456     maPagesArea.Pos( Frm().Pos() );
2457     maPagesArea.SSize( aNewSize );
2458     if ( TWIPS_MAX != nMinPageLeft )
2459         maPagesArea._Left( nMinPageLeft );
2460 
2461     SetCallbackActionEnabled( bOldCallbackActionEnabled );
2462 }
2463 
2464 bool SwRootFrm::IsLeftToRightViewLayout() const
2465 {
2466     // Layout direction determined by layout direction of the first page.
2467     // --> OD 2008-04-08 #i88036#
2468     // Only ask a non-empty page frame for its layout direction
2469 //    const SwPageFrm* pPage = dynamic_cast<const SwPageFrm*>(Lower());
2470 //    return !pPage->IsRightToLeft() && !pPage->IsVertical();
2471     const SwPageFrm& rPage =
2472                     dynamic_cast<const SwPageFrm*>(Lower())->GetFormatPage();
2473     return !rPage.IsRightToLeft() && !rPage.IsVertical();
2474     // <--
2475 }
2476 
2477 /*const SwRect SwRootFrm::GetExtendedPageArea( sal_uInt16 nPageNumber ) const
2478 {
2479     SwRect aRet;
2480     ASSERT( nPageNumber < maPageRects.size(), "No extended page area available" )
2481     if ( nPageNumber < maPageRects.size() )
2482         aRet = maPageRects[ nPageNumber ];
2483     return aRet;
2484 }*/
2485 
2486 
2487 const SwPageFrm& SwPageFrm::GetFormatPage() const
2488 {
2489     const SwPageFrm* pRet = this;
2490     if ( IsEmptyPage() )
2491     {
2492         pRet = static_cast<const SwPageFrm*>( OnRightPage() ? GetNext() : GetPrev() );
2493         // --> OD 2008-04-08 #i88035#
2494         // Typically a right empty page frame has a next non-empty page frame and
2495         // a left empty page frame has a previous non-empty page frame.
2496         // But under certain cirsumstances this assumption is not true -
2497         // e.g. during insertion of a left page at the end of the document right
2498         // after a left page in an intermediate state a right empty page does not
2499         // have a next page frame.
2500         if ( pRet == 0 )
2501         {
2502             if ( OnRightPage() )
2503             {
2504                 pRet = static_cast<const SwPageFrm*>( GetPrev() );
2505             }
2506             else
2507             {
2508                 pRet = static_cast<const SwPageFrm*>( GetNext() );
2509             }
2510         }
2511         ASSERT( pRet,
2512                 "<SwPageFrm::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash." );
2513         // <--
2514     }
2515     return *pRet;
2516 }
2517 
2518