tdf#62032 use style list level when changing style
[LibreOffice.git] / sw / source / core / doc / docfmt.cxx
blob1dd846cb80e4b2b63d5245869ecd11fedacdf01f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
21 #include <hintids.hxx>
22 #include <svl/itemiter.hxx>
23 #include <svl/numformat.hxx>
24 #include <editeng/tstpitem.hxx>
25 #include <editeng/lrspitem.hxx>
26 #include <editeng/formatbreakitem.hxx>
27 #include <editeng/rsiditem.hxx>
28 #include <editeng/colritem.hxx>
29 #include <officecfg/Office/Common.hxx>
30 #include <osl/diagnose.h>
31 #include <svl/zforlist.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <unotools/configmgr.hxx>
34 #include <sal/log.hxx>
35 #include <com/sun/star/i18n/WordType.hpp>
36 #include <com/sun/star/i18n/XBreakIterator.hpp>
37 #include <fmtpdsc.hxx>
38 #include <fmthdft.hxx>
39 #include <fmtcntnt.hxx>
40 #include <doc.hxx>
41 #include <docfunc.hxx>
42 #include <drawdoc.hxx>
43 #include <MarkManager.hxx>
44 #include <IDocumentDrawModelAccess.hxx>
45 #include <IDocumentUndoRedo.hxx>
46 #include <DocumentContentOperationsManager.hxx>
47 #include <DocumentSettingManager.hxx>
48 #include <IDocumentFieldsAccess.hxx>
49 #include <IDocumentState.hxx>
50 #include <IDocumentLayoutAccess.hxx>
51 #include <IDocumentRedlineAccess.hxx>
52 #include <IDocumentStylePoolAccess.hxx>
53 #include <rootfrm.hxx>
54 #include <txtfrm.hxx>
55 #include <hints.hxx>
56 #include <ndtxt.hxx>
57 #include <pam.hxx>
58 #include <UndoCore.hxx>
59 #include <UndoAttribute.hxx>
60 #include <UndoInsert.hxx>
61 #include <pagedesc.hxx>
62 #include <rolbck.hxx>
63 #include <mvsave.hxx>
64 #include <txatbase.hxx>
65 #include <swtblfmt.hxx>
66 #include <charfmt.hxx>
67 #include <docary.hxx>
68 #include <paratr.hxx>
69 #include <redline.hxx>
70 #include <reffld.hxx>
71 #include <fmtinfmt.hxx>
72 #include <breakit.hxx>
73 #include <SwUndoFmt.hxx>
74 #include <UndoManager.hxx>
75 #include <swmodule.hxx>
76 #include <modcfg.hxx>
77 #include <frameformats.hxx>
78 #include <textboxhelper.hxx>
79 #include <memory>
81 using namespace ::com::sun::star::i18n;
82 using namespace ::com::sun::star::lang;
83 using namespace ::com::sun::star::uno;
86 * Internal functions
89 static void SetTextFormatCollNext( SwTextFormatColl* pTextColl, const SwTextFormatColl* pDel )
91 if ( &pTextColl->GetNextTextFormatColl() == pDel )
93 pTextColl->SetNextTextFormatColl( *pTextColl );
97 static bool lcl_RstAttr( SwNode* pNd, void* pArgs )
99 const sw::DocumentContentOperationsManager::ParaRstFormat* pPara = static_cast<sw::DocumentContentOperationsManager::ParaRstFormat*>(pArgs);
100 SwContentNode* pNode = pNd->GetContentNode();
101 if (pPara && pPara->pLayout && pPara->pLayout->HasMergedParas()
102 && pNode && pNode->GetRedlineMergeFlag() == SwNode::Merge::Hidden)
104 return true;
106 if( pNode && pNode->HasSwAttrSet() )
108 const bool bLocked = pNode->IsModifyLocked();
109 pNode->LockModify();
111 SwDoc& rDoc = pNode->GetDoc();
113 // remove unused attribute RES_LR_SPACE
114 // add list attributes
115 SfxItemSetFixed<
116 RES_PARATR_NUMRULE, RES_PARATR_NUMRULE,
117 RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1,
118 RES_PAGEDESC, RES_BREAK> aSavedAttrsSet(rDoc.GetAttrPool());
119 const SfxItemSet* pAttrSetOfNode = pNode->GetpSwAttrSet();
121 std::vector<sal_uInt16> aClearWhichIds;
122 // restoring all paragraph list attributes
124 SfxItemSetFixed<RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1> aListAttrSet( rDoc.GetAttrPool() );
125 aListAttrSet.Set(*pAttrSetOfNode);
126 if ( aListAttrSet.Count() )
128 aSavedAttrsSet.Put(aListAttrSet);
129 SfxItemIter aIter( aListAttrSet );
130 const SfxPoolItem* pItem = aIter.GetCurItem();
131 while( pItem )
133 aClearWhichIds.push_back( pItem->Which() );
134 pItem = aIter.NextItem();
139 const SfxPoolItem* pItem;
141 sal_uInt16 const aSavIds[3] = { RES_PAGEDESC, RES_BREAK, RES_PARATR_NUMRULE };
142 for (sal_uInt16 aSavId : aSavIds)
144 if (SfxItemState::SET == pAttrSetOfNode->GetItemState(aSavId, false, &pItem))
146 bool bSave = false;
147 switch( aSavId )
149 case RES_PAGEDESC:
150 bSave = nullptr != pItem->StaticWhichCast(RES_PAGEDESC).GetPageDesc();
151 break;
152 case RES_BREAK:
153 bSave = SvxBreak::NONE != pItem->StaticWhichCast(RES_BREAK).GetBreak();
154 break;
155 case RES_PARATR_NUMRULE:
156 bSave = !pItem->StaticWhichCast(RES_PARATR_NUMRULE).GetValue().isEmpty();
157 break;
159 if( bSave )
161 aSavedAttrsSet.Put(*pItem);
162 aClearWhichIds.push_back(aSavId);
167 // do not clear items directly from item set and only clear to be kept
168 // attributes, if no deletion item set is found.
169 const bool bKeepAttributes =
170 !pPara || !pPara->pDelSet || pPara->pDelSet->Count() == 0;
171 if ( bKeepAttributes )
173 pNode->ResetAttr( aClearWhichIds );
176 if( !bLocked )
177 pNode->UnlockModify();
179 if( pPara )
181 SwRegHistory aRegH( pNode, *pNode, pPara->pHistory );
183 if( pPara->pDelSet && pPara->pDelSet->Count() )
185 OSL_ENSURE( !bKeepAttributes,
186 "<lcl_RstAttr(..)> - certain attributes are kept, but not needed." );
187 SfxItemIter aIter( *pPara->pDelSet );
188 for (pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
190 if ( ( pItem->Which() != RES_PAGEDESC &&
191 pItem->Which() != RES_BREAK &&
192 pItem->Which() != RES_PARATR_NUMRULE ) ||
193 ( aSavedAttrsSet.GetItemState( pItem->Which(), false ) != SfxItemState::SET ) )
195 pNode->ResetAttr( pItem->Which() );
199 else if( pPara->bResetAll )
200 pNode->ResetAllAttr();
201 else
202 pNode->ResetAttr( RES_PARATR_BEGIN, POOLATTR_END - 1 );
204 else
205 pNode->ResetAllAttr();
207 // only restore saved attributes, if needed
208 if (bKeepAttributes && aSavedAttrsSet.Count())
210 pNode->LockModify();
212 pNode->SetAttr(aSavedAttrsSet);
214 if( !bLocked )
215 pNode->UnlockModify();
218 return true;
221 void SwDoc::RstTextAttrs(const SwPaM &rRg, bool bInclRefToxMark,
222 bool bExactRange, SwRootFrame const*const pLayout)
224 SwHistory* pHst = nullptr;
225 SwDataChanged aTmp( rRg );
226 if (GetIDocumentUndoRedo().DoesUndo())
228 std::unique_ptr<SwUndoResetAttr> pUndo(new SwUndoResetAttr( rRg, RES_CHRFMT ));
229 pHst = &pUndo->GetHistory();
230 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
232 const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
233 sw::DocumentContentOperationsManager::ParaRstFormat aPara(
234 pStt, pEnd, pHst, nullptr, pLayout );
235 aPara.bInclRefToxMark = bInclRefToxMark;
236 aPara.bExactRange = bExactRange;
237 GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1,
238 sw::DocumentContentOperationsManager::lcl_RstTextAttr, &aPara );
239 getIDocumentState().SetModified();
242 void SwDoc::ResetAttrs( const SwPaM &rRg,
243 bool bTextAttr,
244 const o3tl::sorted_vector<sal_uInt16> &rAttrs,
245 const bool bSendDataChangedEvents,
246 SwRootFrame const*const pLayout)
248 SwPaM* pPam = const_cast<SwPaM*>(&rRg);
249 if( !bTextAttr && !rAttrs.empty() && RES_TXTATR_END > *(rAttrs.begin()) )
250 bTextAttr = true;
252 if( !rRg.HasMark() )
254 SwTextNode* pTextNd = rRg.GetPoint()->nNode.GetNode().GetTextNode();
255 if( !pTextNd )
256 return ;
258 pPam = new SwPaM( *rRg.GetPoint() );
260 SwIndex& rSt = pPam->GetPoint()->nContent;
261 sal_Int32 nMkPos, nPtPos = rSt.GetIndex();
263 // Special case: if the Cursor is located within a URL attribute, we take over it's area
264 SwTextAttr const*const pURLAttr(
265 pTextNd->GetTextAttrAt(rSt.GetIndex(), RES_TXTATR_INETFMT));
266 if (pURLAttr && !pURLAttr->GetINetFormat().GetValue().isEmpty())
268 nMkPos = pURLAttr->GetStart();
269 nPtPos = *pURLAttr->End();
271 else
273 assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
274 Boundary aBndry = g_pBreakIt->GetBreakIter()->getWordBoundary(
275 pTextNd->GetText(), nPtPos,
276 g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
277 WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
278 true);
280 if( aBndry.startPos < nPtPos && nPtPos < aBndry.endPos )
282 nMkPos = aBndry.startPos;
283 nPtPos = aBndry.endPos;
285 else
287 nPtPos = nMkPos = rSt.GetIndex();
288 if( bTextAttr )
289 pTextNd->DontExpandFormat( rSt );
293 rSt = nMkPos;
294 pPam->SetMark();
295 pPam->GetPoint()->nContent = nPtPos;
298 // #i96644#
299 std::unique_ptr< SwDataChanged > xDataChanged;
300 if ( bSendDataChangedEvents )
302 xDataChanged.reset( new SwDataChanged( *pPam ) );
304 SwHistory* pHst = nullptr;
305 if (GetIDocumentUndoRedo().DoesUndo())
307 std::unique_ptr<SwUndoResetAttr> pUndo(new SwUndoResetAttr( rRg,
308 bTextAttr ? sal_uInt16(RES_CONDTXTFMTCOLL) : sal_uInt16(RES_TXTFMTCOLL) ));
309 if( !rAttrs.empty() )
311 pUndo->SetAttrs( o3tl::sorted_vector(rAttrs) );
313 pHst = &pUndo->GetHistory();
314 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
317 const SwPosition *pStt = pPam->Start(), *pEnd = pPam->End();
318 sw::DocumentContentOperationsManager::ParaRstFormat aPara(
319 pStt, pEnd, pHst, nullptr, pLayout);
321 // mst: not including META here; it seems attrs with CH_TXTATR are omitted
322 SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
323 RES_TXTATR_INETFMT, RES_TXTATR_UNKNOWN_CONTAINER,
324 RES_PARATR_BEGIN, RES_FRMATR_END - 1,
325 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1>
326 aDelSet(GetAttrPool());
327 for( auto it = rAttrs.rbegin(); it != rAttrs.rend(); ++it )
329 if( POOLATTR_END > *it )
330 aDelSet.Put( *GetDfltAttr( *it ));
332 if( aDelSet.Count() )
333 aPara.pDelSet = &aDelSet;
335 bool bAdd = true;
336 SwNodeIndex aTmpStt( pStt->nNode );
337 SwNodeIndex aTmpEnd( pEnd->nNode );
338 if( pStt->nContent.GetIndex() ) // just one part
340 // set up a later, and all CharFormatAttr -> TextFormatAttr
341 SwTextNode* pTNd = aTmpStt.GetNode().GetTextNode();
342 if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() )
344 if (pHst)
346 SwRegHistory history(pTNd, *pTNd, pHst);
347 pTNd->FormatToTextAttr(pTNd);
349 else
351 pTNd->FormatToTextAttr(pTNd);
355 ++aTmpStt;
357 if( pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetContentNode()->Len() )
359 // set up a later, and all CharFormatAttr -> TextFormatAttr
360 ++aTmpEnd;
361 bAdd = false;
363 else if( pStt->nNode != pEnd->nNode || !pStt->nContent.GetIndex() )
365 SwTextNode* pTNd = aTmpEnd.GetNode().GetTextNode();
366 if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() )
368 if (pHst)
370 SwRegHistory history(pTNd, *pTNd, pHst);
371 pTNd->FormatToTextAttr(pTNd);
373 else
375 pTNd->FormatToTextAttr(pTNd);
380 if( aTmpStt < aTmpEnd )
381 GetNodes().ForEach( pStt->nNode, aTmpEnd, lcl_RstAttr, &aPara );
382 else if( !rRg.HasMark() )
384 aPara.bResetAll = false ;
385 ::lcl_RstAttr( &pStt->nNode.GetNode(), &aPara );
386 aPara.bResetAll = true ;
389 if( bTextAttr )
391 if( bAdd )
392 ++aTmpEnd;
393 GetNodes().ForEach( pStt->nNode, aTmpEnd, sw::DocumentContentOperationsManager::lcl_RstTextAttr, &aPara );
396 getIDocumentState().SetModified();
398 xDataChanged.reset(); //before delete pPam
400 if( pPam != &rRg )
401 delete pPam;
404 /// Set the rsid of the next nLen symbols of rRg to the current session number
405 void SwDoc::UpdateRsid( const SwPaM &rRg, const sal_Int32 nLen )
407 if (!SW_MOD()->GetModuleConfig()->IsStoreRsid())
408 return;
410 SwTextNode *pTextNode = rRg.GetPoint()->nNode.GetNode().GetTextNode();
411 if (!pTextNode)
413 return;
415 const sal_Int32 nStart(rRg.GetPoint()->nContent.GetIndex() - nLen);
416 SvxRsidItem aRsid( mnRsid, RES_CHRATR_RSID );
418 SfxItemSetFixed<RES_CHRATR_RSID, RES_CHRATR_RSID> aSet(GetAttrPool());
419 aSet.Put(aRsid);
420 bool const bRet(pTextNode->SetAttr(aSet, nStart,
421 rRg.GetPoint()->nContent.GetIndex()));
423 if (bRet && GetIDocumentUndoRedo().DoesUndo())
425 SwUndo *const pLastUndo = GetUndoManager().GetLastUndo();
426 SwUndoInsert *const pUndoInsert(dynamic_cast<SwUndoInsert*>(pLastUndo));
427 // this function is called after Insert so expects to find SwUndoInsert
428 assert(pUndoInsert);
429 if (pUndoInsert)
431 pUndoInsert->SetWithRsid();
436 bool SwDoc::UpdateParRsid( SwTextNode *pTextNode, sal_uInt32 nVal )
438 if (!SW_MOD()->GetModuleConfig()->IsStoreRsid())
439 return false;
441 if (!pTextNode)
443 return false;
446 SvxRsidItem aRsid( nVal ? nVal : mnRsid, RES_PARATR_RSID );
447 return pTextNode->SetAttr( aRsid );
450 /// Set the attribute according to the stated format.
451 /// If Undo is enabled, the old values is added to the Undo history.
452 void SwDoc::SetAttr( const SfxPoolItem& rAttr, SwFormat& rFormat )
454 SfxItemSet aSet( GetAttrPool(), rAttr.Which(), rAttr.Which() );
455 aSet.Put( rAttr );
456 SetAttr( aSet, rFormat );
459 /// Set the attribute according to the stated format.
460 /// If Undo is enabled, the old values is added to the Undo history.
461 void SwDoc::SetAttr( const SfxItemSet& rSet, SwFormat& rFormat )
463 if (GetIDocumentUndoRedo().DoesUndo())
465 SwUndoFormatAttrHelper aTmp( rFormat );
466 rFormat.SetFormatAttr( rSet );
467 if ( aTmp.GetUndo() )
469 GetIDocumentUndoRedo().AppendUndo( aTmp.ReleaseUndo() );
471 else
473 GetIDocumentUndoRedo().ClearRedo();
476 else
478 rFormat.SetFormatAttr( rSet );
481 // If the format is a shape, and it has a textbox, sync.
482 auto pShapeFormat = dynamic_cast<SwFrameFormat*>(&rFormat);
483 if (pShapeFormat && SwTextBoxHelper::isTextBox(pShapeFormat, RES_DRAWFRMFMT))
485 if (auto pObj = pShapeFormat->FindRealSdrObject())
487 SwTextBoxHelper::syncFlyFrameAttr(*pShapeFormat, rSet, pObj);
488 SwTextBoxHelper::changeAnchor(pShapeFormat, pObj);
492 getIDocumentState().SetModified();
495 void SwDoc::ResetAttrAtFormat( const sal_uInt16 nWhichId,
496 SwFormat& rChangedFormat )
498 std::unique_ptr<SwUndo> pUndo;
499 if (GetIDocumentUndoRedo().DoesUndo())
500 pUndo.reset(new SwUndoFormatResetAttr( rChangedFormat, nWhichId ));
502 const bool bAttrReset = rChangedFormat.ResetFormatAttr( nWhichId );
504 if ( bAttrReset )
506 if ( pUndo )
508 GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
511 getIDocumentState().SetModified();
515 static bool lcl_SetNewDefTabStops( SwTwips nOldWidth, SwTwips nNewWidth,
516 SvxTabStopItem& rChgTabStop )
518 // Set the default values of all TabStops to the new value.
519 // Attention: we always work with the PoolAttribute here, so that
520 // we don't calculate the same value on the same TabStop (pooled!) for all sets.
521 // We send a FormatChg to modify.
523 sal_uInt16 nOldCnt = rChgTabStop.Count();
524 if( !nOldCnt || nOldWidth == nNewWidth )
525 return false;
527 // Find the default's beginning
528 sal_uInt16 n;
529 for( n = nOldCnt; n ; --n )
530 if( SvxTabAdjust::Default != rChgTabStop[n - 1].GetAdjustment() )
531 break;
532 ++n;
533 if( n < nOldCnt ) // delete the DefTabStops
534 rChgTabStop.Remove( n, nOldCnt - n );
535 return true;
538 /// Set the attribute as new default attribute in this document.
539 /// If Undo is enabled, the old value is added to the Undo history.
540 void SwDoc::SetDefault( const SfxPoolItem& rAttr )
542 SfxItemSet aSet( GetAttrPool(), rAttr.Which(), rAttr.Which() );
543 aSet.Put( rAttr );
544 SetDefault( aSet );
547 void SwDoc::SetDefault( const SfxItemSet& rSet )
549 if( !rSet.Count() )
550 return;
552 sw::BroadcastingModify aCallMod;
553 SwAttrSet aOld( GetAttrPool(), rSet.GetRanges() ),
554 aNew( GetAttrPool(), rSet.GetRanges() );
555 SfxItemIter aIter( rSet );
556 const SfxPoolItem* pItem = aIter.GetCurItem();
557 SfxItemPool* pSdrPool = GetAttrPool().GetSecondaryPool();
560 bool bCheckSdrDflt = false;
561 const sal_uInt16 nWhich = pItem->Which();
562 aOld.Put( GetAttrPool().GetDefaultItem( nWhich ) );
563 GetAttrPool().SetPoolDefaultItem( *pItem );
564 aNew.Put( GetAttrPool().GetDefaultItem( nWhich ) );
566 if (isCHRATR(nWhich) || isTXTATR(nWhich))
568 aCallMod.Add( mpDfltTextFormatColl.get() );
569 aCallMod.Add( mpDfltCharFormat.get() );
570 bCheckSdrDflt = nullptr != pSdrPool;
572 else if ( isPARATR(nWhich) ||
573 isPARATR_LIST(nWhich) )
575 aCallMod.Add( mpDfltTextFormatColl.get() );
576 bCheckSdrDflt = nullptr != pSdrPool;
578 else if (isGRFATR(nWhich))
580 aCallMod.Add( mpDfltGrfFormatColl.get() );
582 else if (isFRMATR(nWhich) || isDrawingLayerAttribute(nWhich) )
584 aCallMod.Add( mpDfltGrfFormatColl.get() );
585 aCallMod.Add( mpDfltTextFormatColl.get() );
586 aCallMod.Add( mpDfltFrameFormat.get() );
588 else if (isBOXATR(nWhich))
590 aCallMod.Add( mpDfltFrameFormat.get() );
593 // also copy the defaults
594 if( bCheckSdrDflt )
596 sal_uInt16 nSlotId = GetAttrPool().GetSlotId( nWhich );
597 if( 0 != nSlotId && nSlotId != nWhich )
599 sal_uInt16 nEdtWhich = pSdrPool->GetWhich( nSlotId );
600 if( 0 != nEdtWhich && nSlotId != nEdtWhich )
602 std::unique_ptr<SfxPoolItem> pCpy(pItem->Clone());
603 pCpy->SetWhich( nEdtWhich );
604 pSdrPool->SetPoolDefaultItem( *pCpy );
609 pItem = aIter.NextItem();
610 } while (pItem);
612 if( aNew.Count() && aCallMod.HasWriterListeners() )
614 if (GetIDocumentUndoRedo().DoesUndo())
616 GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoDefaultAttr>( aOld, *this ) );
619 const SfxPoolItem* pTmpItem;
620 if( ( SfxItemState::SET ==
621 aNew.GetItemState( RES_PARATR_TABSTOP, false, &pTmpItem ) ) &&
622 pTmpItem->StaticWhichCast(RES_PARATR_TABSTOP).Count() )
624 // Set the default values of all TabStops to the new value.
625 // Attention: we always work with the PoolAttribute here, so that
626 // we don't calculate the same value on the same TabStop (pooled!) for all sets.
627 // We send a FormatChg to modify.
628 SwTwips nNewWidth = pTmpItem->StaticWhichCast(RES_PARATR_TABSTOP)[ 0 ].GetTabPos(),
629 nOldWidth = aOld.Get(RES_PARATR_TABSTOP)[ 0 ].GetTabPos();
631 bool bChg = false;
632 for (const SfxPoolItem* pItem2 : GetAttrPool().GetItemSurrogates(RES_PARATR_TABSTOP))
634 if(auto pTabStopItem = pItem2->DynamicWhichCast(RES_PARATR_TABSTOP))
635 bChg |= lcl_SetNewDefTabStops( nOldWidth, nNewWidth,
636 *const_cast<SvxTabStopItem*>(pTabStopItem) );
639 aNew.ClearItem( RES_PARATR_TABSTOP );
640 aOld.ClearItem( RES_PARATR_TABSTOP );
641 if( bChg )
643 SwFormatChg aChgFormat( mpDfltCharFormat.get() );
644 // notify the frames
645 aCallMod.CallSwClientNotify(sw::LegacyModifyHint( &aChgFormat, &aChgFormat ));
650 if( aNew.Count() && aCallMod.HasWriterListeners() )
652 SwAttrSetChg aChgOld( aOld, aOld );
653 SwAttrSetChg aChgNew( aNew, aNew );
654 aCallMod.CallSwClientNotify(sw::LegacyModifyHint( &aChgOld, &aChgNew )); // all changed are sent
657 // remove the default formats from the object again
658 SwIterator<SwClient, sw::BroadcastingModify> aClientIter(aCallMod);
659 for(SwClient* pClient = aClientIter.First(); pClient; pClient = aClientIter.Next())
660 aCallMod.Remove( pClient );
662 getIDocumentState().SetModified();
665 /// Get the default attribute in this document
666 const SfxPoolItem& SwDoc::GetDefault( sal_uInt16 nFormatHint ) const
668 return GetAttrPool().GetDefaultItem( nFormatHint );
671 /// Delete the formats
672 void SwDoc::DelCharFormat(size_t nFormat, bool bBroadcast)
674 SwCharFormat * pDel = (*mpCharFormatTable)[nFormat];
676 if (bBroadcast)
677 BroadcastStyleOperation(pDel->GetName(), SfxStyleFamily::Char,
678 SfxHintId::StyleSheetErased);
680 if (GetIDocumentUndoRedo().DoesUndo())
682 GetIDocumentUndoRedo().AppendUndo(
683 std::make_unique<SwUndoCharFormatDelete>(pDel, *this));
686 delete (*mpCharFormatTable)[nFormat];
687 mpCharFormatTable->erase(mpCharFormatTable->begin() + nFormat);
689 getIDocumentState().SetModified();
692 void SwDoc::DelCharFormat( SwCharFormat const *pFormat, bool bBroadcast )
694 size_t nFormat = mpCharFormatTable->GetPos( pFormat );
695 OSL_ENSURE( SIZE_MAX != nFormat, "Format not found," );
696 DelCharFormat( nFormat, bBroadcast );
699 void SwDoc::DelFrameFormat( SwFrameFormat *pFormat, bool bBroadcast )
701 if( dynamic_cast<const SwTableBoxFormat*>( pFormat) != nullptr || dynamic_cast<const SwTableLineFormat*>( pFormat) != nullptr )
703 OSL_ENSURE( false, "Format is not in the DocArray any more, "
704 "so it can be deleted with delete" );
705 delete pFormat;
707 else
709 // The format has to be in the one or the other, we'll see in which one.
710 if (mpFrameFormatTable->ContainsFormat(*pFormat))
712 if (bBroadcast)
713 BroadcastStyleOperation(pFormat->GetName(),
714 SfxStyleFamily::Frame,
715 SfxHintId::StyleSheetErased);
717 if (GetIDocumentUndoRedo().DoesUndo())
719 GetIDocumentUndoRedo().AppendUndo(
720 std::make_unique<SwUndoFrameFormatDelete>(pFormat, *this));
723 mpFrameFormatTable->erase( pFormat );
724 delete pFormat;
726 else
728 bool contains = GetSpzFrameFormats()->ContainsFormat(*pFormat);
729 OSL_ENSURE( contains, "FrameFormat not found." );
730 if( contains )
732 GetSpzFrameFormats()->erase( pFormat );
733 delete pFormat;
739 void SwDoc::DelTableFrameFormat( SwTableFormat *pFormat )
741 SwFrameFormats::const_iterator it = mpTableFrameFormatTable->find( pFormat );
742 OSL_ENSURE( it != mpTableFrameFormatTable->end(), "Format not found," );
743 mpTableFrameFormatTable->erase( it );
744 delete pFormat;
747 SwFrameFormat* SwDoc::FindFrameFormatByName( const OUString& rName ) const
749 return mpFrameFormatTable->FindFormatByName( rName );
752 /// Create the formats
753 SwFlyFrameFormat *SwDoc::MakeFlyFrameFormat( const OUString &rFormatName,
754 SwFrameFormat *pDerivedFrom )
756 SwFlyFrameFormat *pFormat = new SwFlyFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom );
757 GetSpzFrameFormats()->push_back(pFormat);
758 getIDocumentState().SetModified();
759 return pFormat;
762 SwDrawFrameFormat *SwDoc::MakeDrawFrameFormat( const OUString &rFormatName,
763 SwFrameFormat *pDerivedFrom )
765 SwDrawFrameFormat *pFormat = new SwDrawFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom);
766 GetSpzFrameFormats()->push_back(pFormat);
767 getIDocumentState().SetModified();
768 return pFormat;
771 size_t SwDoc::GetTableFrameFormatCount(bool bUsed) const
773 if (!bUsed)
775 return mpTableFrameFormatTable->size();
778 SwAutoFormatGetDocNode aGetHt(&GetNodes());
779 size_t nCount = 0;
780 for (SwFrameFormat* const & pFormat : *mpTableFrameFormatTable)
782 if (!pFormat->GetInfo(aGetHt))
783 nCount++;
785 return nCount;
788 SwFrameFormat& SwDoc::GetTableFrameFormat(size_t nFormat, bool bUsed) const
790 if (!bUsed)
792 return *((*mpTableFrameFormatTable)[nFormat]);
795 SwAutoFormatGetDocNode aGetHt(&GetNodes());
797 size_t index = 0;
799 for (SwFrameFormat* const & pFormat : *mpTableFrameFormatTable)
801 if (!pFormat->GetInfo(aGetHt))
803 if (index == nFormat)
804 return *pFormat;
805 else
806 index++;
809 throw std::out_of_range("Format index out of range.");
812 SwTableFormat* SwDoc::MakeTableFrameFormat( const OUString &rFormatName,
813 SwFrameFormat *pDerivedFrom )
815 SwTableFormat* pFormat = new SwTableFormat( GetAttrPool(), rFormatName, pDerivedFrom );
816 mpTableFrameFormatTable->push_back( pFormat );
817 getIDocumentState().SetModified();
819 return pFormat;
822 SwFrameFormat *SwDoc::MakeFrameFormat(const OUString &rFormatName,
823 SwFrameFormat *pDerivedFrom,
824 bool bBroadcast, bool bAuto)
826 SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom );
828 pFormat->SetAuto(bAuto);
829 mpFrameFormatTable->push_back( pFormat );
830 getIDocumentState().SetModified();
832 if (GetIDocumentUndoRedo().DoesUndo())
834 GetIDocumentUndoRedo().AppendUndo(
835 std::make_unique<SwUndoFrameFormatCreate>(pFormat, pDerivedFrom, *this));
838 if (bBroadcast)
840 BroadcastStyleOperation(rFormatName, SfxStyleFamily::Frame,
841 SfxHintId::StyleSheetCreated);
844 return pFormat;
847 SwFormat *SwDoc::MakeFrameFormat_(const OUString &rFormatName,
848 SwFormat *pDerivedFrom,
849 bool bBroadcast, bool bAuto)
851 SwFrameFormat *pFrameFormat = dynamic_cast<SwFrameFormat*>(pDerivedFrom);
852 pFrameFormat = MakeFrameFormat( rFormatName, pFrameFormat, bBroadcast, bAuto );
853 return pFrameFormat;
856 SwCharFormat *SwDoc::MakeCharFormat( const OUString &rFormatName,
857 SwCharFormat *pDerivedFrom,
858 bool bBroadcast )
860 SwCharFormat *pFormat = new SwCharFormat( GetAttrPool(), rFormatName, pDerivedFrom );
861 mpCharFormatTable->insert( pFormat );
862 pFormat->SetAuto(false);
863 getIDocumentState().SetModified();
865 if (GetIDocumentUndoRedo().DoesUndo())
867 GetIDocumentUndoRedo().AppendUndo(
868 std::make_unique<SwUndoCharFormatCreate>(pFormat, pDerivedFrom, *this));
871 if (bBroadcast)
873 BroadcastStyleOperation(rFormatName, SfxStyleFamily::Char,
874 SfxHintId::StyleSheetCreated);
877 return pFormat;
880 SwFormat *SwDoc::MakeCharFormat_(const OUString &rFormatName,
881 SwFormat *pDerivedFrom,
882 bool bBroadcast, bool /*bAuto*/)
884 SwCharFormat *pCharFormat = dynamic_cast<SwCharFormat*>(pDerivedFrom);
885 pCharFormat = MakeCharFormat( rFormatName, pCharFormat, bBroadcast );
886 return pCharFormat;
889 /// Create the FormatCollections
890 SwTextFormatColl* SwDoc::MakeTextFormatColl( const OUString &rFormatName,
891 SwTextFormatColl *pDerivedFrom,
892 bool bBroadcast)
894 SwTextFormatColl *pFormatColl = new SwTextFormatColl( GetAttrPool(), rFormatName,
895 pDerivedFrom );
896 mpTextFormatCollTable->push_back(pFormatColl);
897 pFormatColl->SetAuto(false);
898 getIDocumentState().SetModified();
900 if (GetIDocumentUndoRedo().DoesUndo())
902 GetIDocumentUndoRedo().AppendUndo(
903 std::make_unique<SwUndoTextFormatCollCreate>(pFormatColl, pDerivedFrom,
904 *this));
907 if (bBroadcast)
908 BroadcastStyleOperation(rFormatName, SfxStyleFamily::Para,
909 SfxHintId::StyleSheetCreated);
911 return pFormatColl;
914 SwFormat *SwDoc::MakeTextFormatColl_(const OUString &rFormatName,
915 SwFormat *pDerivedFrom,
916 bool bBroadcast, bool /*bAuto*/)
918 SwTextFormatColl *pTextFormatColl = dynamic_cast<SwTextFormatColl*>(pDerivedFrom);
919 pTextFormatColl = MakeTextFormatColl( rFormatName, pTextFormatColl, bBroadcast );
920 return pTextFormatColl;
923 //FEATURE::CONDCOLL
924 SwConditionTextFormatColl* SwDoc::MakeCondTextFormatColl( const OUString &rFormatName,
925 SwTextFormatColl *pDerivedFrom,
926 bool bBroadcast)
928 SwConditionTextFormatColl*pFormatColl = new SwConditionTextFormatColl( GetAttrPool(),
929 rFormatName, pDerivedFrom );
930 mpTextFormatCollTable->push_back(pFormatColl);
931 pFormatColl->SetAuto(false);
932 getIDocumentState().SetModified();
934 if (GetIDocumentUndoRedo().DoesUndo())
936 GetIDocumentUndoRedo().AppendUndo(
937 std::make_unique<SwUndoCondTextFormatCollCreate>(pFormatColl, pDerivedFrom,
938 *this));
941 if (bBroadcast)
942 BroadcastStyleOperation(rFormatName, SfxStyleFamily::Para,
943 SfxHintId::StyleSheetCreated);
945 return pFormatColl;
947 //FEATURE::CONDCOLL
949 // GRF
950 SwGrfFormatColl* SwDoc::MakeGrfFormatColl( const OUString &rFormatName,
951 SwGrfFormatColl *pDerivedFrom )
953 SwGrfFormatColl *pFormatColl = new SwGrfFormatColl( GetAttrPool(), rFormatName,
954 pDerivedFrom );
955 mpGrfFormatCollTable->push_back( pFormatColl );
956 pFormatColl->SetAuto(false);
957 getIDocumentState().SetModified();
958 return pFormatColl;
961 void SwDoc::DelTextFormatColl(size_t nFormatColl, bool bBroadcast)
963 OSL_ENSURE( nFormatColl, "Remove of Coll 0." );
965 // Who has the to-be-deleted as their Next?
966 SwTextFormatColl *pDel = (*mpTextFormatCollTable)[nFormatColl];
967 if( mpDfltTextFormatColl.get() == pDel )
968 return; // never delete default!
970 if (bBroadcast)
971 BroadcastStyleOperation(pDel->GetName(), SfxStyleFamily::Para,
972 SfxHintId::StyleSheetErased);
974 if (GetIDocumentUndoRedo().DoesUndo())
976 std::unique_ptr<SwUndoTextFormatCollDelete> pUndo;
977 if (RES_CONDTXTFMTCOLL == pDel->Which())
979 pUndo.reset(new SwUndoCondTextFormatCollDelete(pDel, *this));
981 else
983 pUndo.reset(new SwUndoTextFormatCollDelete(pDel, *this));
986 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
989 // Remove the FormatColl
990 mpTextFormatCollTable->erase(mpTextFormatCollTable->begin() + nFormatColl);
991 // Correct next
992 for( SwTextFormatColls::const_iterator it = mpTextFormatCollTable->begin() + 1; it != mpTextFormatCollTable->end(); ++it )
993 SetTextFormatCollNext( *it, pDel );
994 delete pDel;
995 getIDocumentState().SetModified();
998 void SwDoc::DelTextFormatColl( SwTextFormatColl const *pColl, bool bBroadcast )
1000 size_t nFormat = mpTextFormatCollTable->GetPos( pColl );
1001 OSL_ENSURE( SIZE_MAX != nFormat, "Collection not found," );
1002 DelTextFormatColl( nFormat, bBroadcast );
1005 static bool lcl_SetTextFormatColl( SwNode* pNode, void* pArgs )
1007 SwContentNode* pCNd = pNode->GetTextNode();
1009 if( pCNd == nullptr)
1010 return true;
1012 sw::DocumentContentOperationsManager::ParaRstFormat* pPara = static_cast<sw::DocumentContentOperationsManager::ParaRstFormat*>(pArgs);
1014 if (pPara->pLayout && pPara->pLayout->HasMergedParas())
1016 if (pCNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)
1018 return true;
1020 if (pCNd->IsTextNode())
1022 pCNd = sw::GetParaPropsNode(*pPara->pLayout, SwNodeIndex(*pCNd));
1026 SwTextFormatColl* pFormat = static_cast<SwTextFormatColl*>(pPara->pFormatColl);
1027 if ( pPara->bReset )
1029 lcl_RstAttr(pCNd, pPara);
1031 // #i62675# check, if paragraph style has changed
1032 if ( pPara->bResetListAttrs &&
1033 pFormat != pCNd->GetFormatColl() &&
1034 pFormat->GetItemState( RES_PARATR_NUMRULE ) == SfxItemState::SET )
1036 // Check, if the list style of the paragraph will change.
1037 bool bChangeOfListStyleAtParagraph( true );
1038 SwTextNode& rTNd(dynamic_cast<SwTextNode&>(*pCNd));
1040 SwNumRule* pNumRuleAtParagraph(rTNd.GetNumRule());
1041 if ( pNumRuleAtParagraph )
1043 const SwNumRuleItem& rNumRuleItemAtParagraphStyle =
1044 pFormat->GetNumRule();
1045 if ( rNumRuleItemAtParagraphStyle.GetValue() ==
1046 pNumRuleAtParagraph->GetName() )
1048 bChangeOfListStyleAtParagraph = false;
1053 if ( bChangeOfListStyleAtParagraph )
1055 std::unique_ptr< SwRegHistory > pRegH;
1056 if ( pPara->pHistory )
1058 pRegH.reset(new SwRegHistory(&rTNd, rTNd, pPara->pHistory));
1061 pCNd->ResetAttr( RES_PARATR_NUMRULE );
1063 // reset all list attributes
1064 pCNd->ResetAttr( RES_PARATR_LIST_LEVEL );
1065 pCNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
1066 pCNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
1067 pCNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
1068 pCNd->ResetAttr( RES_PARATR_LIST_ID );
1070 else
1072 // forcing reset of list level from parapgaph
1073 pCNd->SetAttr(pFormat->GetFormatAttr(RES_PARATR_LIST_LEVEL));
1078 // add to History so that old data is saved, if necessary
1079 if( pPara->pHistory )
1080 pPara->pHistory->Add( pCNd->GetFormatColl(), pCNd->GetIndex(),
1081 SwNodeType::Text );
1083 pCNd->ChgFormatColl( pFormat );
1085 pPara->nWhich++;
1087 return true;
1090 bool SwDoc::SetTextFormatColl(const SwPaM &rRg,
1091 SwTextFormatColl *pFormat,
1092 const bool bReset,
1093 const bool bResetListAttrs,
1094 SwRootFrame const*const pLayout)
1096 SwDataChanged aTmp( rRg );
1097 const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
1098 SwHistory* pHst = nullptr;
1099 bool bRet = true;
1101 if (GetIDocumentUndoRedo().DoesUndo())
1103 std::unique_ptr<SwUndoFormatColl> pUndo(new SwUndoFormatColl( rRg, pFormat,
1104 bReset,
1105 bResetListAttrs ));
1106 pHst = pUndo->GetHistory();
1107 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
1110 sw::DocumentContentOperationsManager::ParaRstFormat aPara(
1111 pStt, pEnd, pHst, nullptr, pLayout);
1112 aPara.pFormatColl = pFormat;
1113 aPara.bReset = bReset;
1114 // #i62675#
1115 aPara.bResetListAttrs = bResetListAttrs;
1117 GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1,
1118 lcl_SetTextFormatColl, &aPara );
1119 if( !aPara.nWhich )
1120 bRet = false; // didn't find a valid Node
1122 if (bRet)
1124 getIDocumentState().SetModified();
1127 return bRet;
1130 /// Copy the formats to itself
1131 SwFormat* SwDoc::CopyFormat( const SwFormat& rFormat,
1132 const SwFormatsBase& rFormatArr,
1133 FNCopyFormat fnCopyFormat, const SwFormat& rDfltFormat )
1135 // It's no autoformat, default format or collection format,
1136 // then search for it.
1137 if( !rFormat.IsAuto() || !rFormat.GetRegisteredIn() )
1138 for( size_t n = 0; n < rFormatArr.GetFormatCount(); ++n )
1140 // Does the Doc already contain the template?
1141 if( rFormatArr.GetFormat(n)->GetName()==rFormat.GetName() )
1142 return rFormatArr.GetFormat(n);
1145 // Search for the "parent" first
1146 SwFormat* pParent = const_cast<SwFormat*>(&rDfltFormat);
1147 if( rFormat.DerivedFrom() && pParent != rFormat.DerivedFrom() )
1148 pParent = CopyFormat( *rFormat.DerivedFrom(), rFormatArr,
1149 fnCopyFormat, rDfltFormat );
1151 // Create the format and copy the attributes
1152 // #i40550#
1153 SwFormat* pNewFormat = (this->*fnCopyFormat)( rFormat.GetName(), pParent, false, true );
1154 pNewFormat->SetAuto( rFormat.IsAuto() );
1155 pNewFormat->CopyAttrs( rFormat ); // copy the attributes
1157 pNewFormat->SetPoolFormatId( rFormat.GetPoolFormatId() );
1158 pNewFormat->SetPoolHelpId( rFormat.GetPoolHelpId() );
1160 // Always set the HelpFile Id to default!
1161 pNewFormat->SetPoolHlpFileId( UCHAR_MAX );
1163 return pNewFormat;
1166 /// copy the frame format
1167 SwFrameFormat* SwDoc::CopyFrameFormat( const SwFrameFormat& rFormat )
1169 return static_cast<SwFrameFormat*>(CopyFormat( rFormat, *GetFrameFormats(), &SwDoc::MakeFrameFormat_,
1170 *GetDfltFrameFormat() ));
1173 /// copy the char format
1174 SwCharFormat* SwDoc::CopyCharFormat( const SwCharFormat& rFormat )
1176 return static_cast<SwCharFormat*>(CopyFormat( rFormat, *GetCharFormats(),
1177 &SwDoc::MakeCharFormat_,
1178 *GetDfltCharFormat() ));
1181 /// copy TextNodes
1182 SwTextFormatColl* SwDoc::CopyTextColl( const SwTextFormatColl& rColl )
1184 SwTextFormatColl* pNewColl = FindTextFormatCollByName( rColl.GetName() );
1185 if( pNewColl )
1186 return pNewColl;
1188 // search for the "parent" first
1189 SwTextFormatColl* pParent = mpDfltTextFormatColl.get();
1190 if( pParent != rColl.DerivedFrom() )
1191 pParent = CopyTextColl( *static_cast<SwTextFormatColl*>(rColl.DerivedFrom()) );
1193 //FEATURE::CONDCOLL
1194 if( RES_CONDTXTFMTCOLL == rColl.Which() )
1196 pNewColl = new SwConditionTextFormatColl( GetAttrPool(), rColl.GetName(),
1197 pParent);
1198 mpTextFormatCollTable->push_back( pNewColl );
1199 pNewColl->SetAuto(false);
1200 getIDocumentState().SetModified();
1202 // copy the conditions
1203 static_cast<SwConditionTextFormatColl*>(pNewColl)->SetConditions(
1204 static_cast<const SwConditionTextFormatColl&>(rColl).GetCondColls() );
1206 else
1207 //FEATURE::CONDCOLL
1208 pNewColl = MakeTextFormatColl( rColl.GetName(), pParent );
1210 // copy the auto formats or the attributes
1211 pNewColl->CopyAttrs( rColl );
1213 if(rColl.IsAssignedToListLevelOfOutlineStyle())
1214 pNewColl->AssignToListLevelOfOutlineStyle(rColl.GetAssignedOutlineStyleLevel());
1215 pNewColl->SetPoolFormatId( rColl.GetPoolFormatId() );
1216 pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() );
1218 // Always set the HelpFile Id to default!
1219 pNewColl->SetPoolHlpFileId( UCHAR_MAX );
1221 if( &rColl.GetNextTextFormatColl() != &rColl )
1222 pNewColl->SetNextTextFormatColl( *CopyTextColl( rColl.GetNextTextFormatColl() ));
1224 // create the NumRule if necessary
1225 if( this != rColl.GetDoc() )
1227 const SfxPoolItem* pItem;
1228 if( SfxItemState::SET == pNewColl->GetItemState( RES_PARATR_NUMRULE,
1229 false, &pItem ))
1231 const OUString& rName = pItem->StaticWhichCast(RES_PARATR_NUMRULE).GetValue();
1232 if( !rName.isEmpty() )
1234 const SwNumRule* pRule = rColl.GetDoc()->FindNumRulePtr( rName );
1235 if( pRule && !pRule->IsAutoRule() )
1237 SwNumRule* pDestRule = FindNumRulePtr( rName );
1238 if( pDestRule )
1239 pDestRule->SetInvalidRule( true );
1240 else
1241 MakeNumRule( rName, pRule );
1246 return pNewColl;
1249 /// copy the graphic nodes
1250 SwGrfFormatColl* SwDoc::CopyGrfColl( const SwGrfFormatColl& rColl )
1252 SwGrfFormatColl* pNewColl = mpGrfFormatCollTable->FindFormatByName( rColl.GetName() );
1253 if( pNewColl )
1254 return pNewColl;
1256 // Search for the "parent" first
1257 SwGrfFormatColl* pParent = mpDfltGrfFormatColl.get();
1258 if( pParent != rColl.DerivedFrom() )
1259 pParent = CopyGrfColl( *static_cast<SwGrfFormatColl*>(rColl.DerivedFrom()) );
1261 // if not, copy them
1262 pNewColl = MakeGrfFormatColl( rColl.GetName(), pParent );
1264 // copy the attributes
1265 pNewColl->CopyAttrs( rColl );
1267 pNewColl->SetPoolFormatId( rColl.GetPoolFormatId() );
1268 pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() );
1270 // Always set the HelpFile Id to default!
1271 pNewColl->SetPoolHlpFileId( UCHAR_MAX );
1273 return pNewColl;
1276 void SwDoc::CopyFormatArr( const SwFormatsBase& rSourceArr,
1277 SwFormatsBase const & rDestArr,
1278 FNCopyFormat fnCopyFormat,
1279 SwFormat& rDfltFormat )
1281 SwFormat* pSrc, *pDest;
1283 // 1st step: Create all formats (skip the 0th - it's the default one)
1284 for( size_t nSrc = rSourceArr.GetFormatCount(); nSrc > 1; )
1286 pSrc = rSourceArr.GetFormat( --nSrc );
1287 if( pSrc->IsDefault() || pSrc->IsAuto() )
1288 continue;
1290 if( nullptr == rDestArr.FindFormatByName( pSrc->GetName() ) )
1292 if( RES_CONDTXTFMTCOLL == pSrc->Which() )
1293 MakeCondTextFormatColl( pSrc->GetName(), static_cast<SwTextFormatColl*>(&rDfltFormat) );
1294 else
1295 // #i40550#
1296 (this->*fnCopyFormat)( pSrc->GetName(), &rDfltFormat, false, true );
1300 // 2nd step: Copy all attributes, set the right parents
1301 for( size_t nSrc = rSourceArr.GetFormatCount(); nSrc > 1; )
1303 pSrc = rSourceArr.GetFormat( --nSrc );
1304 if( pSrc->IsDefault() || pSrc->IsAuto() )
1305 continue;
1307 pDest = rDestArr.FindFormatByName( pSrc->GetName() );
1308 pDest->SetAuto(false);
1309 pDest->DelDiffs( *pSrc );
1311 // #i94285#: existing <SwFormatPageDesc> instance, before copying attributes
1312 const SfxPoolItem* pItem;
1313 if( &GetAttrPool() != pSrc->GetAttrSet().GetPool()
1314 && SfxItemState::SET == pSrc->GetAttrSet().GetItemState( RES_PAGEDESC, false, &pItem )
1315 && pItem->StaticWhichCast(RES_PAGEDESC).GetPageDesc() )
1317 SwFormatPageDesc aPageDesc( pItem->StaticWhichCast(RES_PAGEDESC) );
1318 const OUString& rNm = aPageDesc.GetPageDesc()->GetName();
1319 SwPageDesc* pPageDesc = FindPageDesc( rNm );
1320 if( !pPageDesc )
1322 pPageDesc = MakePageDesc(rNm);
1324 aPageDesc.RegisterToPageDesc( *pPageDesc );
1325 SwAttrSet aTmpAttrSet( pSrc->GetAttrSet() );
1326 aTmpAttrSet.Put( aPageDesc );
1327 pDest->SetFormatAttr( aTmpAttrSet );
1329 else
1331 pDest->SetFormatAttr( pSrc->GetAttrSet() );
1334 pDest->SetPoolFormatId( pSrc->GetPoolFormatId() );
1335 pDest->SetPoolHelpId( pSrc->GetPoolHelpId() );
1337 // Always set the HelpFile Id to default!
1338 pDest->SetPoolHlpFileId( UCHAR_MAX );
1340 if( pSrc->DerivedFrom() )
1341 pDest->SetDerivedFrom( rDestArr.FindFormatByName(
1342 pSrc->DerivedFrom()->GetName() ) );
1343 if( RES_TXTFMTCOLL == pSrc->Which() ||
1344 RES_CONDTXTFMTCOLL == pSrc->Which() )
1346 SwTextFormatColl* pSrcColl = static_cast<SwTextFormatColl*>(pSrc),
1347 * pDstColl = static_cast<SwTextFormatColl*>(pDest);
1348 if( &pSrcColl->GetNextTextFormatColl() != pSrcColl )
1349 pDstColl->SetNextTextFormatColl(
1350 *static_cast<SwTextFormatColl*>(rDestArr.FindFormatByName( pSrcColl->GetNextTextFormatColl().GetName() )) );
1352 if(pSrcColl->IsAssignedToListLevelOfOutlineStyle())
1353 pDstColl->AssignToListLevelOfOutlineStyle(pSrcColl->GetAssignedOutlineStyleLevel());
1355 //FEATURE::CONDCOLL
1356 if( RES_CONDTXTFMTCOLL == pSrc->Which() )
1358 if (pDstColl->Which() != RES_CONDTXTFMTCOLL)
1360 // Target already had a style with a matching name, but it's not a conditional
1361 // style, then don't copy the conditions.
1362 continue;
1365 // Copy the conditions, but delete the old ones first!
1366 static_cast<SwConditionTextFormatColl*>(pDstColl)->SetConditions(
1367 static_cast<SwConditionTextFormatColl*>(pSrc)->GetCondColls() );
1369 //FEATURE::CONDCOLL
1374 void SwDoc::CopyPageDescHeaderFooterImpl( bool bCpyHeader,
1375 const SwFrameFormat& rSrcFormat, SwFrameFormat& rDestFormat )
1377 // Treat the header and footer attributes in the right way:
1378 // Copy content nodes across documents!
1379 sal_uInt16 nAttr = bCpyHeader ? sal_uInt16(RES_HEADER) : sal_uInt16(RES_FOOTER);
1380 const SfxPoolItem* pItem;
1381 if( SfxItemState::SET != rSrcFormat.GetAttrSet().GetItemState( nAttr, false, &pItem ))
1382 return ;
1384 // The header only contains the reference to the format from the other document!
1385 std::unique_ptr<SfxPoolItem> pNewItem(pItem->Clone());
1387 SwFrameFormat* pOldFormat;
1388 if( bCpyHeader )
1389 pOldFormat = pNewItem->StaticWhichCast(RES_HEADER).GetHeaderFormat();
1390 else
1391 pOldFormat = pNewItem->StaticWhichCast(RES_FOOTER).GetFooterFormat();
1393 if( !pOldFormat )
1394 return;
1396 SwFrameFormat* pNewFormat = new SwFrameFormat( GetAttrPool(), "CpyDesc",
1397 GetDfltFrameFormat() );
1398 pNewFormat->CopyAttrs( *pOldFormat );
1400 if( SfxItemState::SET == pNewFormat->GetAttrSet().GetItemState(
1401 RES_CNTNT, false, &pItem ))
1403 const SwFormatContent* pContent = &pItem->StaticWhichCast(RES_CNTNT);
1404 if( pContent->GetContentIdx() )
1406 SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
1407 const SwNodes& rSrcNds = rSrcFormat.GetDoc()->GetNodes();
1408 SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmpIdx,
1409 bCpyHeader
1410 ? SwHeaderStartNode
1411 : SwFooterStartNode );
1412 const SwNode& rCSttNd = pContent->GetContentIdx()->GetNode();
1413 SwNodeRange aRg( rCSttNd, SwNodeOffset(0), *rCSttNd.EndOfSectionNode() );
1414 aTmpIdx = *pSttNd->EndOfSectionNode();
1415 rSrcNds.Copy_( aRg, aTmpIdx );
1416 aTmpIdx = *pSttNd;
1417 rSrcFormat.GetDoc()->GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRg, nullptr, aTmpIdx);
1418 // TODO: investigate calling CopyWithFlyInFly?
1419 SwPaM const source(aRg.aStart, aRg.aEnd);
1420 SwPosition dest(aTmpIdx);
1421 sw::CopyBookmarks(source, dest);
1422 pNewFormat->SetFormatAttr( SwFormatContent( pSttNd ));
1424 else
1425 pNewFormat->ResetFormatAttr( RES_CNTNT );
1427 if( bCpyHeader )
1428 pNewItem->StaticWhichCast(RES_HEADER).RegisterToFormat(*pNewFormat);
1429 else
1430 pNewItem->StaticWhichCast(RES_FOOTER).RegisterToFormat(*pNewFormat);
1431 rDestFormat.SetFormatAttr( *pNewItem );
1434 void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, SwPageDesc& rDstDesc,
1435 bool bCopyPoolIds )
1437 bool bNotifyLayout = false;
1438 SwRootFrame* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout();
1440 rDstDesc.SetLandscape( rSrcDesc.GetLandscape() );
1441 rDstDesc.SetNumType( rSrcDesc.GetNumType() );
1442 if( rDstDesc.ReadUseOn() != rSrcDesc.ReadUseOn() )
1444 rDstDesc.WriteUseOn( rSrcDesc.ReadUseOn() );
1445 bNotifyLayout = true;
1448 if( bCopyPoolIds )
1450 rDstDesc.SetPoolFormatId( rSrcDesc.GetPoolFormatId() );
1451 rDstDesc.SetPoolHelpId( rSrcDesc.GetPoolHelpId() );
1452 // Always set the HelpFile Id to default!
1453 rDstDesc.SetPoolHlpFileId( UCHAR_MAX );
1456 if( rSrcDesc.GetFollow() != &rSrcDesc )
1458 const SwPageDesc* pSrcFollow = rSrcDesc.GetFollow();
1459 SwPageDesc* pFollow = FindPageDesc( pSrcFollow->GetName() );
1460 if( !pFollow )
1462 // copy
1463 pFollow = MakePageDesc( pSrcFollow->GetName() );
1464 CopyPageDesc( *pSrcFollow, *pFollow );
1466 rDstDesc.SetFollow( pFollow );
1467 bNotifyLayout = true;
1470 // the header and footer attributes are copied separately
1471 // the content sections have to be copied in their entirety
1473 SfxItemSet aAttrSet( rSrcDesc.GetMaster().GetAttrSet() );
1474 aAttrSet.ClearItem( RES_HEADER );
1475 aAttrSet.ClearItem( RES_FOOTER );
1477 rDstDesc.GetMaster().DelDiffs( aAttrSet );
1478 rDstDesc.GetMaster().SetFormatAttr( aAttrSet );
1480 aAttrSet.ClearItem();
1481 aAttrSet.Put( rSrcDesc.GetLeft().GetAttrSet() );
1482 aAttrSet.ClearItem( RES_HEADER );
1483 aAttrSet.ClearItem( RES_FOOTER );
1485 rDstDesc.GetLeft().DelDiffs( aAttrSet );
1486 rDstDesc.GetLeft().SetFormatAttr( aAttrSet );
1488 aAttrSet.ClearItem();
1489 aAttrSet.Put( rSrcDesc.GetFirstMaster().GetAttrSet() );
1490 aAttrSet.ClearItem( RES_HEADER );
1491 aAttrSet.ClearItem( RES_FOOTER );
1493 rDstDesc.GetFirstMaster().DelDiffs( aAttrSet );
1494 rDstDesc.GetFirstMaster().SetFormatAttr( aAttrSet );
1496 aAttrSet.ClearItem();
1497 aAttrSet.Put( rSrcDesc.GetFirstLeft().GetAttrSet() );
1498 aAttrSet.ClearItem( RES_HEADER );
1499 aAttrSet.ClearItem( RES_FOOTER );
1501 rDstDesc.GetFirstLeft().DelDiffs( aAttrSet );
1502 rDstDesc.GetFirstLeft().SetFormatAttr( aAttrSet );
1505 CopyHeader( rSrcDesc.GetMaster(), rDstDesc.GetMaster() );
1506 CopyFooter( rSrcDesc.GetMaster(), rDstDesc.GetMaster() );
1507 if( !rDstDesc.IsHeaderShared() )
1508 CopyHeader( rSrcDesc.GetLeft(), rDstDesc.GetLeft() );
1509 else
1510 rDstDesc.GetLeft().SetFormatAttr( rDstDesc.GetMaster().GetHeader() );
1511 if( !rDstDesc.IsFirstShared() )
1513 CopyHeader( rSrcDesc.GetFirstMaster(), rDstDesc.GetFirstMaster() );
1514 rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetFirstMaster().GetHeader());
1516 else
1518 rDstDesc.GetFirstMaster().SetFormatAttr( rDstDesc.GetMaster().GetHeader() );
1519 rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetLeft().GetHeader());
1522 if( !rDstDesc.IsFooterShared() )
1523 CopyFooter( rSrcDesc.GetLeft(), rDstDesc.GetLeft() );
1524 else
1525 rDstDesc.GetLeft().SetFormatAttr( rDstDesc.GetMaster().GetFooter() );
1526 if( !rDstDesc.IsFirstShared() )
1528 CopyFooter( rSrcDesc.GetFirstMaster(), rDstDesc.GetFirstMaster() );
1529 rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetFirstMaster().GetFooter());
1531 else
1533 rDstDesc.GetFirstMaster().SetFormatAttr( rDstDesc.GetMaster().GetFooter() );
1534 rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetLeft().GetFooter());
1537 if( bNotifyLayout && pTmpRoot )
1539 for( auto aLayout : GetAllLayouts() )
1540 aLayout->AllCheckPageDescs();
1543 // If foot notes change the pages have to be triggered
1544 if( !(rDstDesc.GetFootnoteInfo() == rSrcDesc.GetFootnoteInfo()) )
1546 sw::PageFootnoteHint aHint;
1547 rDstDesc.SetFootnoteInfo( rSrcDesc.GetFootnoteInfo() );
1548 rDstDesc.GetMaster().CallSwClientNotify(aHint);
1549 rDstDesc.GetLeft().CallSwClientNotify(aHint);
1550 rDstDesc.GetFirstMaster().CallSwClientNotify(aHint);
1551 rDstDesc.GetFirstLeft().CallSwClientNotify(aHint);
1554 // Copy the stashed formats as well between the page descriptors...
1555 for (bool bFirst : { true, false })
1556 for (bool bLeft : { true, false })
1557 for (bool bHeader : { true, false })
1559 if (!bLeft && !bFirst)
1560 continue;
1561 if (auto pStashedFormat = rSrcDesc.GetStashedFrameFormat(bHeader, bLeft, bFirst))
1562 rDstDesc.StashFrameFormat(*pStashedFormat, bHeader, bLeft, bFirst);
1566 void SwDoc::ReplaceStyles( const SwDoc& rSource, bool bIncludePageStyles )
1568 ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1570 CopyFormatArr( *rSource.mpCharFormatTable, *mpCharFormatTable,
1571 &SwDoc::MakeCharFormat_, *mpDfltCharFormat );
1572 CopyFormatArr( *rSource.mpFrameFormatTable, *mpFrameFormatTable,
1573 &SwDoc::MakeFrameFormat_, *mpDfltFrameFormat );
1574 CopyFormatArr( *rSource.mpTextFormatCollTable, *mpTextFormatCollTable,
1575 &SwDoc::MakeTextFormatColl_, *mpDfltTextFormatColl );
1577 //To-Do:
1578 // a) in rtf export don't export our hideous pgdsctbl
1579 // extension to rtf anymore
1580 // b) in sd rtf import (View::InsertData) don't use
1581 // a super-fragile test for mere presence of \trowd to
1582 // indicate import of rtf into a table
1583 // c) then drop use of bIncludePageStyles
1584 if (bIncludePageStyles)
1586 // and now the page templates
1587 SwPageDescs::size_type nCnt = rSource.m_PageDescs.size();
1588 if( nCnt )
1590 // a different Doc -> Number formatter needs to be merged
1591 SwTableNumFormatMerge aTNFM( rSource, *this );
1593 // 1st step: Create all formats (skip the 0th - it's the default!)
1594 while( nCnt )
1596 const SwPageDesc &rSrc = *rSource.m_PageDescs[ --nCnt ];
1597 if( nullptr == FindPageDesc( rSrc.GetName() ) )
1598 MakePageDesc( rSrc.GetName() );
1601 // 2nd step: Copy all attributes, set the right parents
1602 for (SwPageDescs::size_type i = rSource.m_PageDescs.size(); i; )
1604 const SwPageDesc &rSrc = *rSource.m_PageDescs[ --i ];
1605 SwPageDesc* pDesc = FindPageDesc( rSrc.GetName() );
1606 CopyPageDesc( rSrc, *pDesc);
1611 // then there are the numbering templates
1612 const SwNumRuleTable::size_type nCnt = rSource.GetNumRuleTable().size();
1613 if( nCnt )
1615 const SwNumRuleTable& rArr = rSource.GetNumRuleTable();
1616 for( SwNumRuleTable::size_type n = 0; n < nCnt; ++n )
1618 const SwNumRule& rR = *rArr[ n ];
1619 SwNumRule* pNew = FindNumRulePtr( rR.GetName());
1620 if( pNew )
1621 pNew->CopyNumRule(*this, rR);
1622 else
1624 if( !rR.IsAutoRule() )
1625 MakeNumRule( rR.GetName(), &rR );
1626 else
1628 // as we reset all styles, there shouldn't be any unknown
1629 // automatic SwNumRules, because all should have been
1630 // created by the style copying!
1631 // So just warn and ignore.
1632 SAL_WARN( "sw.core", "Found unknown auto SwNumRule during reset!" );
1638 if (undoGuard.UndoWasEnabled())
1640 // nodes array was modified!
1641 GetIDocumentUndoRedo().DelAllUndoObj();
1644 getIDocumentState().SetModified();
1647 void SwDoc::MoveLeftMargin(const SwPaM& rPam, bool bRight, bool bModulus,
1648 SwRootFrame const*const pLayout)
1650 SwHistory* pHistory = nullptr;
1651 if (GetIDocumentUndoRedo().DoesUndo())
1653 std::unique_ptr<SwUndoMoveLeftMargin> pUndo(new SwUndoMoveLeftMargin( rPam, bRight,
1654 bModulus ));
1655 pHistory = &pUndo->GetHistory();
1656 GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
1659 const SvxTabStopItem& rTabItem = GetDefault( RES_PARATR_TABSTOP );
1660 const sal_Int32 nDefDist = rTabItem.Count() ? rTabItem[0].GetTabPos() : 1134;
1661 const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
1662 SwNodeIndex aIdx( rStt.nNode );
1663 while( aIdx <= rEnd.nNode )
1665 SwTextNode* pTNd = aIdx.GetNode().GetTextNode();
1666 if( pTNd )
1668 pTNd = sw::GetParaPropsNode(*pLayout, aIdx);
1669 SvxLRSpaceItem aLS(pTNd->SwContentNode::GetAttr(RES_LR_SPACE).StaticWhichCast(RES_LR_SPACE));
1671 // #i93873# See also lcl_MergeListLevelIndentAsLRSpaceItem in thints.cxx
1672 if ( pTNd->AreListLevelIndentsApplicable() )
1674 const SwNumRule* pRule = pTNd->GetNumRule();
1675 if ( pRule )
1677 const int nListLevel = pTNd->GetActualListLevel();
1678 if ( nListLevel >= 0 )
1680 const SwNumFormat& rFormat = pRule->Get(o3tl::narrowing<sal_uInt16>(nListLevel));
1681 if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1683 aLS.SetTextLeft( rFormat.GetIndentAt() );
1684 aLS.SetTextFirstLineOffset( static_cast<short>(rFormat.GetFirstLineIndent()) );
1690 tools::Long nNext = aLS.GetTextLeft();
1691 if( bModulus )
1692 nNext = ( nNext / nDefDist ) * nDefDist;
1694 if( bRight )
1695 nNext += nDefDist;
1696 else
1697 if(nNext >0) // fdo#75936 set limit for decreasing indent
1698 nNext -= nDefDist;
1700 aLS.SetTextLeft( nNext );
1702 SwRegHistory aRegH( pTNd, *pTNd, pHistory );
1703 pTNd->SetAttr( aLS );
1704 aIdx = *sw::GetFirstAndLastNode(*pLayout, aIdx).second;
1706 ++aIdx;
1708 getIDocumentState().SetModified();
1711 bool SwDoc::DontExpandFormat( const SwPosition& rPos, bool bFlag )
1713 bool bRet = false;
1714 SwTextNode* pTextNd = rPos.nNode.GetNode().GetTextNode();
1715 if( pTextNd )
1717 bRet = pTextNd->DontExpandFormat( rPos.nContent, bFlag );
1718 if( bRet && GetIDocumentUndoRedo().DoesUndo() )
1720 GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoDontExpandFormat>(rPos) );
1723 return bRet;
1726 SwTableBoxFormat* SwDoc::MakeTableBoxFormat()
1728 SwTableBoxFormat* pFormat = new SwTableBoxFormat( GetAttrPool(), mpDfltFrameFormat.get() );
1729 pFormat->SetName("TableBox" + OUString::number(reinterpret_cast<sal_IntPtr>(pFormat)));
1730 getIDocumentState().SetModified();
1731 return pFormat;
1734 SwTableLineFormat* SwDoc::MakeTableLineFormat()
1736 SwTableLineFormat* pFormat = new SwTableLineFormat( GetAttrPool(), mpDfltFrameFormat.get() );
1737 pFormat->SetName("TableLine" + OUString::number(reinterpret_cast<sal_IntPtr>(pFormat)));
1738 getIDocumentState().SetModified();
1739 return pFormat;
1742 void SwDoc::EnsureNumberFormatter()
1744 if (mpNumberFormatter == nullptr)
1746 LanguageType eLang = LANGUAGE_SYSTEM;
1747 mpNumberFormatter = new SvNumberFormatter(comphelper::getProcessComponentContext(), eLang);
1748 mpNumberFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_FORMAT_INTL );
1749 if (!utl::ConfigManager::IsFuzzing())
1750 mpNumberFormatter->SetYear2000(
1751 officecfg::Office::Common::DateFormat::TwoDigitYear::get());
1755 SwTableNumFormatMerge::SwTableNumFormatMerge( const SwDoc& rSrc, SwDoc& rDest )
1756 : pNFormat( nullptr )
1758 // a different Doc -> Number formatter needs to be merged
1759 if( &rSrc != &rDest )
1761 SvNumberFormatter* pN = const_cast<SwDoc&>(rSrc).GetNumberFormatter( false );
1762 if( pN )
1764 pNFormat = rDest.GetNumberFormatter();
1765 pNFormat->MergeFormatter( *pN );
1769 if( &rSrc != &rDest )
1770 static_cast<SwGetRefFieldType*>(rSrc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::GetRef ))->
1771 MergeWithOtherDoc( rDest );
1774 SwTableNumFormatMerge::~SwTableNumFormatMerge()
1776 if( pNFormat )
1777 pNFormat->ClearMergeTable();
1780 void SwDoc::SetTextFormatCollByAutoFormat( const SwPosition& rPos, sal_uInt16 nPoolId,
1781 const SfxItemSet* pSet )
1783 SwPaM aPam( rPos );
1784 SwTextNode* pTNd = rPos.nNode.GetNode().GetTextNode();
1785 assert(pTNd);
1787 if (mbIsAutoFormatRedline)
1789 // create the redline object
1790 const SwTextFormatColl& rColl = *pTNd->GetTextColl();
1791 SwRangeRedline* pRedl = new SwRangeRedline( RedlineType::FmtColl, aPam );
1792 pRedl->SetMark();
1794 // Only those items that are not set by the Set again in the Node
1795 // are of interest. Thus, we take the difference.
1796 SwRedlineExtraData_FormatColl aExtraData( rColl.GetName(),
1797 rColl.GetPoolFormatId() );
1798 if( pSet && pTNd->HasSwAttrSet() )
1800 SfxItemSet aTmp( *pTNd->GetpSwAttrSet() );
1801 aTmp.Differentiate( *pSet );
1802 // we handle the adjust item separately
1803 const SfxPoolItem* pItem;
1804 if( SfxItemState::SET == pTNd->GetpSwAttrSet()->GetItemState(
1805 RES_PARATR_ADJUST, false, &pItem ))
1806 aTmp.Put( *pItem );
1807 aExtraData.SetItemSet( aTmp );
1809 pRedl->SetExtraData( &aExtraData );
1811 //TODO: Undo is still missing!
1812 getIDocumentRedlineAccess().AppendRedline( pRedl, true );
1815 SetTextFormatColl( aPam, getIDocumentStylePoolAccess().GetTextCollFromPool( nPoolId ) );
1817 if (pSet && pSet->Count())
1819 aPam.SetMark();
1820 aPam.GetMark()->nContent.Assign(pTNd, pTNd->GetText().getLength());
1821 // sw_redlinehide: don't need layout currently because the only caller
1822 // passes in the properties node
1823 assert(static_cast<SwTextFrame const*>(pTNd->getLayoutFrame(nullptr))->GetTextNodeForParaProps() == pTNd);
1824 getIDocumentContentOperations().InsertItemSet( aPam, *pSet );
1828 void SwDoc::SetFormatItemByAutoFormat( const SwPaM& rPam, const SfxItemSet& rSet )
1830 SwTextNode* pTNd = rPam.GetPoint()->nNode.GetNode().GetTextNode();
1831 assert(pTNd);
1833 RedlineFlags eOld = getIDocumentRedlineAccess().GetRedlineFlags();
1835 if (mbIsAutoFormatRedline)
1837 // create the redline object
1838 SwRangeRedline* pRedl = new SwRangeRedline( RedlineType::Format, rPam );
1839 if( !pRedl->HasMark() )
1840 pRedl->SetMark();
1842 // Only those items that are not set by the Set again in the Node
1843 // are of interest. Thus, we take the difference.
1844 SwRedlineExtraData_Format aExtraData( rSet );
1846 pRedl->SetExtraData( &aExtraData );
1848 //TODO: Undo is still missing!
1849 getIDocumentRedlineAccess().AppendRedline( pRedl, true );
1851 getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld | RedlineFlags::Ignore );
1854 const sal_Int32 nEnd(rPam.End()->nContent.GetIndex());
1855 std::vector<WhichPair> whichIds;
1856 SfxItemIter iter(rSet);
1857 for (SfxPoolItem const* pItem = iter.GetCurItem(); pItem; pItem = iter.NextItem())
1859 whichIds.push_back({pItem->Which(), pItem->Which()});
1861 SfxItemSet currentSet(GetAttrPool(), WhichRangesContainer(whichIds.data(), whichIds.size()));
1862 pTNd->GetParaAttr(currentSet, nEnd, nEnd);
1863 for (const WhichPair& rPair : whichIds)
1864 { // yuk - want to explicitly set the pool defaults too :-/
1865 currentSet.Put(currentSet.Get(rPair.first));
1868 getIDocumentContentOperations().InsertItemSet( rPam, rSet, SetAttrMode::DONTEXPAND );
1870 // fdo#62536: DONTEXPAND does not work when there is already an AUTOFMT
1871 // here, so insert the old attributes as an empty hint to stop expand
1872 SwPaM endPam(*pTNd, nEnd);
1873 endPam.SetMark();
1874 getIDocumentContentOperations().InsertItemSet(endPam, currentSet);
1876 getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
1879 void SwDoc::ChgFormat(SwFormat & rFormat, const SfxItemSet & rSet)
1881 if (GetIDocumentUndoRedo().DoesUndo())
1883 // copying <rSet> to <aSet>
1884 SfxItemSet aSet(rSet);
1885 // remove from <aSet> all items, which are already set at the format
1886 aSet.Differentiate(rFormat.GetAttrSet());
1887 // <aSet> contains now all *new* items for the format
1889 // copying current format item set to <aOldSet>
1890 SfxItemSet aOldSet(rFormat.GetAttrSet());
1891 // insert new items into <aOldSet>
1892 aOldSet.Put(aSet);
1893 // invalidate all new items in <aOldSet> in order to clear these items,
1894 // if the undo action is triggered.
1896 SfxItemIter aIter(aSet);
1898 for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
1900 aOldSet.InvalidateItem(pItem->Which());
1904 GetIDocumentUndoRedo().AppendUndo(
1905 std::make_unique<SwUndoFormatAttr>(std::move(aOldSet), rFormat, /*bSaveDrawPt*/true));
1908 rFormat.SetFormatAttr(rSet);
1911 void SwDoc::RenameFormat(SwFormat & rFormat, const OUString & sNewName,
1912 bool bBroadcast)
1914 SfxStyleFamily eFamily = SfxStyleFamily::All;
1916 if (GetIDocumentUndoRedo().DoesUndo())
1918 std::unique_ptr<SwUndo> pUndo;
1920 switch (rFormat.Which())
1922 case RES_CHRFMT:
1923 pUndo.reset(new SwUndoRenameCharFormat(rFormat.GetName(), sNewName, *this));
1924 eFamily = SfxStyleFamily::Char;
1925 break;
1926 case RES_TXTFMTCOLL:
1927 pUndo.reset(new SwUndoRenameFormatColl(rFormat.GetName(), sNewName, *this));
1928 eFamily = SfxStyleFamily::Para;
1929 break;
1930 case RES_FRMFMT:
1931 pUndo.reset(new SwUndoRenameFrameFormat(rFormat.GetName(), sNewName, *this));
1932 eFamily = SfxStyleFamily::Frame;
1933 break;
1935 default:
1936 break;
1939 if (pUndo)
1941 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
1945 // name change means the o3tl::sorted_array is not property sorted
1946 if (rFormat.Which() == RES_CHRFMT)
1947 mpCharFormatTable->SetFormatNameAndReindex(static_cast<SwCharFormat*>(&rFormat), sNewName);
1948 else
1949 rFormat.SetName(sNewName);
1951 if (bBroadcast)
1952 BroadcastStyleOperation(sNewName, eFamily, SfxHintId::StyleSheetModified);
1955 void SwDoc::dumpAsXml(xmlTextWriterPtr pWriter) const
1957 bool bOwns = false;
1958 if (!pWriter)
1960 pWriter = xmlNewTextWriterFilename("nodes.xml", 0);
1961 xmlTextWriterSetIndent(pWriter,1);
1962 (void)xmlTextWriterSetIndentString(pWriter, BAD_CAST(" "));
1963 (void)xmlTextWriterStartDocument(pWriter, nullptr, nullptr, nullptr);
1964 bOwns = true;
1966 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwDoc"));
1967 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1969 m_pNodes->dumpAsXml(pWriter);
1970 m_PageDescs.dumpAsXml(pWriter);
1971 maDBData.dumpAsXml(pWriter);
1972 mpMarkManager->dumpAsXml(pWriter);
1973 m_pUndoManager->dumpAsXml(pWriter);
1974 m_pDocumentSettingManager->dumpAsXml(pWriter);
1975 getIDocumentFieldsAccess().GetFieldTypes()->dumpAsXml(pWriter);
1976 mpTextFormatCollTable->dumpAsXml(pWriter);
1977 mpCharFormatTable->dumpAsXml(pWriter);
1978 mpFrameFormatTable->dumpAsXml(pWriter, "frmFormatTable");
1979 mpSpzFrameFormatTable->dumpAsXml(pWriter, "spzFrameFormatTable");
1980 mpSectionFormatTable->dumpAsXml(pWriter);
1981 mpTableFrameFormatTable->dumpAsXml(pWriter, "tableFrameFormatTable");
1982 mpNumRuleTable->dumpAsXml(pWriter);
1983 getIDocumentRedlineAccess().GetRedlineTable().dumpAsXml(pWriter);
1984 getIDocumentRedlineAccess().GetExtraRedlineTable().dumpAsXml(pWriter);
1985 if (const SdrModel* pModel = getIDocumentDrawModelAccess().GetDrawModel())
1986 pModel->dumpAsXml(pWriter);
1988 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("mbModified"));
1989 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(getIDocumentState().IsModified()).getStr()));
1990 (void)xmlTextWriterEndElement(pWriter);
1992 (void)xmlTextWriterEndElement(pWriter);
1993 if (bOwns)
1995 (void)xmlTextWriterEndDocument(pWriter);
1996 xmlFreeTextWriter(pWriter);
2000 void SwDBData::dumpAsXml(xmlTextWriterPtr pWriter) const
2002 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwDBData"));
2004 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("sDataSource"), BAD_CAST(sDataSource.toUtf8().getStr()));
2005 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("sCommand"), BAD_CAST(sCommand.toUtf8().getStr()));
2006 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nCommandType"), BAD_CAST(OString::number(nCommandType).getStr()));
2008 (void)xmlTextWriterEndElement(pWriter);
2011 std::set<Color> SwDoc::GetDocColors()
2013 std::set<Color> aDocColors;
2014 SwAttrPool& rPool = GetAttrPool();
2015 const sal_uInt16 pAttribs[] = {RES_CHRATR_COLOR, RES_CHRATR_HIGHLIGHT, RES_BACKGROUND};
2016 for (sal_uInt16 nAttrib : pAttribs)
2018 for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(nAttrib))
2020 auto pColorItem = static_cast<const SvxColorItem*>(pItem);
2021 Color aColor( pColorItem->GetValue() );
2022 if (COL_AUTO != aColor)
2023 aDocColors.insert(aColor);
2026 return aDocColors;
2029 // #i69627#
2030 namespace docfunc
2032 bool HasOutlineStyleToBeWrittenAsNormalListStyle( SwDoc& rDoc )
2034 // If a parent paragraph style of one of the paragraph styles, which
2035 // are assigned to the list levels of the outline style, has a list style
2036 // set or inherits a list style from its parent style, the outline style
2037 // has to be written as a normal list style to the OpenDocument file
2038 // format or the OpenOffice.org file format.
2039 bool bRet( false );
2041 const SwTextFormatColls* pTextFormatColls( rDoc.GetTextFormatColls() );
2042 if ( pTextFormatColls )
2044 for ( auto pTextFormatColl : *pTextFormatColls )
2046 if ( pTextFormatColl->IsDefault() ||
2047 ! pTextFormatColl->IsAssignedToListLevelOfOutlineStyle() )
2049 continue;
2052 const SwTextFormatColl* pParentTextFormatColl =
2053 dynamic_cast<const SwTextFormatColl*>( pTextFormatColl->DerivedFrom());
2054 if ( !pParentTextFormatColl )
2055 continue;
2057 if ( SfxItemState::SET == pParentTextFormatColl->GetItemState( RES_PARATR_NUMRULE ) )
2059 // #i106218# consider that the outline style is set
2060 const SwNumRuleItem& rDirectItem = pParentTextFormatColl->GetNumRule();
2061 if ( rDirectItem.GetValue() != rDoc.GetOutlineNumRule()->GetName() )
2063 bRet = true;
2064 break;
2070 return bRet;
2074 SwFrameFormats::SwFrameFormats()
2075 : m_PosIndex( m_Array.get<0>() )
2076 , m_TypeAndNameIndex( m_Array.get<1>() )
2080 SwFrameFormats::~SwFrameFormats()
2082 DeleteAndDestroyAll();
2085 SwFrameFormats::const_iterator SwFrameFormats::find( const value_type& x ) const
2087 ByTypeAndName::iterator it = m_TypeAndNameIndex.find(
2088 std::make_tuple(x->GetName(), x->Which(), x) );
2089 return m_Array.project<0>( it );
2092 SwFrameFormats::ByTypeAndName::const_iterator
2093 SwFrameFormats::findByTypeAndName( sal_uInt16 type, const OUString& name ) const
2095 return m_TypeAndNameIndex.find( std::make_tuple(name, type) );
2098 std::pair<SwFrameFormats::ByTypeAndName::const_iterator, SwFrameFormats::ByTypeAndName::const_iterator>
2099 SwFrameFormats::findRangeByName( const OUString& rName ) const
2101 auto it = m_TypeAndNameIndex.lower_bound( std::make_tuple(rName, sal_uInt16(0)) );
2102 auto itEnd = m_TypeAndNameIndex.upper_bound( std::make_tuple(rName, SAL_MAX_UINT16) );
2103 return { it, itEnd };
2106 SwFrameFormat* SwFrameFormats::FindFormatByName( const OUString& rName ) const
2108 auto it = m_TypeAndNameIndex.lower_bound( std::make_tuple(rName, sal_uInt16(0)) );
2109 if (it != m_TypeAndNameIndex.end() && (*it)->GetName() == rName)
2110 return *it;
2111 return nullptr;
2114 void SwFrameFormats::DeleteAndDestroyAll( bool keepDefault )
2116 if ( empty() )
2117 return;
2118 const int _offset = keepDefault ? 1 : 0;
2119 for( const_iterator it = begin() + _offset; it != end(); ++it )
2120 delete *it;
2121 if ( _offset )
2122 m_PosIndex.erase( begin() + _offset, end() );
2123 else
2124 m_Array.clear();
2127 std::pair<SwFrameFormats::const_iterator,bool> SwFrameFormats::push_back( const value_type& x )
2129 SAL_WARN_IF(x->m_ffList != nullptr, "sw.core", "Inserting already assigned item");
2130 assert(x->m_ffList == nullptr);
2131 x->m_ffList = this;
2132 return m_PosIndex.push_back( x );
2135 bool SwFrameFormats::erase( const value_type& x )
2137 const_iterator const ret = find( x );
2138 SAL_WARN_IF(x->m_ffList != this, "sw.core", "Removing invalid / unassigned item");
2139 if (ret != end()) {
2140 assert( x == *ret );
2141 m_PosIndex.erase( ret );
2142 x->m_ffList = nullptr;
2143 return true;
2145 return false;
2148 void SwFrameFormats::erase( size_type index_ )
2150 erase( begin() + index_ );
2153 void SwFrameFormats::erase( const_iterator const& position )
2155 (*position)->m_ffList = nullptr;
2156 m_PosIndex.erase( begin() + (position - begin()) );
2159 bool SwFrameFormats::ContainsFormat(const SwFrameFormat& x) const
2161 return (x.m_ffList == this);
2164 bool SwFrameFormats::IsAlive(SwFrameFormat const*const p) const
2166 return find(const_cast<SwFrameFormat*>(p)) != end();
2169 bool SwFrameFormats::newDefault( const value_type& x )
2171 std::pair<iterator,bool> res = m_PosIndex.push_front( x );
2172 if( ! res.second )
2173 newDefault( res.first );
2174 return res.second;
2177 void SwFrameFormats::newDefault( const_iterator const& position )
2179 if (position == begin())
2180 return;
2181 m_PosIndex.relocate( begin(), position );
2184 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */