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 <libxml/xmlwriter.h>
22 #include <editeng/pbinitem.hxx>
23 #include <editeng/ulspitem.hxx>
24 #include <editeng/boxitem.hxx>
25 #include <editeng/brushitem.hxx>
26 #include <editeng/shaditem.hxx>
27 #include <editeng/frmdiritem.hxx>
28 #include <sal/log.hxx>
29 #include <fmtclds.hxx>
30 #include <fmtfsize.hxx>
31 #include <pagefrm.hxx>
32 #include <pagedesc.hxx>
33 #include <swtable.hxx>
35 #include <frmtool.hxx>
38 #include <strings.hrc>
39 #include <IDocumentLayoutAccess.hxx>
40 #include <IDocumentStylePoolAccess.hxx>
41 #include <poolfmt.hxx>
45 SwPageDesc::SwPageDesc(const OUString
& rName
, SwFrameFormat
*pFormat
, SwDoc
*const pDoc
)
47 , m_StyleName( rName
)
48 , m_Master( pDoc
->GetAttrPool(), rName
, pFormat
)
49 , m_Left( pDoc
->GetAttrPool(), rName
, pFormat
)
50 , m_FirstMaster( pDoc
->GetAttrPool(), rName
, pFormat
)
51 , m_FirstLeft( pDoc
->GetAttrPool(), rName
, pFormat
)
53 , m_pTextFormatColl(nullptr)
57 , m_nVerticalAdjustment( drawing::TextVerticalAdjust_TOP
)
58 , m_eUse( UseOnPage::All
| UseOnPage::HeaderShare
| UseOnPage::FooterShare
| UseOnPage::FirstShare
)
59 , m_IsLandscape( false )
65 SwPageDesc::SwPageDesc( const SwPageDesc
&rCpy
)
68 , m_StyleName( rCpy
.GetName() )
69 , m_NumType( rCpy
.GetNumType() )
70 , m_Master( rCpy
.GetMaster() )
71 , m_Left( rCpy
.GetLeft() )
72 , m_FirstMaster( rCpy
.GetFirstMaster() )
73 , m_FirstLeft( rCpy
.GetFirstLeft() )
75 , m_pTextFormatColl(nullptr)
76 , m_pFollow( rCpy
.m_pFollow
)
77 , m_nRegHeight( rCpy
.GetRegHeight() )
78 , m_nRegAscent( rCpy
.GetRegAscent() )
79 , m_nVerticalAdjustment( rCpy
.GetVerticalAdjustment() )
80 , m_eUse( rCpy
.ReadUseOn() )
81 , m_IsLandscape( rCpy
.GetLandscape() )
82 , m_IsHidden( rCpy
.IsHidden() )
83 , m_IsFootnoteInfo( rCpy
.GetFootnoteInfo() )
86 if (rCpy
.m_pTextFormatColl
&& rCpy
.m_aDepends
.IsListeningTo(rCpy
.m_pTextFormatColl
))
88 m_pTextFormatColl
= rCpy
.m_pTextFormatColl
;
89 m_aDepends
.StartListening(const_cast<SwTextFormatColl
*>(m_pTextFormatColl
));
93 SwPageDesc
& SwPageDesc::operator = (const SwPageDesc
& rSrc
)
98 m_StyleName
= rSrc
.m_StyleName
;
99 m_NumType
= rSrc
.m_NumType
;
100 m_Master
= rSrc
.m_Master
;
101 m_Left
= rSrc
.m_Left
;
102 m_FirstMaster
= rSrc
.m_FirstMaster
;
103 m_FirstLeft
= rSrc
.m_FirstLeft
;
104 m_aDepends
.EndListeningAll();
105 if (rSrc
.m_pTextFormatColl
&& rSrc
.m_aDepends
.IsListeningTo(rSrc
.m_pTextFormatColl
))
107 m_pTextFormatColl
= rSrc
.m_pTextFormatColl
;
108 m_aDepends
.StartListening(const_cast<SwTextFormatColl
*>(m_pTextFormatColl
));
111 m_pTextFormatColl
= nullptr;
113 if (rSrc
.m_pFollow
== &rSrc
)
116 m_pFollow
= rSrc
.m_pFollow
;
118 m_nRegHeight
= rSrc
.m_nRegHeight
;
119 m_nRegAscent
= rSrc
.m_nRegAscent
;
120 m_nVerticalAdjustment
= rSrc
.m_nVerticalAdjustment
;
121 m_eUse
= rSrc
.m_eUse
;
122 m_IsLandscape
= rSrc
.m_IsLandscape
;
126 SwPageDesc::~SwPageDesc()
130 bool SwPageDesc::SetName( const OUString
& rNewName
)
134 SwPageDescs::iterator it
= m_pdList
->find_( m_StyleName
);
135 if( m_pdList
->end() == it
) {
136 SAL_WARN( "sw", "SwPageDesc not found in expected m_pdList" );
139 renamed
= m_pdList
->m_PosIndex
.modify( it
,
140 change_name( rNewName
), change_name( m_StyleName
) );
143 m_StyleName
= rNewName
;
147 /// Only the margin is mirrored.
148 /// Attributes like borders and so on are copied 1:1.
149 void SwPageDesc::Mirror()
151 //Only the margins are mirrored, all other values are just copied.
152 SvxLRSpaceItem
aLR( RES_LR_SPACE
);
153 const SvxLRSpaceItem
&rLR
= m_Master
.GetLRSpace();
154 aLR
.SetLeft( rLR
.GetRight() );
155 aLR
.SetRight( rLR
.GetLeft() );
156 aLR
.SetRightGutterMargin(rLR
.GetGutterMargin());
158 SfxItemSet
aSet( *m_Master
.GetAttrSet().GetPool(),
159 m_Master
.GetAttrSet().GetRanges() );
161 aSet
.Put( m_Master
.GetFrameSize() );
162 aSet
.Put( m_Master
.GetPaperBin() );
163 aSet
.Put( m_Master
.GetULSpace() );
164 aSet
.Put( m_Master
.GetBox() );
165 aSet
.Put( *m_Master
.makeBackgroundBrushItem() );
166 aSet
.Put( m_Master
.GetShadow() );
167 aSet
.Put( m_Master
.GetCol() );
168 aSet
.Put( m_Master
.GetFrameDir() );
169 m_Left
.SetFormatAttr( aSet
);
172 void SwPageDesc::ResetAllAttr()
174 SwFrameFormat
& rFormat
= GetMaster();
176 // #i73790# - method renamed
177 rFormat
.ResetAllFormatAttr();
178 rFormat
.SetFormatAttr( SvxFrameDirectionItem(SvxFrameDirection::Horizontal_LR_TB
, RES_FRAMEDIR
) );
181 // gets information from Modify
182 bool SwPageDesc::GetInfo( SfxPoolItem
& rInfo
) const
184 if (!m_Master
.GetInfo(rInfo
))
185 return false; // found
186 if (!m_Left
.GetInfo(rInfo
))
188 if ( !m_FirstMaster
.GetInfo( rInfo
) )
190 return m_FirstLeft
.GetInfo( rInfo
);
193 /// set the style for the grid alignment
194 void SwPageDesc::SetRegisterFormatColl(const SwTextFormatColl
* pFormat
)
196 if(pFormat
!= m_pTextFormatColl
)
198 m_aDepends
.EndListeningAll();
199 m_pTextFormatColl
= pFormat
;
200 m_aDepends
.StartListening(const_cast<SwTextFormatColl
*>(m_pTextFormatColl
));
205 /// retrieve the style for the grid alignment
206 const SwTextFormatColl
* SwPageDesc::GetRegisterFormatColl() const
208 if (!m_aDepends
.IsListeningTo(m_pTextFormatColl
))
209 m_pTextFormatColl
= nullptr;
210 return m_pTextFormatColl
;
213 /// notify all affected page frames
214 void SwPageDesc::RegisterChange()
216 // #117072# - During destruction of the document <SwDoc>
217 // the page description is modified. Thus, do nothing, if the document
218 // is in destruction respectively if no viewshell exists.
219 SwDoc
* pDoc
= GetMaster().GetDoc();
220 if ( !pDoc
|| pDoc
->IsInDtor() )
224 SwViewShell
* pSh
= pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell();
232 SwIterator
<SwFrame
,SwFormat
> aIter( GetMaster() );
233 for( SwFrame
* pLast
= aIter
.First(); pLast
; pLast
= aIter
.Next() )
235 if( pLast
->IsPageFrame() )
236 static_cast<SwPageFrame
*>(pLast
)->PrepareRegisterChg();
240 SwIterator
<SwFrame
,SwFormat
> aIter( GetLeft() );
241 for( SwFrame
* pLast
= aIter
.First(); pLast
; pLast
= aIter
.Next() )
243 if( pLast
->IsPageFrame() )
244 static_cast<SwPageFrame
*>(pLast
)->PrepareRegisterChg();
248 SwIterator
<SwFrame
,SwFormat
> aIter( GetFirstMaster() );
249 for( SwFrame
* pLast
= aIter
.First(); pLast
; pLast
= aIter
.Next() )
251 if( pLast
->IsPageFrame() )
252 static_cast<SwPageFrame
*>(pLast
)->PrepareRegisterChg();
256 SwIterator
<SwFrame
,SwFormat
> aIter( GetFirstLeft() );
257 for( SwFrame
* pLast
= aIter
.First(); pLast
; pLast
= aIter
.Next() )
259 if( pLast
->IsPageFrame() )
260 static_cast<SwPageFrame
*>(pLast
)->PrepareRegisterChg();
265 /// special handling if the style of the grid alignment changes
266 void SwPageDesc::SwClientNotify(const SwModify
& rModify
, const SfxHint
& rHint
)
268 if(auto pLegacyHint
= dynamic_cast<const sw::LegacyModifyHint
*>(&rHint
))
270 const sal_uInt16 nWhich
= pLegacyHint
->m_pOld
271 ? pLegacyHint
->m_pOld
->Which()
272 : pLegacyHint
->m_pNew
273 ? pLegacyHint
->m_pNew
->Which()
275 NotifyClients(pLegacyHint
->m_pOld
, pLegacyHint
->m_pNew
);
276 if((RES_ATTRSET_CHG
== nWhich
)
277 || (RES_FMT_CHG
== nWhich
)
279 || (RES_PARATR_LINESPACING
== nWhich
))
282 else if (auto pModifyChangedHint
= dynamic_cast<const sw::ModifyChangedHint
*>(&rHint
))
284 if(m_pTextFormatColl
== &rModify
)
285 m_pTextFormatColl
= static_cast<const SwTextFormatColl
*>(pModifyChangedHint
->m_pNew
);
291 static const SwFrame
* lcl_GetFrameOfNode( const SwNode
& rNd
)
293 const SwModify
* pMod
;
294 SwFrameType nFrameType
= FRM_CNTNT
;
296 if( rNd
.IsContentNode() )
298 pMod
= &static_cast<const SwContentNode
&>(rNd
);
300 else if( rNd
.IsTableNode() )
302 pMod
= static_cast<const SwTableNode
&>(rNd
).GetTable().GetFrameFormat();
303 nFrameType
= SwFrameType::Tab
;
309 std::pair
<Point
, bool> const tmp(aNullPt
, false);
310 return pMod
? ::GetFrameOfModify(nullptr, *pMod
, nFrameType
, nullptr, &tmp
)
314 const SwPageDesc
* SwPageDesc::GetPageDescOfNode(const SwNode
& rNd
)
316 const SwPageDesc
* pRet
= nullptr;
317 const SwFrame
* pChkFrame
= lcl_GetFrameOfNode( rNd
);
318 if (pChkFrame
&& nullptr != (pChkFrame
= pChkFrame
->FindPageFrame()))
319 pRet
= static_cast<const SwPageFrame
*>(pChkFrame
)->GetPageDesc();
323 const SwFrameFormat
* SwPageDesc::GetPageFormatOfNode( const SwNode
& rNd
,
324 bool bCheckForThisPgDc
) const
326 // which PageDescFormat is valid for this node?
327 const SwFrameFormat
* pRet
;
328 const SwFrame
* pChkFrame
= lcl_GetFrameOfNode( rNd
);
330 if( pChkFrame
&& nullptr != ( pChkFrame
= pChkFrame
->FindPageFrame() ))
332 const SwPageDesc
* pPd
= bCheckForThisPgDc
? this :
333 static_cast<const SwPageFrame
*>(pChkFrame
)->GetPageDesc();
334 pRet
= &pPd
->GetMaster();
335 OSL_ENSURE( static_cast<const SwPageFrame
*>(pChkFrame
)->GetPageDesc() == pPd
, "Wrong node for detection of page format!" );
336 // this page is assigned to which format?
337 if( !pChkFrame
->KnowsFormat(*pRet
) )
339 pRet
= &pPd
->GetLeft();
340 OSL_ENSURE( pChkFrame
->KnowsFormat(*pRet
), "Wrong node for detection of page format!" );
348 bool SwPageDesc::IsFollowNextPageOfNode( const SwNode
& rNd
) const
351 if( GetFollow() && this != GetFollow() )
353 const SwFrame
* pChkFrame
= lcl_GetFrameOfNode( rNd
);
354 if( pChkFrame
&& nullptr != ( pChkFrame
= pChkFrame
->FindPageFrame() ) &&
355 pChkFrame
->IsPageFrame() &&
356 ( !pChkFrame
->GetNext() || GetFollow() ==
357 static_cast<const SwPageFrame
*>(pChkFrame
->GetNext())->GetPageDesc() ))
358 // the page on which the follow points was found
364 SwFrameFormat
*SwPageDesc::GetLeftFormat(bool const bFirst
)
366 return (UseOnPage::Left
& m_eUse
)
367 ? (bFirst
? &m_FirstLeft
: &m_Left
)
371 SwFrameFormat
*SwPageDesc::GetRightFormat(bool const bFirst
)
373 return (UseOnPage::Right
& m_eUse
)
374 ? (bFirst
? &m_FirstMaster
: &m_Master
)
378 bool SwPageDesc::IsFirstShared() const
380 return bool(m_eUse
& UseOnPage::FirstShare
);
383 void SwPageDesc::ChgFirstShare( bool bNew
)
386 m_eUse
|= UseOnPage::FirstShare
;
388 m_eUse
&= UseOnPage::NoFirstShare
;
392 static const char* STR_POOLPAGE
[] =
394 STR_POOLPAGE_STANDARD
,
399 STR_POOLPAGE_REGISTER
,
401 STR_POOLPAGE_FOOTNOTE
,
402 STR_POOLPAGE_ENDNOTE
,
403 STR_POOLPAGE_LANDSCAPE
406 SwPageDesc
* SwPageDesc::GetByName(SwDoc
& rDoc
, const OUString
& rName
)
408 const size_t nDCount
= rDoc
.GetPageDescCnt();
410 for( size_t i
= 0; i
< nDCount
; i
++ )
412 SwPageDesc
* pDsc
= &rDoc
.GetPageDesc( i
);
413 if(pDsc
->GetName() == rName
)
419 for (size_t i
= 0; i
< SAL_N_ELEMENTS(STR_POOLPAGE
); ++i
)
421 if (rName
== SwResId(STR_POOLPAGE
[i
]))
423 return rDoc
.getIDocumentStylePoolAccess().GetPageDescFromPool( static_cast< sal_uInt16
>(
424 i
+ RES_POOLPAGE_BEGIN
) );
431 void SwPageDesc::dumpAsXml(xmlTextWriterPtr pWriter
) const
433 xmlTextWriterStartElement(pWriter
, BAD_CAST("SwPageDesc"));
434 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
435 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("m_StyleName"), "%s",
436 BAD_CAST(m_StyleName
.toUtf8().getStr()));
437 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("m_pFollow"), "%p", m_pFollow
);
438 xmlTextWriterWriteFormatAttribute(
439 pWriter
, BAD_CAST("m_eUse"), "0x%s",
440 BAD_CAST(OString::number(static_cast<int>(m_eUse
), 16).getStr()));
442 xmlTextWriterStartElement(pWriter
, BAD_CAST("m_Master"));
443 m_Master
.dumpAsXml(pWriter
);
444 xmlTextWriterEndElement(pWriter
);
446 xmlTextWriterStartElement(pWriter
, BAD_CAST("m_Left"));
447 m_Left
.dumpAsXml(pWriter
);
448 xmlTextWriterEndElement(pWriter
);
450 xmlTextWriterStartElement(pWriter
, BAD_CAST("m_FirstMaster"));
451 m_FirstMaster
.dumpAsXml(pWriter
);
452 xmlTextWriterEndElement(pWriter
);
454 xmlTextWriterStartElement(pWriter
, BAD_CAST("m_FirstLeft"));
455 m_FirstLeft
.dumpAsXml(pWriter
);
456 xmlTextWriterEndElement(pWriter
);
458 xmlTextWriterEndElement(pWriter
);
461 SwPageFootnoteInfo::SwPageFootnoteInfo()
464 , m_eLineStyle( SvxBorderLineStyle::SOLID
)
466 , m_nTopDist( 57 ) //1mm
467 , m_nBottomDist( 57 )
469 m_eAdjust
= SvxFrameDirection::Horizontal_RL_TB
== GetDefaultFrameDirection(GetAppLanguage()) ?
470 css::text::HorizontalAdjust_RIGHT
:
471 css::text::HorizontalAdjust_LEFT
;
474 SwPageFootnoteInfo::SwPageFootnoteInfo( const SwPageFootnoteInfo
&rCpy
)
475 : m_nMaxHeight(rCpy
.GetHeight())
476 , m_nLineWidth(rCpy
.m_nLineWidth
)
477 , m_eLineStyle(rCpy
.m_eLineStyle
)
478 , m_LineColor(rCpy
.m_LineColor
)
479 , m_Width(rCpy
.GetWidth())
480 , m_eAdjust(rCpy
.GetAdj())
481 , m_nTopDist(rCpy
.GetTopDist())
482 , m_nBottomDist(rCpy
.GetBottomDist())
486 SwPageFootnoteInfo
&SwPageFootnoteInfo::operator=( const SwPageFootnoteInfo
& rCpy
)
488 m_nMaxHeight
= rCpy
.GetHeight();
489 m_nLineWidth
= rCpy
.m_nLineWidth
;
490 m_eLineStyle
= rCpy
.m_eLineStyle
;
491 m_LineColor
= rCpy
.m_LineColor
;
492 m_Width
= rCpy
.GetWidth();
493 m_eAdjust
= rCpy
.GetAdj();
494 m_nTopDist
= rCpy
.GetTopDist();
495 m_nBottomDist
= rCpy
.GetBottomDist();
499 bool SwPageFootnoteInfo::operator==( const SwPageFootnoteInfo
& rCmp
) const
501 return m_nMaxHeight
== rCmp
.GetHeight()
502 && m_nLineWidth
== rCmp
.m_nLineWidth
503 && m_eLineStyle
== rCmp
.m_eLineStyle
504 && m_LineColor
== rCmp
.m_LineColor
505 && m_Width
== rCmp
.GetWidth()
506 && m_eAdjust
== rCmp
.GetAdj()
507 && m_nTopDist
== rCmp
.GetTopDist()
508 && m_nBottomDist
== rCmp
.GetBottomDist();
511 SwPageDescExt::SwPageDescExt(const SwPageDesc
& rPageDesc
, SwDoc
*const pDoc
)
512 : m_PageDesc(rPageDesc
)
515 SetPageDesc(rPageDesc
);
518 SwPageDescExt::SwPageDescExt(const SwPageDescExt
& rSrc
)
519 : m_PageDesc(rSrc
.m_PageDesc
)
520 , m_pDoc(rSrc
.m_pDoc
)
522 SetPageDesc(rSrc
.m_PageDesc
);
525 SwPageDescExt::~SwPageDescExt()
529 OUString
const & SwPageDescExt::GetName() const
531 return m_PageDesc
.GetName();
534 void SwPageDescExt::SetPageDesc(const SwPageDesc
& rPageDesc
)
536 m_PageDesc
= rPageDesc
;
538 if (m_PageDesc
.GetFollow())
539 m_sFollow
= m_PageDesc
.GetFollow()->GetName();
542 SwPageDescExt
& SwPageDescExt::operator = (const SwPageDesc
& rSrc
)
549 SwPageDescExt
& SwPageDescExt::operator = (const SwPageDescExt
& rSrc
)
551 operator=(rSrc
.m_PageDesc
);
555 SwPageDescExt::operator SwPageDesc() const
557 SwPageDesc
aResult(m_PageDesc
);
559 SwPageDesc
* pPageDesc
= m_pDoc
->FindPageDesc(m_sFollow
);
561 if ( nullptr != pPageDesc
)
562 aResult
.SetFollow(pPageDesc
);
567 SwPageDescs::SwPageDescs()
568 : m_PosIndex( m_Array
.get
<0>() )
569 , m_NameIndex( m_Array
.get
<1>() )
573 SwPageDescs::~SwPageDescs()
575 for(const_iterator it
= begin(); it
!= end(); ++it
)
579 SwPageDescs::iterator
SwPageDescs::find_(const OUString
&name
) const
581 ByName::iterator it
= m_NameIndex
.find( name
);
582 return m_Array
.iterator_to( *it
);
585 std::pair
<SwPageDescs::const_iterator
,bool> SwPageDescs::push_back( const value_type
& x
)
587 // SwPageDesc is not already in a SwPageDescs list!
588 assert( x
->m_pdList
== nullptr );
590 std::pair
<iterator
,bool> res
= m_PosIndex
.push_back( x
);
596 void SwPageDescs::erase( const value_type
& x
)
598 // SwPageDesc is not in this SwPageDescs list!
599 assert( x
->m_pdList
== this );
601 iterator
const ret
= find_( x
->GetName() );
603 m_PosIndex
.erase( ret
);
605 SAL_WARN( "sw", "SwPageDesc is not in SwPageDescs m_pdList!" );
606 x
->m_pdList
= nullptr;
609 void SwPageDescs::erase( const_iterator
const& position
)
611 // SwPageDesc is not in this SwPageDescs list!
612 assert( (*position
)->m_pdList
== this );
614 (*position
)->m_pdList
= nullptr;
615 m_PosIndex
.erase( position
);
618 void SwPageDescs::erase( size_type index_
)
620 erase( begin() + index_
);
623 void SwPageDescs::dumpAsXml(xmlTextWriterPtr pWriter
) const
625 xmlTextWriterStartElement(pWriter
, BAD_CAST("SwPageDescs"));
627 for (const auto& pPageDesc
: m_PosIndex
)
629 pPageDesc
->dumpAsXml(pWriter
);
632 xmlTextWriterEndElement(pWriter
);
635 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */