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 .
22 #include <editeng/lrspitem.hxx>
23 #include <editeng/ulspitem.hxx>
24 #include <editeng/paperinf.hxx>
25 #include <editeng/frmdiritem.hxx>
26 #include <sfx2/bindings.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <tools/globname.hxx>
29 #include <sal/log.hxx>
30 #include <osl/diagnose.h>
31 #include <unotools/localedatawrapper.hxx>
32 #include <fmtfsize.hxx>
33 #include <fmthdft.hxx>
34 #include <fmtcntnt.hxx>
35 #include <ftninfo.hxx>
40 #include <IDocumentUndoRedo.hxx>
41 #include <IDocumentFieldsAccess.hxx>
42 #include <DocumentContentOperationsManager.hxx>
43 #include <IDocumentState.hxx>
44 #include <IDocumentLayoutAccess.hxx>
45 #include <rootfrm.hxx>
46 #include <poolfmt.hxx>
52 #include <strings.hrc>
54 #include <SwUndoPageDesc.hxx>
55 #include <pagedeschint.hxx>
56 #include <tgrditem.hxx>
57 #include <unotools/configmgr.hxx>
58 #include <unotools/syslocale.hxx>
59 #include <svx/swframetypes.hxx>
60 #include <o3tl/unit_conversion.hxx>
62 #include <com/sun/star/embed/XEmbeddedObject.hpp>
64 using namespace com::sun::star
;
66 static void lcl_DefaultPageFormat( sal_uInt16 nPoolFormatId
,
67 SwFrameFormat
&rFormat1
,
68 SwFrameFormat
&rFormat2
,
69 SwFrameFormat
&rFormat3
,
70 SwFrameFormat
&rFormat4
)
72 // --> #i41075# Printer on demand
73 // This function does not require a printer anymore.
74 // The default page size is obtained from the application
77 SwFormatFrameSize
aFrameSize( SwFrameSize::Fixed
);
78 const Size aPhysSize
= SvxPaperInfo::GetDefaultPaperSize();
79 aFrameSize
.SetSize( aPhysSize
);
81 // Prepare for default margins.
82 // Margins have a default minimum size.
83 // If the printer forces a larger margins, that's ok too.
84 // The HTML page desc had A4 as page size always.
85 // This has been changed to take the page size from the printer.
86 // Unfortunately, the margins of the HTML page desc are smaller than
87 // the margins used here in general, so one extra case is required.
88 // In the long term, this needs to be changed to always keep the
89 // margins from the page desc.
90 sal_Int32 nMinTop
, nMinBottom
, nMinLeft
, nMinRight
;
91 if( RES_POOLPAGE_HTML
== nPoolFormatId
)
93 nMinRight
= nMinTop
= nMinBottom
= o3tl::toTwips(1, o3tl::Length::cm
);
94 nMinLeft
= o3tl::toTwips(2, o3tl::Length::cm
);
96 else if (!utl::ConfigManager::IsFuzzing() && MeasurementSystem::Metric
== SvtSysLocale().GetLocaleData().getMeasurementSystemEnum() )
98 nMinTop
= nMinBottom
= nMinLeft
= nMinRight
= o3tl::toTwips(2, o3tl::Length::cm
);
102 nMinTop
= nMinBottom
= o3tl::toTwips(1, o3tl::Length::in
); // as in MS Word
103 nMinLeft
= nMinRight
= o3tl::toTwips(1.25, o3tl::Length::in
);
107 SvxLRSpaceItem
aLR( RES_LR_SPACE
);
108 SvxULSpaceItem
aUL( RES_UL_SPACE
);
110 aUL
.SetUpper( o3tl::narrowing
<sal_uInt16
>(nMinTop
) );
111 aUL
.SetLower( o3tl::narrowing
<sal_uInt16
>(nMinBottom
) );
112 aLR
.SetRight( nMinRight
);
113 aLR
.SetLeft( nMinLeft
);
115 rFormat1
.SetFormatAttr( aFrameSize
);
116 rFormat1
.SetFormatAttr( aLR
);
117 rFormat1
.SetFormatAttr( aUL
);
119 rFormat2
.SetFormatAttr( aFrameSize
);
120 rFormat2
.SetFormatAttr( aLR
);
121 rFormat2
.SetFormatAttr( aUL
);
123 rFormat3
.SetFormatAttr( aFrameSize
);
124 rFormat3
.SetFormatAttr( aLR
);
125 rFormat3
.SetFormatAttr( aUL
);
127 rFormat4
.SetFormatAttr( aFrameSize
);
128 rFormat4
.SetFormatAttr( aLR
);
129 rFormat4
.SetFormatAttr( aUL
);
132 static void lcl_DescSetAttr( const SwFrameFormat
&rSource
, SwFrameFormat
&rDest
,
133 const bool bPage
= true )
135 // We should actually use ItemSet's Intersect here, but that doesn't work
136 // correctly if we have different WhichRanges.
138 // Take over the attributes which are of interest.
139 sal_uInt16
const aIdArr
[] = {
140 RES_FRM_SIZE
, RES_UL_SPACE
, // [83..86
141 RES_BACKGROUND
, RES_SHADOW
, // [99..101
142 RES_COL
, RES_COL
, // [103
143 RES_TEXTGRID
, RES_TEXTGRID
, // [109
144 RES_FRAMEDIR
, RES_FRAMEDIR
, // [114
145 RES_HEADER_FOOTER_EAT_SPACING
, RES_HEADER_FOOTER_EAT_SPACING
, // [115
146 RES_BACKGROUND_FULL_SIZE
, RES_BACKGROUND_FULL_SIZE
, // [131
147 RES_RTL_GUTTER
, RES_RTL_GUTTER
, // [132
148 RES_UNKNOWNATR_CONTAINER
, RES_UNKNOWNATR_CONTAINER
, // [143
150 // take over DrawingLayer FillStyles
151 XATTR_FILL_FIRST
, XATTR_FILL_LAST
, // [1014
155 const SfxPoolItem
* pItem
;
156 for( sal_uInt16 n
= 0; aIdArr
[ n
]; n
+= 2 )
158 for( sal_uInt16 nId
= aIdArr
[ n
]; nId
<= aIdArr
[ n
+1]; ++nId
)
162 // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING
164 // All in aIdArr except from RES_COL and RES_PAPER_BIN:
165 bool bExecuteId(true);
172 // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING
173 case RES_HEADER_FOOTER_EAT_SPACING
:
174 // take out SvxBrushItem; it's the result of the fallback
175 // at SwFormat::GetItemState and not really in state SfxItemState::SET
188 // When not Page: All in aIdArr except these:
191 case RES_BACKGROUND_FULL_SIZE
:
202 if (SfxItemState::SET
== rSource
.GetItemState(nId
, false, &pItem
))
204 rDest
.SetFormatAttr(*pItem
);
208 rDest
.ResetFormatAttr(nId
);
214 // Transmit pool and help IDs too
215 rDest
.SetPoolFormatId( rSource
.GetPoolFormatId() );
216 rDest
.SetPoolHelpId( rSource
.GetPoolHelpId() );
217 rDest
.SetPoolHlpFileId( rSource
.GetPoolHlpFileId() );
222 SwFrameFormat
& getFrameFormat(SwPageDesc
&rDesc
, bool bLeft
, bool bFirst
)
227 return rDesc
.GetFirstLeft();
228 return rDesc
.GetFirstMaster();
230 return rDesc
.GetLeft();
233 const SwFrameFormat
& getConstFrameFormat(const SwPageDesc
&rDesc
, bool bLeft
, bool bFirst
)
235 return getFrameFormat(const_cast<SwPageDesc
&>(rDesc
), bLeft
, bFirst
);
239 void SwDoc::CopyMasterHeader(const SwPageDesc
&rChged
, const SwFormatHeader
&rHead
, SwPageDesc
&rDesc
, bool bLeft
, bool bFirst
)
241 assert(bLeft
|| bFirst
);
242 SwFrameFormat
& rDescFrameFormat
= getFrameFormat(rDesc
, bLeft
, bFirst
);
245 // special case: always shared with something
246 rDescFrameFormat
.SetFormatAttr( rChged
.IsFirstShared()
247 ? rDesc
.GetLeft().GetHeader()
248 : rDesc
.GetFirstMaster().GetHeader());
250 else if ((bFirst
? rChged
.IsFirstShared() : rChged
.IsHeaderShared())
251 || !rHead
.IsActive())
253 // Left or first shares the header with the Master.
254 rDescFrameFormat
.SetFormatAttr( rDesc
.GetMaster().GetHeader() );
256 else if ( rHead
.IsActive() )
257 { // Left or first gets its own header if the Format doesn't already have one.
258 // If it already has one and it points to the same Section as the
259 // Right one, it needs to get an own Header.
260 // The content is evidently copied.
261 const SwFormatHeader
&rFormatHead
= rDescFrameFormat
.GetHeader();
262 if ( !rFormatHead
.IsActive() )
264 SwFormatHeader
aHead( getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::HEADERL
, nullptr ) );
265 rDescFrameFormat
.SetFormatAttr( aHead
);
266 // take over additional attributes (margins, borders ...)
267 ::lcl_DescSetAttr( *rHead
.GetHeaderFormat(), *aHead
.GetHeaderFormat(), false);
271 const SwFormatContent
&aCnt
= rFormatHead
.GetHeaderFormat()->GetContent();
273 if (!aCnt
.GetContentIdx())
275 const SwFrameFormat
& rChgedFrameFormat
= getConstFrameFormat(rChged
, bLeft
, bFirst
);
276 rDescFrameFormat
.SetFormatAttr( rChgedFrameFormat
.GetHeader() );
280 const SwFrameFormat
*pRight
= rHead
.GetHeaderFormat();
283 const SwFormatContent
&aRCnt
= pRight
->GetContent();
285 if ((*aRCnt
.GetContentIdx() == *aCnt
.GetContentIdx()) ||
286 // The ContentIdx is _always_ different when called from
287 // SwDocStyleSheet::SetItemSet, because it deep-copies the
288 // PageDesc. So check if it was previously shared.
289 (bFirst
? rDesc
.IsFirstShared() : rDesc
.IsHeaderShared()))
291 SwFrameFormat
*pFormat
= new SwFrameFormat( GetAttrPool(),
292 bFirst
? "First header" : "Left header",
293 GetDfltFrameFormat() );
294 ::lcl_DescSetAttr( *pRight
, *pFormat
, false );
295 // The section which the right header attribute is pointing
296 // is copied, and the Index to the StartNode is set to
297 // the left or first header attribute.
298 SwStartNode
* pSttNd
= SwNodes::MakeEmptySection( GetNodes().GetEndOfAutotext(), SwHeaderStartNode
);
299 SwNodeRange
aRange( aRCnt
.GetContentIdx()->GetNode(), SwNodeOffset(0),
300 *aRCnt
.GetContentIdx()->GetNode().EndOfSectionNode() );
301 GetNodes().Copy_( aRange
, *pSttNd
->EndOfSectionNode(), false );
302 GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange
, nullptr, *pSttNd
);
303 SwPaM
const source(aRange
.aStart
, aRange
.aEnd
);
304 SwPosition
dest(*pSttNd
);
305 sw::CopyBookmarks(source
, dest
);
306 pFormat
->SetFormatAttr( SwFormatContent( pSttNd
) );
307 rDescFrameFormat
.SetFormatAttr( SwFormatHeader( pFormat
) );
310 ::lcl_DescSetAttr( *pRight
,
311 *const_cast<SwFrameFormat
*>(rFormatHead
.GetHeaderFormat()), false );
317 void SwDoc::CopyMasterFooter(const SwPageDesc
&rChged
, const SwFormatFooter
&rFoot
, SwPageDesc
&rDesc
, bool bLeft
, bool bFirst
)
319 assert(bLeft
|| bFirst
);
320 SwFrameFormat
& rDescFrameFormat
= getFrameFormat(rDesc
, bLeft
, bFirst
);
323 // special case: always shared with something
324 rDescFrameFormat
.SetFormatAttr( rChged
.IsFirstShared()
325 ? rDesc
.GetLeft().GetFooter()
326 : rDesc
.GetFirstMaster().GetFooter());
328 else if ((bFirst
? rChged
.IsFirstShared() : rChged
.IsFooterShared())
329 || !rFoot
.IsActive())
331 // Left or first shares the Header with the Master.
332 rDescFrameFormat
.SetFormatAttr( rDesc
.GetMaster().GetFooter() );
334 else if ( rFoot
.IsActive() )
335 { // Left or first gets its own Footer if the Format does not already have one.
336 // If the Format already has a Footer and it points to the same section as the Right one,
337 // it needs to get an own one.
338 // The content is evidently copied.
339 const SwFormatFooter
&rFormatFoot
= rDescFrameFormat
.GetFooter();
340 if ( !rFormatFoot
.IsActive() )
342 SwFormatFooter
aFoot( getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::FOOTER
, nullptr ) );
343 rDescFrameFormat
.SetFormatAttr( aFoot
);
344 // Take over additional attributes (margins, borders ...).
345 ::lcl_DescSetAttr( *rFoot
.GetFooterFormat(), *aFoot
.GetFooterFormat(), false);
349 const SwFormatContent
&aLCnt
= rFormatFoot
.GetFooterFormat()->GetContent();
350 if( !aLCnt
.GetContentIdx() )
352 const SwFrameFormat
& rChgedFrameFormat
= getConstFrameFormat(rChged
, bLeft
, bFirst
);
353 rDescFrameFormat
.SetFormatAttr( rChgedFrameFormat
.GetFooter() );
357 const SwFrameFormat
*pRight
= rFoot
.GetFooterFormat();
360 const SwFormatContent
&aRCnt
= pRight
->GetContent();
362 if ((*aRCnt
.GetContentIdx() == *aLCnt
.GetContentIdx()) ||
363 // The ContentIdx is _always_ different when called from
364 // SwDocStyleSheet::SetItemSet, because it deep-copies the
365 // PageDesc. So check if it was previously shared.
366 (bFirst
? rDesc
.IsFirstShared() : rDesc
.IsFooterShared()))
368 SwFrameFormat
*pFormat
= new SwFrameFormat( GetAttrPool(),
369 bFirst
? "First footer" : "Left footer",
370 GetDfltFrameFormat() );
371 ::lcl_DescSetAttr( *pRight
, *pFormat
, false );
372 // The section to which the right footer attribute is pointing
373 // is copied, and the Index to the StartNode is set to
374 // the left footer attribute.
375 SwStartNode
* pSttNd
= SwNodes::MakeEmptySection( GetNodes().GetEndOfAutotext(), SwFooterStartNode
);
376 SwNodeRange
aRange( aRCnt
.GetContentIdx()->GetNode(), SwNodeOffset(0),
377 *aRCnt
.GetContentIdx()->GetNode().EndOfSectionNode() );
378 GetNodes().Copy_( aRange
, *pSttNd
->EndOfSectionNode(), false );
379 GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange
, nullptr, *pSttNd
);
380 SwPaM
const source(aRange
.aStart
, aRange
.aEnd
);
381 SwPosition
dest(*pSttNd
);
382 sw::CopyBookmarks(source
, dest
);
383 pFormat
->SetFormatAttr( SwFormatContent( pSttNd
) );
384 rDescFrameFormat
.SetFormatAttr( SwFormatFooter( pFormat
) );
387 ::lcl_DescSetAttr( *pRight
,
388 *const_cast<SwFrameFormat
*>(rFormatFoot
.GetFooterFormat()), false );
394 void SwDoc::ChgPageDesc( size_t i
, const SwPageDesc
&rChged
)
396 assert(i
< m_PageDescs
.size() && "PageDescs is out of range.");
398 SwPageDesc
& rDesc
= *m_PageDescs
[i
];
399 SwRootFrame
* pTmpRoot
= getIDocumentLayoutAccess().GetCurrentLayout();
401 if (GetIDocumentUndoRedo().DoesUndo())
403 // Stash header formats as needed.
404 const SwFormatHeader
& rLeftHead
= rChged
.GetLeft().GetHeader();
405 const SwFormatHeader
& rFirstMasterHead
= rChged
.GetFirstMaster().GetHeader();
406 const SwFormatHeader
& rFirstLeftHead
= rChged
.GetFirstLeft().GetHeader();
407 const bool bStashLeftHead
= !rDesc
.IsHeaderShared() && rChged
.IsHeaderShared();
408 const bool bStashFirstMasterHead
= !rDesc
.IsFirstShared() && rChged
.IsFirstShared();
409 const bool bStashFirstLeftHead
= (!rDesc
.IsHeaderShared() && rChged
.IsHeaderShared()) || (!rDesc
.IsFirstShared() && rChged
.IsFirstShared());
410 if (bStashLeftHead
&& rLeftHead
.GetRegisteredIn() && !rDesc
.HasStashedFormat(true, true, false))
411 rDesc
.StashFrameFormat(rChged
.GetLeft(), true, true, false);
412 if (bStashFirstMasterHead
&& rFirstMasterHead
.GetRegisteredIn() && !rDesc
.HasStashedFormat(true, false, true))
413 rDesc
.StashFrameFormat(rChged
.GetFirstMaster(), true, false, true);
414 if (bStashFirstLeftHead
&& rFirstLeftHead
.GetRegisteredIn() && !rDesc
.HasStashedFormat(true, true, true))
415 rDesc
.StashFrameFormat(rChged
.GetFirstLeft(), true, true, true);
417 // Stash footer formats as needed.
418 const SwFormatFooter
& rLeftFoot
= rChged
.GetLeft().GetFooter();
419 const SwFormatFooter
& rFirstMasterFoot
= rChged
.GetFirstMaster().GetFooter();
420 const SwFormatFooter
& rFirstLeftFoot
= rChged
.GetFirstLeft().GetFooter();
421 const bool bStashLeftFoot
= !rDesc
.IsFooterShared() && rChged
.IsFooterShared();
422 const bool bStashFirstMasterFoot
= !rDesc
.IsFirstShared() && rChged
.IsFirstShared();
423 const bool bStashFirstLeftFoot
= (!rDesc
.IsFooterShared() && rChged
.IsFooterShared()) || (!rDesc
.IsFirstShared() && rChged
.IsFirstShared());
424 if (bStashLeftFoot
&& rLeftFoot
.GetRegisteredIn() && !rDesc
.HasStashedFormat(false, true, false))
425 rDesc
.StashFrameFormat(rChged
.GetLeft(), false, true, false);
426 if (bStashFirstMasterFoot
&& rFirstMasterFoot
.GetRegisteredIn() && !rDesc
.HasStashedFormat(false, false, true))
427 rDesc
.StashFrameFormat(rChged
.GetFirstMaster(), false, false, true);
428 if (bStashFirstLeftFoot
&& rFirstLeftFoot
.GetRegisteredIn() && !rDesc
.HasStashedFormat(false, true, true))
429 rDesc
.StashFrameFormat(rChged
.GetFirstLeft(), false, true, true);
431 GetIDocumentUndoRedo().AppendUndo(std::make_unique
<SwUndoPageDesc
>(rDesc
, rChged
, this));
435 SwUndoId
nBeingUndone(SwUndoId::EMPTY
);
436 GetIDocumentUndoRedo().GetFirstRedoInfo(nullptr, &nBeingUndone
);
437 if (SwUndoId::HEADER_FOOTER
== nBeingUndone
)
439 // The last format change is currently being undone. Remove header/footer and corresponding nodes.
440 auto rDescMasterHeaderFormat
= rDesc
.GetMaster().GetFormatAttr(RES_HEADER
);
441 auto rDescLeftHeaderFormat
= rDesc
.GetLeft().GetFormatAttr(RES_HEADER
);
442 auto rDescFirstLeftHeaderFormat
= rDesc
.GetFirstLeft().GetFormatAttr(RES_HEADER
);
443 auto rDescMasterFooterFormat
= rDesc
.GetMaster().GetFormatAttr(RES_FOOTER
);
444 auto rDescLeftFooterFormat
= rDesc
.GetLeft().GetFormatAttr(RES_FOOTER
);
445 auto rDescFirstLeftFooterFormat
= rDesc
.GetFirstLeft().GetFormatAttr(RES_FOOTER
);
447 auto rChgedMasterHeaderFormat
= rChged
.GetMaster().GetFormatAttr(RES_HEADER
);
448 auto rChgedLeftHeaderFormat
= rChged
.GetLeft().GetFormatAttr(RES_HEADER
);
449 auto rChgedFirstLeftHeaderFormat
= rChged
.GetFirstLeft().GetFormatAttr(RES_HEADER
);
450 auto rChgedMasterFooterFormat
= rChged
.GetMaster().GetFormatAttr(RES_FOOTER
);
451 auto rChgedLeftFooterFormat
= rChged
.GetLeft().GetFormatAttr(RES_FOOTER
);
452 auto rChgedFirstLeftFooterFormat
= rChged
.GetFirstLeft().GetFormatAttr(RES_FOOTER
);
454 rDesc
.GetMaster().ResetFormatAttr(RES_HEADER
);
455 rDesc
.GetLeft().ResetFormatAttr(RES_HEADER
);
456 rDesc
.GetFirstLeft().ResetFormatAttr(RES_HEADER
);
457 rDesc
.GetMaster().ResetFormatAttr(RES_FOOTER
);
458 rDesc
.GetLeft().ResetFormatAttr(RES_FOOTER
);
459 rDesc
.GetFirstLeft().ResetFormatAttr(RES_FOOTER
);
461 auto lDelHFFormat
= [this](SwClient
* pToRemove
, SwFrameFormat
* pFormat
)
463 // Code taken from lcl_DelHFFormat
464 pFormat
->Remove(pToRemove
);
465 SwFormatContent
& rCnt
= const_cast<SwFormatContent
&>(pFormat
->GetContent());
466 if (rCnt
.GetContentIdx())
468 SwNode
* pNode
= nullptr;
470 SwNodeIndex
aIdx(*rCnt
.GetContentIdx(), 0);
471 pNode
= &aIdx
.GetNode();
472 SwNodeOffset nEnd
= pNode
->EndOfSectionIndex();
475 if (pNode
->IsContentNode() &&
476 static_cast<SwContentNode
*>(pNode
)->HasWriterListeners())
478 SwCursorShell
* pShell
= SwIterator
<SwCursorShell
, SwContentNode
>(*static_cast<SwContentNode
*>(pNode
)).First();
481 pShell
->ParkCursor(aIdx
.GetNode());
486 pNode
= &aIdx
.GetNode();
489 rCnt
.SetNewContentIdx(nullptr);
491 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
494 getIDocumentContentOperations().DeleteSection(pNode
);
499 if (rDescMasterHeaderFormat
.GetHeaderFormat() && rDescMasterHeaderFormat
!= rChgedMasterHeaderFormat
)
500 lDelHFFormat(&rDescMasterHeaderFormat
, rDescMasterHeaderFormat
.GetHeaderFormat());
501 else if (rDescLeftHeaderFormat
.GetHeaderFormat() && rDescLeftHeaderFormat
!= rChgedLeftHeaderFormat
)
502 lDelHFFormat(&rDescLeftHeaderFormat
, rDescLeftHeaderFormat
.GetHeaderFormat());
503 else if (rDescFirstLeftHeaderFormat
.GetHeaderFormat() && rDescFirstLeftHeaderFormat
!= rChgedFirstLeftHeaderFormat
)
504 lDelHFFormat(&rDescFirstLeftHeaderFormat
, rDescFirstLeftHeaderFormat
.GetHeaderFormat());
506 else if (rDescMasterFooterFormat
.GetFooterFormat() && rDescMasterFooterFormat
!= rChgedMasterFooterFormat
)
507 lDelHFFormat(&rDescMasterFooterFormat
, rDescMasterFooterFormat
.GetFooterFormat());
508 else if (rDescLeftFooterFormat
.GetFooterFormat() && rDescLeftFooterFormat
!= rChgedLeftFooterFormat
)
509 lDelHFFormat(&rDescLeftFooterFormat
, rDescLeftFooterFormat
.GetFooterFormat());
510 else if (rDescFirstLeftFooterFormat
.GetFooterFormat() && rDescFirstLeftFooterFormat
!= rChgedFirstLeftFooterFormat
)
511 lDelHFFormat(&rDescFirstLeftFooterFormat
, rDescFirstLeftFooterFormat
.GetFooterFormat());
514 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
516 // Mirror at first if needed.
517 if ( rChged
.GetUseOn() == UseOnPage::Mirror
)
518 const_cast<SwPageDesc
&>(rChged
).Mirror();
521 // Or else transfer values from Master to Left
522 ::lcl_DescSetAttr(rChged
.GetMaster(),
523 const_cast<SwPageDesc
&>(rChged
).GetLeft());
525 ::lcl_DescSetAttr(rChged
.GetMaster(),
526 const_cast<SwPageDesc
&>(rChged
).GetFirstMaster());
527 ::lcl_DescSetAttr(rChged
.GetLeft(),
528 const_cast<SwPageDesc
&>(rChged
).GetFirstLeft());
530 // Take over NumType.
531 if( rChged
.GetNumType().GetNumberingType() != rDesc
.GetNumType().GetNumberingType() )
533 rDesc
.SetNumType( rChged
.GetNumType() );
534 // Notify page number fields that NumFormat has changed
535 getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::PageNumber
)->UpdateFields();
536 getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::RefPageGet
)->UpdateFields();
538 // If the numbering scheme has changed we could have QuoVadis/ErgoSum texts
539 // that refer to a changed page, so we invalidate foot notes.
540 SwFootnoteIdxs
& rFootnoteIdxs
= GetFootnoteIdxs();
541 for( SwFootnoteIdxs::size_type nPos
= 0; nPos
< rFootnoteIdxs
.size(); ++nPos
)
543 SwTextFootnote
*pTextFootnote
= rFootnoteIdxs
[ nPos
];
544 const SwFormatFootnote
&rFootnote
= pTextFootnote
->GetFootnote();
545 pTextFootnote
->SetNumber(rFootnote
.GetNumber(), rFootnote
.GetNumberRLHidden(), rFootnote
.GetNumStr());
549 // Take over orientation
550 rDesc
.SetLandscape( rChged
.GetLandscape() );
553 const SwFormatHeader
& rMasterHead
= rChged
.GetMaster().GetHeader();
554 rDesc
.GetMaster().SetFormatAttr( rMasterHead
);
555 const bool bRestoreStashedLeftHead
= rDesc
.IsHeaderShared() && !rChged
.IsHeaderShared();
556 const bool bRestoreStashedFirstMasterHead
= rDesc
.IsFirstShared() && !rChged
.IsFirstShared();
557 const bool bRestoreStashedFirstLeftHead
= (rDesc
.IsHeaderShared() && !rChged
.IsHeaderShared()) || (rDesc
.IsFirstShared() && !rChged
.IsFirstShared());
558 const SwFrameFormat
* pStashedLeftFormat
= bRestoreStashedLeftHead
? rChged
.GetStashedFrameFormat(true, true, false) : nullptr;
559 const SwFrameFormat
* pStashedFirstMasterFormat
= bRestoreStashedFirstMasterHead
? rChged
.GetStashedFrameFormat(true, false, true) : nullptr;
560 const SwFrameFormat
* pStashedFirstLeftFormat
= bRestoreStashedFirstLeftHead
? rChged
.GetStashedFrameFormat(true, true, true) : nullptr;
561 CopyMasterHeader(rChged
, pStashedLeftFormat
? pStashedLeftFormat
->GetHeader() : rMasterHead
, rDesc
, true, false); // Copy left header
562 CopyMasterHeader(rChged
, pStashedFirstMasterFormat
? pStashedFirstMasterFormat
->GetHeader() : rMasterHead
, rDesc
, false, true); // Copy first master
563 CopyMasterHeader(rChged
, pStashedFirstLeftFormat
? pStashedFirstLeftFormat
->GetHeader() : rMasterHead
, rDesc
, true, true); // Copy first left
565 if (pStashedLeftFormat
)
566 rDesc
.RemoveStashedFormat(true, true, false);
568 if (pStashedFirstMasterFormat
)
569 rDesc
.RemoveStashedFormat(true, false, true);
571 if (pStashedFirstLeftFormat
)
572 rDesc
.RemoveStashedFormat(true, true, true);
574 rDesc
.ChgHeaderShare( rChged
.IsHeaderShared() );
577 const SwFormatFooter
& rMasterFoot
= rChged
.GetMaster().GetFooter();
578 rDesc
.GetMaster().SetFormatAttr( rMasterFoot
);
579 const bool bRestoreStashedLeftFoot
= rDesc
.IsFooterShared() && !rChged
.IsFooterShared();
580 const bool bRestoreStashedFirstMasterFoot
= rDesc
.IsFirstShared() && !rChged
.IsFirstShared();
581 const bool bRestoreStashedFirstLeftFoot
= (rDesc
.IsFooterShared() && !rChged
.IsFooterShared()) || (rDesc
.IsFirstShared() && !rChged
.IsFirstShared());
582 const SwFrameFormat
* pStashedLeftFoot
= bRestoreStashedLeftFoot
? rChged
.GetStashedFrameFormat(false, true, false) : nullptr;
583 const SwFrameFormat
* pStashedFirstMasterFoot
= bRestoreStashedFirstMasterFoot
? rChged
.GetStashedFrameFormat(false, false, true) : nullptr;
584 const SwFrameFormat
* pStashedFirstLeftFoot
= bRestoreStashedFirstLeftFoot
? rChged
.GetStashedFrameFormat(false, true, true) : nullptr;
585 CopyMasterFooter(rChged
, pStashedLeftFoot
? pStashedLeftFoot
->GetFooter() : rMasterFoot
, rDesc
, true, false); // Copy left footer
586 CopyMasterFooter(rChged
, pStashedFirstMasterFoot
? pStashedFirstMasterFoot
->GetFooter() : rMasterFoot
, rDesc
, false, true); // Copy first master
587 CopyMasterFooter(rChged
, pStashedFirstLeftFoot
? pStashedFirstLeftFoot
->GetFooter() : rMasterFoot
, rDesc
, true, true); // Copy first left
589 if (pStashedLeftFormat
)
590 rDesc
.RemoveStashedFormat(false, true, false);
592 if (pStashedFirstMasterFoot
)
593 rDesc
.RemoveStashedFormat(false, false, true);
595 if (pStashedFirstLeftFoot
)
596 rDesc
.RemoveStashedFormat(false, true, true);
598 rDesc
.ChgFooterShare( rChged
.IsFooterShared() );
599 // there is just one first shared flag for both header and footer?
600 rDesc
.ChgFirstShare( rChged
.IsFirstShared() );
602 if ( rDesc
.GetName() != rChged
.GetName() )
603 rDesc
.SetName( rChged
.GetName() );
605 // A RegisterChange is triggered, if necessary
606 rDesc
.SetRegisterFormatColl( rChged
.GetRegisterFormatColl() );
608 // If UseOn or the Follow change, the paragraphs need to know about it.
610 bool bFollow
= false;
611 if (rDesc
.GetUseOn() != rChged
.GetUseOn())
613 rDesc
.SetUseOn( rChged
.GetUseOn() );
616 if (rDesc
.GetFollow() != rChged
.GetFollow())
618 if (rChged
.GetFollow() == &rChged
)
620 if (rDesc
.GetFollow() != &rDesc
)
622 rDesc
.SetFollow( &rDesc
);
628 rDesc
.SetFollow( rChged
.m_pFollow
);
633 if ( (bUseOn
|| bFollow
) && pTmpRoot
)
636 for( auto aLayout
: GetAllLayouts() )
637 aLayout
->AllCheckPageDescs();
640 // Take over the page attributes.
641 ::lcl_DescSetAttr( rChged
.GetMaster(), rDesc
.GetMaster() );
642 ::lcl_DescSetAttr( rChged
.GetLeft(), rDesc
.GetLeft() );
643 ::lcl_DescSetAttr( rChged
.GetFirstMaster(), rDesc
.GetFirstMaster() );
644 ::lcl_DescSetAttr( rChged
.GetFirstLeft(), rDesc
.GetFirstLeft() );
646 // If the FootnoteInfo changes, the pages are triggered.
647 if( !(rDesc
.GetFootnoteInfo() == rChged
.GetFootnoteInfo()) )
649 rDesc
.SetFootnoteInfo( rChged
.GetFootnoteInfo() );
650 sw::PageFootnoteHint aHint
;
651 rDesc
.GetMaster().CallSwClientNotify(aHint
);
652 rDesc
.GetLeft().CallSwClientNotify(aHint
);
653 rDesc
.GetFirstMaster().CallSwClientNotify(aHint
);
654 rDesc
.GetFirstLeft().CallSwClientNotify(aHint
);
656 getIDocumentState().SetModified();
658 SfxBindings
* pBindings
=
659 ( GetDocShell() && GetDocShell()->GetDispatcher() ) ? GetDocShell()->GetDispatcher()->GetBindings() : nullptr;
662 pBindings
->Invalidate( SID_ATTR_PAGE_COLUMN
);
663 pBindings
->Invalidate( SID_ATTR_PAGE
);
664 pBindings
->Invalidate( SID_ATTR_PAGE_SIZE
);
665 pBindings
->Invalidate( SID_ATTR_PAGE_ULSPACE
);
666 pBindings
->Invalidate( SID_ATTR_PAGE_LRSPACE
);
669 //h/f of first-left page must not be unique but same as first master or left
670 assert((rDesc
.IsFirstShared())
671 ? rDesc
.GetFirstLeft().GetHeader().GetHeaderFormat() == rDesc
.GetLeft().GetHeader().GetHeaderFormat()
672 : rDesc
.GetFirstLeft().GetHeader().GetHeaderFormat() == rDesc
.GetFirstMaster().GetHeader().GetHeaderFormat());
673 assert((rDesc
.IsFirstShared())
674 ? rDesc
.GetFirstLeft().GetFooter().GetFooterFormat() == rDesc
.GetLeft().GetFooter().GetFooterFormat()
675 : rDesc
.GetFirstLeft().GetFooter().GetFooterFormat() == rDesc
.GetFirstMaster().GetFooter().GetFooterFormat());
678 /// All descriptors whose Follow point to the to-be-deleted have to be adapted.
680 void SwDoc::PreDelPageDesc(SwPageDesc
const * pDel
)
685 // mba: test iteration as clients are removed while iteration
686 SwPageDescHint
aHint( m_PageDescs
[0] );
687 pDel
->CallSwClientNotify( aHint
);
689 bool bHasLayout
= getIDocumentLayoutAccess().HasLayout();
690 if ( mpFootnoteInfo
->DependsOn( pDel
) )
692 mpFootnoteInfo
->ChgPageDesc( m_PageDescs
[0] );
695 for( auto aLayout
: GetAllLayouts() )
696 aLayout
->CheckFootnotePageDescs(false);
699 else if ( mpEndNoteInfo
->DependsOn( pDel
) )
701 mpEndNoteInfo
->ChgPageDesc( m_PageDescs
[0] );
704 for( auto aLayout
: GetAllLayouts() )
705 aLayout
->CheckFootnotePageDescs(true);
709 for (SwPageDesc
* pPageDesc
: m_PageDescs
)
711 if (pPageDesc
->GetFollow() == pDel
)
713 pPageDesc
->SetFollow(nullptr);
716 for( auto aLayout
: GetAllLayouts() )
717 aLayout
->AllCheckPageDescs();
723 void SwDoc::BroadcastStyleOperation(const OUString
& rName
, SfxStyleFamily eFamily
,
728 SfxStyleSheetBasePool
* pPool
= mpDocShell
->GetStyleSheetPool();
732 SfxStyleSheetBase
* pBase
= pPool
->Find(rName
, eFamily
);
734 if (pBase
!= nullptr)
735 pPool
->Broadcast(SfxStyleSheetHint( nOp
, *pBase
));
740 void SwDoc::DelPageDesc( size_t i
, bool bBroadcast
)
742 OSL_ENSURE(i
< m_PageDescs
.size(), "PageDescs is out of range.");
743 OSL_ENSURE( i
!= 0, "You cannot delete the default Pagedesc.");
747 SwPageDesc
&rDel
= *m_PageDescs
[i
];
750 BroadcastStyleOperation(rDel
.GetName(), SfxStyleFamily::Page
,
751 SfxHintId::StyleSheetErased
);
753 if (GetIDocumentUndoRedo().DoesUndo())
755 GetIDocumentUndoRedo().AppendUndo(
756 std::make_unique
<SwUndoPageDescDelete
>(rDel
, this));
759 PreDelPageDesc(&rDel
); // #i7983#
761 m_PageDescs
.erase(m_PageDescs
.begin() + i
);
762 getIDocumentState().SetModified();
765 SwPageDesc
* SwDoc::MakePageDesc(const OUString
&rName
, const SwPageDesc
*pCpy
,
766 bool bRegardLanguage
, bool bBroadcast
)
771 pNew
= new SwPageDesc( *pCpy
);
772 pNew
->SetName( rName
);
773 if( rName
!= pCpy
->GetName() )
775 pNew
->SetPoolFormatId( USHRT_MAX
);
776 pNew
->SetPoolHelpId( USHRT_MAX
);
777 pNew
->SetPoolHlpFileId( UCHAR_MAX
);
782 pNew
= new SwPageDesc( rName
, GetDfltFrameFormat(), this );
783 // Set the default page format.
784 lcl_DefaultPageFormat( USHRT_MAX
, pNew
->GetMaster(), pNew
->GetLeft(), pNew
->GetFirstMaster(), pNew
->GetFirstLeft() );
786 SvxFrameDirection aFrameDirection
= bRegardLanguage
?
787 GetDefaultFrameDirection(GetAppLanguage())
788 : SvxFrameDirection::Horizontal_LR_TB
;
790 pNew
->GetMaster().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection
, RES_FRAMEDIR
) );
791 pNew
->GetLeft().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection
, RES_FRAMEDIR
) );
792 pNew
->GetFirstMaster().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection
, RES_FRAMEDIR
) );
793 pNew
->GetFirstLeft().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection
, RES_FRAMEDIR
) );
796 std::pair
<SwPageDescs::const_iterator
, bool> res
= m_PageDescs
.push_back( pNew
);
797 SAL_WARN_IF(!res
.second
, "sw", "MakePageDesc called with existing name" );
800 BroadcastStyleOperation(rName
, SfxStyleFamily::Page
,
801 SfxHintId::StyleSheetCreated
);
803 if (GetIDocumentUndoRedo().DoesUndo())
805 GetIDocumentUndoRedo().AppendUndo(std::make_unique
<SwUndoPageDescCreate
>(pNew
, this));
808 getIDocumentState().SetModified();
812 void SwDoc::PrtOLENotify( bool bAll
)
814 SwFEShell
*pShell
= nullptr;
816 SwViewShell
*pSh
= getIDocumentLayoutAccess().GetCurrentViewShell();
819 for(SwViewShell
& rShell
: pSh
->GetRingContainer())
821 if(auto pFEShell
= dynamic_cast<SwFEShell
*>( &rShell
))
831 // This doesn't make sense without a Shell and thus without a client, because
832 // the communication about size changes is implemented by these components.
833 // Because we don't have a Shell we remember this unfortunate situation
835 // which is made up for later on when creating the first Shell.
836 mbOLEPrtNotifyPending
= true;
838 mbAllOLENotify
= true;
842 if ( mbAllOLENotify
)
845 mbOLEPrtNotifyPending
= mbAllOLENotify
= false;
847 std::unique_ptr
<SwOLENodes
> pNodes
= SwContentNode::CreateOLENodesArray( *GetDfltGrfFormatColl(), !bAll
);
850 ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY
,
851 0, pNodes
->size(), GetDocShell());
852 getIDocumentLayoutAccess().GetCurrentLayout()->StartAllAction();
854 for( SwOLENodes::size_type i
= 0; i
< pNodes
->size(); ++i
)
856 ::SetProgressState( i
, GetDocShell() );
858 SwOLENode
* pOLENd
= (*pNodes
)[i
];
859 pOLENd
->SetOLESizeInvalid( false );
861 // At first load the Infos and see if it's not already in the exclude list.
864 svt::EmbeddedObjectRef
& xObj
= pOLENd
->GetOLEObj().GetObject();
866 aName
= SvGlobalName( xObj
->getClassID() );
867 else // Not yet loaded
869 // TODO/LATER: retrieve ClassID of an unloaded object
874 for ( std::vector
<SvGlobalName
>::size_type j
= 0;
875 j
< pGlobalOLEExcludeList
->size() && !bFound
;
878 bFound
= (*pGlobalOLEExcludeList
)[j
] == aName
;
883 // We don't know it, so the object has to be loaded.
884 // If it doesn't want to be informed
887 pGlobalOLEExcludeList
->push_back( aName
);
891 getIDocumentLayoutAccess().GetCurrentLayout()->EndAllAction();
892 ::EndProgress( GetDocShell() );
897 IMPL_LINK_NOARG( SwDoc
, DoUpdateModifiedOLE
, Timer
*, void )
899 SwFEShell
* pSh
= static_cast<SwFEShell
*>(GetEditShell());
903 mbOLEPrtNotifyPending
= mbAllOLENotify
= false;
905 std::unique_ptr
<SwOLENodes
> pNodes
= SwContentNode::CreateOLENodesArray( *GetDfltGrfFormatColl(), true );
909 ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY
,
910 0, pNodes
->size(), GetDocShell());
911 getIDocumentLayoutAccess().GetCurrentLayout()->StartAllAction();
912 SwUpdateAttr
aHint(0,0,0);
913 for( SwOLENodes::size_type i
= 0; i
< pNodes
->size(); ++i
)
915 ::SetProgressState( i
, GetDocShell() );
917 SwOLENode
* pOLENd
= (*pNodes
)[i
];
918 pOLENd
->SetOLESizeInvalid( false );
920 // We don't know it, so the object has to be loaded.
921 // If it doesn't want to be informed
922 if( pOLENd
->GetOLEObj().GetOleRef().is() ) // Broken?
924 pOLENd
->UpdateAttr(aHint
);
927 getIDocumentLayoutAccess().GetCurrentLayout()->EndAllAction();
928 ::EndProgress( GetDocShell() );
931 static SwPageDesc
* lcl_FindPageDesc( const SwPageDescs
*pPageDescs
,
932 size_t *pPos
, const OUString
&rName
)
934 SwPageDesc
* res
= nullptr;
935 SwPageDescs::const_iterator it
= pPageDescs
->find( rName
);
936 if( it
!= pPageDescs
->end() )
940 *pPos
= std::distance( pPageDescs
->begin(), it
);
947 SwPageDesc
* SwDoc::FindPageDesc( const OUString
& rName
, size_t* pPos
) const
949 return lcl_FindPageDesc( &m_PageDescs
, pPos
, rName
);
952 bool SwDoc::ContainsPageDesc( const SwPageDesc
*pDesc
, size_t* pPos
) const
954 if( pDesc
== nullptr )
956 if( !m_PageDescs
.contains( const_cast <SwPageDesc
*>( pDesc
) ) ) {
964 SwPageDesc
* desc
= lcl_FindPageDesc(
965 &m_PageDescs
, pPos
, pDesc
->GetName() );
966 SAL_WARN_IF( desc
!= pDesc
, "sw", "SwPageDescs container is broken!" );
970 void SwDoc::DelPageDesc( const OUString
& rName
, bool bBroadcast
)
974 if (FindPageDesc(rName
, &nI
))
975 DelPageDesc(nI
, bBroadcast
);
978 void SwDoc::ChgPageDesc( const OUString
& rName
, const SwPageDesc
& rDesc
)
982 if (FindPageDesc(rName
, &nI
))
983 ChgPageDesc(nI
, rDesc
);
987 * The HTML import cannot resist changing the page descriptions, I don't
988 * know why. This function is meant to check the page descriptors for invalid
991 void SwDoc::CheckDefaultPageFormat()
993 for ( size_t i
= 0; i
< GetPageDescCnt(); ++i
)
995 SwPageDesc
& rDesc
= GetPageDesc( i
);
997 SwFrameFormat
& rMaster
= rDesc
.GetMaster();
998 SwFrameFormat
& rLeft
= rDesc
.GetLeft();
1000 const SwFormatFrameSize
& rMasterSize
= rMaster
.GetFrameSize();
1001 const SwFormatFrameSize
& rLeftSize
= rLeft
.GetFrameSize();
1003 const bool bSetSize
= INVALID_TWIPS
== rMasterSize
.GetWidth() ||
1004 INVALID_TWIPS
== rMasterSize
.GetHeight() ||
1005 INVALID_TWIPS
== rLeftSize
.GetWidth() ||
1006 INVALID_TWIPS
== rLeftSize
.GetHeight();
1009 lcl_DefaultPageFormat( rDesc
.GetPoolFormatId(), rDesc
.GetMaster(), rDesc
.GetLeft(), rDesc
.GetFirstMaster(), rDesc
.GetFirstLeft() );
1013 void SwDoc::SetDefaultPageMode(bool bSquaredPageMode
)
1015 if( !bSquaredPageMode
== !IsSquaredPageMode() )
1018 const SwTextGridItem
& rGrid
= GetDefault( RES_TEXTGRID
);
1019 SwTextGridItem aNewGrid
= rGrid
;
1020 aNewGrid
.SetSquaredMode(bSquaredPageMode
);
1022 SetDefault(aNewGrid
);
1024 for ( size_t i
= 0; i
< GetPageDescCnt(); ++i
)
1026 SwPageDesc
& rDesc
= GetPageDesc( i
);
1028 SwFrameFormat
& rMaster
= rDesc
.GetMaster();
1029 SwFrameFormat
& rLeft
= rDesc
.GetLeft();
1031 SwTextGridItem
aGrid(rMaster
.GetFormatAttr(RES_TEXTGRID
));
1032 aGrid
.SwitchPaperMode( bSquaredPageMode
);
1033 rMaster
.SetFormatAttr(aGrid
);
1034 rLeft
.SetFormatAttr(aGrid
);
1038 bool SwDoc::IsSquaredPageMode() const
1040 const SwTextGridItem
& rGrid
= GetDefault( RES_TEXTGRID
);
1041 return rGrid
.IsSquaredMode();
1044 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */