xref: /AOO41X/main/sw/source/core/layout/pagechg.cxx (revision e9dc4413f135904da32ef1f941cdd792fe26a8dd)
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