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