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