1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_wasm_strip.h>
22 #include <comphelper/lok.hxx>
24 #include <sal/log.hxx>
25 #include <osl/diagnose.h>
26 #include <svl/itemiter.hxx>
27 #include <fmtfsize.hxx>
28 #include <fmthdft.hxx>
29 #include <fmtclds.hxx>
30 #include <fmtpdsc.hxx>
31 #include <fmtornt.hxx>
32 #include <fmtsrnd.hxx>
33 #include <ftninfo.hxx>
34 #include <frmtool.hxx>
35 #include <tgrditem.hxx>
36 #include <viewopt.hxx>
41 #include <frameformats.hxx>
43 #include <viewimp.hxx>
44 #include <pagefrm.hxx>
45 #include <rootfrm.hxx>
46 #include <IDocumentDrawModelAccess.hxx>
47 #include <IDocumentSettingAccess.hxx>
48 #include <IDocumentFieldsAccess.hxx>
49 #include <dcontact.hxx>
51 #include <FrameControlsManager.hxx>
54 #include <bodyfrm.hxx>
58 #include <notxtfrm.hxx>
60 #include <flyfrms.hxx>
61 #include <htmltbl.hxx>
62 #include <pagedesc.hxx>
63 #include <editeng/frmdiritem.hxx>
64 #include <sortedobjs.hxx>
68 using namespace ::com::sun::star
;
70 SwBodyFrame::SwBodyFrame( SwFrameFormat
*pFormat
, SwFrame
* pSib
):
71 SwLayoutFrame( pFormat
, pSib
)
73 mnFrameType
= SwFrameType::Body
;
76 void SwBodyFrame::Format( vcl::RenderContext
* /*pRenderContext*/, const SwBorderAttrs
* )
78 // Formatting of the body is too simple, thus, it gets its own format method.
79 // Borders etc. are not taken into account here.
80 // Width is taken from the PrtArea of the Upper. Height is the height of the
81 // PrtArea of the Upper minus any neighbors (for robustness).
82 // The PrtArea has always the size of the frame.
84 if ( !isFrameAreaSizeValid() )
86 SwTwips nHeight
= GetUpper()->getFramePrintArea().Height();
87 SwTwips nWidth
= GetUpper()->getFramePrintArea().Width();
88 const SwFrame
*pFrame
= GetUpper()->Lower();
93 if( pFrame
->IsVertical() )
94 nWidth
-= pFrame
->getFrameArea().Width();
96 nHeight
-= pFrame
->getFrameArea().Height();
98 pFrame
= pFrame
->GetNext();
106 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
107 aFrm
.Height( nHeight
);
109 if( IsVertical() && !IsVertLR() && nWidth
!= aFrm
.Width() )
111 aFrm
.Pos().setX(aFrm
.Pos().getX() + aFrm
.Width() - nWidth
);
114 aFrm
.Width( nWidth
);
118 if( GetUpper()->IsPageFrame() && static_cast<SwPageFrame
*>(GetUpper())->HasGrid() )
120 SwTextGridItem
const*const pGrid(
121 GetGridItem(static_cast<SwPageFrame
*>(GetUpper())));
125 tools::Long nSum
= pGrid
->GetBaseHeight() + pGrid
->GetRubyHeight();
126 SwRectFnSet
aRectFnSet(this);
127 tools::Long nSize
= aRectFnSet
.GetWidth(getFrameArea());
128 tools::Long nBorder
= 0;
129 if( GRID_LINES_CHARS
== pGrid
->GetGridType() )
131 //for textgrid refactor
132 SwDoc
*pDoc
= GetFormat()->GetDoc();
133 nBorder
= nSize
% (GetGridWidth(*pGrid
, *pDoc
));
138 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
139 aRectFnSet
.SetPosX( aPrt
, nBorder
);
140 aRectFnSet
.SetWidth( aPrt
, nSize
);
142 // Height of body frame:
143 nBorder
= aRectFnSet
.GetHeight(getFrameArea());
145 // Number of possible lines in area of body frame:
146 tools::Long nNumberOfLines
= nBorder
/ nSum
;
147 if( nNumberOfLines
> pGrid
->GetLines() )
148 nNumberOfLines
= pGrid
->GetLines();
150 // Space required for nNumberOfLines lines:
151 nSize
= nNumberOfLines
* nSum
;
155 // #i21774# Footnotes and centering the grid does not work together:
156 const bool bAdjust
= static_cast<SwPageFrame
*>(GetUpper())->GetFormat()->GetDoc()->
157 GetFootnoteIdxs().empty();
159 aRectFnSet
.SetPosY( aPrt
, bAdjust
? nBorder
: 0 );
160 aRectFnSet
.SetHeight( aPrt
, nSize
);
166 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
169 aPrt
.Height( getFrameArea().Height() );
170 aPrt
.Width( getFrameArea().Width() );
173 setFrameAreaSizeValid(true);
174 setFramePrintAreaValid(true);
177 void SwBodyFrame::dumpAsXml(xmlTextWriterPtr writer
) const
179 (void)xmlTextWriterStartElement(writer
, reinterpret_cast<const xmlChar
*>("body"));
180 dumpAsXmlAttributes(writer
);
182 (void)xmlTextWriterStartElement(writer
, BAD_CAST("infos"));
183 dumpInfosAsXml(writer
);
184 (void)xmlTextWriterEndElement(writer
);
185 dumpChildrenAsXml(writer
);
187 (void)xmlTextWriterEndElement(writer
);
190 SwPageFrame::SwPageFrame( SwFrameFormat
*pFormat
, SwFrame
* pSib
, SwPageDesc
*pPgDsc
) :
191 SwFootnoteBossFrame( pFormat
, pSib
),
195 SetDerivedVert( false );
196 SetDerivedR2L( false );
200 SwTextGridItem
const*const pGrid(GetGridItem(this));
206 SetMaxFootnoteHeight( pPgDsc
->GetFootnoteInfo().GetHeight() ?
207 pPgDsc
->GetFootnoteInfo().GetHeight() : LONG_MAX
);
208 mnFrameType
= SwFrameType::Page
;
209 m_bInvalidLayout
= m_bInvalidContent
= m_bInvalidSpelling
= m_bInvalidSmartTags
= m_bInvalidAutoCmplWrds
= m_bInvalidWordCount
= true;
210 m_bInvalidFlyLayout
= m_bInvalidFlyContent
= m_bInvalidFlyInCnt
= m_bFootnotePage
= m_bEndNotePage
= false;
212 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
213 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
214 vcl::RenderContext
* pRenderContext
= pSh
? pSh
->GetOut() : nullptr;
217 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
222 tools::Long nWidth
= pSh
->VisArea().Width();
226 nWidth
= 5000; // changes anyway
229 aFrm
.Width ( nWidth
);
233 aFrm
.SSize( pFormat
->GetFrameSize().GetSize() );
237 // create and insert body area if it is not a blank page
238 SwDoc
* pDoc(pFormat
->GetDoc());
239 m_bEmptyPage
= (pFormat
== pDoc
->GetEmptyPageFormat());
246 Calc(pRenderContext
); // so that the PrtArea is correct
247 SwBodyFrame
*pBodyFrame
= new SwBodyFrame( pDoc
->GetDfltFrameFormat(), this );
248 pBodyFrame
->ChgSize( getFramePrintArea().SSize() );
249 pBodyFrame
->Paste( this );
250 pBodyFrame
->Calc(pRenderContext
); // so that the columns can be inserted correctly
251 pBodyFrame
->InvalidatePos();
256 // insert header/footer,, but only if active.
257 if ( pFormat
->GetHeader().IsActive() )
259 if ( pFormat
->GetFooter().IsActive() )
262 const SwFormatCol
&rCol
= pFormat
->GetCol();
263 if ( rCol
.GetNumCols() > 1 )
265 const SwFormatCol aOld
; //ChgColumns() needs an old value
266 pBodyFrame
->ChgColumns( aOld
, rCol
);
271 void SwPageFrame::DestroyImpl()
273 // Cleanup the header-footer controls in all SwEditWins
274 SwViewShell
* pSh
= getRootFrame()->GetCurrShell();
277 for (SwViewShell
& rSh
: pSh
->GetRingContainer())
279 SwWrtShell
* pWrtSh
= dynamic_cast< SwWrtShell
* >( &rSh
);
282 SwEditWin
& rEditWin
= pWrtSh
->GetView().GetEditWin();
283 rEditWin
.GetFrameControlsManager( ).RemoveControls( this );
288 // empty FlyContainer, deletion of the Flys is done by the anchor (in base class SwFrame)
291 // Objects can be anchored at pages that are before their anchors (why ever...).
292 // In such cases, we would access already freed memory.
293 for (SwAnchoredObject
* pAnchoredObj
: *m_pSortedObjs
)
295 pAnchoredObj
->SetPageFrame( nullptr );
297 m_pSortedObjs
.reset(); // reset to zero to prevent problems when detaching the Flys
300 // prevent access to destroyed pages
301 SwDoc
*pDoc
= GetFormat() ? GetFormat()->GetDoc() : nullptr;
302 if( pDoc
&& !pDoc
->IsInDtor() )
306 SwViewShellImp
*pImp
= pSh
->Imp();
307 pImp
->SetFirstVisPageInvalid();
308 if ( pImp
->IsAction() )
309 pImp
->GetLayAction().SetAgain(true);
310 // #i9719# - retouche area of page
311 // including border and shadow area.
312 const bool bRightSidebar
= (SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT
);
313 SwRect aRetoucheRect
;
314 SwPageFrame::GetBorderAndShadowBoundRect( getFrameArea(), pSh
, pSh
->GetOut(), aRetoucheRect
, IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar
);
315 pSh
->AddPaintRect( aRetoucheRect
);
319 SwFootnoteBossFrame::DestroyImpl();
322 SwPageFrame::~SwPageFrame()
326 void SwPageFrame::CheckGrid( bool bInvalidate
)
328 bool bOld
= m_bHasGrid
;
330 SwTextGridItem
const*const pGrid(GetGridItem(this));
331 m_bHasGrid
= nullptr != pGrid
;
332 if( !(bInvalidate
|| bOld
!= m_bHasGrid
) )
335 SwLayoutFrame
* pBody
= FindBodyCont();
338 pBody
->InvalidatePrt();
339 SwContentFrame
* pFrame
= pBody
->ContainsContent();
340 while( pBody
->IsAnLower( pFrame
) )
342 static_cast<SwTextFrame
*>(pFrame
)->Prepare();
343 pFrame
= pFrame
->GetNextContentFrame();
349 void SwPageFrame::CheckDirection( bool bVert
)
351 SvxFrameDirection nDir
= GetFormat()->GetFormatAttr( RES_FRAMEDIR
).GetValue();
354 if( SvxFrameDirection::Horizontal_LR_TB
== nDir
|| SvxFrameDirection::Horizontal_RL_TB
== nDir
)
361 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
362 if( pSh
&& pSh
->GetViewOptions()->getBrowseMode() )
371 if(SvxFrameDirection::Vertical_RL_TB
== nDir
)
373 else if(SvxFrameDirection::Vertical_LR_TB
==nDir
)
378 mbInvalidVert
= false;
382 if( SvxFrameDirection::Horizontal_RL_TB
== nDir
)
383 mbRightToLeft
= true;
385 mbRightToLeft
= false;
386 mbInvalidR2L
= false;
390 /// create specific Flys for this page and format generic content
391 static void lcl_FormatLay( SwLayoutFrame
*pLay
)
393 vcl::RenderContext
* pRenderContext
= pLay
->getRootFrame()->GetCurrShell()->GetOut();
394 // format all LayoutFrames - no tables, Flys etc.
396 SwFrame
*pTmp
= pLay
->Lower();
397 // first the low-level ones
400 const SwFrameType nTypes
= SwFrameType::Root
| SwFrameType::Page
| SwFrameType::Column
401 | SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::FtnCont
402 | SwFrameType::Ftn
| SwFrameType::Body
;
403 if ( pTmp
->GetType() & nTypes
)
404 ::lcl_FormatLay( static_cast<SwLayoutFrame
*>(pTmp
) );
405 pTmp
= pTmp
->GetNext();
407 pLay
->Calc(pRenderContext
);
410 /// Create Flys or register draw objects
411 static void lcl_MakeObjs(const sw::FrameFormats
<sw::SpzFrameFormat
*>& rSpzs
, SwPageFrame
* pPage
)
413 // formats are in the special table of the document
414 for(size_t i
= 0; i
< rSpzs
.size(); ++i
)
416 auto pSpz
= rSpzs
[i
];
417 const SwFormatAnchor
&rAnch
= pSpz
->GetAnchor();
418 if ( rAnch
.GetPageNum() == pPage
->GetPhyPageNum() )
420 if( rAnch
.GetAnchorNode() )
422 if (RndStdIds::FLY_AT_PAGE
== rAnch
.GetAnchorId())
424 SwFormatAnchor
aAnch( rAnch
);
425 aAnch
.SetAnchor( nullptr );
426 pSpz
->SetFormatAttr( aAnch
);
432 // is it a border or a SdrObject?
433 bool bSdrObj
= RES_DRAWFRMFMT
== pSpz
->Which();
434 SdrObject
*pSdrObj
= nullptr;
435 if ( bSdrObj
&& nullptr == (pSdrObj
= pSpz
->FindSdrObject()) )
437 OSL_FAIL( "DrawObject not found." );
438 pSpz
->GetDoc()->DelFrameFormat( pSpz
);
442 // The object might be anchored to another page, e.g. when inserting
443 // a new page due to a page descriptor change. In such cases, the
444 // object needs to be moved.
445 // In some cases the object is already anchored to the correct page.
446 // This will be handled here and does not need to be coded extra.
447 SwPageFrame
*pPg
= pPage
->IsEmptyPage() ? static_cast<SwPageFrame
*>(pPage
->GetNext()) : pPage
;
450 // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
451 SwDrawContact
*pContact
=
452 static_cast<SwDrawContact
*>(::GetUserCall(pSdrObj
));
453 if ( auto pDrawVirtObj
= dynamic_cast<SwDrawVirtObj
*>( pSdrObj
) )
457 pDrawVirtObj
->RemoveFromWriterLayout();
458 pDrawVirtObj
->RemoveFromDrawingPage();
459 pPg
->AppendDrawObj( *(pContact
->GetAnchoredObj( pDrawVirtObj
)) );
464 if ( pContact
->GetAnchorFrame() )
465 pContact
->DisconnectFromLayout( false );
466 pPg
->AppendDrawObj( *(pContact
->GetAnchoredObj( pSdrObj
)) );
471 SwIterator
<SwFlyFrame
,SwFormat
> aIter( *pSpz
);
472 SwFlyFrame
*pFly
= aIter
.First();
475 if( pFly
->GetAnchorFrame() )
476 pFly
->AnchorFrame()->RemoveFly( pFly
);
479 pFly
= new SwFlyLayFrame( static_cast<SwFlyFrameFormat
*>(pSpz
), pPg
, pPg
);
480 pPg
->AppendFly( pFly
);
481 ::RegistFlys( pPg
, pFly
);
487 void SwPageFrame::PreparePage( bool bFootnote
)
489 SetFootnotePage( bFootnote
);
492 // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has
493 // the side effect, that the content of page header and footer are formatted.
494 // For this formatting it is needed that the anchored objects are registered
495 // at the <SwPageFrame> instance.
496 // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)>
497 ::RegistFlys( this, this );
501 ::lcl_FormatLay( this );
504 // Flys and draw objects that are still attached to the document.
505 // Footnote pages do not have page-bound Flys!
506 // There might be Flys or draw objects that want to be placed on
507 // empty pages, however, the empty pages ignore that and the following
508 // pages take care of them.
509 if ( !bFootnote
&& !IsEmptyPage() )
511 SwDoc
*pDoc
= GetFormat()->GetDoc();
513 if ( GetPrev() && static_cast<SwPageFrame
*>(GetPrev())->IsEmptyPage() )
514 lcl_MakeObjs( *pDoc
->GetSpzFrameFormats(), static_cast<SwPageFrame
*>(GetPrev()) );
515 lcl_MakeObjs( *pDoc
->GetSpzFrameFormats(), this );
519 void SwPageFrame::SwClientNotify(const SwModify
& rModify
, const SfxHint
& rHint
)
521 if(typeid(sw::PageFootnoteHint
) == typeid(rHint
))
523 // currently the savest way:
524 static_cast<SwRootFrame
*>(GetUpper())->SetSuperfluous();
525 SetMaxFootnoteHeight(m_pDesc
->GetFootnoteInfo().GetHeight());
526 if(!GetMaxFootnoteHeight())
527 SetMaxFootnoteHeight(LONG_MAX
);
528 SetColMaxFootnoteHeight();
529 // here, the page might be destroyed:
530 static_cast<SwRootFrame
*>(GetUpper())->RemoveFootnotes(nullptr, false, true);
532 else if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
534 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
535 if(auto pSh
= getRootFrame()->GetCurrShell())
536 pSh
->SetFirstVisPageInvalid();
538 SwPageFrameInvFlags eInvFlags
= SwPageFrameInvFlags::NONE
;
539 if(pLegacy
->m_pNew
&& RES_ATTRSET_CHG
== pLegacy
->m_pNew
->Which())
541 auto& rOldSetChg
= *static_cast<const SwAttrSetChg
*>(pLegacy
->m_pOld
);
542 auto& rNewSetChg
= *static_cast<const SwAttrSetChg
*>(pLegacy
->m_pNew
);
543 SfxItemIter
aOIter(*rOldSetChg
.GetChgSet());
544 SfxItemIter
aNIter(*rNewSetChg
.GetChgSet());
545 const SfxPoolItem
* pOItem
= aOIter
.GetCurItem();
546 const SfxPoolItem
* pNItem
= aNIter
.GetCurItem();
547 SwAttrSetChg
aOldSet(rOldSetChg
);
548 SwAttrSetChg
aNewSet(rNewSetChg
);
551 UpdateAttr_(pOItem
, pNItem
, eInvFlags
, &aOldSet
, &aNewSet
);
552 pOItem
= aOIter
.NextItem();
553 pNItem
= aNIter
.NextItem();
555 if(aOldSet
.Count() || aNewSet
.Count())
556 SwLayoutFrame::SwClientNotify(rModify
, sw::LegacyModifyHint(&aOldSet
, &aNewSet
));
559 UpdateAttr_(pLegacy
->m_pOld
, pLegacy
->m_pNew
, eInvFlags
);
561 if (eInvFlags
== SwPageFrameInvFlags::NONE
)
564 InvalidatePage( this );
565 if(eInvFlags
& SwPageFrameInvFlags::InvalidatePrt
)
567 if(eInvFlags
& SwPageFrameInvFlags::SetCompletePaint
)
569 if(eInvFlags
& SwPageFrameInvFlags::InvalidateNextPos
&& GetNext() )
570 GetNext()->InvalidatePos();
571 if(eInvFlags
& SwPageFrameInvFlags::PrepareHeader
)
573 if(eInvFlags
& SwPageFrameInvFlags::PrepareFooter
)
575 if(eInvFlags
& SwPageFrameInvFlags::CheckGrid
)
576 CheckGrid(bool(eInvFlags
& SwPageFrameInvFlags::InvalidateGrid
));
578 SwFrame::SwClientNotify(rModify
, rHint
);
581 void SwPageFrame::UpdateAttr_( const SfxPoolItem
*pOld
, const SfxPoolItem
*pNew
,
582 SwPageFrameInvFlags
&rInvFlags
,
583 SwAttrSetChg
*pOldSet
, SwAttrSetChg
*pNewSet
)
586 const sal_uInt16 nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
591 // state of m_bEmptyPage needs to be determined newly
592 const bool bNewState(GetFormat() == GetFormat()->GetDoc()->GetEmptyPageFormat());
594 if(m_bEmptyPage
!= bNewState
)
597 m_bEmptyPage
= bNewState
;
599 if(nullptr == GetLower())
601 // if we were an empty page before there is not yet a BodyArea in the
602 // form of a SwBodyFrame, see constructor
603 SwViewShell
* pSh(getRootFrame()->GetCurrShell());
604 vcl::RenderContext
* pRenderContext(pSh
? pSh
->GetOut() : nullptr);
605 Calc(pRenderContext
); // so that the PrtArea is correct
606 SwBodyFrame
* pBodyFrame
= new SwBodyFrame(GetFormat(), this);
607 pBodyFrame
->ChgSize(getFramePrintArea().SSize());
608 pBodyFrame
->Paste(this);
609 pBodyFrame
->InvalidatePos();
613 // If the frame format is changed, several things might also change:
615 assert(pOld
&& pNew
); //FMT_CHG Missing Format
616 const SwFormat
*const pOldFormat
= static_cast<const SwFormatChg
*>(pOld
)->pChangedFormat
;
617 const SwFormat
*const pNewFormat
= static_cast<const SwFormatChg
*>(pNew
)->pChangedFormat
;
618 assert(pOldFormat
&& pNewFormat
); //FMT_CHG Missing Format
619 const SwFormatCol
&rOldCol
= pOldFormat
->GetCol();
620 const SwFormatCol
&rNewCol
= pNewFormat
->GetCol();
621 if( rOldCol
!= rNewCol
)
623 SwLayoutFrame
*pB
= FindBodyCont();
624 assert(pB
&& "Page without Body.");
625 pB
->ChgColumns( rOldCol
, rNewCol
);
626 rInvFlags
|= SwPageFrameInvFlags::CheckGrid
;
629 // 2. header and footer:
630 const SwFormatHeader
&rOldH
= pOldFormat
->GetHeader();
631 const SwFormatHeader
&rNewH
= pNewFormat
->GetHeader();
633 rInvFlags
|= SwPageFrameInvFlags::PrepareHeader
;
635 const SwFormatFooter
&rOldF
= pOldFormat
->GetFooter();
636 const SwFormatFooter
&rNewF
= pNewFormat
->GetFooter();
638 rInvFlags
|= SwPageFrameInvFlags::PrepareFooter
;
645 const SwRect
aOldPageFrameRect( getFrameArea() );
646 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
647 if( pSh
&& pSh
->GetViewOptions()->getBrowseMode() )
649 setFrameAreaSizeValid(false);
650 // OD 28.10.2002 #97265# - Don't call <SwPageFrame::MakeAll()>
651 // Calculation of the page is not necessary, because its size is
652 // invalidated here and further invalidation is done in the
653 // calling method <SwPageFrame::Modify(..)> and probably by calling
654 // <SwLayoutFrame::SwClientNotify(..)> at the end.
655 // It can also causes inconsistences, because the lowers are
656 // adjusted, but not calculated, and a <SwPageFrame::MakeAll()> of
657 // a next page is called. This is performed on the switch to the
663 const SwFormatFrameSize
&rSz
= nWhich
== RES_FMT_CHG
?
664 static_cast<const SwFormatChg
*>(pNew
)->pChangedFormat
->GetFrameSize() :
665 static_cast<const SwFormatFrameSize
&>(*pNew
);
668 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
669 aFrm
.Height( std::max( rSz
.GetHeight(), tools::Long(MINLAY
) ) );
670 aFrm
.Width ( std::max( rSz
.GetWidth(), tools::Long(MINLAY
) ) );
675 static_cast<SwRootFrame
*>(GetUpper())->CheckViewLayout( nullptr, nullptr );
679 if( pSh
&& pSh
->GetWin() && aOldPageFrameRect
.HasArea() )
681 // #i9719# - consider border and shadow of
682 // page frame for determine 'old' rectangle - it's used for invalidating.
683 const bool bRightSidebar
= (SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT
);
684 SwRect aOldRectWithBorderAndShadow
;
685 SwPageFrame::GetBorderAndShadowBoundRect( aOldPageFrameRect
, pSh
, pSh
->GetOut(), aOldRectWithBorderAndShadow
,
686 IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar
);
687 pSh
->InvalidateWindows( aOldRectWithBorderAndShadow
);
689 rInvFlags
|= SwPageFrameInvFlags::InvalidatePrt
| SwPageFrameInvFlags::SetCompletePaint
;
690 if ( aOldPageFrameRect
.Height() != getFrameArea().Height() )
691 rInvFlags
|= SwPageFrameInvFlags::InvalidateNextPos
;
696 assert(pOld
&& pNew
); //COL Missing Format
699 SwLayoutFrame
*pB
= FindBodyCont();
700 assert(pB
); //page without body
701 pB
->ChgColumns( *static_cast<const SwFormatCol
*>(pOld
), *static_cast<const SwFormatCol
*>(pNew
) );
702 rInvFlags
|= SwPageFrameInvFlags::SetCompletePaint
| SwPageFrameInvFlags::CheckGrid
;
707 rInvFlags
|= SwPageFrameInvFlags::PrepareHeader
;
711 rInvFlags
|= SwPageFrameInvFlags::PrepareFooter
;
714 rInvFlags
|= SwPageFrameInvFlags::CheckGrid
| SwPageFrameInvFlags::InvalidateGrid
;
726 if ( pOldSet
|| pNewSet
)
729 pOldSet
->ClearItem( nWhich
);
731 pNewSet
->ClearItem( nWhich
);
736 SwLayoutFrame::SwClientNotify(aMod
, sw::LegacyModifyHint(pOld
, pNew
));
740 /// get information from Modify
741 bool SwPageFrame::GetInfo( SfxPoolItem
& rInfo
) const
743 if( RES_AUTOFMT_DOCNODE
== rInfo
.Which() )
745 // a page frame exists, so use this one
748 return true; // continue searching
751 void SwPageFrame::SetPageDesc( SwPageDesc
*pNew
, SwFrameFormat
*pFormat
)
755 SetFrameFormat( pFormat
);
758 /* determine the right PageDesc:
759 * 0. from the document for footnote and endnote pages
760 * 1. from the first BodyContent below a page
761 * 2. from PageDesc of the predecessor page
762 * 3. from PageDesc of the previous page if blank page
763 * 3.1 from PageDesc of the next page if no predecessor exists
764 * 4. default PageDesc
765 * 5. In BrowseMode use the first paragraph or default PageDesc.
767 SwPageDesc
*SwPageFrame::FindPageDesc()
770 if ( IsFootnotePage() )
772 SwDoc
*pDoc
= GetFormat()->GetDoc();
773 if ( IsEndNotePage() )
774 return pDoc
->GetEndNoteInfo().GetPageDesc( *pDoc
);
776 return pDoc
->GetFootnoteInfo().GetPageDesc( *pDoc
);
779 SwPageDesc
*pRet
= nullptr;
782 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
783 if( pSh
&& pSh
->GetViewOptions()->getBrowseMode() )
785 SwContentFrame
*pFrame
= GetUpper()->ContainsContent();
786 while (pFrame
&& !pFrame
->IsInDocBody())
787 pFrame
= pFrame
->GetNextContentFrame();
790 SwFrame
*pFlow
= pFrame
;
791 if ( pFlow
->IsInTab() )
792 pFlow
= pFlow
->FindTabFrame();
793 pRet
= const_cast<SwPageDesc
*>(pFlow
->GetPageDescItem().GetPageDesc());
796 pRet
= &GetFormat()->GetDoc()->GetPageDesc( 0 );
800 SwFrame
*pFlow
= FindFirstBodyContent();
801 if ( pFlow
&& pFlow
->IsInTab() )
802 pFlow
= pFlow
->FindTabFrame();
807 SwFlowFrame
*pTmp
= SwFlowFrame::CastFlowFrame( pFlow
);
808 if ( !pTmp
->IsFollow() )
809 pRet
= const_cast<SwPageDesc
*>(pFlow
->GetPageDescItem().GetPageDesc());
813 if ( !pRet
&& IsEmptyPage() )
814 // FME 2008-03-03 #i81544# lijian/fme: an empty page should have
815 // the same page description as its prev, just like after construction
816 // of the empty page.
817 pRet
= GetPrev() ? static_cast<SwPageFrame
*>(GetPrev())->GetPageDesc() :
818 GetNext() ? static_cast<SwPageFrame
*>(GetNext())->GetPageDesc() : nullptr;
823 static_cast<SwPageFrame
*>(GetPrev())->GetPageDesc()->GetFollow() : nullptr;
827 pRet
= &GetFormat()->GetDoc()->GetPageDesc( 0 );
829 OSL_ENSURE( pRet
, "could not find page descriptor." );
833 // Notify if the RootFrame changes its size
834 void AdjustSizeChgNotify( SwRootFrame
*pRoot
)
836 const bool bOld
= pRoot
->IsSuperfluous();
837 pRoot
->mbCheckSuperfluous
= false;
838 if ( pRoot
->GetCurrShell() )
840 for(SwViewShell
& rSh
: pRoot
->GetCurrShell()->GetRingContainer())
842 if( pRoot
== rSh
.GetLayout() )
846 rSh
.Imp()->NotifySizeChg( pRoot
->getFrameArea().SSize() );
850 pRoot
->mbCheckSuperfluous
= bOld
;
853 inline void SetLastPage( SwPageFrame
*pPage
)
855 static_cast<SwRootFrame
*>(pPage
->GetUpper())->mpLastPage
= pPage
;
858 void SwPageFrame::Cut()
860 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
861 if ( !IsEmptyPage() )
864 GetNext()->InvalidatePos();
866 // move Flys whose anchor is on a different page (draw objects are not relevant here)
867 if ( GetSortedObjs() )
870 while ( GetSortedObjs() && i
< GetSortedObjs()->size() )
873 SwAnchoredObject
* pAnchoredObj
= (*GetSortedObjs())[i
];
875 if ( auto pFly
= dynamic_cast<SwFlyAtContentFrame
*>( pAnchoredObj
) )
877 SwPageFrame
*pAnchPage
= pFly
->GetAnchorFrame() ?
878 pFly
->AnchorFrame()->FindPageFrame() : nullptr;
879 if ( pAnchPage
&& (pAnchPage
!= this) )
881 MoveFly( pFly
, pAnchPage
);
882 pFly
->InvalidateSize();
883 pFly
->InvalidatePos_();
884 // Do not increment index, in this case
892 if ( pSh
&& pSh
->GetWin() )
893 pSh
->InvalidateWindows( getFrameArea() );
896 // decrease the root's page number
897 static_cast<SwRootFrame
*>(GetUpper())->DecrPhyPageNums();
898 SwPageFrame
*pPg
= static_cast<SwPageFrame
*>(GetNext());
903 --pPg
->m_nPhyPageNum
;
904 pPg
= static_cast<SwPageFrame
*>(pPg
->GetNext());
908 ::SetLastPage( static_cast<SwPageFrame
*>(GetPrev()) );
910 SwFrame
* pRootFrame
= GetUpper();
912 // cut all connections
916 static_cast<SwRootFrame
*>(pRootFrame
)->CheckViewLayout( nullptr, nullptr );
919 void SwPageFrame::Paste( SwFrame
* pParent
, SwFrame
* pSibling
)
921 OSL_ENSURE( pParent
->IsRootFrame(), "Parent is no Root." );
922 OSL_ENSURE( pParent
, "No parent for Paste()." );
923 OSL_ENSURE( pParent
!= this, "I'm my own parent." );
924 OSL_ENSURE( pSibling
!= this, "I'm my own neighbour." );
925 OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
926 "I am still registered somewhere." );
928 // insert into tree structure
929 InsertBefore( static_cast<SwLayoutFrame
*>(pParent
), pSibling
);
931 // increase the root's page number
932 static_cast<SwRootFrame
*>(GetUpper())->IncrPhyPageNums();
934 SetPhyPageNum( static_cast<SwPageFrame
*>(GetPrev())->GetPhyPageNum() + 1 );
937 SwPageFrame
*pPg
= static_cast<SwPageFrame
*>(GetNext());
942 ++pPg
->m_nPhyPageNum
;
943 pPg
->InvalidatePos_();
944 pPg
->InvalidateLayout();
945 pPg
= static_cast<SwPageFrame
*>(pPg
->GetNext());
949 ::SetLastPage( this );
951 if( getFrameArea().Width() != pParent
->getFramePrintArea().Width() )
956 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
958 pSh
->SetFirstVisPageInvalid();
960 getRootFrame()->CheckViewLayout( nullptr, nullptr );
963 static void lcl_PrepFlyInCntRegister( SwContentFrame
*pFrame
)
965 pFrame
->Prepare( PrepareHint::Register
);
966 if( !pFrame
->GetDrawObjs() )
969 for(SwAnchoredObject
* pAnchoredObj
: *pFrame
->GetDrawObjs())
972 if ( auto pFly
= dynamic_cast<SwFlyInContentFrame
*>( pAnchoredObj
) )
974 SwContentFrame
*pCnt
= pFly
->ContainsContent();
977 lcl_PrepFlyInCntRegister( pCnt
);
978 pCnt
= pCnt
->GetNextContentFrame();
984 void SwPageFrame::PrepareRegisterChg()
986 SwContentFrame
*pFrame
= FindFirstBodyContent();
989 lcl_PrepFlyInCntRegister( pFrame
);
990 pFrame
= pFrame
->GetNextContentFrame();
991 if( !IsAnLower( pFrame
) )
994 if( !GetSortedObjs() )
997 for(SwAnchoredObject
* pAnchoredObj
: *GetSortedObjs())
1000 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
1002 pFrame
= pFly
->ContainsContent();
1005 ::lcl_PrepFlyInCntRegister( pFrame
);
1006 pFrame
= pFrame
->GetNextContentFrame();
1014 /// check if there's content on the page that requires it to exist
1015 bool IsPageFrameEmpty(SwPageFrame
const& rPage
)
1017 bool bExistEssentialObjs
= (nullptr != rPage
.GetSortedObjs());
1018 if (bExistEssentialObjs
)
1020 // Only because the page has Flys does not mean that it is needed. If all Flys are
1021 // attached to generic content it is also superfluous (checking DocBody should be enough)
1022 // OD 19.06.2003 - consider that drawing objects in
1023 // header/footer are supported now.
1024 bool bOnlySuperfluousObjs
= true;
1025 SwSortedObjs
const& rObjs
= *rPage
.GetSortedObjs();
1026 for (size_t i
= 0; bOnlySuperfluousObjs
&& i
< rObjs
.size(); ++i
)
1029 SwAnchoredObject
* pAnchoredObj
= rObjs
[i
];
1030 // do not consider hidden objects
1031 if ( rPage
.GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId(
1032 pAnchoredObj
->GetDrawObj()->GetLayer() ) &&
1033 !pAnchoredObj
->GetAnchorFrame()->FindFooterOrHeader() )
1035 bOnlySuperfluousObjs
= false;
1038 bExistEssentialObjs
= !bOnlySuperfluousObjs
;
1041 // optimization: check first if essential objects exist.
1042 const SwLayoutFrame
* pBody
= nullptr;
1043 if ( bExistEssentialObjs
||
1044 rPage
.FindFootnoteCont() ||
1045 (nullptr != (pBody
= rPage
.FindBodyCont()) &&
1046 ( pBody
->ContainsContent() ||
1047 // check for section frames that are being formatted on the stack
1048 rPage
.ContainsDeleteForbiddenLayFrame() ||
1050 // Do not delete page if there's an empty tabframe
1051 // left. I think it might be correct to use ContainsAny()
1052 // instead of ContainsContent() to cover the empty-table-case,
1053 // but I'm not fully sure, since ContainsAny() also returns
1054 // SectionFrames. Therefore I prefer to do it the safe way:
1055 ( pBody
->Lower() && pBody
->Lower()->IsTabFrame() ) ) ) )
1067 //FIXME: provide missing documentation
1068 /** Check all pages (starting from the given one) if they use the appropriate frame format.
1070 * If "wrong" pages are found, try to fix this as simple as possible.
1072 * Also delete pages that don't have content on them.
1074 * @param pStart the page from where to start searching
1075 * @param bNotifyFields
1078 void SwFrame::CheckPageDescs( SwPageFrame
*pStart
, bool bNotifyFields
, SwPageFrame
** ppPrev
)
1080 SAL_INFO( "sw.pageframe", "(CheckPageDescs in phy: " << pStart
->GetPhyPageNum() );
1081 assert(pStart
&& "no starting page.");
1083 SwViewShell
*pSh
= pStart
->getRootFrame()->GetCurrShell();
1084 SwViewShellImp
*pImp
= pSh
? pSh
->Imp() : nullptr;
1086 if ( pImp
&& pImp
->IsAction() && !pImp
->GetLayAction().IsCheckPages() )
1088 pImp
->GetLayAction().SetCheckPageNum( pStart
->GetPhyPageNum() );
1089 SAL_INFO( "sw.pageframe", "CheckPageDescs out fast - via SetCheckPageNum: "
1090 << pStart
->GetPhyPageNum() << ")" );
1094 // For the update of page numbering fields, nDocPos provides
1095 // the page position from where invalidation should start.
1096 SwTwips nDocPos
= LONG_MAX
;
1098 SwRootFrame
*pRoot
= static_cast<SwRootFrame
*>(pStart
->GetUpper());
1099 SwDoc
* pDoc
= pStart
->GetFormat()->GetDoc();
1100 const bool bFootnotes
= !pDoc
->GetFootnoteIdxs().empty();
1102 SwPageFrame
*pPage
= pStart
;
1103 if( pPage
->GetPrev() && static_cast<SwPageFrame
*>(pPage
->GetPrev())->IsEmptyPage() )
1104 pPage
= static_cast<SwPageFrame
*>(pPage
->GetPrev());
1107 SwPageFrame
*pPrevPage
= static_cast<SwPageFrame
*>(pPage
->GetPrev());
1108 SwPageFrame
*pNextPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1110 SwPageDesc
*pDesc
= pPage
->FindPageDesc();
1111 /// page is intentionally empty page
1112 bool bIsEmpty
= pPage
->IsEmptyPage();
1113 // false for intentionally empty pages, they need additional check
1114 bool isPageFrameEmpty(!bIsEmpty
&& sw::IsPageFrameEmpty(*pPage
));
1115 bool bIsOdd
= pPage
->OnRightPage();
1116 bool bWantOdd
= pPage
->WannaRightPage();
1117 bool bFirst
= pPage
->OnFirstPage();
1118 SwFrameFormat
*pFormatWish
= bWantOdd
1119 ? pDesc
->GetRightFormat(bFirst
) : pDesc
->GetLeftFormat(bFirst
);
1121 if ( bIsOdd
!= bWantOdd
||
1122 pDesc
!= pPage
->GetPageDesc() || // wrong Desc
1123 ( pFormatWish
!= pPage
->GetFormat() && // wrong format and
1124 ( !bIsEmpty
|| pFormatWish
) // not blank /empty
1128 // Updating a page might take a while, so check the WaitCursor
1130 pImp
->CheckWaitCursor();
1132 // invalidate the field, starting from here
1133 if ( nDocPos
== LONG_MAX
)
1134 nDocPos
= pPrevPage
? pPrevPage
->getFrameArea().Top() : pPage
->getFrameArea().Top();
1137 // 1. Empty page should be "normal" page -> remove empty page and take next one
1138 // 2. Empty page should have different descriptor -> change
1139 // 3. Normal page should be empty -> insert empty page if previous page
1140 // is not empty, otherwise see (6).
1141 // 4. Normal page should have different descriptor -> change
1142 // 5. Normal page should have different format -> change
1143 // 6. No "wish" format provided -> take the "other" format (left/right) of the PageDesc
1145 if ( bIsEmpty
&& ( pFormatWish
|| //1.
1146 ( !bWantOdd
&& !pPrevPage
) ) )
1148 // Check all cases for the next page, so we don't oscillate empty pages
1149 // Skip case 1 and 2, as we require a non-empty next page to save the empty page
1150 // Case 3 is the one we actually want to predict and skip
1151 // We can skip the empty check of case 3, as we just work on an existing next page
1153 SwPageDesc
*pNextDesc
;
1154 if ( pNextPage
&& !pNextPage
->IsEmptyPage() && //3.
1155 pNextPage
->OnRightPage() == (bNextWantOdd
= pNextPage
->WannaRightPage()) &&
1156 pNextPage
->GetPageDesc() == (pNextDesc
= pNextPage
->FindPageDesc()) ) //4.
1158 bool bNextFirst
= pNextPage
->OnFirstPage();
1159 SwFrameFormat
*pNextFormatWish
= bNextWantOdd
? //5.
1160 pNextDesc
->GetRightFormat(bNextFirst
) : pNextDesc
->GetLeftFormat(bNextFirst
);
1161 if ( !pNextFormatWish
) // 6.
1162 pNextFormatWish
= bNextWantOdd
? pNextDesc
->GetLeftFormat() : pNextDesc
->GetRightFormat();
1163 if ( pNextFormatWish
&& pNextPage
->GetFormat() == pNextFormatWish
)
1165 SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage
->GetPhyPageNum()
1166 << " c: 1+3 - skip next page of p: " << pPage
);
1167 if (pPrevPage
&& pPage
->GetPageDesc() != pPrevPage
->GetPageDesc())
1168 pPage
->SetPageDesc( pPrevPage
->GetPageDesc(), nullptr );
1169 // We can skip the next page, as all checks were already done!
1170 pPage
= static_cast<SwPageFrame
*>(pNextPage
->GetNext());
1176 bool bUpdatePrev
= false;
1177 if (ppPrev
&& *ppPrev
== pPage
)
1179 SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage
->GetPhyPageNum()
1180 << " c: 1 - destroy p: " << pPage
);
1181 SwFrame::DestroyFrame(pPage
);
1182 if ( pStart
== pPage
)
1186 *ppPrev
= pNextPage
;
1189 else if ( bIsEmpty
&& !pFormatWish
&& //2.
1190 pDesc
!= pPage
->GetPageDesc() )
1192 SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage
->GetPhyPageNum()
1193 << " c: 2 - set desc p: " << pPage
<< " d: " << pDesc
);
1194 pPage
->SetPageDesc( pDesc
, nullptr );
1196 else if ( !bIsEmpty
&& //3.
1197 bIsOdd
!= bWantOdd
&&
1198 ( ( !pPrevPage
&& !bWantOdd
) ||
1199 ( pPrevPage
&& !pPrevPage
->IsEmptyPage() )
1204 pDesc
= pPrevPage
->GetPageDesc();
1205 SwPageFrame
*pTmp
= new SwPageFrame( pDoc
->GetEmptyPageFormat(), pRoot
, pDesc
);
1206 SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage
->GetPhyPageNum()
1207 << " c: 3 - insert empty p: " << pTmp
<< " d: " << pDesc
);
1208 pTmp
->Paste( pRoot
, pPage
);
1209 pTmp
->PreparePage( false );
1211 isPageFrameEmpty
= false; // don't delete it right away!
1213 else if ( pPage
->GetPageDesc() != pDesc
) //4.
1215 SwPageDesc
*pOld
= pPage
->GetPageDesc();
1216 pPage
->SetPageDesc( pDesc
, pFormatWish
);
1217 SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage
->GetPhyPageNum()
1218 << " c: 4 - set desc + format p: " << pPage
1219 << " d: " << pDesc
<< " f: " << pFormatWish
);
1222 // If specific values of the FootnoteInfo are changed, something has to happen.
1223 // We try to limit the damage...
1224 // If the page has no FootnoteCont it might be problematic.
1225 // Let's hope that invalidation is enough.
1226 SwFootnoteContFrame
*pCont
= pPage
->FindFootnoteCont();
1227 if ( pCont
&& !(pOld
->GetFootnoteInfo() == pDesc
->GetFootnoteInfo()) )
1228 pCont
->InvalidateAll_();
1231 else if ( pFormatWish
&& pPage
->GetFormat() != pFormatWish
) //5.
1233 pPage
->SetFrameFormat( pFormatWish
);
1234 SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage
->GetPhyPageNum()
1235 << " c: 5 - set format p: " << pPage
<< " f: " << pFormatWish
);
1237 else if ( !pFormatWish
) //6.
1239 // get format with inverted logic
1240 pFormatWish
= bWantOdd
? pDesc
->GetLeftFormat() : pDesc
->GetRightFormat();
1241 if ( pFormatWish
&& pPage
->GetFormat() != pFormatWish
)
1243 pPage
->SetFrameFormat( pFormatWish
);
1244 SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage
->GetPhyPageNum()
1245 << " c: 6 - set format p: " << pPage
<< " f: " << pFormatWish
);
1248 #if OSL_DEBUG_LEVEL > 0
1251 OSL_FAIL( "CheckPageDescs, missing solution" );
1255 assert(!bIsEmpty
|| !isPageFrameEmpty
);
1256 const bool bWantRemovePage
= bIsEmpty
|| isPageFrameEmpty
;
1257 if (bWantRemovePage
&& !pPage
->IsDeleteForbidden())
1259 // It also might be that an empty page is not needed at all.
1260 // However, the algorithm above cannot determine that. It is not needed if the following
1261 // page can live without it. Do obtain that information, we need to dig deeper...
1262 SwPageFrame
*pPg
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1263 if (isPageFrameEmpty
|| !pPg
|| pPage
->OnRightPage() == pPg
->WannaRightPage())
1265 // The following page can find a FrameFormat or has no successor -> empty page not needed
1266 SwPageFrame
*pTmp
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1267 if (isPageFrameEmpty
&& pPage
->GetPrev())
1268 { // check previous *again* vs. its new next! see "ooo321_stylepagenumber.odt"
1269 pTmp
= static_cast<SwPageFrame
*>(pPage
->GetPrev());
1272 bool bUpdatePrev
= false;
1273 if (ppPrev
&& *ppPrev
== pPage
)
1275 SwFrame::DestroyFrame(pPage
);
1276 SAL_INFO( "sw.pageframe", "CheckPageDescs - handle bIsEmpty - destroy p: " << pPage
);
1277 if ( pStart
== pPage
)
1285 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1288 pRoot
->SetAssertFlyPages();
1289 SwRootFrame::AssertPageFlys( pStart
);
1291 if ( bNotifyFields
&& (!pImp
|| !pImp
->IsUpdateExpFields()) )
1293 pDoc
->getIDocumentFieldsAccess().UpdatePageFields(nDocPos
);
1296 #if OSL_DEBUG_LEVEL > 0
1297 //1. check if two empty pages are behind one another
1298 bool bEmpty
= false;
1299 SwPageFrame
*pPg
= pStart
;
1302 if ( pPg
->IsEmptyPage() )
1306 OSL_FAIL( "double empty pages." );
1307 break; // once is enough
1314 pPg
= static_cast<SwPageFrame
*>(pPg
->GetNext());
1317 SAL_INFO( "sw.pageframe", "CheckPageDescs out)" );
1322 bool isDeleteForbidden(const SwPageFrame
*pDel
)
1324 if (pDel
->IsDeleteForbidden())
1326 const SwLayoutFrame
* pBody
= pDel
->FindBodyCont();
1327 const SwFrame
* pBodyContent
= pBody
? pBody
->Lower() : nullptr;
1328 return pBodyContent
&& pBodyContent
->IsDeleteForbidden();
1331 bool doInsertPage( SwRootFrame
*pRoot
, SwPageFrame
**pRefSibling
,
1332 SwFrameFormat
*pFormat
, SwPageDesc
*pDesc
,
1333 bool bFootnote
, SwPageFrame
**pRefPage
)
1335 SwPageFrame
*pPage
= new SwPageFrame(pFormat
, pRoot
, pDesc
);
1336 SwPageFrame
*pSibling
= *pRefSibling
;
1340 SAL_INFO( "sw.pageframe", "doInsertPage p: " << pPage
1341 << " d: " << pDesc
<< " f: " << pFormat
);
1344 SAL_INFO( "sw.pageframe", "doInsertPage - insert empty p: "
1345 << pPage
<< " d: " << pDesc
);
1346 pPage
->Paste( pRoot
, pSibling
);
1348 SwViewShell
* pViewShell
= pRoot
->GetCurrShell();
1349 if (pViewShell
&& pViewShell
->GetViewOptions()->IsHideWhitespaceMode())
1351 // Hide-whitespace mode does not shrink the last page, so resize the page that used to
1353 if (SwFrame
* pPrevPage
= pPage
->GetPrev())
1355 pPrevPage
->InvalidateSize();
1359 pPage
->PreparePage( bFootnote
);
1360 // If the sibling has no body text, destroy it as long as it is no footnote page.
1363 if (pSibling
->IsFootnotePage())
1365 if (pSibling
->FindFirstBodyContent())
1368 if (!pRefPage
|| !isDeleteForbidden(pSibling
))
1370 pRoot
->RemovePage( pRefSibling
, SwRemoveResult::Next
) ;
1378 SwPageFrame
*SwFrame::InsertPage( SwPageFrame
*pPrevPage
, bool bFootnote
)
1380 SwRootFrame
*pRoot
= static_cast<SwRootFrame
*>(pPrevPage
->GetUpper());
1381 SwPageFrame
*pSibling
= static_cast<SwPageFrame
*>(pPrevPage
->GetNext());
1382 SwPageDesc
*pDesc
= nullptr;
1384 // insert right (odd) or left (even) page?
1385 bool bNextRightPage
= !pPrevPage
->OnRightPage();
1386 bool bWishedRightPage
= bNextRightPage
;
1388 // Which PageDesc is relevant?
1389 // For ContentFrame take the one from format if provided,
1390 // otherwise from the Follow of the PrevPage
1391 if ( IsFlowFrame() && !SwFlowFrame::CastFlowFrame( this )->IsFollow() )
1393 SwFormatPageDesc
&rDesc
= const_cast<SwFormatPageDesc
&>(GetPageDescItem());
1394 pDesc
= rDesc
.GetPageDesc();
1395 if ( rDesc
.GetNumOffset() )
1397 ::std::optional
<sal_uInt16
> oNumOffset
= rDesc
.GetNumOffset();
1398 bWishedRightPage
= sw::IsRightPageByNumber(*pRoot
, *oNumOffset
);
1399 // use the opportunity to set the flag at root
1400 pRoot
->SetVirtPageNum( true );
1404 pDesc
= pPrevPage
->GetPageDesc()->GetFollow();
1406 assert(pDesc
&& "Missing PageDesc");
1407 if( !(bWishedRightPage
? pDesc
->GetRightFormat() : pDesc
->GetLeftFormat()) )
1408 bWishedRightPage
= !bWishedRightPage
;
1409 bool const bWishedFirst
= pDesc
!= pPrevPage
->GetPageDesc();
1411 SwDoc
*pDoc
= pPrevPage
->GetFormat()->GetDoc();
1412 bool bCheckPages
= false;
1413 // If there is no FrameFormat for this page, create an empty page.
1414 if (bWishedRightPage
!= bNextRightPage
)
1416 if( doInsertPage( pRoot
, &pSibling
, pDoc
->GetEmptyPageFormat(),
1417 pPrevPage
->GetPageDesc(), bFootnote
, nullptr ) )
1420 SwFrameFormat
*const pFormat( bWishedRightPage
1421 ? pDesc
->GetRightFormat(bWishedFirst
)
1422 : pDesc
->GetLeftFormat(bWishedFirst
) );
1424 SwPageFrame
*pPage
= nullptr;
1425 if( doInsertPage( pRoot
, &pSibling
, pFormat
, pDesc
, bFootnote
, &pPage
) )
1432 CheckPageDescs( pSibling
, false );
1433 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
1434 SwViewShellImp
*pImp
= pSh
? pSh
->Imp() : nullptr;
1435 if ( pImp
&& pImp
->IsAction() && !pImp
->GetLayAction().IsCheckPages() )
1437 const sal_uInt16 nNum
= pImp
->GetLayAction().GetCheckPageNum();
1438 if ( nNum
== pPrevPage
->GetPhyPageNum() + 1 )
1440 pImp
->GetLayAction().SetCheckPageNumDirect(
1441 pSibling
->GetPhyPageNum() );
1442 SAL_INFO( "sw.pageframe", "InsertPage - SetCheckPageNumDirect: "
1443 << pSibling
->GetPhyPageNum() );
1449 SwRootFrame::AssertPageFlys( pSibling
);
1452 // For the update of page numbering fields, nDocPos provides
1453 // the page position from where invalidation should start.
1454 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
1455 if ( !pSh
|| !pSh
->Imp()->IsUpdateExpFields() )
1457 pDoc
->getIDocumentFieldsAccess().UpdatePageFields(pPrevPage
->getFrameArea().Top());
1462 sw::sidebarwindows::SidebarPosition
SwPageFrame::SidebarPosition() const
1464 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
1465 if( !pSh
|| pSh
->GetViewOptions()->getBrowseMode() )
1467 return sw::sidebarwindows::SidebarPosition::RIGHT
;
1471 const bool bLTR
= getRootFrame()->IsLeftToRightViewLayout();
1472 const bool bBookMode
= pSh
->GetViewOptions()->IsViewLayoutBookMode();
1473 const bool bRightSidebar
= bLTR
? (!bBookMode
|| OnRightPage()) : (bBookMode
&& !OnRightPage());
1475 return bRightSidebar
1476 ? sw::sidebarwindows::SidebarPosition::RIGHT
1477 : sw::sidebarwindows::SidebarPosition::LEFT
;
1481 SwTwips
SwRootFrame::GrowFrame( SwTwips nDist
, bool bTst
, bool )
1485 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1486 aFrm
.AddHeight(nDist
);
1492 SwTwips
SwRootFrame::ShrinkFrame( SwTwips nDist
, bool bTst
, bool )
1494 OSL_ENSURE( nDist
>= 0, "nDist < 0." );
1495 OSL_ENSURE( nDist
<= getFrameArea().Height(), "nDist greater than current size." );
1499 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1500 aFrm
.AddHeight( -nDist
);
1506 void SwRootFrame::RemovePage( SwPageFrame
**pDelRef
, SwRemoveResult eResult
)
1508 SwPageFrame
*pDel
= *pDelRef
;
1509 (*pDelRef
) = static_cast<SwPageFrame
*>(
1510 eResult
== SwRemoveResult::Next
? pDel
->GetNext() : pDel
->GetPrev() );
1511 if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() )
1512 RemoveFootnotes( pDel
, true );
1514 SwFrame::DestroyFrame( pDel
);
1517 /// remove pages that are not needed at all
1518 void SwRootFrame::RemoveSuperfluous()
1520 // A page is empty if the body text area has no ContentFrame, but not if there
1521 // is at least one Fly or one footnote attached to the page. Two runs are
1522 // needed: one for endnote pages and one for the pages of the body text.
1524 if ( !IsSuperfluous() )
1526 mbCheckSuperfluous
= false;
1528 SwPageFrame
*pPage
= GetLastPage();
1529 tools::Long nDocPos
= LONG_MAX
;
1531 // Check the corresponding last page if it is empty and stop loop at the last non-empty page.
1534 if (!sw::IsPageFrameEmpty(*pPage
))
1536 if ( pPage
->IsFootnotePage() )
1538 while ( pPage
->IsFootnotePage() )
1540 pPage
= static_cast<SwPageFrame
*>(pPage
->GetPrev());
1541 OSL_ENSURE( pPage
, "only endnote pages remain." );
1551 SAL_INFO( "sw.pageframe", "RemoveSuperfluous - DestroyFrm p: " << pPage
);
1552 RemovePage( &pPage
, SwRemoveResult::Prev
);
1553 nDocPos
= pPage
? pPage
->getFrameArea().Top() : 0;
1557 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
1558 if ( nDocPos
!= LONG_MAX
&&
1559 (!pSh
|| !pSh
->Imp()->IsUpdateExpFields()) )
1561 GetFormat()->GetDoc()->getIDocumentFieldsAccess().UpdatePageFields(nDocPos
);
1565 /// Ensures that enough pages exist, so that all page bound frames and draw objects can be placed
1566 void SwRootFrame::AssertFlyPages()
1568 if ( !IsAssertFlyPages() )
1570 mbAssertFlyPages
= false;
1572 SwDoc
*pDoc
= GetFormat()->GetDoc();
1573 const sw::SpzFrameFormats
* pSpzs
= pDoc
->GetSpzFrameFormats();
1575 // what page targets the "last" Fly?
1576 // note the needed pages in a set
1577 sal_uInt16
nMaxPg(0);
1578 o3tl::sorted_vector
< sal_uInt16
> neededPages
;
1579 neededPages
.reserve(pSpzs
->size());
1581 for(auto pSpz
: *pSpzs
)
1583 const SwFormatAnchor
&rAnch
= pSpz
->GetAnchor();
1584 if(!rAnch
.GetAnchorNode())
1586 const sal_uInt16
nPageNum(rAnch
.GetPageNum());
1588 // calc MaxPage (as before)
1589 nMaxPg
= std::max(nMaxPg
, nPageNum
);
1591 // note as needed page
1592 neededPages
.insert(nPageNum
);
1596 // How many pages exist at the moment?
1597 // And are there EmptyPages that are needed?
1598 SwPageFrame
* pPage(static_cast<SwPageFrame
*>(Lower()));
1599 SwPageFrame
* pPrevPage(nullptr);
1600 SwPageFrame
* pFirstRevivedEmptyPage(nullptr);
1602 while(pPage
) // moved two while-conditions to break-statements (see below)
1604 const sal_uInt16
nPageNum(pPage
->GetPhyPageNum());
1606 if(pPage
->IsEmptyPage() &&
1607 nullptr != pPrevPage
&&
1608 neededPages
.find(nPageNum
) != neededPages
.end())
1610 // This is an empty page, but it *is* needed since a SwFrame
1611 // is anchored at it directly. Initially these SwFrames are
1612 // not fully initialized. Need to change the format of this SwFrame
1613 // and let the ::Notify mechanism newly evaluate
1614 // m_bEmptyPage (see SwPageFrame::UpdateAttr_). Code is taken and
1615 // adapted from ::InsertPage (used below), this needs previous page
1616 bool bWishedRightPage(!pPrevPage
->OnRightPage());
1617 SwPageDesc
* pDesc(pPrevPage
->GetPageDesc()->GetFollow());
1618 assert(pDesc
&& "Missing PageDesc");
1620 if (!(bWishedRightPage
? pDesc
->GetRightFormat() : pDesc
->GetLeftFormat()))
1622 bWishedRightPage
= !bWishedRightPage
;
1625 bool const bWishedFirst(pDesc
!= pPrevPage
->GetPageDesc());
1626 SwFrameFormat
* pFormat(bWishedRightPage
? pDesc
->GetRightFormat(bWishedFirst
) : pDesc
->GetLeftFormat(bWishedFirst
));
1628 // set SwFrameFormat, this will trigger SwPageFrame::UpdateAttr_ and re-evaluate
1629 // m_bEmptyPage, too
1630 pPage
->SetFrameFormat(pFormat
);
1632 if(nullptr == pFirstRevivedEmptyPage
)
1634 // remember first (lowest) SwPageFrame which needed correction
1635 pFirstRevivedEmptyPage
= pPage
;
1639 // original while-condition II
1640 if(nullptr == pPage
->GetNext())
1645 // original while-condition III
1646 if(static_cast< SwPageFrame
* >(pPage
->GetNext())->IsFootnotePage())
1652 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1655 if ( nMaxPg
> pPage
->GetPhyPageNum() )
1657 for ( sal_uInt16 i
= pPage
->GetPhyPageNum(); i
< nMaxPg
; ++i
)
1658 pPage
= InsertPage( pPage
, false );
1660 // If the endnote pages are now corrupt, destroy them.
1661 if ( !pDoc
->GetFootnoteIdxs().empty() )
1663 pPage
= static_cast<SwPageFrame
*>(Lower());
1664 while ( pPage
&& !pPage
->IsFootnotePage() )
1665 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1669 SwPageDesc
*pTmpDesc
= pPage
->FindPageDesc();
1670 bool isRightPage
= pPage
->OnRightPage();
1671 if ( pPage
->GetFormat() !=
1672 (isRightPage
? pTmpDesc
->GetRightFormat() : pTmpDesc
->GetLeftFormat()) )
1673 RemoveFootnotes( pPage
, false, true );
1678 // if we corrected SwFrameFormat and changed one (or more) m_bEmptyPage
1679 // flags, we need to correct evtl. currently wrong positioned SwFrame(s)
1680 // which did think until now that these Page(s) are empty.
1681 // After trying to correct myself I found SwRootFrame::AssertPageFlys
1682 // directly below that already does that, so use it.
1683 if(nullptr != pFirstRevivedEmptyPage
)
1685 AssertPageFlys(pFirstRevivedEmptyPage
);
1688 //Remove masters that haven't been replaced yet from the list.
1689 RemoveMasterObjs( mpDrawPage
);
1691 #if OSL_DEBUG_LEVEL > 0
1692 pPage
= static_cast<SwPageFrame
*>(Lower());
1693 while ( pPage
&& pPage
->GetNext() &&
1694 !static_cast<SwPageFrame
*>(pPage
->GetNext())->IsFootnotePage() )
1696 SAL_INFO( "sw.pageframe", "AssertFlyPages p: " << pPage
<< " d: " << pPage
->GetPageDesc()
1697 << " f: " << pPage
->GetFormat() << " virt: " << pPage
->GetVirtPageNum()
1698 << " phys: " << pPage
->GetPhyPageNum() << " empty: " << pPage
->IsEmptyPage() );
1699 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1701 SAL_INFO( "sw.pageframe", "AssertFlyPages p: " << pPage
<< " d: " << pPage
->GetPageDesc()
1702 << " f: " << pPage
->GetFormat() << " virt: " << pPage
->GetVirtPageNum()
1703 << " phys: " << pPage
->GetPhyPageNum() << " empty: " << pPage
->IsEmptyPage() );
1707 /// Ensure that after the given page all page-bound objects are located on the correct page
1708 void SwRootFrame::AssertPageFlys( SwPageFrame
*pPage
)
1710 SAL_INFO( "sw.pageframe", "(AssertPageFlys in" );
1713 if (pPage
->GetSortedObjs())
1716 while ( pPage
->GetSortedObjs() && i
< pPage
->GetSortedObjs()->size() )
1719 SwFrameFormat
& rFormat
= (*pPage
->GetSortedObjs())[i
]->GetFrameFormat();
1720 const SwFormatAnchor
&rAnch
= rFormat
.GetAnchor();
1721 const sal_uInt16 nPg
= rAnch
.GetPageNum();
1722 if ((rAnch
.GetAnchorId() == RndStdIds::FLY_AT_PAGE
) &&
1723 nPg
!= pPage
->GetPhyPageNum() )
1725 SAL_INFO( "sw.pageframe", nPg
<< " " << pPage
->GetPhyPageNum() );
1726 // If on the wrong page, check if previous page is empty
1727 if( nPg
&& !(pPage
->GetPhyPageNum()-1 == nPg
&&
1728 static_cast<SwPageFrame
*>(pPage
->GetPrev())->IsEmptyPage()) )
1730 // It can move by itself. Just send a modify to its anchor attribute.
1731 #if OSL_DEBUG_LEVEL > 1
1732 const size_t nCnt
= pPage
->GetSortedObjs()->size();
1733 rFormat
.CallSwClientNotify(sw::LegacyModifyHint(nullptr, &rAnch
));
1734 OSL_ENSURE( !pPage
->GetSortedObjs() ||
1735 nCnt
!= pPage
->GetSortedObjs()->size(),
1736 "Object couldn't be reattached!" );
1738 rFormat
.CallSwClientNotify(sw::LegacyModifyHint(nullptr, &rAnch
));
1740 // Do not increment index, in this case
1747 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
1749 SAL_INFO( "sw.pageframe", "AssertPageFlys out)" );
1752 Size
SwRootFrame::ChgSize( const Size
& aNewSize
)
1755 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1756 aFrm
.SSize(aNewSize
);
1761 return getFrameArea().SSize();
1764 void SwRootFrame::MakeAll(vcl::RenderContext
* /*pRenderContext*/)
1766 if ( !isFrameAreaPositionValid() )
1768 setFrameAreaPositionValid(true);
1769 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1770 aFrm
.Pos().setX(DOCUMENTBORDER
);
1771 aFrm
.Pos().setY(DOCUMENTBORDER
);
1774 if ( !isFramePrintAreaValid() )
1776 setFramePrintAreaValid(true);
1777 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1780 aPrt
.SSize( getFrameArea().SSize() );
1783 if ( !isFrameAreaSizeValid() )
1785 // SSize is set by the pages (Cut/Paste).
1786 setFrameAreaSizeValid(true);
1790 void SwRootFrame::ImplInvalidateBrowseWidth()
1792 mbBrowseWidthValid
= false;
1793 SwFrame
*pPg
= Lower();
1796 pPg
->InvalidateSize();
1797 pPg
= pPg
->GetNext();
1801 void SwRootFrame::ImplCalcBrowseWidth()
1803 OSL_ENSURE( GetCurrShell() && GetCurrShell()->GetViewOptions()->getBrowseMode(),
1804 "CalcBrowseWidth and not in BrowseView" );
1806 // The (minimal) with is determined from borders, tables and paint objects.
1807 // It is calculated based on the attributes. Thus, it is not relevant how wide they are
1808 // currently but only how wide they want to be.
1809 // Frames and paint objects inside other objects (frames, tables) do not count.
1810 // Borders and columns are not taken into account.
1812 SwFrame
*pFrame
= ContainsContent();
1813 while ( pFrame
&& !pFrame
->IsInDocBody() )
1814 pFrame
= static_cast<SwContentFrame
*>(pFrame
)->GetNextContentFrame();
1818 mbBrowseWidthValid
= true;
1819 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
1820 mnBrowseWidth
= (!comphelper::LibreOfficeKit::isActive() && pSh
)? MINLAY
+ 2 * pSh
->GetOut()-> PixelToLogic( pSh
->GetBrowseBorder() ).Width(): MIN_BROWSE_WIDTH
;
1824 if ( pFrame
->IsInTab() )
1825 pFrame
= pFrame
->FindTabFrame();
1827 if ( pFrame
->IsTabFrame() &&
1828 !static_cast<SwLayoutFrame
*>(pFrame
)->GetFormat()->GetFrameSize().GetWidthPercent() )
1830 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), pFrame
);
1831 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
1832 const SwFormatHoriOrient
&rHori
= rAttrs
.GetAttrSet().GetHoriOrient();
1833 tools::Long nWidth
= rAttrs
.GetSize().Width();
1834 if ( nWidth
< int(USHRT_MAX
)-2000 && //-2k, because USHRT_MAX gets missing while trying to resize! (and cast to int to avoid -Wsign-compare due to broken USHRT_MAX on Android)
1835 text::HoriOrientation::FULL
!= rHori
.GetHoriOrient() )
1837 const SwHTMLTableLayout
*pLayoutInfo
=
1838 static_cast<const SwTabFrame
*>(pFrame
)->GetTable()
1839 ->GetHTMLTableLayout();
1841 nWidth
= std::min( nWidth
, pLayoutInfo
->GetBrowseWidthMin() );
1843 switch ( rHori
.GetHoriOrient() )
1845 case text::HoriOrientation::NONE
:
1846 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
1847 nWidth
+= rAttrs
.CalcLeft( pFrame
) + rAttrs
.CalcRight( pFrame
);
1849 case text::HoriOrientation::LEFT_AND_WIDTH
:
1850 nWidth
+= rAttrs
.CalcLeft( pFrame
);
1855 mnBrowseWidth
= std::max( mnBrowseWidth
, nWidth
);
1858 else if ( pFrame
->GetDrawObjs() )
1860 for ( size_t i
= 0; i
< pFrame
->GetDrawObjs()->size(); ++i
)
1863 SwAnchoredObject
* pAnchoredObj
= (*pFrame
->GetDrawObjs())[i
];
1864 const SwFrameFormat
& rFormat
= pAnchoredObj
->GetFrameFormat();
1865 const bool bFly
= pAnchoredObj
->DynCastFlyFrame() != nullptr;
1866 if ((bFly
&& (FAR_AWAY
== pAnchoredObj
->GetObjRect().Width()))
1867 || rFormat
.GetFrameSize().GetWidthPercent())
1872 tools::Long nWidth
= 0;
1873 switch ( rFormat
.GetAnchor().GetAnchorId() )
1875 case RndStdIds::FLY_AS_CHAR
:
1876 nWidth
= bFly
? rFormat
.GetFrameSize().GetWidth() :
1877 pAnchoredObj
->GetObjRect().Width();
1879 case RndStdIds::FLY_AT_PARA
:
1882 // Reactivated old code because
1883 // nWidth = pAnchoredObj->GetObjRect().Right()
1884 // gives wrong results for objects that are still
1885 // at position FAR_AWAY.
1888 nWidth
= rFormat
.GetFrameSize().GetWidth();
1889 const SwFormatHoriOrient
&rHori
= rFormat
.GetHoriOrient();
1890 switch ( rHori
.GetHoriOrient() )
1892 case text::HoriOrientation::NONE
:
1893 nWidth
+= rHori
.GetPos();
1895 case text::HoriOrientation::INSIDE
:
1896 case text::HoriOrientation::LEFT
:
1897 if ( text::RelOrientation::PRINT_AREA
== rHori
.GetRelationOrient() )
1898 nWidth
+= pFrame
->getFramePrintArea().Left();
1905 // Paint objects to not have attributes and
1906 // are defined by their current size
1907 nWidth
= pAnchoredObj
->GetObjRect().Right() -
1908 pAnchoredObj
->GetDrawObj()->GetAnchorPos().X();
1911 default: /* do nothing */;
1913 mnBrowseWidth
= std::max( mnBrowseWidth
, nWidth
);
1916 pFrame
= pFrame
->FindNextCnt();
1920 void SwRootFrame::StartAllAction()
1922 if ( GetCurrShell() )
1923 for(SwViewShell
& rSh
: GetCurrShell()->GetRingContainer())
1925 if ( auto pCursorShell
= dynamic_cast<SwCursorShell
*>( &rSh
) )
1926 pCursorShell
->StartAction();
1932 void SwRootFrame::EndAllAction()
1934 if ( !GetCurrShell() )
1937 for(SwViewShell
& rSh
: GetCurrShell()->GetRingContainer())
1939 if ( auto pCursorShell
= dynamic_cast<SwCursorShell
*>( &rSh
) )
1941 pCursorShell
->EndAction();
1942 pCursorShell
->CallChgLnk();
1943 if ( auto pFEShell
= dynamic_cast<SwFEShell
*>( &rSh
) )
1944 pFEShell
->SetChainMarker();
1951 void SwRootFrame::UnoRemoveAllActions()
1953 if ( !GetCurrShell() )
1956 for(SwViewShell
& rSh
: GetCurrShell()->GetRingContainer())
1959 // No end action, if <SwViewShell> instance is currently in its end action.
1960 // Recursive calls to <::EndAction()> are not allowed.
1961 if ( !rSh
.IsInEndAction() )
1963 OSL_ENSURE(!rSh
.GetRestoreActions(), "Restore action count is already set!");
1964 bool bCursor
= dynamic_cast<const SwCursorShell
*>( &rSh
) != nullptr;
1965 bool bFE
= dynamic_cast<const SwFEShell
*>( &rSh
) != nullptr;
1966 sal_uInt16 nRestore
= 0;
1967 while( rSh
.ActionCount() )
1971 static_cast<SwCursorShell
*>(&rSh
)->EndAction();
1972 static_cast<SwCursorShell
*>(&rSh
)->CallChgLnk();
1974 static_cast<SwFEShell
*>(&rSh
)->SetChainMarker();
1980 rSh
.SetRestoreActions(nRestore
);
1986 void SwRootFrame::UnoRestoreAllActions()
1988 if ( !GetCurrShell() )
1991 for(SwViewShell
& rSh
: GetCurrShell()->GetRingContainer())
1993 sal_uInt16 nActions
= rSh
.GetRestoreActions();
1996 if ( auto pCursorShell
= dynamic_cast<SwCursorShell
*>( &rSh
) )
1997 pCursorShell
->StartAction();
2001 rSh
.SetRestoreActions(0);
2002 rSh
.LockView(false);
2006 // Helper functions for SwRootFrame::CheckViewLayout
2007 static void lcl_MoveAllLowers( SwFrame
* pFrame
, const Point
& rOffset
);
2009 static void lcl_MoveAllLowerObjs( SwFrame
* pFrame
, const Point
& rOffset
)
2011 const bool bPage
= pFrame
->IsPageFrame();
2012 const SwSortedObjs
* pSortedObj
= bPage
2013 ? static_cast<SwPageFrame
*>(pFrame
)->GetSortedObjs()
2014 : pFrame
->GetDrawObjs();
2015 if (pSortedObj
== nullptr)
2018 // note: pSortedObj elements may be removed and inserted from
2019 // MoveObjectIfActive(), invalidating iterators
2020 // DO NOT CONVERT THIS TO A C++11 FOR LOOP, IT DID NOT WORK THE LAST 2 TIMES
2021 for (size_t i
= 0; i
< pSortedObj
->size(); ++i
)
2023 SwAnchoredObject
*const pAnchoredObj
= (*pSortedObj
)[i
];
2024 const SwFrameFormat
& rObjFormat
= pAnchoredObj
->GetFrameFormat();
2025 const SwFormatAnchor
& rAnchor
= rObjFormat
.GetAnchor();
2027 // all except from the as character anchored objects are moved
2028 // when processing the page frame:
2029 if ( !bPage
&& (rAnchor
.GetAnchorId() != RndStdIds::FLY_AS_CHAR
) )
2032 SwObjPositioningInProgress
aPosInProgress( *pAnchoredObj
);
2034 if ( auto pFlyFrame
= pAnchoredObj
->DynCastFlyFrame() )
2036 lcl_MoveAllLowers( pFlyFrame
, rOffset
);
2037 // tdf#138785 update position specific to as-char flys
2038 if (pFlyFrame
->IsFlyInContentFrame())
2040 static_cast<SwFlyInContentFrame
*>(pFlyFrame
)->AddRefOfst(rOffset
);
2042 pFlyFrame
->NotifyDrawObj();
2043 // --> let the active embedded object be moved
2044 SwFrame
* pLower
= pFlyFrame
->Lower();
2045 if ( pLower
&& pLower
->IsNoTextFrame() )
2047 SwRootFrame
* pRoot
= pLower
->getRootFrame();
2048 SwViewShell
*pSh
= pRoot
? pRoot
->GetCurrShell() : nullptr;
2051 SwNoTextFrame
*const pContentFrame
= static_cast<SwNoTextFrame
*>(pLower
);
2052 SwOLENode
* pNode
= pContentFrame
->GetNode()->GetOLENode();
2055 svt::EmbeddedObjectRef
& xObj
= pNode
->GetOLEObj().GetObject();
2058 for(SwViewShell
& rSh
: pSh
->GetRingContainer())
2060 SwFEShell
* pFEShell
= dynamic_cast< SwFEShell
* >( &rSh
);
2062 pFEShell
->MoveObjectIfActive( xObj
, rOffset
);
2069 else if ( auto pAnchoredDrawObj
= dynamic_cast<SwAnchoredDrawObject
*>( pAnchoredObj
) )
2071 // don't touch objects that are not yet positioned:
2072 if ( pAnchoredDrawObj
->NotYetPositioned() )
2075 const Point
& aCurrAnchorPos
= pAnchoredDrawObj
->GetDrawObj()->GetAnchorPos();
2076 const Point
aNewAnchorPos( aCurrAnchorPos
+ rOffset
);
2077 pAnchoredDrawObj
->DrawObj()->SetAnchorPos( aNewAnchorPos
);
2078 pAnchoredDrawObj
->SetLastObjRect( pAnchoredDrawObj
->GetObjRect().SVRect() );
2080 // clear contour cache
2081 if ( pAnchoredDrawObj
->GetFrameFormat().GetSurround().IsContour() )
2082 ClrContourCache( pAnchoredDrawObj
->GetDrawObj() );
2085 // cache for object rectangle inclusive spaces has to be invalidated.
2086 pAnchoredObj
->InvalidateObjRectWithSpaces();
2090 static void lcl_MoveAllLowers( SwFrame
* pFrame
, const Point
& rOffset
)
2092 // first move the current frame
2093 // RotateFlyFrame3: moved to transform_translate instead of
2094 // direct modification to allow the SwFrame evtl. needed own reactions
2095 pFrame
->transform_translate(rOffset
);
2097 // Don't forget accessibility:
2098 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2099 if( pFrame
->IsAccessibleFrame() )
2101 SwRootFrame
*pRootFrame
= pFrame
->getRootFrame();
2102 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
2103 pRootFrame
->GetCurrShell() )
2105 const SwRect
aFrame( pFrame
->getFrameArea() );
2107 pRootFrame
->GetCurrShell()->Imp()->MoveAccessibleFrame( pFrame
, aFrame
);
2112 // the move any objects
2113 lcl_MoveAllLowerObjs( pFrame
, rOffset
);
2115 // finally, for layout frames we have to call this function recursively:
2116 if (pFrame
->IsLayoutFrame())
2118 SwFrame
* pLowerFrame
= pFrame
->GetLower();
2119 while ( pLowerFrame
)
2121 lcl_MoveAllLowers( pLowerFrame
, rOffset
);
2122 pLowerFrame
= pLowerFrame
->GetNext();
2127 // Calculate how the pages have to be positioned
2128 void SwRootFrame::CheckViewLayout( const SwViewOption
* pViewOpt
, const SwRect
* pVisArea
)
2130 SwViewShell
* pSh
= GetCurrShell();
2131 vcl::RenderContext
* pRenderContext
= pSh
? pSh
->GetOut() : nullptr;
2133 // No calculation of page positions, if only an empty page is present.
2134 // This situation occurs when <SwRootFrame> instance is in construction
2135 // and the document contains only left pages.
2136 if ( Lower()->GetNext() == nullptr &&
2137 static_cast<SwPageFrame
*>(Lower())->IsEmptyPage() )
2144 // no early return for bNewPage
2145 if ( mnViewWidth
< 0 )
2150 assert(pViewOpt
&& "CheckViewLayout required ViewOptions");
2152 const sal_uInt16 nColumns
= pViewOpt
->GetViewLayoutColumns();
2153 const bool bBookMode
= pViewOpt
->IsViewLayoutBookMode();
2155 if ( nColumns
== mnColumns
&& bBookMode
== mbBookMode
&& pVisArea
->Width() == mnViewWidth
&& !mbSidebarChanged
)
2158 mnColumns
= nColumns
;
2159 mbBookMode
= bBookMode
;
2160 mnViewWidth
= pVisArea
->Width();
2161 mbSidebarChanged
= false;
2164 if( GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE
) )
2170 Calc(pRenderContext
);
2172 const bool bOldCallbackActionEnabled
= IsCallbackActionEnabled();
2173 SetCallbackActionEnabled( false );
2175 maPageRects
.clear();
2177 const tools::Long nBorder
= getFrameArea().Pos().getX();
2178 const tools::Long nVisWidth
= mnViewWidth
- 2 * nBorder
;
2179 const tools::Long nGapBetweenPages
= pViewOpt
? pViewOpt
->GetGapBetweenPages()
2180 : (pSh
? pSh
->GetViewOptions()->GetGapBetweenPages()
2181 : SwViewOption::defGapBetweenPages
);
2183 // check how many pages fit into the first page layout row:
2184 SwPageFrame
* pPageFrame
= static_cast<SwPageFrame
*>(Lower());
2186 // will contain the number of pages per row. 0 means that
2187 // the page does not fit.
2188 tools::Long nWidthRemain
= nVisWidth
;
2190 // after one row has been processed, these variables contain
2191 // the width of the row and the maximum of the page heights
2192 tools::Long nCurrentRowHeight
= 0;
2193 tools::Long nCurrentRowWidth
= 0;
2195 // these variables are used to finally set the size of the
2197 tools::Long nSumRowHeight
= 0;
2198 SwTwips nMinPageLeft
= TWIPS_MAX
;
2199 SwTwips nMaxPageRight
= 0;
2200 SwPageFrame
* pStartOfRow
= pPageFrame
;
2201 sal_uInt16 nNumberOfPagesInRow
= mbBookMode
? 1 : 0; // in book view, start with right page
2202 bool bFirstRow
= true;
2204 bool bPageChanged
= false;
2205 const bool bRTL
= !IsLeftToRightViewLayout();
2206 const SwTwips nSidebarWidth
= SwPageFrame::GetSidebarBorderWidth( pSh
);
2208 while ( pPageFrame
)
2210 // we consider the current page to be "start of row" if
2211 // 1. it is the first page in the current row or
2212 // 2. it is the second page in the row and the first page is an empty page in non-book view:
2213 const bool bStartOfRow
= pPageFrame
== pStartOfRow
||
2214 ( pStartOfRow
->IsEmptyPage() && pPageFrame
== pStartOfRow
->GetNext() && !mbBookMode
);
2216 const bool bEmptyPage
= pPageFrame
->IsEmptyPage() && !mbBookMode
;
2218 // no half doc border space for first page in each row and
2219 tools::Long nPageWidth
= 0;
2220 tools::Long nPageHeight
= 0;
2224 const SwFrame
& rFormatPage
= pPageFrame
->GetFormatPage();
2226 nPageWidth
= rFormatPage
.getFrameArea().Width() + nSidebarWidth
+ ((bStartOfRow
|| 1 == (pPageFrame
->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages
);
2227 nPageHeight
= rFormatPage
.getFrameArea().Height() + nGapBetweenPages
;
2231 if ( !pPageFrame
->IsEmptyPage() )
2233 nPageWidth
= pPageFrame
->getFrameArea().Width() + nSidebarWidth
+ (bStartOfRow
? 0 : nGapBetweenPages
);
2234 nPageHeight
= pPageFrame
->getFrameArea().Height() + nGapBetweenPages
;
2239 ++nNumberOfPagesInRow
;
2241 // finish current row if
2242 // 1. in dynamic mode the current page does not fit anymore or
2243 // 2. the current page exceeds the maximum number of columns
2244 bool bRowFinished
= (0 == mnColumns
&& nWidthRemain
< nPageWidth
) ||
2245 (0 != mnColumns
&& mnColumns
< nNumberOfPagesInRow
);
2247 // make sure that at least one page goes to the current row:
2248 if ( !bRowFinished
|| bStartOfRow
)
2250 // current page is allowed to be in current row
2251 nWidthRemain
= nWidthRemain
- nPageWidth
;
2253 nCurrentRowWidth
= nCurrentRowWidth
+ nPageWidth
;
2254 nCurrentRowHeight
= std::max( nCurrentRowHeight
, nPageHeight
);
2256 pPageFrame
= static_cast<SwPageFrame
*>(pPageFrame
->GetNext());
2259 bRowFinished
= true;
2264 // pPageFrame now points to the first page in the new row or null
2265 // pStartOfRow points to the first page in the current row
2267 // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
2268 if ( !pPageFrame
&& nWidthRemain
> 0 )
2270 // find last page in current row:
2271 const SwPageFrame
* pLastPageInCurrentRow
= pStartOfRow
;
2272 while( pLastPageInCurrentRow
->GetNext() )
2273 pLastPageInCurrentRow
= static_cast<const SwPageFrame
*>(pLastPageInCurrentRow
->GetNext());
2275 if ( pLastPageInCurrentRow
->IsEmptyPage() )
2276 pLastPageInCurrentRow
= static_cast<const SwPageFrame
*>(pLastPageInCurrentRow
->GetPrev());
2278 // check how many times the last page would still fit into the remaining space:
2279 sal_uInt16 nNumberOfVirtualPages
= 0;
2280 const sal_uInt16 nMaxNumberOfVirtualPages
= mnColumns
> 0 ? mnColumns
- nNumberOfPagesInRow
: USHRT_MAX
;
2281 SwTwips nRemain
= nWidthRemain
;
2282 SwTwips nVirtualPagesWidth
= 0;
2283 SwTwips nLastPageWidth
= pLastPageInCurrentRow
->getFrameArea().Width() + nSidebarWidth
;
2285 while ( ( mnColumns
> 0 || nRemain
> 0 ) && nNumberOfVirtualPages
< nMaxNumberOfVirtualPages
)
2287 SwTwips nLastPageWidthWithGap
= nLastPageWidth
;
2288 if ( !mbBookMode
|| ( 0 == (nNumberOfVirtualPages
+ nNumberOfPagesInRow
) %2) )
2289 nLastPageWidthWithGap
+= nGapBetweenPages
;
2291 if ( mnColumns
> 0 || nLastPageWidthWithGap
< nRemain
)
2293 ++nNumberOfVirtualPages
;
2294 nVirtualPagesWidth
+= nLastPageWidthWithGap
;
2296 nRemain
= nRemain
- nLastPageWidthWithGap
;
2299 nCurrentRowWidth
= nCurrentRowWidth
+ nVirtualPagesWidth
;
2302 // first page in book mode is always special:
2303 if ( bFirstRow
&& mbBookMode
)
2307 pStartOfRow
->GetFormatPage().getFrameArea().Width() + nSidebarWidth
;
2310 // center page if possible
2311 tools::Long nSizeDiff
= 0;
2312 if (nVisWidth
> nCurrentRowWidth
&& !comphelper::LibreOfficeKit::isActive())
2313 nSizeDiff
= ( nVisWidth
- nCurrentRowWidth
) / 2;
2315 // adjust positions of pages in current row
2316 tools::Long nX
= nSizeDiff
;
2318 const tools::Long nRowStart
= nBorder
+ nSizeDiff
;
2319 const tools::Long nRowEnd
= nRowStart
+ nCurrentRowWidth
;
2321 if ( bFirstRow
&& mbBookMode
)
2324 nX
+= pStartOfRow
->GetFormatPage().getFrameArea().Width() + nSidebarWidth
;
2327 SwPageFrame
* pEndOfRow
= pPageFrame
;
2328 SwPageFrame
* pPageToAdjust
= pStartOfRow
;
2332 const SwPageFrame
* pFormatPage
= pPageToAdjust
;
2334 pFormatPage
= &pPageToAdjust
->GetFormatPage();
2336 const SwTwips nCurrentPageWidth
= pFormatPage
->getFrameArea().Width() + (pFormatPage
->IsEmptyPage() ? 0 : nSidebarWidth
);
2337 const Point aOldPagePos
= pPageToAdjust
->getFrameArea().Pos();
2338 const bool bLeftSidebar
= pPageToAdjust
->SidebarPosition() == sw::sidebarwindows::SidebarPosition::LEFT
;
2339 const SwTwips nLeftPageAddOffset
= bLeftSidebar
?
2343 Point
aNewPagePos( nBorder
+ nX
, nBorder
+ nSumRowHeight
);
2344 Point
aNewPagePosWithLeftOffset( nBorder
+ nX
+ nLeftPageAddOffset
, nBorder
+ nSumRowHeight
);
2346 // RTL view layout: Calculate mirrored page position
2349 const tools::Long nXOffsetInRow
= aNewPagePos
.getX() - nRowStart
;
2350 aNewPagePos
.setX(nRowEnd
- nXOffsetInRow
- nCurrentPageWidth
);
2351 aNewPagePosWithLeftOffset
= aNewPagePos
;
2352 aNewPagePosWithLeftOffset
.setX(aNewPagePosWithLeftOffset
.getX() + nLeftPageAddOffset
);
2355 if ( aNewPagePosWithLeftOffset
!= aOldPagePos
)
2357 lcl_MoveAllLowers( pPageToAdjust
, aNewPagePosWithLeftOffset
- aOldPagePos
);
2358 pPageToAdjust
->SetCompletePaint();
2359 bPageChanged
= true;
2362 // calculate area covered by the current page and store to
2363 // maPageRects. This is used e.g., for cursor setting
2364 const bool bFirstColumn
= pPageToAdjust
== pStartOfRow
;
2365 const bool bLastColumn
= pPageToAdjust
->GetNext() == pEndOfRow
;
2366 const bool bLastRow
= !pEndOfRow
;
2368 nMinPageLeft
= std::min( nMinPageLeft
, SwTwips(aNewPagePos
.getX()) );
2369 nMaxPageRight
= std::max( nMaxPageRight
, SwTwips(aNewPagePos
.getX() + nCurrentPageWidth
));
2371 // border of nGapBetweenPages around the current page:
2372 SwRect
aPageRectWithBorders( aNewPagePos
.getX() - nGapBetweenPages
,
2374 pPageToAdjust
->getFrameArea().SSize().Width() + nGapBetweenPages
+ nSidebarWidth
,
2375 nCurrentRowHeight
);
2377 static const tools::Long nOuterClickDiff
= 1000000;
2379 // adjust borders for these special cases:
2380 if ( (bFirstColumn
&& !bRTL
) || (bLastColumn
&& bRTL
) )
2381 aPageRectWithBorders
.SubLeft( nOuterClickDiff
);
2382 if ( (bLastColumn
&& !bRTL
) || (bFirstColumn
&& bRTL
) )
2383 aPageRectWithBorders
.AddRight( nOuterClickDiff
);
2385 aPageRectWithBorders
.SubTop( nOuterClickDiff
);
2387 aPageRectWithBorders
.AddBottom( nOuterClickDiff
);
2389 maPageRects
.push_back( aPageRectWithBorders
);
2391 nX
= nX
+ nCurrentPageWidth
;
2392 pPageToAdjust
= static_cast<SwPageFrame
*>(pPageToAdjust
->GetNext());
2394 // distance to next page
2395 if ( pPageToAdjust
&& pPageToAdjust
!= pEndOfRow
)
2397 // in book view, we add the x gap before left (even) pages:
2400 if ( 0 == (pPageToAdjust
->GetPhyPageNum()%2) )
2401 nX
= nX
+ nGapBetweenPages
;
2405 // in non-book view, don't add x gap before
2406 // 1. the last empty page in a row
2407 // 2. after an empty page
2408 const bool bDontAddGap
= ( pPageToAdjust
->IsEmptyPage() && pPageToAdjust
->GetNext() == pEndOfRow
) ||
2409 ( static_cast<SwPageFrame
*>(pPageToAdjust
->GetPrev())->IsEmptyPage() );
2412 nX
= nX
+ nGapBetweenPages
;
2416 while (pPageToAdjust
&& pPageToAdjust
!= pEndOfRow
);
2418 // adjust values for root frame size
2419 nSumRowHeight
= nSumRowHeight
+ nCurrentRowHeight
;
2422 nCurrentRowHeight
= 0;
2423 nCurrentRowWidth
= 0;
2424 pStartOfRow
= pEndOfRow
;
2425 nWidthRemain
= nVisWidth
;
2426 nNumberOfPagesInRow
= 0;
2428 } // end row finished
2431 // set size of root frame:
2432 const Size
aOldSize( getFrameArea().SSize() );
2433 const Size
aNewSize( nMaxPageRight
- nBorder
, nSumRowHeight
- nGapBetweenPages
);
2435 if ( bPageChanged
|| aNewSize
!= aOldSize
)
2437 ChgSize( aNewSize
);
2438 ::AdjustSizeChgNotify( this );
2439 Calc(pRenderContext
);
2441 if ( pSh
&& pSh
->GetDoc()->GetDocShell() )
2443 pSh
->SetFirstVisPageInvalid();
2444 if (bOldCallbackActionEnabled
)
2446 pSh
->InvalidateWindows( SwRect( 0, 0, SAL_MAX_INT32
, SAL_MAX_INT32
) );
2447 pSh
->GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged
));
2452 maPagesArea
.Pos( getFrameArea().Pos() );
2453 maPagesArea
.SSize( aNewSize
);
2454 if ( TWIPS_MAX
!= nMinPageLeft
)
2455 maPagesArea
.Left_( nMinPageLeft
);
2457 SetCallbackActionEnabled( bOldCallbackActionEnabled
);
2460 bool SwRootFrame::IsLeftToRightViewLayout() const
2462 // Layout direction determined by layout direction of the first page.
2464 // Only ask a non-empty page frame for its layout direction
2465 assert(dynamic_cast<const SwPageFrame
*>(Lower()) != nullptr);
2466 const SwPageFrame
& rPage
= static_cast<const SwPageFrame
&>(*Lower()).GetFormatPage();
2467 return !rPage
.IsRightToLeft() && !rPage
.IsVertical();
2470 const SwPageFrame
& SwPageFrame::GetFormatPage() const
2472 const SwPageFrame
* pRet
= this;
2473 if ( IsEmptyPage() )
2475 pRet
= static_cast<const SwPageFrame
*>( OnRightPage() ? GetNext() : GetPrev() );
2477 // Typically a right empty page frame has a next non-empty page frame and
2478 // a left empty page frame has a previous non-empty page frame.
2479 // But under certain circumstances this assumption is not true -
2480 // e.g. during insertion of a left page at the end of the document right
2481 // after a left page in an intermediate state a right empty page does not
2482 // have a next page frame.
2483 if ( pRet
== nullptr )
2485 if ( OnRightPage() )
2487 pRet
= static_cast<const SwPageFrame
*>( GetPrev() );
2491 pRet
= static_cast<const SwPageFrame
*>( GetNext() );
2495 "<SwPageFrame::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash.");
2500 bool SwPageFrame::IsOverHeaderFooterArea( const Point
& rPt
, FrameControlType
&rControl
) const
2502 tools::Long nUpperLimit
= 0;
2503 tools::Long nLowerLimit
= 0;
2504 const SwFrame
* pFrame
= Lower();
2507 if ( pFrame
->IsBodyFrame() )
2509 nUpperLimit
= pFrame
->getFrameArea().Top();
2510 nLowerLimit
= pFrame
->getFrameArea().Bottom();
2512 else if ( pFrame
->IsFootnoteContFrame() )
2513 nLowerLimit
= pFrame
->getFrameArea().Bottom();
2515 pFrame
= pFrame
->GetNext();
2518 SwRect
aHeaderArea( getFrameArea().TopLeft(),
2519 Size( getFrameArea().Width(), nUpperLimit
- getFrameArea().Top() ) );
2521 SwViewShell
* pViewShell
= getRootFrame()->GetCurrShell();
2522 const bool bHideWhitespaceMode
= pViewShell
->GetViewOptions()->IsHideWhitespaceMode();
2523 if ( aHeaderArea
.Contains( rPt
) )
2525 if (!bHideWhitespaceMode
|| static_cast<const SwFrameFormat
*>(GetDep())->GetHeader().IsActive())
2527 rControl
= FrameControlType::Header
;
2533 SwRect
aFooterArea( Point( getFrameArea().Left(), nLowerLimit
),
2534 Size( getFrameArea().Width(), getFrameArea().Bottom() - nLowerLimit
) );
2536 if ( aFooterArea
.Contains( rPt
) &&
2537 (!bHideWhitespaceMode
|| static_cast<const SwFrameFormat
*>(GetDep())->GetFooter().IsActive()) )
2539 rControl
= FrameControlType::Footer
;
2547 bool SwPageFrame::CheckPageHeightValidForHideWhitespace(SwTwips nDiff
)
2549 SwViewShell
* pShell
= getRootFrame()->GetCurrShell();
2550 if (pShell
&& pShell
->GetViewOptions()->IsWhitespaceHidden())
2552 // When whitespace is hidden, the page frame has two heights: the
2553 // nominal (defined by the frame format), and the actual (which is
2554 // at most the nominal height, but can be smaller in case there is
2555 // no content for the whole page).
2556 // The layout size is the actual one, but we want to move the
2557 // content frame to a new page only in case it doesn't fit the
2561 // Content frame doesn't fit the actual size, check if it fits the nominal one.
2562 const SwFrameFormat
* pPageFormat
= static_cast<const SwFrameFormat
*>(GetDep());
2563 const Size
& rPageSize
= pPageFormat
->GetFrameSize().GetSize();
2564 tools::Long nWhitespace
= rPageSize
.getHeight() - getFrameArea().Height();
2565 if (nWhitespace
> -nDiff
)
2567 // It does: don't move it and invalidate our page frame so
2568 // that it gets a larger height.
2577 const SwHeaderFrame
* SwPageFrame::GetHeaderFrame() const
2579 const SwFrame
* pLowerFrame
= Lower();
2582 if (pLowerFrame
->IsHeaderFrame())
2583 return dynamic_cast<const SwHeaderFrame
*>(pLowerFrame
);
2584 pLowerFrame
= pLowerFrame
->GetNext();
2589 const SwFooterFrame
* SwPageFrame::GetFooterFrame() const
2591 const SwFrame
* pLowerFrame
= Lower();
2594 if (pLowerFrame
->IsFooterFrame())
2595 return dynamic_cast<const SwFooterFrame
*>(pLowerFrame
);
2596 pLowerFrame
= pLowerFrame
->GetNext();
2601 void SwPageFrame::dumpAsXml(xmlTextWriterPtr writer
) const
2603 (void)xmlTextWriterStartElement(writer
, reinterpret_cast<const xmlChar
*>("page"));
2604 dumpAsXmlAttributes(writer
);
2606 (void)xmlTextWriterStartElement(writer
, BAD_CAST("page_status"));
2607 (void)xmlTextWriterWriteAttribute(writer
, BAD_CAST("ValidFlyLayout"), BAD_CAST(OString::boolean(!IsInvalidFlyLayout()).getStr()));
2608 (void)xmlTextWriterWriteAttribute(writer
, BAD_CAST("ValidFlyContent"), BAD_CAST(OString::boolean(!IsInvalidFlyContent()).getStr()));
2609 (void)xmlTextWriterWriteAttribute(writer
, BAD_CAST("ValidFlyInCnt"), BAD_CAST(OString::boolean(!IsInvalidFlyInCnt()).getStr()));
2610 (void)xmlTextWriterWriteAttribute(writer
, BAD_CAST("ValidLayout"), BAD_CAST(OString::boolean(!IsInvalidLayout()).getStr()));
2611 (void)xmlTextWriterWriteAttribute(writer
, BAD_CAST("ValidContent"), BAD_CAST(OString::boolean(!IsInvalidContent()).getStr()));
2612 (void)xmlTextWriterEndElement(writer
);
2613 (void)xmlTextWriterStartElement(writer
, BAD_CAST("page_info"));
2614 (void)xmlTextWriterWriteFormatAttribute(writer
, BAD_CAST("phyNum"), "%d", GetPhyPageNum());
2615 (void)xmlTextWriterWriteFormatAttribute(writer
, BAD_CAST("virtNum"), "%d", GetVirtPageNum());
2616 OUString aFormatName
= GetPageDesc()->GetName();
2617 (void)xmlTextWriterWriteFormatAttribute( writer
, BAD_CAST("pageDesc"), "%s", BAD_CAST(OUStringToOString(aFormatName
, RTL_TEXTENCODING_UTF8
).getStr()));
2618 (void)xmlTextWriterEndElement(writer
);
2619 if (auto const* pObjs
= GetSortedObjs())
2621 (void)xmlTextWriterStartElement(writer
, BAD_CAST("sorted_objs"));
2622 for (SwAnchoredObject
const*const pObj
: *pObjs
)
2623 { // just print pointer, full details will be printed on its anchor frame
2624 // this nonsense is needed because of multiple inheritance
2625 if (SwFlyFrame
const* pFly
= pObj
->DynCastFlyFrame())
2627 (void)xmlTextWriterStartElement(writer
, BAD_CAST("fly"));
2628 (void)xmlTextWriterWriteFormatAttribute(writer
, BAD_CAST("ptr"), "%p", pFly
);
2632 (void)xmlTextWriterStartElement(writer
, BAD_CAST(pObj
->getElementName()));
2633 (void)xmlTextWriterWriteFormatAttribute(writer
, BAD_CAST("ptr"), "%p", pObj
);
2635 (void)xmlTextWriterEndElement(writer
);
2637 (void)xmlTextWriterEndElement(writer
);
2640 (void)xmlTextWriterStartElement(writer
, BAD_CAST("infos"));
2641 dumpInfosAsXml(writer
);
2642 (void)xmlTextWriterEndElement(writer
);
2643 const SwSortedObjs
* pAnchored
= GetDrawObjs();
2644 if ( pAnchored
&& pAnchored
->size() > 0 )
2646 (void)xmlTextWriterStartElement( writer
, BAD_CAST( "anchored" ) );
2648 for (SwAnchoredObject
* pObject
: *pAnchored
)
2650 pObject
->dumpAsXml( writer
);
2653 (void)xmlTextWriterEndElement( writer
);
2655 dumpChildrenAsXml(writer
);
2656 (void)xmlTextWriterEndElement(writer
);
2659 SwTextGridItem
const* GetGridItem(SwPageFrame
const*const pPage
)
2661 if (pPage
&& pPage
->HasGrid())
2663 SwTextGridItem
const& rGridItem(
2664 pPage
->GetPageDesc()->GetMaster().GetTextGrid());
2665 if (GRID_NONE
!= rGridItem
.GetGridType())
2673 sal_uInt16
GetGridWidth(SwTextGridItem
const& rG
, SwDoc
const& rDoc
)
2675 return (rDoc
.IsSquaredPageMode()) ? rG
.GetBaseHeight() : rG
.GetBaseWidth();
2678 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */