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