1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pagechg.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include <com/sun/star/embed/EmbedStates.hpp>
37 #include <svtools/itemiter.hxx>
38 #include <fmtfsize.hxx>
39 #include <fmthdft.hxx>
40 #include <fmtclds.hxx>
41 #include <fmtanchr.hxx>
42 #include <fmtpdsc.hxx>
43 #include <fmtfordr.hxx>
45 #include <fmtornt.hxx>
46 #include <ftninfo.hxx>
47 #include <tgrditem.hxx>
48 #include <viewopt.hxx>
53 #include "viewimp.hxx"
54 #include "pagefrm.hxx"
55 #include "rootfrm.hxx"
61 #include "dflyobj.hxx"
62 #include "dcontact.hxx"
63 #include "frmtool.hxx"
67 #include "swtable.hxx"
70 #include "bodyfrm.hxx"
75 #include "flyfrms.hxx"
76 #include "htmltbl.hxx"
77 #include "pagedesc.hxx"
78 #include "poolfmt.hxx"
79 #include <svx/frmdiritem.hxx>
80 #include <swfntcch.hxx> // SwFontAccess
81 // OD 2004-05-24 #i28701#
82 #include <sortedobjs.hxx>
84 #include <vcl/svapp.hxx>
86 using namespace ::com::sun::star
;
89 /*************************************************************************
91 |* SwBodyFrm::SwBodyFrm()
93 |* Ersterstellung MA ??
94 |* Letzte Aenderung MA 01. Aug. 93
96 |*************************************************************************/
97 SwBodyFrm::SwBodyFrm( SwFrmFmt
*pFmt
):
103 /*************************************************************************
105 |* SwBodyFrm::Format()
107 |* Ersterstellung MA 30. May. 94
108 |* Letzte Aenderung MA 20. Jan. 99
110 |*************************************************************************/
111 void SwBodyFrm::Format( const SwBorderAttrs
* )
113 //Formatieren des Body ist zu einfach, deshalb bekommt er ein eigenes
114 //Format; Umrandungen und dergl. sind hier nicht zu beruecksichtigen.
115 //Breite ist die der PrtArea des Uppers, Hoehe ist die Hoehe der PrtArea
116 //des Uppers abzueglich der Nachbarn (Wird eigentlich eingestellt aber
117 //Vorsicht ist die Mutter der Robustheit).
118 //Die PrtArea ist stets so gross wie der Frm itself.
122 SwTwips nHeight
= GetUpper()->Prt().Height();
123 SwTwips nWidth
= GetUpper()->Prt().Width();
124 const SwFrm
*pFrm
= GetUpper()->Lower();
129 if( pFrm
->IsVertical() )
130 nWidth
-= pFrm
->Frm().Width();
132 nHeight
-= pFrm
->Frm().Height();
134 pFrm
= pFrm
->GetNext();
138 Frm().Height( nHeight
);
139 if( IsVertical() && !IsReverse() && nWidth
!= Frm().Width() )
140 Frm().Pos().X() += Frm().Width() - nWidth
;
141 Frm().Width( nWidth
);
145 if( GetUpper()->IsPageFrm() && ((SwPageFrm
*)GetUpper())->HasGrid() )
147 GETGRID( ((SwPageFrm
*)GetUpper()) )
151 long nSum
= pGrid
->GetBaseHeight() + pGrid
->GetRubyHeight();
153 long nSize
= (Frm().*fnRect
->fnGetWidth
)();
155 if( GRID_LINES_CHARS
== pGrid
->GetGridType() )
157 //for textgrid refactor
158 SwDoc
*pDoc
= GetFmt()->GetDoc();
159 nBorder
= nSize
% (GETGRIDWIDTH(pGrid
, pDoc
));
163 (Prt().*fnRect
->fnSetPosX
)( nBorder
);
164 (Prt().*fnRect
->fnSetWidth
)( nSize
);
166 // Height of body frame:
167 nBorder
= (Frm().*fnRect
->fnGetHeight
)();
169 // Number of possible lines in area of body frame:
170 long nNumberOfLines
= nBorder
/ nSum
;
171 if( nNumberOfLines
> pGrid
->GetLines() )
172 nNumberOfLines
= pGrid
->GetLines();
174 // Space required for nNumberOfLines lines:
175 nSize
= nNumberOfLines
* nSum
;
179 // #i21774# Footnotes and centering the grid does not work together:
180 const bool bAdjust
= 0 == ((SwPageFrm
*)GetUpper())->GetFmt()->GetDoc()->
181 GetFtnIdxs().Count();
183 (Prt().*fnRect
->fnSetPosY
)( bAdjust
? nBorder
: 0 );
184 (Prt().*fnRect
->fnSetHeight
)( nSize
);
189 Prt().Pos().X() = Prt().Pos().Y() = 0;
190 Prt().Height( Frm().Height() );
191 Prt().Width( Frm().Width() );
193 bValidSize
= bValidPrtArea
= TRUE
;
196 /*************************************************************************
198 |* SwPageFrm::SwPageFrm(), ~SwPageFrm()
200 |* Ersterstellung MA 20. Oct. 92
201 |* Letzte Aenderung MA 08. Dec. 97
203 |*************************************************************************/
204 SwPageFrm::SwPageFrm( SwFrmFmt
*pFmt
, SwPageDesc
*pPgDsc
) :
205 SwFtnBossFrm( pFmt
),
209 // OD 2004-05-17 #i28701#
210 mbLayoutInProgress( false )
212 SetDerivedVert( FALSE
);
213 SetDerivedR2L( FALSE
);
223 SetMaxFtnHeight( pPgDsc
->GetFtnInfo().GetHeight() ?
224 pPgDsc
->GetFtnInfo().GetHeight() : LONG_MAX
),
226 bInvalidLayout
= bInvalidCntnt
= bInvalidSpelling
= bInvalidSmartTags
= bInvalidAutoCmplWrds
= bInvalidWordCount
= TRUE
;
227 bInvalidFlyLayout
= bInvalidFlyCntnt
= bInvalidFlyInCnt
= bFtnPage
= bEndNotePage
= FALSE
;
229 const bool bBrowseMode
= pFmt
->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
);
233 ViewShell
*pSh
= GetShell();
234 long nWidth
= pSh
? pSh
->VisArea().Width():0;
236 nWidth
= 5000L; //aendert sich sowieso
237 Frm().Width ( nWidth
);
240 Frm().SSize( pFmt
->GetFrmSize().GetSize() );
242 //Body-Bereich erzeugen und einsetzen, aber nur wenn ich nicht gerade
243 //eine Leerseite bin.
244 SwDoc
*pDoc
= pFmt
->GetDoc();
245 if ( FALSE
== (bEmptyPage
= pFmt
== pDoc
->GetEmptyPageFmt()) )
248 Calc(); //Damit die PrtArea stimmt.
249 SwBodyFrm
*pBodyFrm
= new SwBodyFrm( pDoc
->GetDfltFrmFmt() );
250 pBodyFrm
->ChgSize( Prt().SSize() );
251 pBodyFrm
->Paste( this );
252 pBodyFrm
->Calc(); //Damit die Spalten korrekt
253 //eingesetzt werden koennen.
254 pBodyFrm
->InvalidatePos();
257 _InvalidateSize(); //Alles nur gelogen
259 //Header/Footer einsetzen, nur rufen wenn aktiv.
260 if ( pFmt
->GetHeader().IsActive() )
262 if ( pFmt
->GetFooter().IsActive() )
265 const SwFmtCol
&rCol
= pFmt
->GetCol();
266 if ( rCol
.GetNumCols() > 1 )
268 const SwFmtCol aOld
; //ChgColumns() verlaesst sich darauf, dass ein
269 //Old-Wert hereingereicht wird.
270 pBodyFrm
->ChgColumns( aOld
, rCol
);
275 SwPageFrm::~SwPageFrm()
277 //FlyContainer entleeren, delete der Flys uebernimmt der Anchor
278 //(Basisklasse SwFrm)
281 //Objekte koennen (warum auch immer) auch an Seiten verankert sein,
282 //die vor Ihren Ankern stehen. Dann wuerde auf bereits freigegebenen
283 //Speicher zugegriffen.
284 for ( USHORT i
= 0; i
< pSortedObjs
->Count(); ++i
)
286 SwAnchoredObject
* pAnchoredObj
= (*pSortedObjs
)[i
];
287 pAnchoredObj
->SetPageFrm( 0L );
290 pSortedObjs
= 0; //Auf 0 setzen, sonst rauchts beim Abmdelden von Flys!
293 //Damit der Zugriff auf zerstoerte Seiten verhindert werden kann.
294 if ( !IsEmptyPage() ) //#59184# sollte fuer Leerseiten unnoetig sein.
296 SwDoc
*pDoc
= GetFmt()->GetDoc();
297 if( pDoc
&& !pDoc
->IsInDtor() )
299 ViewShell
*pSh
= GetShell();
302 SwViewImp
*pImp
= pSh
->Imp();
303 pImp
->SetFirstVisPageInvalid();
304 if ( pImp
->IsAction() )
305 pImp
->GetLayAction().SetAgain();
306 // OD 12.02.2003 #i9719#, #105645# - retouche area of page
307 // including border and shadow area.
308 const bool bRightSidebar
= !MarginSide();
309 SwRect aRetoucheRect
;
310 SwPageFrm::GetBorderAndShadowBoundRect( Frm(), pSh
, aRetoucheRect
, bRightSidebar
);
311 pSh
->AddPaintRect( aRetoucheRect
);
318 void SwPageFrm::CheckGrid( BOOL bInvalidate
)
320 BOOL bOld
= bHasGrid
;
323 bHasGrid
= 0 != pGrid
;
324 if( bInvalidate
|| bOld
!= bHasGrid
)
326 SwLayoutFrm
* pBody
= FindBodyCont();
329 pBody
->InvalidatePrt();
330 SwCntntFrm
* pFrm
= pBody
->ContainsCntnt();
331 while( pBody
->IsAnLower( pFrm
) )
333 ((SwTxtFrm
*)pFrm
)->Prepare( PREP_CLEAR
);
334 pFrm
= pFrm
->GetNextCntntFrm();
342 void SwPageFrm::CheckDirection( BOOL bVert
)
345 ((SvxFrameDirectionItem
&)GetFmt()->GetFmtAttr( RES_FRAMEDIR
)).GetValue();
348 if( FRMDIR_HORI_LEFT_TOP
== nDir
|| FRMDIR_HORI_RIGHT_TOP
== nDir
||
349 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
354 if( pDesc && pDesc->GetName().GetChar(0)=='x')
363 if( FRMDIR_HORI_RIGHT_TOP
== nDir
)
371 /*************************************************************************
373 |* SwPageFrm::PreparePage()
375 |* Beschreibung Erzeugt die Spezifischen Flys zur Seite und formatiert
377 |* Ersterstellung MA 20. Oct. 92
378 |* Letzte Aenderung MA 09. Nov. 95
380 |*************************************************************************/
381 void MA_FASTCALL
lcl_FormatLay( SwLayoutFrm
*pLay
)
383 //Alle LayoutFrms - nicht aber Tables, Flys o.ae. - formatieren.
385 SwFrm
*pTmp
= pLay
->Lower();
386 //Erst die untergeordneten
389 if ( pTmp
->GetType() & 0x00FF )
390 ::lcl_FormatLay( (SwLayoutFrm
*)pTmp
);
391 pTmp
= pTmp
->GetNext();
396 void MA_FASTCALL
lcl_MakeObjs( const SwSpzFrmFmts
&rTbl
, SwPageFrm
*pPage
)
398 //Anlegen bzw. registrieren von Flys und Drawobjekten.
399 //Die Formate stehen in der SpzTbl (vom Dokument).
400 //Flys werden angelegt, DrawObjekte werden bei der Seite angemeldet.
402 for ( USHORT i
= 0; i
< rTbl
.Count(); ++i
)
405 SwFrmFmt
*pFmt
= rTbl
[i
];
406 const SwFmtAnchor
&rAnch
= pFmt
->GetAnchor();
407 if ( rAnch
.GetPageNum() == pPage
->GetPhyPageNum() )
409 if( rAnch
.GetCntntAnchor() )
411 if( FLY_PAGE
== rAnch
.GetAnchorId() )
413 SwFmtAnchor
aAnch( rAnch
);
414 aAnch
.SetAnchor( 0 );
415 pFmt
->SetFmtAttr( aAnch
);
421 //Wird ein Rahmen oder ein SdrObject beschrieben?
422 BOOL bSdrObj
= RES_DRAWFRMFMT
== pFmt
->Which();
424 if ( bSdrObj
&& 0 == (pSdrObj
= pFmt
->FindSdrObject()) )
426 ASSERT( FALSE
, "DrawObject not found." );
427 pFmt
->GetDoc()->DelFrmFmt( pFmt
);
431 //Das Objekt kann noch an einer anderen Seite verankert sein.
432 //Z.B. beim Einfuegen einer neuen Seite aufgrund eines
433 //Pagedescriptor-Wechsels. Das Objekt muss dann umgehaengt
435 //Fuer bestimmte Faelle ist das Objekt bereits an der richtigen
436 //Seite verankert. Das wird hier automatisch erledigt und braucht
437 //- wenngleich performater machbar - nicht extra codiert werden.
438 SwPageFrm
*pPg
= pPage
->IsEmptyPage() ? (SwPageFrm
*)pPage
->GetNext() : pPage
;
441 // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
442 SwDrawContact
*pContact
=
443 static_cast<SwDrawContact
*>(::GetUserCall(pSdrObj
));
444 if ( pSdrObj
->ISA(SwDrawVirtObj
) )
446 SwDrawVirtObj
* pDrawVirtObj
= static_cast<SwDrawVirtObj
*>(pSdrObj
);
449 pDrawVirtObj
->RemoveFromWriterLayout();
450 pDrawVirtObj
->RemoveFromDrawingPage();
451 pPg
->AppendDrawObj( *(pContact
->GetAnchoredObj( pDrawVirtObj
)) );
456 if ( pContact
->GetAnchorFrm() )
457 pContact
->DisconnectFromLayout( false );
458 pPg
->AppendDrawObj( *(pContact
->GetAnchoredObj( pSdrObj
)) );
463 SwClientIter
aIter( *pFmt
);
464 SwClient
*pTmp
= aIter
.First( TYPE(SwFrm
) );
468 pFly
= (SwFlyFrm
*)pTmp
;
469 if( pFly
->GetAnchorFrm() )
470 pFly
->AnchorFrm()->RemoveFly( pFly
);
473 pFly
= new SwFlyLayFrm( (SwFlyFrmFmt
*)pFmt
, pPg
);
474 pPg
->AppendFly( pFly
);
475 ::RegistFlys( pPg
, pFly
);
481 void SwPageFrm::PreparePage( BOOL bFtn
)
485 // --> OD 2008-01-30 #i82258#
486 // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has
487 // the side effect, that the content of page header and footer are formatted.
488 // For this formatting it is needed that the anchored objects are registered
489 // at the <SwPageFrm> instance.
490 // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)>
491 ::RegistFlys( this, this );
495 ::lcl_FormatLay( this );
499 //Flys und DrawObjekte die noch am Dokument bereitstehen.
500 //Fussnotenseiten tragen keine Seitengebundenen Flys!
501 //Es kann Flys und Objekte geben, die auf Leerseiten (Seitennummernmaessig)
502 //stehen wollen, diese werden jedoch von den Leerseiten ignoriert;
503 //sie werden von den Folgeseiten aufgenommen.
504 if ( !bFtn
&& !IsEmptyPage() )
506 SwDoc
*pDoc
= GetFmt()->GetDoc();
508 if ( GetPrev() && ((SwPageFrm
*)GetPrev())->IsEmptyPage() )
509 lcl_MakeObjs( *pDoc
->GetSpzFrmFmts(), (SwPageFrm
*)GetPrev() );
510 lcl_MakeObjs( *pDoc
->GetSpzFrmFmts(), this );
512 //Kopf-/Fusszeilen) formatieren.
513 SwLayoutFrm
*pLow
= (SwLayoutFrm
*)Lower();
516 if ( pLow
->GetType() & (FRMTYPE_HEADER
|FRMTYPE_FOOTER
) )
518 SwCntntFrm
*pCntnt
= pLow
->ContainsCntnt();
519 while ( pCntnt
&& pLow
->IsAnLower( pCntnt
) )
521 pCntnt
->OptCalc(); //Nicht die Vorgaenger
522 pCntnt
= pCntnt
->GetNextCntntFrm();
525 pLow
= (SwLayoutFrm
*)pLow
->GetNext();
530 /*************************************************************************
532 |* SwPageFrm::Modify()
534 |* Ersterstellung MA 20. Oct. 92
535 |* Letzte Aenderung MA 03. Mar. 96
537 |*************************************************************************/
538 void SwPageFrm::Modify( SfxPoolItem
* pOld
, SfxPoolItem
* pNew
)
540 ViewShell
*pSh
= GetShell();
542 pSh
->SetFirstVisPageInvalid();
545 if( pNew
&& RES_ATTRSET_CHG
== pNew
->Which() )
547 SfxItemIter
aNIter( *((SwAttrSetChg
*)pNew
)->GetChgSet() );
548 SfxItemIter
aOIter( *((SwAttrSetChg
*)pOld
)->GetChgSet() );
549 SwAttrSetChg
aOldSet( *(SwAttrSetChg
*)pOld
);
550 SwAttrSetChg
aNewSet( *(SwAttrSetChg
*)pNew
);
553 _UpdateAttr( (SfxPoolItem
*)aOIter
.GetCurItem(),
554 (SfxPoolItem
*)aNIter
.GetCurItem(), nInvFlags
,
555 &aOldSet
, &aNewSet
);
556 if( aNIter
.IsAtEnd() )
561 if ( aOldSet
.Count() || aNewSet
.Count() )
562 SwLayoutFrm::Modify( &aOldSet
, &aNewSet
);
565 _UpdateAttr( pOld
, pNew
, nInvFlags
);
567 if ( nInvFlags
!= 0 )
569 InvalidatePage( this );
570 if ( nInvFlags
& 0x01 )
572 if ( nInvFlags
& 0x02 )
574 if ( nInvFlags
& 0x04 && GetNext() )
575 GetNext()->InvalidatePos();
576 if ( nInvFlags
& 0x08 )
578 if ( nInvFlags
& 0x10 )
580 if ( nInvFlags
& 0x20 )
581 CheckGrid( nInvFlags
& 0x40 );
585 void SwPageFrm::_UpdateAttr( SfxPoolItem
*pOld
, SfxPoolItem
*pNew
,
587 SwAttrSetChg
*pOldSet
, SwAttrSetChg
*pNewSet
)
590 const USHORT nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
595 //Wenn sich das FrmFmt aendert kann hier einiges passieren.
596 //Abgesehen von den Grossenverhaeltnissen sind noch andere
599 ASSERT( pOld
&& pNew
, "FMT_CHG Missing Format." );
600 const SwFmt
* pOldFmt
= ((SwFmtChg
*)pOld
)->pChangedFmt
;
601 const SwFmt
* pNewFmt
= ((SwFmtChg
*)pNew
)->pChangedFmt
;
602 ASSERT( pOldFmt
&& pNewFmt
, "FMT_CHG Missing Format." );
604 const SwFmtCol
&rOldCol
= pOldFmt
->GetCol();
605 const SwFmtCol
&rNewCol
= pNewFmt
->GetCol();
606 if( rOldCol
!= rNewCol
)
608 SwLayoutFrm
*pB
= FindBodyCont();
609 ASSERT( pB
, "Seite ohne Body." );
610 pB
->ChgColumns( rOldCol
, rNewCol
);
614 //2. Kopf- und Fusszeilen.
615 const SwFmtHeader
&rOldH
= pOldFmt
->GetHeader();
616 const SwFmtHeader
&rNewH
= pNewFmt
->GetHeader();
620 const SwFmtFooter
&rOldF
= pOldFmt
->GetFooter();
621 const SwFmtFooter
&rNewF
= pNewFmt
->GetFooter();
626 /* kein break hier */
629 const SwRect
aOldPageFrmRect( Frm() );
630 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
633 // OD 28.10.2002 #97265# - Don't call <SwPageFrm::MakeAll()>
634 // Calculation of the page is not necessary, because its size is
635 // is invalidated here and further invalidation is done in the
636 // calling method <SwPageFrm::Modify(..)> and probably by calling
637 // <SwLayoutFrm::Modify(..)> at the end.
638 // It can also causes inconsistences, because the lowers are
639 // adjusted, but not calculated, and a <SwPageFrm::MakeAll()> of
640 // a next page is called. This is performed on the switch to the
646 const SwFmtFrmSize
&rSz
= nWhich
== RES_FMT_CHG
?
647 ((SwFmtChg
*)pNew
)->pChangedFmt
->GetFrmSize() :
648 (const SwFmtFrmSize
&)*pNew
;
650 Frm().Height( Max( rSz
.GetHeight(), long(MINLAY
) ) );
651 Frm().Width ( Max( rSz
.GetWidth(), long(MINLAY
) ) );
655 static_cast<SwRootFrm
*>(GetUpper())->CheckViewLayout( 0, 0 );
659 if ( 0 != (pSh
= GetShell()) && pSh
->GetWin() && aOldPageFrmRect
.HasArea() )
661 // OD 12.02.2003 #i9719#, #105645# - consider border and shadow of
662 // page frame for determine 'old' rectangle - it's used for invalidating.
663 const bool bRightSidebar
= !MarginSide();
664 SwRect aOldRectWithBorderAndShadow
;
665 SwPageFrm::GetBorderAndShadowBoundRect( aOldPageFrmRect
, pSh
, aOldRectWithBorderAndShadow
, bRightSidebar
);
666 pSh
->InvalidateWindows( aOldRectWithBorderAndShadow
);
669 if ( aOldPageFrmRect
.Height() != Frm().Height() )
676 SwLayoutFrm
*pB
= FindBodyCont();
677 ASSERT( pB
, "Seite ohne Body." );
678 pB
->ChgColumns( *(const SwFmtCol
*)pOld
, *(const SwFmtCol
*)pNew
);
694 case RES_PAGEDESC_FTNINFO
:
695 //Die derzeit einzig sichere Methode:
696 ((SwRootFrm
*)GetUpper())->SetSuperfluous();
697 SetMaxFtnHeight( pDesc
->GetFtnInfo().GetHeight() );
698 if ( !GetMaxFtnHeight() )
699 SetMaxFtnHeight( LONG_MAX
);
700 SetColMaxFtnHeight();
701 //Hier wird die Seite ggf. zerstoert!
702 ((SwRootFrm
*)GetUpper())->RemoveFtns( 0, FALSE
, TRUE
);
713 if ( pOldSet
|| pNewSet
)
716 pOldSet
->ClearItem( nWhich
);
718 pNewSet
->ClearItem( nWhich
);
721 SwLayoutFrm::Modify( pOld
, pNew
);
725 /*************************************************************************
727 |* SwPageFrm::GetInfo()
729 |* Beschreibung erfragt Informationen
730 |* Ersterstellung JP 31.03.94
731 |* Letzte Aenderung JP 31.03.94
733 *************************************************************************/
734 // erfrage vom Modify Informationen
735 BOOL
SwPageFrm::GetInfo( SfxPoolItem
& rInfo
) const
737 if( RES_AUTOFMT_DOCNODE
== rInfo
.Which() )
739 // es gibt einen PageFrm also wird er benutzt
742 return TRUE
; // weiter suchen
745 /*************************************************************************
747 |* SwPageFrm::SetPageDesc()
749 |* Ersterstellung MA 02. Nov. 94
750 |* Letzte Aenderung MA 02. Nov. 94
752 |*************************************************************************/
753 void SwPageFrm::SetPageDesc( SwPageDesc
*pNew
, SwFrmFmt
*pFmt
)
760 /*************************************************************************
762 |* SwPageFrm::FindPageDesc()
764 |* Beschreibung Der richtige PageDesc wird bestimmt:
765 |* 0. Vom Dokument bei Fussnotenseiten und Endnotenseiten
766 |* 1. vom ersten BodyCntnt unterhalb der Seite.
767 |* 2. vom PageDesc der vorstehenden Seite.
768 |* 3. bei Leerseiten vom PageDesc der vorigen Seite.
769 |* 3.1 vom PageDesc der folgenden Seite wenn es keinen Vorgaenger gibt.
770 |* 4. es ist der Default-PageDesc sonst.
771 |* 5. Im BrowseMode ist der Pagedesc immer der vom ersten Absatz im
772 |* Dokument oder Standard (der 0-te) wenn der erste Absatz keinen
774 |* (6. Im HTML-Mode ist der Pagedesc immer die HTML-Seitenvorlage.)
775 |* Ersterstellung MA 15. Feb. 93
776 |* Letzte Aenderung MA 17. Jun. 99
778 |*************************************************************************/
779 SwPageDesc
*SwPageFrm::FindPageDesc()
784 SwDoc
*pDoc
= GetFmt()->GetDoc();
785 if ( IsEndNotePage() )
786 return pDoc
->GetEndNoteInfo().GetPageDesc( *pDoc
);
788 return pDoc
->GetFtnInfo().GetPageDesc( *pDoc
);
792 //if ( GetFmt()->GetDoc()->IsHTMLMode() )
793 // return GetFmt()->GetDoc()->GetPageDescFromPool( RES_POOLPAGE_HTML );
795 SwPageDesc
*pRet
= 0;
798 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
800 SwCntntFrm
*pFrm
= GetUpper()->ContainsCntnt();
801 while ( !pFrm
->IsInDocBody() )
802 pFrm
= pFrm
->GetNextCntntFrm();
804 if ( pFlow
->IsInTab() )
805 pFlow
= pFlow
->FindTabFrm();
806 pRet
= (SwPageDesc
*)pFlow
->GetAttrSet()->GetPageDesc().GetPageDesc();
808 pRet
= &GetFmt()->GetDoc()->_GetPageDesc( 0 );
812 SwFrm
*pFlow
= FindFirstBodyCntnt();
813 if ( pFlow
&& pFlow
->IsInTab() )
814 pFlow
= pFlow
->FindTabFrm();
819 SwFlowFrm
*pTmp
= SwFlowFrm::CastFlowFrm( pFlow
);
820 if ( !pTmp
->IsFollow() )
821 pRet
= (SwPageDesc
*)pFlow
->GetAttrSet()->GetPageDesc().GetPageDesc();
825 if ( !pRet
&& IsEmptyPage() )
826 // FME 2008-03-03 #i81544# lijian/fme: an empty page should have
827 // the same page description as its prev, just like after construction
828 // of the empty page.
829 pRet
= GetPrev() ? ((SwPageFrm
*)GetPrev())->GetPageDesc() :
830 GetNext() ? ((SwPageFrm
*)GetNext())->GetPageDesc() : 0;
835 ((SwPageFrm
*)GetPrev())->GetPageDesc()->GetFollow() : 0;
839 pRet
= (SwPageDesc
*)&(const_cast<const SwDoc
*>(GetFmt()->GetDoc())
843 ASSERT( pRet
, "Kein Descriptor gefunden." );
847 //Wenn der RootFrm seine Groesse aendert muss benachrichtigt werden.
848 void AdjustSizeChgNotify( SwRootFrm
*pRoot
)
850 const BOOL bOld
= pRoot
->IsSuperfluous();
851 pRoot
->bCheckSuperfluous
= FALSE
;
852 ViewShell
*pSh
= pRoot
->GetCurrShell();
855 pSh
->Imp()->NotifySizeChg( pRoot
->Frm().SSize() );//Einmal fuer das Drawing.
858 pSh
->SizeChgNotify(); //Einmal fuer jede Sicht.
859 pSh
= (ViewShell
*)pSh
->GetNext();
860 } while ( pSh
!= pRoot
->GetCurrShell() );
862 pRoot
->bCheckSuperfluous
= bOld
;
866 inline void SetLastPage( SwPageFrm
*pPage
)
868 ((SwRootFrm
*)pPage
->GetUpper())->pLastPage
= pPage
;
871 /*************************************************************************
875 |* Ersterstellung MA 23. Feb. 94
876 |* Letzte Aenderung MA 22. Jun. 95
878 |*************************************************************************/
879 void SwPageFrm::Cut()
882 //AdjustRootSize( CHG_CUTPAGE, 0 );
884 ViewShell
*pSh
= GetShell();
885 if ( !IsEmptyPage() )
888 GetNext()->InvalidatePos();
890 //Flys deren Anker auf anderen Seiten stehen umhaengen.
891 //DrawObjecte spielen hier keine Rolle.
892 if ( GetSortedObjs() )
894 for ( int i
= 0; GetSortedObjs() &&
895 (USHORT
)i
< GetSortedObjs()->Count(); ++i
)
897 // --> OD 2004-06-29 #i28701#
898 SwAnchoredObject
* pAnchoredObj
= (*GetSortedObjs())[i
];
900 if ( pAnchoredObj
->ISA(SwFlyAtCntFrm
) )
902 SwFlyFrm
* pFly
= static_cast<SwFlyAtCntFrm
*>(pAnchoredObj
);
903 SwPageFrm
*pAnchPage
= pFly
->GetAnchorFrm() ?
904 pFly
->AnchorFrm()->FindPageFrm() : 0;
905 if ( pAnchPage
&& (pAnchPage
!= this) )
907 MoveFly( pFly
, pAnchPage
);
909 pFly
->InvalidateSize();
910 pFly
->_InvalidatePos();
917 if ( pSh
&& pSh
->GetWin() )
918 pSh
->InvalidateWindows( Frm() );
921 // die Seitennummer der Root runterzaehlen.
922 ((SwRootFrm
*)GetUpper())->DecrPhyPageNums();
923 SwPageFrm
*pPg
= (SwPageFrm
*)GetNext();
928 pPg
->DecrPhyPageNum(); //inline --nPhyPageNum
929 pPg
= (SwPageFrm
*)pPg
->GetNext();
933 ::SetLastPage( (SwPageFrm
*)GetPrev() );
935 SwFrm
* pRootFrm
= GetUpper();
937 // Alle Verbindungen kappen.
942 static_cast<SwRootFrm
*>(pRootFrm
)->CheckViewLayout( 0, 0 );
945 /*************************************************************************
947 |* SwPageFrm::Paste()
949 |* Ersterstellung MA 23. Feb. 94
950 |* Letzte Aenderung MA 07. Dec. 94
952 |*************************************************************************/
953 void SwPageFrm::Paste( SwFrm
* pParent
, SwFrm
* pSibling
)
955 ASSERT( pParent
->IsRootFrm(), "Parent ist keine Root." );
956 ASSERT( pParent
, "Kein Parent fuer Paste." );
957 ASSERT( pParent
!= this, "Bin selbst der Parent." );
958 ASSERT( pSibling
!= this, "Bin mein eigener Nachbar." );
959 ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
960 "Bin noch irgendwo angemeldet." );
962 //In den Baum einhaengen.
963 InsertBefore( (SwLayoutFrm
*)pParent
, pSibling
);
965 // die Seitennummer am Root hochzaehlen.
966 ((SwRootFrm
*)GetUpper())->IncrPhyPageNums();
968 SetPhyPageNum( ((SwPageFrm
*)GetPrev())->GetPhyPageNum() + 1 );
971 SwPageFrm
*pPg
= (SwPageFrm
*)GetNext();
976 pPg
->IncrPhyPageNum(); //inline ++nPhyPageNum
977 pPg
->_InvalidatePos();
978 pPg
->InvalidateLayout();
979 pPg
= (SwPageFrm
*)pPg
->GetNext();
983 ::SetLastPage( this );
985 if( Frm().Width() != pParent
->Prt().Width() )
992 static_cast<SwRootFrm
*>(GetUpper())->CheckViewLayout( 0, 0 );
995 /*************************************************************************
997 |* SwPageFrm::PrepareRegisterChg()
999 |* Ersterstellung AMA 22. Jul. 96
1000 |* Letzte Aenderung AMA 22. Jul. 96
1002 |*************************************************************************/
1003 void lcl_PrepFlyInCntRegister( SwCntntFrm
*pFrm
)
1005 pFrm
->Prepare( PREP_REGISTER
);
1006 if( pFrm
->GetDrawObjs() )
1008 for( USHORT i
= 0; i
< pFrm
->GetDrawObjs()->Count(); ++i
)
1010 // --> OD 2004-06-29 #i28701#
1011 SwAnchoredObject
* pAnchoredObj
= (*pFrm
->GetDrawObjs())[i
];
1012 if ( pAnchoredObj
->ISA(SwFlyInCntFrm
) )
1014 SwFlyFrm
* pFly
= static_cast<SwFlyInCntFrm
*>(pAnchoredObj
);
1015 SwCntntFrm
*pCnt
= pFly
->ContainsCntnt();
1018 lcl_PrepFlyInCntRegister( pCnt
);
1019 pCnt
= pCnt
->GetNextCntntFrm();
1027 void SwPageFrm::PrepareRegisterChg()
1029 SwCntntFrm
*pFrm
= FindFirstBodyCntnt();
1032 lcl_PrepFlyInCntRegister( pFrm
);
1033 pFrm
= pFrm
->GetNextCntntFrm();
1034 if( !IsAnLower( pFrm
) )
1037 if( GetSortedObjs() )
1039 for( USHORT i
= 0; i
< GetSortedObjs()->Count(); ++i
)
1041 // --> OD 2004-06-29 #i28701#
1042 SwAnchoredObject
* pAnchoredObj
= (*GetSortedObjs())[i
];
1043 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
1045 SwFlyFrm
*pFly
= static_cast<SwFlyFrm
*>(pAnchoredObj
);
1046 pFrm
= pFly
->ContainsCntnt();
1049 ::lcl_PrepFlyInCntRegister( pFrm
);
1050 pFrm
= pFrm
->GetNextCntntFrm();
1057 /*************************************************************************
1059 |* SwFrm::CheckPageDescs()
1061 |* Beschreibung Prueft alle Seiten ab der uebergebenen, daraufhin,
1062 |* ob sie das richtige FrmFmt verwenden. Wenn 'falsche' Seiten
1063 |* aufgespuehrt werden, so wird versucht die Situation moeglichst
1064 |* einfache zu bereinigen.
1066 |* Ersterstellung MA 10. Feb. 93
1067 |* Letzte Aenderung MA 18. Apr. 96
1069 |*************************************************************************/
1070 void SwFrm::CheckPageDescs( SwPageFrm
*pStart
, BOOL bNotifyFields
)
1072 ASSERT( pStart
, "Keine Startpage." );
1074 ViewShell
*pSh
= pStart
->GetShell();
1075 SwViewImp
*pImp
= pSh
? pSh
->Imp() : 0;
1077 if ( pImp
&& pImp
->IsAction() && !pImp
->GetLayAction().IsCheckPages() )
1079 pImp
->GetLayAction().SetCheckPageNum( pStart
->GetPhyPageNum() );
1083 //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
1084 //die Seitenposition an, _ab_ der invalidiert werden soll.
1085 SwTwips nDocPos
= LONG_MAX
;
1087 SwRootFrm
*pRoot
= (SwRootFrm
*)pStart
->GetUpper();
1088 SwDoc
* pDoc
= pStart
->GetFmt()->GetDoc();
1089 const BOOL bFtns
= 0 != pDoc
->GetFtnIdxs().Count();
1091 SwPageFrm
*pPage
= pStart
;
1092 if( pPage
->GetPrev() && ((SwPageFrm
*)pPage
->GetPrev())->IsEmptyPage() )
1093 pPage
= (SwPageFrm
*)pPage
->GetPrev();
1096 //gewuenschten PageDesc und FrmFmt festellen.
1097 SwPageDesc
*pDesc
= pPage
->FindPageDesc();
1098 BOOL bCheckEmpty
= pPage
->IsEmptyPage();
1099 BOOL bActOdd
= pPage
->OnRightPage();
1100 BOOL bOdd
= pPage
->WannaRightPage();
1101 SwFrmFmt
*pFmtWish
= bOdd
? pDesc
->GetRightFmt()
1102 : pDesc
->GetLeftFmt();
1104 if ( bActOdd
!= bOdd
||
1105 pDesc
!= pPage
->GetPageDesc() || //falscher Desc
1106 ( pFmtWish
!= pPage
->GetFmt() && //falsches Format und
1107 ( !pPage
->IsEmptyPage() || pFmtWish
) //nicht Leerseite
1111 //Wenn wir schon ein Seite veraendern muessen kann das eine
1112 //Weile dauern, deshalb hier den WaitCrsr pruefen.
1114 pImp
->CheckWaitCrsr();
1116 //Ab hier muessen die Felder invalidiert werden!
1117 if ( nDocPos
== LONG_MAX
)
1118 nDocPos
= pPage
->GetPrev() ?
1119 pPage
->GetPrev()->Frm().Top() : pPage
->Frm().Top();
1122 //1. Wir haben eine EmptyPage und wollen eine "Normalseite".
1123 // ->EmptyPage wegwerfen und weiter mit der naechsten.
1124 //2. Wir haben eine EmptyPage und wollen eine EmptyPage mit
1125 // anderem Descriptor.
1126 // ->Descriptor austauschen.
1127 //3. Wir haben eine "Normalseite" und wollen eine EmptyPage.
1128 // ->Emptypage einfuegen, nicht aber wenn die Vorseite
1129 // bereits eine EmptyPage ist -> 6.
1130 //4. Wir haben eine "Normalseite" und wollen eine "Normalseite"
1131 // mit anderem Descriptor
1132 // ->Descriptor und Format austauschen
1133 //5. Wir haben eine "Normalseite" und wollen eine "Normalseite"
1134 // mit anderem Format
1135 // ->Format austauschen.
1136 //6. Wir haben kein Wunschformat erhalten, also nehmen wir das
1137 // 'andere' Format (rechts/links) des PageDesc.
1139 if ( pPage
->IsEmptyPage() && ( pFmtWish
|| //1.
1140 ( !bOdd
&& !pPage
->GetPrev() ) ) )
1142 SwPageFrm
*pTmp
= (SwPageFrm
*)pPage
->GetNext();
1145 if ( pStart
== pPage
)
1150 else if ( pPage
->IsEmptyPage() && !pFmtWish
&& //2.
1151 pDesc
!= pPage
->GetPageDesc() )
1153 pPage
->SetPageDesc( pDesc
, 0 );
1155 else if ( !pPage
->IsEmptyPage() && //3.
1157 ( ( !pPage
->GetPrev() && !bOdd
) ||
1158 ( pPage
->GetPrev() &&
1159 !((SwPageFrm
*)pPage
->GetPrev())->IsEmptyPage() )
1163 if ( pPage
->GetPrev() )
1164 pDesc
= ((SwPageFrm
*)pPage
->GetPrev())->GetPageDesc();
1165 SwPageFrm
*pTmp
= new SwPageFrm( pDoc
->GetEmptyPageFmt(),pDesc
);
1166 pTmp
->Paste( pRoot
, pPage
);
1167 pTmp
->PreparePage( FALSE
);
1170 else if ( pPage
->GetPageDesc() != pDesc
) //4.
1172 SwPageDesc
*pOld
= pPage
->GetPageDesc();
1173 pPage
->SetPageDesc( pDesc
, pFmtWish
);
1176 //Wenn sich bestimmte Werte der FtnInfo veraendert haben
1177 //muss etwas passieren. Wir versuchen den Schaden zu
1179 //Wenn die Seiten keinen FtnCont hat, ist zwar theoretisches
1180 //ein Problem denkbar, aber das ignorieren wir mit aller Kraft.
1181 //Bei Aenderungen hoffen wir mal, dass eine Invalidierung
1182 //ausreicht, denn alles andere wuerde viel Kraft kosten.
1183 SwFtnContFrm
*pCont
= pPage
->FindFtnCont();
1184 if ( pCont
&& !(pOld
->GetFtnInfo() == pDesc
->GetFtnInfo()) )
1185 pCont
->_InvalidateAll();
1188 else if ( pFmtWish
&& pPage
->GetFmt() != pFmtWish
) //5.
1190 pPage
->SetFrmFmt( pFmtWish
);
1192 else if ( !pFmtWish
) //6.
1194 //Format mit verdrehter Logic besorgen.
1195 pFmtWish
= bOdd
? pDesc
->GetLeftFmt() : pDesc
->GetRightFmt();
1196 if ( pPage
->GetFmt() != pFmtWish
)
1197 pPage
->SetFrmFmt( pFmtWish
);
1202 ASSERT( FALSE
, "CheckPageDescs, missing solution" );
1208 //Es kann noch sein, dass die Leerseite schlicht ueberflussig ist.
1209 //Obiger Algorithmus kann dies leider nicht feststellen.
1210 //Eigentlich muesste die Leerseite einfach praeventiv entfernt
1211 //werden; sie wuerde ja ggf. wieder eingefuegt.
1212 //Die EmptyPage ist genau dann ueberfluessig, wenn die Folgeseite
1213 //auch ohne sie auskommt. Dazu muessen wir uns die Verhaeltnisse
1214 //genauer ansehen. Wir bestimmen den PageDesc und die virtuelle
1215 //Seitennummer manuell.
1216 SwPageFrm
*pPg
= (SwPageFrm
*)pPage
->GetNext();
1217 if( !pPg
|| pPage
->OnRightPage() == pPg
->WannaRightPage() )
1219 //Die Folgeseite hat kein Problem ein FrmFmt zu finden oder keinen
1220 //Nachfolger, also ist die Leerseite ueberfluessig.
1221 SwPageFrm
*pTmp
= (SwPageFrm
*)pPage
->GetNext();
1224 if ( pStart
== pPage
)
1230 pPage
= (SwPageFrm
*)pPage
->GetNext();
1233 pRoot
->SetAssertFlyPages();
1234 pRoot
->AssertPageFlys( pStart
);
1236 if ( bNotifyFields
&& (!pImp
|| !pImp
->IsUpdateExpFlds()) )
1238 SwDocPosUpdate
aMsgHnt( nDocPos
);
1239 pDoc
->UpdatePageFlds( &aMsgHnt
);
1243 //Ein paar Pruefungen muessen schon erlaubt sein.
1245 //1. Keine zwei EmptyPages hintereinander.
1246 //2. Alle PageDescs richtig?
1247 BOOL bEmpty
= FALSE
;
1248 SwPageFrm
*pPg
= pStart
;
1251 if ( pPg
->IsEmptyPage() )
1255 ASSERT( FALSE
, "Doppelte Leerseiten." );
1256 break; //Einmal reicht.
1263 //MA 21. Jun. 95: Kann zu testzwecken 'rein, ist aber bei zyklen durchaus
1264 //moeglich: Ein paar Seiten, auf der ersten 'erste Seite' anwenden,
1265 //rechte als folge der ersten, linke als folge der rechten, rechte als
1267 // ASSERT( pPg->GetPageDesc() == pPg->FindPageDesc(),
1268 // "Seite mit falschem Descriptor." );
1270 pPg
= (SwPageFrm
*)pPg
->GetNext();
1275 /*************************************************************************
1277 |* SwFrm::InsertPage()
1280 |* Ersterstellung MA 10. Feb. 93
1281 |* Letzte Aenderung MA 27. Jul. 93
1283 |*************************************************************************/
1284 SwPageFrm
*SwFrm::InsertPage( SwPageFrm
*pPrevPage
, BOOL bFtn
)
1286 SwRootFrm
*pRoot
= (SwRootFrm
*)pPrevPage
->GetUpper();
1287 SwPageFrm
*pSibling
= (SwPageFrm
*)pRoot
->GetLower();
1288 SwPageDesc
*pDesc
= pSibling
->GetPageDesc();
1290 pSibling
= (SwPageFrm
*)pPrevPage
->GetNext();
1291 //Rechte (ungerade) oder linke (gerade) Seite einfuegen?
1292 BOOL bNextOdd
= !pPrevPage
->OnRightPage();
1293 BOOL bWishedOdd
= bNextOdd
;
1295 //Welcher PageDesc gilt?
1296 //Bei CntntFrm der aus dem Format wenn einer angegeben ist,
1297 //der Follow vom bereits in der PrevPage gueltigen sonst.
1299 if ( IsFlowFrm() && !SwFlowFrm::CastFlowFrm( this )->IsFollow() )
1300 { SwFmtPageDesc
&rDesc
= (SwFmtPageDesc
&)GetAttrSet()->GetPageDesc();
1301 pDesc
= rDesc
.GetPageDesc();
1302 if ( rDesc
.GetNumOffset() )
1304 bWishedOdd
= rDesc
.GetNumOffset() % 2 ? TRUE
: FALSE
;
1305 //Die Gelegenheit nutzen wir um das Flag an der Root zu pflegen.
1306 pRoot
->SetVirtPageNum( TRUE
);
1310 pDesc
= pPrevPage
->GetPageDesc()->GetFollow();
1312 ASSERT( pDesc
, "Missing PageDesc" );
1313 if( !(bWishedOdd
? pDesc
->GetRightFmt() : pDesc
->GetLeftFmt()) )
1314 bWishedOdd
= !bWishedOdd
;
1316 SwDoc
*pDoc
= pPrevPage
->GetFmt()->GetDoc();
1318 BOOL bCheckPages
= FALSE
;
1319 //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben eine
1320 //Leerseite einfuegen.
1321 if( bWishedOdd
!= bNextOdd
)
1322 { pFmt
= pDoc
->GetEmptyPageFmt();
1323 SwPageDesc
*pTmpDesc
= pPrevPage
->GetPageDesc();
1324 SwPageFrm
*pPage
= new SwPageFrm( pFmt
, pTmpDesc
);
1325 pPage
->Paste( pRoot
, pSibling
);
1326 pPage
->PreparePage( bFtn
);
1327 //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
1328 //Es sei denn, es ist eine Fussnotenseite
1329 if ( pSibling
&& !pSibling
->IsFtnPage() &&
1330 !pSibling
->FindFirstBodyCntnt() )
1332 SwPageFrm
*pDel
= pSibling
;
1333 pSibling
= (SwPageFrm
*)pSibling
->GetNext();
1334 if ( pDoc
->GetFtnIdxs().Count() )
1335 pRoot
->RemoveFtns( pDel
, TRUE
);
1342 pFmt
= bWishedOdd
? pDesc
->GetRightFmt() : pDesc
->GetLeftFmt();
1343 ASSERT( pFmt
, "Descriptor without format." );
1344 SwPageFrm
*pPage
= new SwPageFrm( pFmt
, pDesc
);
1345 pPage
->Paste( pRoot
, pSibling
);
1346 pPage
->PreparePage( bFtn
);
1347 //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
1348 //Es sei denn es ist eine Fussnotenseite.
1349 if ( pSibling
&& !pSibling
->IsFtnPage() &&
1350 !pSibling
->FindFirstBodyCntnt() )
1352 SwPageFrm
*pDel
= pSibling
;
1353 pSibling
= (SwPageFrm
*)pSibling
->GetNext();
1354 if ( pDoc
->GetFtnIdxs().Count() )
1355 pRoot
->RemoveFtns( pDel
, TRUE
);
1366 CheckPageDescs( pSibling
, FALSE
);
1367 ViewShell
*pSh
= GetShell();
1368 SwViewImp
*pImp
= pSh
? pSh
->Imp() : 0;
1369 if ( pImp
&& pImp
->IsAction() && !pImp
->GetLayAction().IsCheckPages() )
1371 const USHORT nNum
= pImp
->GetLayAction().GetCheckPageNum();
1372 if ( nNum
== pPrevPage
->GetPhyPageNum() + 1 )
1373 pImp
->GetLayAction().SetCheckPageNumDirect(
1374 pSibling
->GetPhyPageNum() );
1379 pRoot
->AssertPageFlys( pSibling
);
1382 //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
1383 //die Seitenposition an, _ab_ der invalidiert werden soll.
1384 ViewShell
*pSh
= GetShell();
1385 if ( !pSh
|| !pSh
->Imp()->IsUpdateExpFlds() )
1387 SwDocPosUpdate
aMsgHnt( pPrevPage
->Frm().Top() );
1388 pDoc
->UpdatePageFlds( &aMsgHnt
);
1393 // false = right, true = left
1394 bool SwPageFrm::MarginSide() const
1396 if (!GetShell() || GetShell()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
))
1400 const bool bLTR
= GetUpper() ? static_cast<const SwRootFrm
*>(GetUpper())->IsLeftToRightViewLayout() : true;
1401 const bool bBookMode
= GetShell()->GetViewOptions()->IsViewLayoutBookMode();
1402 const bool bRightSidebar
= bLTR
? (!bBookMode
|| OnRightPage()) : (bBookMode
&& !OnRightPage());
1404 return !bRightSidebar
;
1408 /*************************************************************************
1410 |* SwRootFrm::GrowFrm()
1412 |* Ersterstellung MA 30. Jul. 92
1413 |* Letzte Aenderung MA 05. May. 94
1415 |*************************************************************************/
1417 SwTwips
SwRootFrm::GrowFrm( SwTwips nDist
, BOOL bTst
, BOOL
)
1420 Frm().SSize().Height() += nDist
;
1423 /*************************************************************************
1425 |* SwRootFrm::ShrinkFrm()
1427 |* Ersterstellung MA 30. Jul. 92
1428 |* Letzte Aenderung MA 05. May. 94
1430 |*************************************************************************/
1431 SwTwips
SwRootFrm::ShrinkFrm( SwTwips nDist
, BOOL bTst
, BOOL
)
1433 ASSERT( nDist
>= 0, "nDist < 0." );
1434 ASSERT( nDist
<= Frm().Height(), "nDist > als aktuelle Groesse." );
1437 Frm().SSize().Height() -= nDist
;
1441 /*************************************************************************
1443 |* SwRootFrm::RemoveSuperfluous()
1445 |* Beschreibung: Entfernung von ueberfluessigen Seiten.
1446 |* Arbeitet nur wenn das Flag bCheckSuperfluous gesetzt ist.
1447 |* Definition: Eine Seite ist genau dann leer, wenn der
1448 |* Body-Textbereich keinen CntntFrm enthaelt, aber nicht, wenn noch
1449 |* mindestens ein Fly an der Seite klebt.
1450 |* Die Seite ist auch dann nicht leer, wenn sie noch eine
1451 |* Fussnote enthaelt.
1452 |* Es muss zweimal angesetzt werden um leeren Seiten aufzuspueren:
1453 |* - einmal fuer die Endnotenseiten.
1454 |* - und einmal fuer die Seiten des Bodytextes.
1456 |* Ersterstellung MA 20. May. 92
1457 |* Letzte Aenderung MA 10. Jan. 95
1459 |*************************************************************************/
1460 void SwRootFrm::RemoveSuperfluous()
1462 if ( !IsSuperfluous() )
1464 bCheckSuperfluous
= FALSE
;
1466 SwPageFrm
*pPage
= GetLastPage();
1467 long nDocPos
= LONG_MAX
;
1469 //Jetzt wird fuer die jeweils letzte Seite geprueft ob sie leer ist
1470 //bei der ersten nicht leeren Seite wird die Schleife beendet.
1473 bool bExistEssentialObjs
= ( 0 != pPage
->GetSortedObjs() );
1474 if ( bExistEssentialObjs
)
1476 //Nur weil die Seite Flys hat sind wir noch lange nicht fertig,
1477 //denn wenn alle Flys an generischem Inhalt haengen, so ist sie
1478 //trotzdem ueberfluessig (Ueberpruefung auf DocBody sollte reichen).
1479 // OD 19.06.2003 #108784# - consider that drawing objects in
1480 // header/footer are supported now.
1481 bool bOnlySuperfluosObjs
= true;
1482 SwSortedObjs
&rObjs
= *pPage
->GetSortedObjs();
1483 for ( USHORT i
= 0; bOnlySuperfluosObjs
&& i
< rObjs
.Count(); ++i
)
1485 // --> OD 2004-06-29 #i28701#
1486 SwAnchoredObject
* pAnchoredObj
= rObjs
[i
];
1487 // OD 2004-01-19 #110582# - do not consider hidden objects
1488 if ( pPage
->GetFmt()->GetDoc()->IsVisibleLayerId(
1489 pAnchoredObj
->GetDrawObj()->GetLayer() ) &&
1490 !pAnchoredObj
->GetAnchorFrm()->FindFooterOrHeader() )
1492 bOnlySuperfluosObjs
= false;
1496 bExistEssentialObjs
= !bOnlySuperfluosObjs
;
1499 // OD 19.06.2003 #108784# - optimization: check first, if essential objects
1501 const SwLayoutFrm
* pBody
= 0;
1502 if ( bExistEssentialObjs
||
1503 pPage
->FindFtnCont() ||
1504 ( 0 != ( pBody
= pPage
->FindBodyCont() ) &&
1505 ( pBody
->ContainsCntnt() ||
1506 // --> FME 2005-05-18 #i47580#
1507 // Do not delete page if there's an empty tabframe
1508 // left. I think it might be correct to use ContainsAny()
1509 // instead of ContainsCntnt() to cover the empty-table-case,
1510 // but I'm not fully sure, since ContainsAny() also returns
1511 // SectionFrames. Therefore I prefer to do it the safe way:
1512 ( pBody
->Lower() && pBody
->Lower()->IsTabFrm() ) ) ) )
1515 if ( pPage
->IsFtnPage() )
1517 while ( pPage
->IsFtnPage() )
1519 pPage
= (SwPageFrm
*)pPage
->GetPrev();
1520 ASSERT( pPage
, "Nur noch Endnotenseiten uebrig." );
1530 SwPageFrm
*pEmpty
= pPage
;
1531 pPage
= (SwPageFrm
*)pPage
->GetPrev();
1532 if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
1533 RemoveFtns( pEmpty
, TRUE
);
1536 nDocPos
= pPage
? pPage
->Frm().Top() : 0;
1540 ViewShell
*pSh
= GetShell();
1541 if ( nDocPos
!= LONG_MAX
&&
1542 (!pSh
|| !pSh
->Imp()->IsUpdateExpFlds()) )
1544 SwDocPosUpdate
aMsgHnt( nDocPos
);
1545 GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt
);
1549 /*************************************************************************
1551 |* SwRootFrm::AssertFlyPages()
1553 |* Beschreibung Stellt sicher, dass genuegend Seiten vorhanden
1554 |* sind, damit alle Seitengebundenen Rahmen und DrawObject
1555 |* untergebracht sind.
1557 |* Ersterstellung MA 27. Jul. 93
1558 |* Letzte Aenderung MA 24. Apr. 97
1560 |*************************************************************************/
1561 void SwRootFrm::AssertFlyPages()
1563 if ( !IsAssertFlyPages() )
1565 bAssertFlyPages
= FALSE
;
1567 SwDoc
*pDoc
= GetFmt()->GetDoc();
1568 const SwSpzFrmFmts
*pTbl
= pDoc
->GetSpzFrmFmts();
1570 //Auf welche Seite will der 'letzte' Fly?
1574 for ( i
= 0; i
< pTbl
->Count(); ++i
)
1576 const SwFmtAnchor
&rAnch
= (*pTbl
)[i
]->GetAnchor();
1577 if ( !rAnch
.GetCntntAnchor() && nMaxPg
< rAnch
.GetPageNum() )
1578 nMaxPg
= rAnch
.GetPageNum();
1580 //Wieviele Seiten haben wir derzeit?
1581 SwPageFrm
*pPage
= (SwPageFrm
*)Lower();
1582 while ( pPage
&& pPage
->GetNext() &&
1583 !((SwPageFrm
*)pPage
->GetNext())->IsFtnPage() )
1585 pPage
= (SwPageFrm
*)pPage
->GetNext();
1588 if ( nMaxPg
> pPage
->GetPhyPageNum() )
1590 //Die Seiten werden ausgehend von der letzten Seite konsequent
1591 //nach den Regeln der PageDescs weitergefuehrt.
1592 BOOL bOdd
= pPage
->GetPhyPageNum() % 2 ? TRUE
: FALSE
;
1593 SwPageDesc
*pDesc
= pPage
->GetPageDesc();
1594 SwFrm
*pSibling
= pPage
->GetNext();
1595 for ( i
= pPage
->GetPhyPageNum(); i
< nMaxPg
; ++i
)
1597 if ( !(bOdd
? pDesc
->GetRightFmt() : pDesc
->GetLeftFmt()) )
1599 //Leerseite einfuegen, die Flys werden aber erst von
1600 //der naechsten Seite aufgenommen!
1601 pPage
= new SwPageFrm( pDoc
->GetEmptyPageFmt(), pDesc
);
1602 pPage
->Paste( this, pSibling
);
1603 pPage
->PreparePage( FALSE
);
1604 bOdd
= bOdd
? FALSE
: TRUE
;
1608 SwPageFrm( (bOdd
? pDesc
->GetRightFmt() :
1609 pDesc
->GetLeftFmt()), pDesc
);
1610 pPage
->Paste( this, pSibling
);
1611 pPage
->PreparePage( FALSE
);
1612 bOdd
= bOdd
? FALSE
: TRUE
;
1613 pDesc
= pDesc
->GetFollow();
1615 //Jetzt koennen die Endnotenseiten natuerlich wieder krumm sein;
1616 //in diesem Fall werden sie vernichtet.
1617 if ( pDoc
->GetFtnIdxs().Count() )
1619 pPage
= (SwPageFrm
*)Lower();
1620 while ( pPage
&& !pPage
->IsFtnPage() )
1621 pPage
= (SwPageFrm
*)pPage
->GetNext();
1625 SwPageDesc
*pTmpDesc
= pPage
->FindPageDesc();
1626 bOdd
= pPage
->OnRightPage();
1627 if ( pPage
->GetFmt() !=
1628 (bOdd
? pTmpDesc
->GetRightFmt() : pTmpDesc
->GetLeftFmt()) )
1629 RemoveFtns( pPage
, FALSE
, TRUE
);
1635 /*************************************************************************
1637 |* SwRootFrm::AssertPageFlys()
1639 |* Beschreibung Stellt sicher, dass ab der uebergebenen Seite
1640 |* auf allen Seiten die Seitengebunden Objecte auf der richtigen
1641 |* Seite (Seitennummer stehen).
1643 |* Ersterstellung MA 02. Nov. 94
1644 |* Letzte Aenderung MA 10. Aug. 95
1646 |*************************************************************************/
1647 void SwRootFrm::AssertPageFlys( SwPageFrm
*pPage
)
1651 if ( pPage
->GetSortedObjs() )
1653 pPage
->GetSortedObjs();
1655 pPage
->GetSortedObjs() && USHORT(i
) < pPage
->GetSortedObjs()->Count();
1658 // --> OD 2004-06-29 #i28701#
1659 SwFrmFmt
& rFmt
= (*pPage
->GetSortedObjs())[i
]->GetFrmFmt();
1660 const SwFmtAnchor
&rAnch
= rFmt
.GetAnchor();
1661 const USHORT nPg
= rAnch
.GetPageNum();
1662 if ( rAnch
.GetAnchorId() == FLY_PAGE
&&
1663 nPg
!= pPage
->GetPhyPageNum() )
1665 //Das er auf der falschen Seite steht muss noch nichts
1666 //heissen, wenn er eigentlich auf der Vorseite
1667 //stehen will und diese eine EmptyPage ist.
1668 if( nPg
&& !(pPage
->GetPhyPageNum()-1 == nPg
&&
1669 ((SwPageFrm
*)pPage
->GetPrev())->IsEmptyPage()) )
1671 //Umhaengen kann er sich selbst, indem wir ihm
1672 //einfach ein Modify mit seinem AnkerAttr schicken.
1674 rFmt
.SwModify::Modify( 0, (SwFmtAnchor
*)&rAnch
);
1676 const sal_uInt32 nCnt
= pPage
->GetSortedObjs()->Count();
1677 rFmt
.SwModify::Modify( 0, (SwFmtAnchor
*)&rAnch
);
1678 ASSERT( !pPage
->GetSortedObjs() ||
1679 nCnt
!= pPage
->GetSortedObjs()->Count(),
1680 "Kann das Obj nicht umhaengen." );
1687 pPage
= (SwPageFrm
*)pPage
->GetNext();
1691 /*************************************************************************
1693 |* SwRootFrm::ChgSize()
1695 |* Ersterstellung MA 24. Jul. 92
1696 |* Letzte Aenderung MA 13. Aug. 93
1698 |*************************************************************************/
1699 Size
SwRootFrm::ChgSize( const Size
& aNewSize
)
1701 Frm().SSize() = aNewSize
;
1704 return Frm().SSize();
1707 /*************************************************************************
1709 |* SwRootFrm::MakeAll()
1711 |* Ersterstellung MA 17. Nov. 92
1712 |* Letzte Aenderung MA 19. Apr. 93
1714 |*************************************************************************/
1715 void SwRootFrm::MakeAll()
1719 aFrm
.Pos().X() = aFrm
.Pos().Y() = DOCUMENTBORDER
;
1721 if ( !bValidPrtArea
)
1722 { bValidPrtArea
= TRUE
;
1723 aPrt
.Pos().X() = aPrt
.Pos().Y() = 0;
1724 aPrt
.SSize( aFrm
.SSize() );
1727 //SSize wird von den Seiten (Cut/Paste) eingestellt.
1731 /*************************************************************************
1733 |* SwRootFrm::ImplInvalidateBrowseWidth()
1735 |* Ersterstellung MA 08. Jun. 96
1736 |* Letzte Aenderung MA 08. Jun. 96
1738 |*************************************************************************/
1739 void SwRootFrm::ImplInvalidateBrowseWidth()
1741 bBrowseWidthValid
= FALSE
;
1742 SwFrm
*pPg
= Lower();
1745 pPg
->InvalidateSize();
1746 pPg
= pPg
->GetNext();
1750 /*************************************************************************
1752 |* SwRootFrm::ImplCalcBrowseWidth()
1754 |* Ersterstellung MA 07. Jun. 96
1755 |* Letzte Aenderung MA 13. Jun. 96
1757 |*************************************************************************/
1758 void SwRootFrm::ImplCalcBrowseWidth()
1760 ASSERT( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
),
1761 "CalcBrowseWidth and not in BrowseView" );
1763 //Die (minimale) Breite wird von Rahmen, Tabellen und Zeichenobjekten
1764 //bestimmt. Die Breite wird nicht anhand ihrer aktuellen Groessen bestimmt,
1765 //sondern anhand der Attribute. Es interessiert also nicht wie breit sie
1766 //sind, sondern wie breit sie sein wollen.
1767 //Rahmen und Zeichenobjekte innerhalb ander Objekte (Rahmen, Tabellen)
1769 //Seitenraender und Spalten werden hier nicht beruecksichtigt.
1771 SwFrm
*pFrm
= ContainsCntnt();
1772 while ( pFrm
&& !pFrm
->IsInDocBody() )
1773 pFrm
= ((SwCntntFrm
*)pFrm
)->GetNextCntntFrm();
1777 bBrowseWidthValid
= TRUE
;
1778 ViewShell
*pSh
= GetShell();
1780 ? MINLAY
+ 2 * pSh
->GetOut()->
1781 PixelToLogic( pSh
->GetBrowseBorder() ).Width()
1785 if ( pFrm
->IsInTab() )
1786 pFrm
= pFrm
->FindTabFrm();
1788 if ( pFrm
->IsTabFrm() &&
1789 !((SwLayoutFrm
*)pFrm
)->GetFmt()->GetFrmSize().GetWidthPercent() )
1791 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), pFrm
);
1792 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
1793 const SwFmtHoriOrient
&rHori
= rAttrs
.GetAttrSet().GetHoriOrient();
1794 long nWidth
= rAttrs
.GetSize().Width();
1795 if ( nWidth
< USHRT_MAX
-2000 && //-2000, weil bei Randeinstellung per
1796 //Zuppeln das USHRT_MAX verlorengeht!
1797 text::HoriOrientation::FULL
!= rHori
.GetHoriOrient() )
1799 const SwHTMLTableLayout
*pLayoutInfo
=
1800 ((const SwTabFrm
*)pFrm
)->GetTable()
1801 ->GetHTMLTableLayout();
1803 nWidth
= Min( nWidth
, pLayoutInfo
->GetBrowseWidthMin() );
1805 switch ( rHori
.GetHoriOrient() )
1807 case text::HoriOrientation::NONE
:
1808 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
1809 nWidth
+= rAttrs
.CalcLeft( pFrm
) + rAttrs
.CalcRight( pFrm
);
1811 case text::HoriOrientation::LEFT_AND_WIDTH
:
1812 nWidth
+= rAttrs
.CalcLeft( pFrm
);
1818 nBrowseWidth
= Max( nBrowseWidth
, nWidth
);
1821 else if ( pFrm
->GetDrawObjs() )
1823 for ( USHORT i
= 0; i
< pFrm
->GetDrawObjs()->Count(); ++i
)
1825 // --> OD 2004-06-29 #i28701#
1826 SwAnchoredObject
* pAnchoredObj
= (*pFrm
->GetDrawObjs())[i
];
1827 const SwFrmFmt
& rFmt
= pAnchoredObj
->GetFrmFmt();
1828 const BOOL bFly
= pAnchoredObj
->ISA(SwFlyFrm
);
1830 WEIT_WECH
== pAnchoredObj
->GetObjRect().Width()||
1831 rFmt
.GetFrmSize().GetWidthPercent() )
1835 switch ( rFmt
.GetAnchor().GetAnchorId() )
1838 nWidth
= bFly
? rFmt
.GetFrmSize().GetWidth() :
1839 pAnchoredObj
->GetObjRect().Width();
1843 // --> FME 2004-09-13 #i33170#
1844 // Reactivated old code because
1845 // nWidth = pAnchoredObj->GetObjRect().Right()
1846 // gives wrong results for objects that are still
1847 // at position WEIT_WECH.
1850 nWidth
= rFmt
.GetFrmSize().GetWidth();
1851 const SwFmtHoriOrient
&rHori
= rFmt
.GetHoriOrient();
1852 switch ( rHori
.GetHoriOrient() )
1854 case text::HoriOrientation::NONE
:
1855 nWidth
+= rHori
.GetPos();
1857 case text::HoriOrientation::INSIDE
:
1858 case text::HoriOrientation::LEFT
:
1859 if ( text::RelOrientation::PRINT_AREA
== rHori
.GetRelationOrient() )
1860 nWidth
+= pFrm
->Prt().Left();
1867 //Fuer Zeichenobjekte ist die Auswahl sehr klein,
1868 //weil sie keine Attribute haben, also durch ihre
1869 //aktuelle Groesse bestimmt werden.
1870 nWidth
= pAnchoredObj
->GetObjRect().Right() -
1871 pAnchoredObj
->GetDrawObj()->GetAnchorPos().X();
1875 default: /* do nothing */;
1877 nBrowseWidth
= Max( nBrowseWidth
, nWidth
);
1880 pFrm
= pFrm
->FindNextCnt();
1884 /*************************************************************************
1886 |* SwRootFrm::StartAllAction()
1888 |* Ersterstellung MA 08. Mar. 98
1889 |* Letzte Aenderung MA 08. Mar. 98
1891 |*************************************************************************/
1893 void SwRootFrm::StartAllAction()
1895 ViewShell
*pSh
= GetCurrShell();
1898 { if ( pSh
->ISA( SwCrsrShell
) )
1899 ((SwCrsrShell
*)pSh
)->StartAction();
1902 pSh
= (ViewShell
*)pSh
->GetNext();
1904 } while ( pSh
!= GetCurrShell() );
1907 void SwRootFrm::EndAllAction( BOOL bVirDev
)
1909 ViewShell
*pSh
= GetCurrShell();
1913 const BOOL bOldEndActionByVirDev
= pSh
->IsEndActionByVirDev();
1914 pSh
->SetEndActionByVirDev( bVirDev
);
1915 if ( pSh
->ISA( SwCrsrShell
) )
1917 ((SwCrsrShell
*)pSh
)->EndAction();
1918 ((SwCrsrShell
*)pSh
)->CallChgLnk();
1919 if ( pSh
->ISA( SwFEShell
) )
1920 ((SwFEShell
*)pSh
)->SetChainMarker();
1924 pSh
->SetEndActionByVirDev( bOldEndActionByVirDev
);
1925 pSh
= (ViewShell
*)pSh
->GetNext();
1927 } while ( pSh
!= GetCurrShell() );
1930 void SwRootFrm::UnoRemoveAllActions()
1932 ViewShell
*pSh
= GetCurrShell();
1936 // --> OD 2008-05-16 #i84729#
1937 // No end action, if <ViewShell> instance is currently in its end action.
1938 // Recursives calls to <::EndAction()> are not allowed.
1939 if ( !pSh
->IsInEndAction() )
1941 DBG_ASSERT(!pSh
->GetRestoreActions(), "Restore action count is already set!");
1942 BOOL bCrsr
= pSh
->ISA( SwCrsrShell
);
1943 BOOL bFE
= pSh
->ISA( SwFEShell
);
1944 USHORT nRestore
= 0;
1945 while( pSh
->ActionCount() )
1949 ((SwCrsrShell
*)pSh
)->EndAction();
1950 ((SwCrsrShell
*)pSh
)->CallChgLnk();
1952 ((SwFEShell
*)pSh
)->SetChainMarker();
1958 pSh
->SetRestoreActions(nRestore
);
1961 pSh
->LockView(TRUE
);
1962 pSh
= (ViewShell
*)pSh
->GetNext();
1964 } while ( pSh
!= GetCurrShell() );
1967 void SwRootFrm::UnoRestoreAllActions()
1969 ViewShell
*pSh
= GetCurrShell();
1973 USHORT nActions
= pSh
->GetRestoreActions();
1976 if ( pSh
->ISA( SwCrsrShell
) )
1977 ((SwCrsrShell
*)pSh
)->StartAction();
1981 pSh
->SetRestoreActions(0);
1982 pSh
->LockView(FALSE
);
1983 pSh
= (ViewShell
*)pSh
->GetNext();
1985 } while ( pSh
!= GetCurrShell() );
1988 // PAGES01: Helper functions for SwRootFrm::CheckViewLayout
1989 void lcl_MoveAllLowers( SwFrm
* pFrm
, const Point
& rOffset
);
1991 void lcl_MoveAllLowerObjs( SwFrm
* pFrm
, const Point
& rOffset
)
1993 SwSortedObjs
* pSortedObj
= 0;
1994 const bool bPage
= pFrm
->IsPageFrm();
1997 pSortedObj
= static_cast<SwPageFrm
*>(pFrm
)->GetSortedObjs();
1999 pSortedObj
= pFrm
->GetDrawObjs();
2001 for ( USHORT i
= 0; pSortedObj
&& i
< pSortedObj
->Count(); ++i
)
2003 SwAnchoredObject
* pAnchoredObj
= (*pSortedObj
)[i
];
2005 const SwFrmFmt
& rObjFmt
= pAnchoredObj
->GetFrmFmt();
2006 const SwFmtAnchor
& rAnchor
= rObjFmt
.GetAnchor();
2008 // all except from the as character anchored objects are moved
2009 // when processing the page frame:
2010 const bool bAsChar
= rAnchor
.GetAnchorId() == FLY_IN_CNTNT
;
2011 if ( !bPage
&& !bAsChar
)
2014 SwObjPositioningInProgress
aPosInProgress( *pAnchoredObj
);
2016 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
2018 SwFlyFrm
* pFlyFrm( static_cast<SwFlyFrm
*>(pAnchoredObj
) );
2019 lcl_MoveAllLowers( pFlyFrm
, rOffset
);
2020 pFlyFrm
->NotifyDrawObj();
2021 // --> let the active embedded object be moved
2022 if ( pFlyFrm
->Lower() )
2024 if ( pFlyFrm
->Lower()->IsNoTxtFrm() )
2026 SwCntntFrm
* pCntntFrm
= static_cast<SwCntntFrm
*>(pFlyFrm
->Lower());
2027 ViewShell
*pSh
= pFlyFrm
->Lower()->GetShell();
2030 SwOLENode
* pNode
= pCntntFrm
->GetNode()->GetOLENode();
2033 svt::EmbeddedObjectRef
& xObj
= pNode
->GetOLEObj().GetObject();
2036 ViewShell
* pTmp
= pSh
;
2039 SwFEShell
* pFEShell
= dynamic_cast< SwFEShell
* >( pTmp
);
2041 pFEShell
->MoveObjectIfActive( xObj
, rOffset
);
2042 pTmp
= static_cast<ViewShell
*>( pTmp
->GetNext() );
2043 } while( pTmp
!= pSh
);
2051 else if ( pAnchoredObj
->ISA(SwAnchoredDrawObject
) )
2053 SwAnchoredDrawObject
* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject
*>(pAnchoredObj
) );
2055 // don't touch objects that are not yet positioned:
2056 const bool bNotYetPositioned
= pAnchoredDrawObj
->NotYetPositioned();
2057 if ( bNotYetPositioned
)
2060 const Point aCurrAnchorPos
= pAnchoredDrawObj
->GetDrawObj()->GetAnchorPos();
2061 const Point
aNewAnchorPos( ( aCurrAnchorPos
+ rOffset
) );
2062 pAnchoredDrawObj
->DrawObj()->SetAnchorPos( aNewAnchorPos
);
2063 pAnchoredDrawObj
->SetLastObjRect( pAnchoredDrawObj
->GetObjRect().SVRect() );
2065 // --> OD 2009-08-20 #i92511#
2066 // cache for object rectangle inclusive spaces has to be invalidated.
2067 pAnchoredObj
->InvalidateObjRectWithSpaces();
2072 void lcl_MoveAllLowers( SwFrm
* pFrm
, const Point
& rOffset
)
2074 const SwRect
aFrm( pFrm
->Frm() );
2076 // first move the current frame
2077 pFrm
->Frm().Pos() += rOffset
;
2079 // Don't forget accessibility:
2080 if( pFrm
->IsAccessibleFrm() )
2082 SwRootFrm
*pRootFrm
= pFrm
->FindRootFrm();
2083 if( pRootFrm
&& pRootFrm
->IsAnyShellAccessible() &&
2084 pRootFrm
->GetCurrShell() )
2086 pRootFrm
->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm
, aFrm
);
2090 // the move any objects
2091 lcl_MoveAllLowerObjs( pFrm
, rOffset
);
2093 // finally, for layout frames we have to call this function recursively:
2094 if ( pFrm
->ISA(SwLayoutFrm
) )
2096 SwFrm
* pLowerFrm
= pFrm
->GetLower();
2099 lcl_MoveAllLowers( pLowerFrm
, rOffset
);
2100 pLowerFrm
= pLowerFrm
->GetNext();
2105 // PAGES01: Calculate how the pages have to be positioned
2106 void SwRootFrm::CheckViewLayout( const SwViewOption
* pViewOpt
, const SwRect
* pVisArea
)
2108 // --> OD 2008-07-07 #i91432#
2109 // No calculation of page positions, if only an empty page is present.
2110 // This situation occurs when <SwRootFrm> instance is in construction
2111 // and the document contains only left pages.
2112 if ( Lower()->GetNext() == 0 &&
2113 static_cast<SwPageFrm
*>(Lower())->IsEmptyPage() )
2121 // no early return for bNewPage
2122 if ( mnViewWidth
< 0 )
2127 ASSERT( pViewOpt
, "CheckViewLayout required ViewOptions" )
2129 const USHORT nColumns
= pViewOpt
->GetViewLayoutColumns();
2130 const bool bBookMode
= pViewOpt
->IsViewLayoutBookMode();
2132 if ( nColumns
== mnColumns
&& bBookMode
== mbBookMode
&& pVisArea
->Width() == mnViewWidth
&& !mbSidebarChanged
)
2135 mnColumns
= nColumns
;
2136 mbBookMode
= bBookMode
;
2137 mnViewWidth
= pVisArea
->Width();
2138 mbSidebarChanged
= false;
2141 if( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
2149 const BOOL bOldCallbackActionEnabled
= IsCallbackActionEnabled();
2150 SetCallbackActionEnabled( FALSE
);
2152 maPageRects
.clear();
2154 const long nBorder
= Frm().Pos().X();
2155 const long nVisWidth
= mnViewWidth
- 2 * nBorder
;
2156 const long nGapBetweenPages
= GAPBETWEENPAGES
;
2158 // check how many pages fit into the first page layout row:
2159 SwPageFrm
* pPageFrm
= static_cast<SwPageFrm
*>(Lower());
2161 // will contain the number of pages per row. 0 means that
2162 // the page does not fit.
2163 long nWidthRemain
= nVisWidth
;
2165 // after one row has been processed, these variables contain
2166 // the width of the row and the maxium of the page heights
2167 long nCurrentRowHeight
= 0;
2168 long nCurrentRowWidth
= 0;
2170 // these variables are used to finally set the size of the
2172 long nSumRowHeight
= 0;
2173 SwTwips nMinPageLeft
= TWIPS_MAX
;
2174 SwTwips nMaxPageRight
= 0;
2175 SwPageFrm
* pStartOfRow
= pPageFrm
;
2176 USHORT nNumberOfPagesInRow
= mbBookMode
? 1 : 0; // in book view, start with right page
2177 bool bFirstRow
= true;
2179 bool bPageChanged
= false;
2180 const bool bRTL
= !IsLeftToRightViewLayout();
2181 const SwTwips nSidebarWidth
= SwPageFrm::GetSidebarBorderWidth( GetShell() );
2185 // we consider the current page to be "start of row" if
2186 // 1. it is the first page in the current row or
2187 // 2. it is the second page in the row and the first page is an empty page in non-book view:
2188 const bool bStartOfRow
= pPageFrm
== pStartOfRow
||
2189 ( pStartOfRow
->IsEmptyPage() && pPageFrm
== pStartOfRow
->GetNext() && !mbBookMode
);
2191 const bool bEmptyPage
= pPageFrm
->IsEmptyPage() && !mbBookMode
;
2193 // no half doc border space for first page in each row and
2194 long nPageWidth
= 0;
2195 long nPageHeight
= 0;
2199 const SwFrm
& rFormatPage
= pPageFrm
->GetFormatPage();
2201 nPageWidth
= rFormatPage
.Frm().Width() + nSidebarWidth
+ ((bStartOfRow
|| 1 == (pPageFrm
->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages
);
2202 nPageHeight
= rFormatPage
.Frm().Height() + nGapBetweenPages
;
2207 if ( !pPageFrm
->IsEmptyPage() )
2209 nPageWidth
= pPageFrm
->Frm().Width() + nSidebarWidth
+ (bStartOfRow
? 0 : nGapBetweenPages
);
2210 nPageHeight
= pPageFrm
->Frm().Height() + nGapBetweenPages
;
2215 ++nNumberOfPagesInRow
;
2217 // finish current row if
2218 // 1. in dynamic mode the current page does not fit anymore or
2219 // 2. the current page exceeds the maximum number of columns
2220 bool bRowFinished
= (0 == mnColumns
&& nWidthRemain
< nPageWidth
) ||
2221 (0 != mnColumns
&& mnColumns
< nNumberOfPagesInRow
);
2223 // make sure that at least one page goes to the current row:
2224 if ( !bRowFinished
|| bStartOfRow
)
2226 // current page is allowed to be in current row
2227 nWidthRemain
= nWidthRemain
- nPageWidth
;
2229 nCurrentRowWidth
= nCurrentRowWidth
+ nPageWidth
;
2230 nCurrentRowHeight
= Max( nCurrentRowHeight
, nPageHeight
);
2232 pPageFrm
= static_cast<SwPageFrm
*>(pPageFrm
->GetNext());
2235 bRowFinished
= true;
2240 // pPageFrm now points to the first page in the new row or null
2241 // pStartOfRow points to the first page in the current row
2243 // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
2244 if ( !pPageFrm
&& nWidthRemain
> 0 )
2246 // find last page in current row:
2247 const SwPageFrm
* pLastPageInCurrentRow
= pStartOfRow
;
2248 while( pLastPageInCurrentRow
->GetNext() )
2249 pLastPageInCurrentRow
= static_cast<const SwPageFrm
*>(pLastPageInCurrentRow
->GetNext());
2251 if ( pLastPageInCurrentRow
->IsEmptyPage() )
2252 pLastPageInCurrentRow
= static_cast<const SwPageFrm
*>(pLastPageInCurrentRow
->GetPrev());
2254 // check how many times the last page would still fit into the remaining space:
2255 USHORT nNumberOfVirtualPages
= 0;
2256 const USHORT nMaxNumberOfVirtualPages
= mnColumns
> 0 ? mnColumns
- nNumberOfPagesInRow
: USHRT_MAX
;
2257 SwTwips nRemain
= nWidthRemain
;
2258 SwTwips nVirtualPagesWidth
= 0;
2259 SwTwips nLastPageWidth
= pLastPageInCurrentRow
->Frm().Width() + nSidebarWidth
;
2261 while ( ( mnColumns
> 0 || nRemain
> 0 ) && nNumberOfVirtualPages
< nMaxNumberOfVirtualPages
)
2263 SwTwips nLastPageWidthWithGap
= nLastPageWidth
;
2264 if ( !mbBookMode
|| ( 0 == (nNumberOfVirtualPages
+ nNumberOfPagesInRow
) %2) )
2265 nLastPageWidthWithGap
+= nGapBetweenPages
;
2267 if ( mnColumns
> 0 || nLastPageWidthWithGap
< nRemain
)
2269 ++nNumberOfVirtualPages
;
2270 nVirtualPagesWidth
+= nLastPageWidthWithGap
;
2272 nRemain
= nRemain
- nLastPageWidthWithGap
;
2275 nCurrentRowWidth
= nCurrentRowWidth
+ nVirtualPagesWidth
;
2278 // first page in book mode is always special:
2279 if ( bFirstRow
&& mbBookMode
)
2281 // --> OD 2008-04-08 #i88036#
2282 // nCurrentRowWidth += pStartOfRow->Frm().Width() + nSidebarWidth;
2284 pStartOfRow
->GetFormatPage().Frm().Width() + nSidebarWidth
;
2288 // center page if possible
2289 const long nSizeDiff
= nVisWidth
> nCurrentRowWidth
?
2290 ( nVisWidth
- nCurrentRowWidth
) / 2 :
2293 // adjust positions of pages in current row
2294 long nX
= nSizeDiff
;
2296 const long nRowStart
= nBorder
+ nSizeDiff
;
2297 const long nRowEnd
= nRowStart
+ nCurrentRowWidth
;
2299 if ( bFirstRow
&& mbBookMode
)
2301 // --> OD 2008-04-08 #i88036#
2302 // nX += pStartOfRow->Frm().Width() + nSidebarWidth;
2303 nX
+= pStartOfRow
->GetFormatPage().Frm().Width() + nSidebarWidth
;
2307 SwPageFrm
* pEndOfRow
= pPageFrm
;
2308 SwPageFrm
* pPageToAdjust
= pStartOfRow
;
2312 const SwPageFrm
* pFormatPage
= pPageToAdjust
;
2314 pFormatPage
= &pPageToAdjust
->GetFormatPage();
2316 const SwTwips nCurrentPageWidth
= pFormatPage
->Frm().Width() + (pFormatPage
->IsEmptyPage() ? 0 : nSidebarWidth
);
2317 const Point aOldPagePos
= pPageToAdjust
->Frm().Pos();
2318 const bool bLeftSidebar
= pPageToAdjust
->MarginSide();
2319 const SwTwips nLeftPageAddOffset
= bLeftSidebar
?
2323 Point
aNewPagePos( nBorder
+ nX
, nBorder
+ nSumRowHeight
);
2324 Point
aNewPagePosWithLeftOffset( nBorder
+ nX
+ nLeftPageAddOffset
, nBorder
+ nSumRowHeight
);
2326 // RTL view layout: Calculate mirrored page position
2329 const long nXOffsetInRow
= aNewPagePos
.X() - nRowStart
;
2330 aNewPagePos
.X() = nRowEnd
- nXOffsetInRow
- nCurrentPageWidth
;
2331 aNewPagePosWithLeftOffset
= aNewPagePos
;
2332 aNewPagePosWithLeftOffset
.X() += nLeftPageAddOffset
;
2335 if ( aNewPagePosWithLeftOffset
!= aOldPagePos
)
2337 lcl_MoveAllLowers( pPageToAdjust
, aNewPagePosWithLeftOffset
- aOldPagePos
);
2338 pPageToAdjust
->SetCompletePaint();
2339 bPageChanged
= true;
2342 // calculate area covered by the current page and store to
2343 // maPageRects. This is used e.g., for cursor setting
2344 const bool bFirstColumn
= pPageToAdjust
== pStartOfRow
;
2345 const bool bLastColumn
= pPageToAdjust
->GetNext() == pEndOfRow
;
2346 const bool bLastRow
= !pEndOfRow
;
2348 nMinPageLeft
= Min( nMinPageLeft
, aNewPagePos
.X() );
2349 nMaxPageRight
= Max( nMaxPageRight
, aNewPagePos
.X() + nCurrentPageWidth
);
2351 // border of nGapBetweenPages around the current page:
2352 SwRect
aPageRectWithBorders( aNewPagePos
.X() - nGapBetweenPages
,
2354 pPageToAdjust
->Frm().SSize().Width() + nGapBetweenPages
+ nSidebarWidth
,
2355 nCurrentRowHeight
);
2357 static const long nOuterClickDiff
= 1000000;
2359 // adjust borders for these special cases:
2360 if ( bFirstColumn
&& !bRTL
|| bLastColumn
&& bRTL
)
2361 aPageRectWithBorders
.SubLeft( nOuterClickDiff
);
2362 if ( bLastColumn
&& !bRTL
|| bFirstColumn
&& bRTL
)
2363 aPageRectWithBorders
.AddRight( nOuterClickDiff
);
2365 aPageRectWithBorders
.SubTop( nOuterClickDiff
);
2367 aPageRectWithBorders
.AddBottom( nOuterClickDiff
);
2369 maPageRects
.push_back( aPageRectWithBorders
);
2371 nX
= nX
+ nCurrentPageWidth
;
2372 pPageToAdjust
= static_cast<SwPageFrm
*>(pPageToAdjust
->GetNext());
2374 // distance to next page
2375 if ( pPageToAdjust
&& pPageToAdjust
!= pEndOfRow
)
2377 // in book view, we add the x gap before left (even) pages:
2380 if ( 0 == (pPageToAdjust
->GetPhyPageNum()%2) )
2381 nX
= nX
+ nGapBetweenPages
;
2385 // in non-book view, dont add x gap before
2386 // 1. the last empty page in a row
2387 // 2. after an empty page
2388 const bool bDontAddGap
= ( pPageToAdjust
->IsEmptyPage() && pPageToAdjust
->GetNext() == pEndOfRow
) ||
2389 ( static_cast<SwPageFrm
*>(pPageToAdjust
->GetPrev())->IsEmptyPage() );
2392 nX
= nX
+ nGapBetweenPages
;
2396 while ( pPageToAdjust
!= pEndOfRow
);
2398 // adjust values for root frame size
2399 nSumRowHeight
= nSumRowHeight
+ nCurrentRowHeight
;
2402 nCurrentRowHeight
= 0;
2403 nCurrentRowWidth
= 0;
2404 pStartOfRow
= pEndOfRow
;
2405 nWidthRemain
= nVisWidth
;
2406 nNumberOfPagesInRow
= 0;
2408 } // end row finished
2411 // set size of root frame:
2412 const Size
aOldSize( Frm().SSize() );
2413 const Size
aNewSize( nMaxPageRight
- nBorder
, nSumRowHeight
- nGapBetweenPages
);
2415 if ( bPageChanged
|| aNewSize
!= aOldSize
)
2417 ChgSize( aNewSize
);
2418 ::AdjustSizeChgNotify( this );
2421 ViewShell
* pSh
= GetShell();
2423 if ( pSh
&& pSh
->GetDoc()->GetDocShell() )
2425 pSh
->SetFirstVisPageInvalid();
2426 if (bOldCallbackActionEnabled
)
2428 pSh
->InvalidateWindows( SwRect( 0, 0, LONG_MAX
, LONG_MAX
) );
2429 pSh
->GetDoc()->GetDocShell()->Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED
));
2434 maPagesArea
.Pos( Frm().Pos() );
2435 maPagesArea
.SSize( aNewSize
);
2436 if ( TWIPS_MAX
!= nMinPageLeft
)
2437 maPagesArea
._Left( nMinPageLeft
);
2439 SetCallbackActionEnabled( bOldCallbackActionEnabled
);
2442 bool SwRootFrm::IsLeftToRightViewLayout() const
2444 // Layout direction determined by layout direction of the first page.
2445 // --> OD 2008-04-08 #i88036#
2446 // Only ask a non-empty page frame for its layout direction
2447 // const SwPageFrm* pPage = dynamic_cast<const SwPageFrm*>(Lower());
2448 // return !pPage->IsRightToLeft() && !pPage->IsVertical();
2449 const SwPageFrm
& rPage
=
2450 dynamic_cast<const SwPageFrm
*>(Lower())->GetFormatPage();
2451 return !rPage
.IsRightToLeft() && !rPage
.IsVertical();
2455 /*const SwRect SwRootFrm::GetExtendedPageArea( USHORT nPageNumber ) const
2458 ASSERT( nPageNumber < maPageRects.size(), "No extended page area available" )
2459 if ( nPageNumber < maPageRects.size() )
2460 aRet = maPageRects[ nPageNumber ];
2465 const SwPageFrm
& SwPageFrm::GetFormatPage() const
2467 const SwPageFrm
* pRet
= this;
2468 if ( IsEmptyPage() )
2470 pRet
= static_cast<const SwPageFrm
*>( OnRightPage() ? GetNext() : GetPrev() );
2471 // --> OD 2008-04-08 #i88035#
2472 // Typically a right empty page frame has a next non-empty page frame and
2473 // a left empty page frame has a previous non-empty page frame.
2474 // But under certain cirsumstances this assumption is not true -
2475 // e.g. during insertion of a left page at the end of the document right
2476 // after a left page in an intermediate state a right empty page does not
2477 // have a next page frame.
2480 if ( OnRightPage() )
2482 pRet
= static_cast<const SwPageFrm
*>( GetPrev() );
2486 pRet
= static_cast<const SwPageFrm
*>( GetNext() );
2490 "<SwPageFrm::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash." );