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