xref: /core/sw/source/core/doc/docfmt.cxx (revision 28bff4bd)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <libxml/xmlwriter.h>
21 #include <hintids.hxx>
22 #include <svl/itemiter.hxx>
23 #include <sfx2/app.hxx>
24 #include <editeng/tstpitem.hxx>
25 #include <editeng/eeitem.hxx>
26 #include <editeng/langitem.hxx>
27 #include <editeng/lrspitem.hxx>
28 #include <editeng/formatbreakitem.hxx>
29 #include <editeng/rsiditem.hxx>
30 #include <editeng/colritem.hxx>
31 #include <svl/whiter.hxx>
32 #include <svl/zforlist.hxx>
33 #include <comphelper/doublecheckedinit.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <unotools/configmgr.hxx>
36 #include <unotools/misccfg.hxx>
37 #include <sal/log.hxx>
38 #include <com/sun/star/i18n/WordType.hpp>
39 #include <com/sun/star/i18n/XBreakIterator.hpp>
40 #include <fmtpdsc.hxx>
41 #include <fmthdft.hxx>
42 #include <fmtcntnt.hxx>
43 #include <frmatr.hxx>
44 #include <doc.hxx>
45 #include <docfunc.hxx>
46 #include <drawdoc.hxx>
47 #include <MarkManager.hxx>
48 #include <IDocumentDrawModelAccess.hxx>
49 #include <IDocumentUndoRedo.hxx>
50 #include <DocumentContentOperationsManager.hxx>
51 #include <IDocumentFieldsAccess.hxx>
52 #include <IDocumentState.hxx>
53 #include <IDocumentLayoutAccess.hxx>
54 #include <IDocumentStylePoolAccess.hxx>
55 #include <rootfrm.hxx>
56 #include <pagefrm.hxx>
57 #include <txtfrm.hxx>
58 #include <hints.hxx>
59 #include <ndtxt.hxx>
60 #include <pam.hxx>
61 #include <UndoCore.hxx>
62 #include <UndoAttribute.hxx>
63 #include <UndoInsert.hxx>
64 #include <ndgrf.hxx>
65 #include <pagedesc.hxx>
66 #include <rolbck.hxx>
67 #include <mvsave.hxx>
68 #include <txatbase.hxx>
69 #include <swtable.hxx>
70 #include <swtblfmt.hxx>
71 #include <charfmt.hxx>
72 #include <docary.hxx>
73 #include <paratr.hxx>
74 #include <redline.hxx>
75 #include <reffld.hxx>
76 #include <txtinet.hxx>
77 #include <fmtinfmt.hxx>
78 #include <breakit.hxx>
79 #include <SwStyleNameMapper.hxx>
80 #include <fmtautofmt.hxx>
81 #include <istyleaccess.hxx>
82 #include <SwUndoFmt.hxx>
83 #include <UndoManager.hxx>
84 #include <docsh.hxx>
85 #include <swmodule.hxx>
86 #include <modcfg.hxx>
87 #include <memory>
88 
89 using namespace ::com::sun::star::i18n;
90 using namespace ::com::sun::star::lang;
91 using namespace ::com::sun::star::uno;
92 
93 /*
94  * Internal functions
95  */
96 
97 static void SetTextFormatCollNext( SwTextFormatColl* pTextColl, const SwTextFormatColl* pDel )
98 {
99     if ( &pTextColl->GetNextTextFormatColl() == pDel )
100     {
101         pTextColl->SetNextTextFormatColl( *pTextColl );
102     }
103 }
104 
105 static bool lcl_RstAttr( const SwNodePtr& rpNd, void* pArgs )
106 {
107     const sw::DocumentContentOperationsManager::ParaRstFormat* pPara = static_cast<sw::DocumentContentOperationsManager::ParaRstFormat*>(pArgs);
108     SwContentNode* pNode = rpNd->GetContentNode();
109     if (pPara->pLayout && pPara->pLayout->IsHideRedlines()
110         && pNode && pNode->GetRedlineMergeFlag() == SwNode::Merge::Hidden)
111     {
112         return true;
113     }
114     if( pNode && pNode->HasSwAttrSet() )
115     {
116         const bool bLocked = pNode->IsModifyLocked();
117         pNode->LockModify();
118 
119         SwDoc* pDoc = pNode->GetDoc();
120 
121         // remove unused attribute RES_LR_SPACE
122         // add list attributes
123         SfxItemSet aSavedAttrsSet(
124             pDoc->GetAttrPool(),
125             svl::Items<
126                 RES_PARATR_NUMRULE, RES_PARATR_NUMRULE,
127                 RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1,
128                 RES_PAGEDESC, RES_BREAK>{});
129         const SfxItemSet* pAttrSetOfNode = pNode->GetpSwAttrSet();
130 
131         std::vector<sal_uInt16> aClearWhichIds;
132         // restoring all paragraph list attributes
133         {
134             SfxItemSet aListAttrSet( pDoc->GetAttrPool(), svl::Items<RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1>{} );
135             aListAttrSet.Set(*pAttrSetOfNode);
136             if ( aListAttrSet.Count() )
137             {
138                 aSavedAttrsSet.Put(aListAttrSet);
139                 SfxItemIter aIter( aListAttrSet );
140                 const SfxPoolItem* pItem = aIter.GetCurItem();
141                 while( pItem )
142                 {
143                     aClearWhichIds.push_back( pItem->Which() );
144                     pItem = aIter.NextItem();
145                 }
146             }
147         }
148 
149         const SfxPoolItem* pItem;
150 
151         sal_uInt16 const aSavIds[3] = { RES_PAGEDESC, RES_BREAK, RES_PARATR_NUMRULE };
152         for (sal_uInt16 aSavId : aSavIds)
153         {
154             if (SfxItemState::SET == pAttrSetOfNode->GetItemState(aSavId, false, &pItem))
155             {
156                 bool bSave = false;
157                 switch( aSavId )
158                 {
159                     case RES_PAGEDESC:
160                         bSave = nullptr != static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc();
161                     break;
162                     case RES_BREAK:
163                         bSave = SvxBreak::NONE != static_cast<const SvxFormatBreakItem*>(pItem)->GetBreak();
164                     break;
165                     case RES_PARATR_NUMRULE:
166                         bSave = !static_cast<const SwNumRuleItem*>(pItem)->GetValue().isEmpty();
167                     break;
168                 }
169                 if( bSave )
170                 {
171                     aSavedAttrsSet.Put(*pItem);
172                     aClearWhichIds.push_back(aSavId);
173                 }
174             }
175         }
176 
177         // do not clear items directly from item set and only clear to be kept
178         // attributes, if no deletion item set is found.
179         const bool bKeepAttributes =
180                     !pPara || !pPara->pDelSet || pPara->pDelSet->Count() == 0;
181         if ( bKeepAttributes )
182         {
183             pNode->ResetAttr( aClearWhichIds );
184         }
185 
186         if( !bLocked )
187             pNode->UnlockModify();
188 
189         if( pPara )
190         {
191             SwRegHistory aRegH( pNode, *pNode, pPara->pHistory );
192 
193             if( pPara->pDelSet && pPara->pDelSet->Count() )
194             {
195                 OSL_ENSURE( !bKeepAttributes,
196                         "<lcl_RstAttr(..)> - certain attributes are kept, but not needed." );
197                 SfxItemIter aIter( *pPara->pDelSet );
198                 pItem = aIter.FirstItem();
199                 while(pItem)
200                 {
201                     if ( ( pItem->Which() != RES_PAGEDESC &&
202                            pItem->Which() != RES_BREAK &&
203                            pItem->Which() != RES_PARATR_NUMRULE ) ||
204                          ( aSavedAttrsSet.GetItemState( pItem->Which(), false ) != SfxItemState::SET ) )
205                     {
206                         pNode->ResetAttr( pItem->Which() );
207                     }
208                     if (aIter.IsAtEnd())
209                         break;
210                     pItem = aIter.NextItem();
211                 }
212             }
213             else if( pPara->bResetAll )
214                 pNode->ResetAllAttr();
215             else
216                 pNode->ResetAttr( RES_PARATR_BEGIN, POOLATTR_END - 1 );
217         }
218         else
219             pNode->ResetAllAttr();
220 
221         // only restore saved attributes, if needed
222         if (bKeepAttributes && aSavedAttrsSet.Count())
223         {
224             pNode->LockModify();
225 
226             pNode->SetAttr(aSavedAttrsSet);
227 
228             if( !bLocked )
229                 pNode->UnlockModify();
230         }
231     }
232     return true;
233 }
234 
235 void SwDoc::RstTextAttrs(const SwPaM &rRg, bool bInclRefToxMark,
236         bool bExactRange, SwRootFrame const*const pLayout)
237 {
238     SwHistory* pHst = nullptr;
239     SwDataChanged aTmp( rRg );
240     if (GetIDocumentUndoRedo().DoesUndo())
241     {
242         std::unique_ptr<SwUndoResetAttr> pUndo(new SwUndoResetAttr( rRg, RES_CHRFMT ));
243         pHst = &pUndo->GetHistory();
244         GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
245     }
246     const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
247     sw::DocumentContentOperationsManager::ParaRstFormat aPara(
248             pStt, pEnd, pHst, nullptr, pLayout );
249     aPara.bInclRefToxMark = bInclRefToxMark;
250     aPara.bExactRange = bExactRange;
251     GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1,
252                         sw::DocumentContentOperationsManager::lcl_RstTextAttr, &aPara );
253     getIDocumentState().SetModified();
254 }
255 
256 void SwDoc::ResetAttrs( const SwPaM &rRg,
257                         bool bTextAttr,
258                         const std::set<sal_uInt16> &rAttrs,
259                         const bool bSendDataChangedEvents,
260                         SwRootFrame const*const pLayout)
261 {
262     SwPaM* pPam = const_cast<SwPaM*>(&rRg);
263     if( !bTextAttr && !rAttrs.empty() && RES_TXTATR_END > *(rAttrs.begin()) )
264         bTextAttr = true;
265 
266     if( !rRg.HasMark() )
267     {
268         SwTextNode* pTextNd = rRg.GetPoint()->nNode.GetNode().GetTextNode();
269         if( !pTextNd )
270             return ;
271 
272         pPam = new SwPaM( *rRg.GetPoint() );
273 
274         SwIndex& rSt = pPam->GetPoint()->nContent;
275         sal_Int32 nMkPos, nPtPos = rSt.GetIndex();
276 
277         // Special case: if the Cursor is located within a URL attribute, we take over it's area
278         SwTextAttr const*const pURLAttr(
279             pTextNd->GetTextAttrAt(rSt.GetIndex(), RES_TXTATR_INETFMT));
280         if (pURLAttr && !pURLAttr->GetINetFormat().GetValue().isEmpty())
281         {
282             nMkPos = pURLAttr->GetStart();
283             nPtPos = *pURLAttr->End();
284         }
285         else
286         {
287             assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
288             Boundary aBndry = g_pBreakIt->GetBreakIter()->getWordBoundary(
289                                 pTextNd->GetText(), nPtPos,
290                                 g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
291                                 WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
292                                 true);
293 
294             if( aBndry.startPos < nPtPos && nPtPos < aBndry.endPos )
295             {
296                 nMkPos = aBndry.startPos;
297                 nPtPos = aBndry.endPos;
298             }
299             else
300             {
301                 nPtPos = nMkPos = rSt.GetIndex();
302                 if( bTextAttr )
303                     pTextNd->DontExpandFormat( rSt );
304             }
305         }
306 
307         rSt = nMkPos;
308         pPam->SetMark();
309         pPam->GetPoint()->nContent = nPtPos;
310     }
311 
312     // #i96644#
313     std::unique_ptr< SwDataChanged > xDataChanged;
314     if ( bSendDataChangedEvents )
315     {
316         xDataChanged.reset( new SwDataChanged( *pPam ) );
317     }
318     SwHistory* pHst = nullptr;
319     if (GetIDocumentUndoRedo().DoesUndo())
320     {
321         std::unique_ptr<SwUndoResetAttr> pUndo(new SwUndoResetAttr( rRg,
322             bTextAttr ? sal_uInt16(RES_CONDTXTFMTCOLL) : sal_uInt16(RES_TXTFMTCOLL) ));
323         if( !rAttrs.empty() )
324         {
325             pUndo->SetAttrs( rAttrs );
326         }
327         pHst = &pUndo->GetHistory();
328         GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
329     }
330 
331     const SwPosition *pStt = pPam->Start(), *pEnd = pPam->End();
332     sw::DocumentContentOperationsManager::ParaRstFormat aPara(
333             pStt, pEnd, pHst, nullptr, pLayout);
334 
335     // mst: not including META here; it seems attrs with CH_TXTATR are omitted
336     sal_uInt16 const aResetableSetRange[] {
337         RES_FRMATR_BEGIN, RES_FRMATR_END-1,
338         RES_CHRATR_BEGIN, RES_CHRATR_END-1,
339         RES_PARATR_BEGIN, RES_PARATR_END-1,
340         RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
341         RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
342         RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
343         RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY,
344         RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
345         RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
346         0
347     };
348 
349     SfxItemSet aDelSet( GetAttrPool(), aResetableSetRange );
350     if( !rAttrs.empty() )
351     {
352         for( std::set<sal_uInt16>::const_reverse_iterator it = rAttrs.rbegin(); it != rAttrs.rend(); ++it )
353         {
354             if( POOLATTR_END > *it )
355                 aDelSet.Put( *GetDfltAttr( *it ));
356         }
357         if( aDelSet.Count() )
358             aPara.pDelSet = &aDelSet;
359     }
360 
361     bool bAdd = true;
362     SwNodeIndex aTmpStt( pStt->nNode );
363     SwNodeIndex aTmpEnd( pEnd->nNode );
364     if( pStt->nContent.GetIndex() )     // just one part
365     {
366         // set up a later, and all CharFormatAttr -> TextFormatAttr
367         SwTextNode* pTNd = aTmpStt.GetNode().GetTextNode();
368         if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() )
369         {
370             if (pHst)
371             {
372                 SwRegHistory history(pTNd, *pTNd, pHst);
373                 pTNd->FormatToTextAttr(pTNd);
374             }
375             else
376             {
377                 pTNd->FormatToTextAttr(pTNd);
378             }
379         }
380 
381         ++aTmpStt;
382     }
383     if( pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetContentNode()->Len() )
384     {
385          // set up a later, and all CharFormatAttr -> TextFormatAttr
386         ++aTmpEnd;
387         bAdd = false;
388     }
389     else if( pStt->nNode != pEnd->nNode || !pStt->nContent.GetIndex() )
390     {
391         SwTextNode* pTNd = aTmpEnd.GetNode().GetTextNode();
392         if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() )
393         {
394             if (pHst)
395             {
396                 SwRegHistory history(pTNd, *pTNd, pHst);
397                 pTNd->FormatToTextAttr(pTNd);
398             }
399             else
400             {
401                 pTNd->FormatToTextAttr(pTNd);
402             }
403         }
404     }
405 
406     if( aTmpStt < aTmpEnd )
407         GetNodes().ForEach( pStt->nNode, aTmpEnd, lcl_RstAttr, &aPara );
408     else if( !rRg.HasMark() )
409     {
410         aPara.bResetAll = false ;
411         ::lcl_RstAttr( &pStt->nNode.GetNode(), &aPara );
412         aPara.bResetAll = true ;
413     }
414 
415     if( bTextAttr )
416     {
417         if( bAdd )
418             ++aTmpEnd;
419         GetNodes().ForEach( pStt->nNode, aTmpEnd, sw::DocumentContentOperationsManager::lcl_RstTextAttr, &aPara );
420     }
421 
422     getIDocumentState().SetModified();
423 
424     xDataChanged.reset(); //before delete pPam
425 
426     if( pPam != &rRg )
427         delete pPam;
428 }
429 
430 /// Set the rsid of the next nLen symbols of rRg to the current session number
431 void SwDoc::UpdateRsid( const SwPaM &rRg, const sal_Int32 nLen )
432 {
433     if (!SW_MOD()->GetModuleConfig()->IsStoreRsid())
434         return;
435 
436     SwTextNode *pTextNode = rRg.GetPoint()->nNode.GetNode().GetTextNode();
437     if (!pTextNode)
438     {
439         return;
440     }
441     const sal_Int32 nStart(rRg.GetPoint()->nContent.GetIndex() - nLen);
442     SvxRsidItem aRsid( mnRsid, RES_CHRATR_RSID );
443 
444     SfxItemSet aSet(GetAttrPool(), svl::Items<RES_CHRATR_RSID, RES_CHRATR_RSID>{});
445     aSet.Put(aRsid);
446     bool const bRet(pTextNode->SetAttr(aSet, nStart,
447         rRg.GetPoint()->nContent.GetIndex()));
448 
449     if (bRet && GetIDocumentUndoRedo().DoesUndo())
450     {
451         SwUndo *const pLastUndo = GetUndoManager().GetLastUndo();
452         SwUndoInsert *const pUndoInsert(dynamic_cast<SwUndoInsert*>(pLastUndo));
453         // this function is called after Insert so expects to find SwUndoInsert
454         assert(pUndoInsert);
455         if (pUndoInsert)
456         {
457             pUndoInsert->SetWithRsid();
458         }
459     }
460 }
461 
462 bool SwDoc::UpdateParRsid( SwTextNode *pTextNode, sal_uInt32 nVal )
463 {
464     if (!SW_MOD()->GetModuleConfig()->IsStoreRsid())
465         return false;
466 
467     if (!pTextNode)
468     {
469         return false;
470     }
471 
472     SvxRsidItem aRsid( nVal ? nVal : mnRsid, RES_PARATR_RSID );
473     return pTextNode->SetAttr( aRsid );
474 }
475 
476 /// Set the attribute according to the stated format.
477 /// If Undo is enabled, the old values is added to the Undo history.
478 void SwDoc::SetAttr( const SfxPoolItem& rAttr, SwFormat& rFormat )
479 {
480     SfxItemSet aSet( GetAttrPool(), {{rAttr.Which(), rAttr.Which()}} );
481     aSet.Put( rAttr );
482     SetAttr( aSet, rFormat );
483 }
484 
485 /// Set the attribute according to the stated format.
486 /// If Undo is enabled, the old values is added to the Undo history.
487 void SwDoc::SetAttr( const SfxItemSet& rSet, SwFormat& rFormat )
488 {
489     if (GetIDocumentUndoRedo().DoesUndo())
490     {
491         SwUndoFormatAttrHelper aTmp( rFormat );
492         rFormat.SetFormatAttr( rSet );
493         if ( aTmp.GetUndo() )
494         {
495             GetIDocumentUndoRedo().AppendUndo( aTmp.ReleaseUndo() );
496         }
497         else
498         {
499             GetIDocumentUndoRedo().ClearRedo();
500         }
501     }
502     else
503     {
504         rFormat.SetFormatAttr( rSet );
505     }
506     getIDocumentState().SetModified();
507 }
508 
509 void SwDoc::ResetAttrAtFormat( const sal_uInt16 nWhichId,
510                                SwFormat& rChangedFormat )
511 {
512     std::unique_ptr<SwUndo> pUndo;
513     if (GetIDocumentUndoRedo().DoesUndo())
514         pUndo.reset(new SwUndoFormatResetAttr( rChangedFormat, nWhichId ));
515 
516     const bool bAttrReset = rChangedFormat.ResetFormatAttr( nWhichId );
517 
518     if ( bAttrReset )
519     {
520         if ( pUndo )
521         {
522             GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
523         }
524 
525         getIDocumentState().SetModified();
526     }
527 }
528 
529 static bool lcl_SetNewDefTabStops( SwTwips nOldWidth, SwTwips nNewWidth,
530                                 SvxTabStopItem& rChgTabStop )
531 {
532     // Set the default values of all TabStops to the new value.
533     // Attention: we always work with the PoolAttribute here, so that
534     // we don't calculate the same value on the same TabStop (pooled!) for all sets.
535     // We send a FormatChg to modify.
536 
537     sal_uInt16 nOldCnt = rChgTabStop.Count();
538     if( !nOldCnt || nOldWidth == nNewWidth )
539         return false;
540 
541     // Find the default's beginning
542     sal_uInt16 n;
543     for( n = nOldCnt; n ; --n )
544         if( SvxTabAdjust::Default != rChgTabStop[n - 1].GetAdjustment() )
545             break;
546     ++n;
547     if( n < nOldCnt )   // delete the DefTabStops
548         rChgTabStop.Remove( n, nOldCnt - n );
549     return true;
550 }
551 
552 /// Set the attribute as new default attribute in this document.
553 /// If Undo is enabled, the old value is added to the Undo history.
554 void SwDoc::SetDefault( const SfxPoolItem& rAttr )
555 {
556     SfxItemSet aSet( GetAttrPool(), {{rAttr.Which(), rAttr.Which()}} );
557     aSet.Put( rAttr );
558     SetDefault( aSet );
559 }
560 
561 void SwDoc::SetDefault( const SfxItemSet& rSet )
562 {
563     if( !rSet.Count() )
564         return;
565 
566     SwModify aCallMod( nullptr );
567     SwAttrSet aOld( GetAttrPool(), rSet.GetRanges() ),
568             aNew( GetAttrPool(), rSet.GetRanges() );
569     SfxItemIter aIter( rSet );
570     const SfxPoolItem* pItem = aIter.GetCurItem();
571     SfxItemPool* pSdrPool = GetAttrPool().GetSecondaryPool();
572     while( true )
573     {
574         bool bCheckSdrDflt = false;
575         const sal_uInt16 nWhich = pItem->Which();
576         aOld.Put( GetAttrPool().GetDefaultItem( nWhich ) );
577         GetAttrPool().SetPoolDefaultItem( *pItem );
578         aNew.Put( GetAttrPool().GetDefaultItem( nWhich ) );
579 
580         if (isCHRATR(nWhich) || isTXTATR(nWhich))
581         {
582             aCallMod.Add( mpDfltTextFormatColl.get() );
583             aCallMod.Add( mpDfltCharFormat.get() );
584             bCheckSdrDflt = nullptr != pSdrPool;
585         }
586         else if ( isPARATR(nWhich) ||
587                   isPARATR_LIST(nWhich) )
588         {
589             aCallMod.Add( mpDfltTextFormatColl.get() );
590             bCheckSdrDflt = nullptr != pSdrPool;
591         }
592         else if (isGRFATR(nWhich))
593         {
594             aCallMod.Add( mpDfltGrfFormatColl.get() );
595         }
596         else if (isFRMATR(nWhich) || isDrawingLayerAttribute(nWhich) )
597         {
598             aCallMod.Add( mpDfltGrfFormatColl.get() );
599             aCallMod.Add( mpDfltTextFormatColl.get() );
600             aCallMod.Add( mpDfltFrameFormat.get() );
601         }
602         else if (isBOXATR(nWhich))
603         {
604             aCallMod.Add( mpDfltFrameFormat.get() );
605         }
606 
607         // also copy the defaults
608         if( bCheckSdrDflt )
609         {
610             sal_uInt16 nEdtWhich, nSlotId;
611             if( 0 != (nSlotId = GetAttrPool().GetSlotId( nWhich ) ) &&
612                 nSlotId != nWhich &&
613                 0 != (nEdtWhich = pSdrPool->GetWhich( nSlotId )) &&
614                 nSlotId != nEdtWhich )
615             {
616                 std::unique_ptr<SfxPoolItem> pCpy(pItem->Clone());
617                 pCpy->SetWhich( nEdtWhich );
618                 pSdrPool->SetPoolDefaultItem( *pCpy );
619             }
620         }
621 
622         if( aIter.IsAtEnd() )
623             break;
624         pItem = aIter.NextItem();
625     }
626 
627     if( aNew.Count() && aCallMod.HasWriterListeners() )
628     {
629         if (GetIDocumentUndoRedo().DoesUndo())
630         {
631             GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoDefaultAttr>( aOld, this ) );
632         }
633 
634         const SfxPoolItem* pTmpItem;
635         if( ( SfxItemState::SET ==
636                 aNew.GetItemState( RES_PARATR_TABSTOP, false, &pTmpItem ) ) &&
637             static_cast<const SvxTabStopItem*>(pTmpItem)->Count() )
638         {
639             // Set the default values of all TabStops to the new value.
640             // Attention: we always work with the PoolAttribute here, so that
641             // we don't calculate the same value on the same TabStop (pooled!) for all sets.
642             // We send a FormatChg to modify.
643             SwTwips nNewWidth = (*static_cast<const SvxTabStopItem*>(pTmpItem))[ 0 ].GetTabPos(),
644                     nOldWidth = aOld.Get(RES_PARATR_TABSTOP)[ 0 ].GetTabPos();
645 
646             bool bChg = false;
647             for (const SfxPoolItem* pItem2 : GetAttrPool().GetItemSurrogates(RES_PARATR_TABSTOP))
648             {
649                 auto pTabStopItem = dynamic_cast<const SvxTabStopItem*>(pItem2);
650                 if(pTabStopItem)
651                     bChg |= lcl_SetNewDefTabStops( nOldWidth, nNewWidth,
652                                                    *const_cast<SvxTabStopItem*>(pTabStopItem) );
653             }
654 
655             aNew.ClearItem( RES_PARATR_TABSTOP );
656             aOld.ClearItem( RES_PARATR_TABSTOP );
657             if( bChg )
658             {
659                 SwFormatChg aChgFormat( mpDfltCharFormat.get() );
660                 // notify the frames
661                 aCallMod.ModifyNotification( &aChgFormat, &aChgFormat );
662             }
663         }
664     }
665 
666     if( aNew.Count() && aCallMod.HasWriterListeners() )
667     {
668         SwAttrSetChg aChgOld( aOld, aOld );
669         SwAttrSetChg aChgNew( aNew, aNew );
670         aCallMod.ModifyNotification( &aChgOld, &aChgNew );      // all changed are sent
671     }
672 
673     // remove the default formats from the object again
674     SwIterator<SwClient, SwModify> aClientIter(aCallMod);
675     for(SwClient* pClient = aClientIter.First(); pClient; pClient = aClientIter.Next())
676         aCallMod.Remove( pClient );
677 
678     getIDocumentState().SetModified();
679 }
680 
681 /// Get the default attribute in this document
682 const SfxPoolItem& SwDoc::GetDefault( sal_uInt16 nFormatHint ) const
683 {
684     return GetAttrPool().GetDefaultItem( nFormatHint );
685 }
686 
687 /// Delete the formats
688 void SwDoc::DelCharFormat(size_t nFormat, bool bBroadcast)
689 {
690     SwCharFormat * pDel = (*mpCharFormatTable)[nFormat];
691 
692     if (bBroadcast)
693         BroadcastStyleOperation(pDel->GetName(), SfxStyleFamily::Char,
694                                 SfxHintId::StyleSheetErased);
695 
696     if (GetIDocumentUndoRedo().DoesUndo())
697     {
698         GetIDocumentUndoRedo().AppendUndo(
699             std::make_unique<SwUndoCharFormatDelete>(pDel, this));
700     }
701 
702     delete (*mpCharFormatTable)[nFormat];
703     mpCharFormatTable->erase(mpCharFormatTable->begin() + nFormat);
704 
705     getIDocumentState().SetModified();
706 }
707 
708 void SwDoc::DelCharFormat( SwCharFormat const *pFormat, bool bBroadcast )
709 {
710     size_t nFormat = mpCharFormatTable->GetPos( pFormat );
711     OSL_ENSURE( SIZE_MAX != nFormat, "Format not found," );
712     DelCharFormat( nFormat, bBroadcast );
713 }
714 
715 void SwDoc::DelFrameFormat( SwFrameFormat *pFormat, bool bBroadcast )
716 {
717     if( dynamic_cast<const SwTableBoxFormat*>( pFormat) != nullptr || dynamic_cast<const SwTableLineFormat*>( pFormat) != nullptr )
718     {
719         OSL_ENSURE( false, "Format is not in the DocArray any more, "
720                        "so it can be deleted with delete" );
721         delete pFormat;
722     }
723     else
724     {
725         // The format has to be in the one or the other, we'll see in which one.
726         if (mpFrameFormatTable->ContainsFormat(*pFormat))
727         {
728             if (bBroadcast)
729                 BroadcastStyleOperation(pFormat->GetName(),
730                                         SfxStyleFamily::Frame,
731                                         SfxHintId::StyleSheetErased);
732 
733             if (GetIDocumentUndoRedo().DoesUndo())
734             {
735                 GetIDocumentUndoRedo().AppendUndo(
736                     std::make_unique<SwUndoFrameFormatDelete>(pFormat, this));
737             }
738 
739             mpFrameFormatTable->erase( pFormat );
740             delete pFormat;
741         }
742         else
743         {
744             bool contains = GetSpzFrameFormats()->ContainsFormat(*pFormat);
745             OSL_ENSURE( contains, "FrameFormat not found." );
746             if( contains )
747             {
748                 GetSpzFrameFormats()->erase( pFormat );
749                 delete pFormat;
750             }
751         }
752     }
753 }
754 
755 void SwDoc::DelTableFrameFormat( SwTableFormat *pFormat )
756 {
757     SwFrameFormats::const_iterator it = mpTableFrameFormatTable->find( pFormat );
758     OSL_ENSURE( it != mpTableFrameFormatTable->end(), "Format not found," );
759     mpTableFrameFormatTable->erase( it );
760     delete pFormat;
761 }
762 
763 /// Create the formats
764 SwFlyFrameFormat *SwDoc::MakeFlyFrameFormat( const OUString &rFormatName,
765                                     SwFrameFormat *pDerivedFrom )
766 {
767     SwFlyFrameFormat *pFormat = new SwFlyFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom );
768     GetSpzFrameFormats()->push_back(pFormat);
769     getIDocumentState().SetModified();
770     return pFormat;
771 }
772 
773 SwDrawFrameFormat *SwDoc::MakeDrawFrameFormat( const OUString &rFormatName,
774                                      SwFrameFormat *pDerivedFrom )
775 {
776     SwDrawFrameFormat *pFormat = new SwDrawFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom);
777     GetSpzFrameFormats()->push_back(pFormat);
778     getIDocumentState().SetModified();
779     return pFormat;
780 }
781 
782 size_t SwDoc::GetTableFrameFormatCount(bool bUsed) const
783 {
784     if (!bUsed)
785     {
786         return mpTableFrameFormatTable->size();
787     }
788 
789     SwAutoFormatGetDocNode aGetHt(&GetNodes());
790     size_t nCount = 0;
791     for (SwFrameFormat* const & pFormat : *mpTableFrameFormatTable)
792     {
793         if (!pFormat->GetInfo(aGetHt))
794             nCount++;
795     }
796     return nCount;
797 }
798 
799 SwFrameFormat& SwDoc::GetTableFrameFormat(size_t nFormat, bool bUsed) const
800 {
801     if (!bUsed)
802     {
803         return *((*mpTableFrameFormatTable)[nFormat]);
804     }
805 
806     SwAutoFormatGetDocNode aGetHt(&GetNodes());
807 
808     size_t index = 0;
809 
810     for (SwFrameFormat* const & pFormat : *mpTableFrameFormatTable)
811     {
812         if (!pFormat->GetInfo(aGetHt))
813         {
814             if (index == nFormat)
815                 return *pFormat;
816             else
817                 index++;
818         }
819     }
820     throw std::out_of_range("Format index out of range.");
821 }
822 
823 SwTableFormat* SwDoc::MakeTableFrameFormat( const OUString &rFormatName,
824                                     SwFrameFormat *pDerivedFrom )
825 {
826     SwTableFormat* pFormat = new SwTableFormat( GetAttrPool(), rFormatName, pDerivedFrom );
827     mpTableFrameFormatTable->push_back( pFormat );
828     getIDocumentState().SetModified();
829 
830     return pFormat;
831 }
832 
833 SwFrameFormat *SwDoc::MakeFrameFormat(const OUString &rFormatName,
834                             SwFrameFormat *pDerivedFrom,
835                             bool bBroadcast, bool bAuto)
836 {
837     SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom );
838 
839     pFormat->SetAuto(bAuto);
840     mpFrameFormatTable->push_back( pFormat );
841     getIDocumentState().SetModified();
842 
843     if (GetIDocumentUndoRedo().DoesUndo())
844     {
845         GetIDocumentUndoRedo().AppendUndo(
846             std::make_unique<SwUndoFrameFormatCreate>(pFormat, pDerivedFrom, this));
847     }
848 
849     if (bBroadcast)
850     {
851         BroadcastStyleOperation(rFormatName, SfxStyleFamily::Frame,
852                                 SfxHintId::StyleSheetCreated);
853     }
854 
855     return pFormat;
856 }
857 
858 SwFormat *SwDoc::MakeFrameFormat_(const OUString &rFormatName,
859                             SwFormat *pDerivedFrom,
860                             bool bBroadcast, bool bAuto)
861 {
862     SwFrameFormat *pFrameFormat = dynamic_cast<SwFrameFormat*>(pDerivedFrom);
863     pFrameFormat = MakeFrameFormat( rFormatName, pFrameFormat, bBroadcast, bAuto );
864     return dynamic_cast<SwFormat*>(pFrameFormat);
865 }
866 
867 SwCharFormat *SwDoc::MakeCharFormat( const OUString &rFormatName,
868                                SwCharFormat *pDerivedFrom,
869                                bool bBroadcast )
870 {
871     SwCharFormat *pFormat = new SwCharFormat( GetAttrPool(), rFormatName, pDerivedFrom );
872     mpCharFormatTable->push_back( pFormat );
873     pFormat->SetAuto(false);
874     getIDocumentState().SetModified();
875 
876     if (GetIDocumentUndoRedo().DoesUndo())
877     {
878         GetIDocumentUndoRedo().AppendUndo(
879             std::make_unique<SwUndoCharFormatCreate>(pFormat, pDerivedFrom, this));
880     }
881 
882     if (bBroadcast)
883     {
884         BroadcastStyleOperation(rFormatName, SfxStyleFamily::Char,
885                                 SfxHintId::StyleSheetCreated);
886     }
887 
888     return pFormat;
889 }
890 
891 SwFormat *SwDoc::MakeCharFormat_(const OUString &rFormatName,
892                             SwFormat *pDerivedFrom,
893                             bool bBroadcast, bool /*bAuto*/)
894 {
895     SwCharFormat *pCharFormat = dynamic_cast<SwCharFormat*>(pDerivedFrom);
896     pCharFormat = MakeCharFormat( rFormatName, pCharFormat, bBroadcast );
897     return dynamic_cast<SwFormat*>(pCharFormat);
898 }
899 
900 /// Create the FormatCollections
901 SwTextFormatColl* SwDoc::MakeTextFormatColl( const OUString &rFormatName,
902                                      SwTextFormatColl *pDerivedFrom,
903                                      bool bBroadcast)
904 {
905     SwTextFormatColl *pFormatColl = new SwTextFormatColl( GetAttrPool(), rFormatName,
906                                                 pDerivedFrom );
907     mpTextFormatCollTable->push_back(pFormatColl);
908     pFormatColl->SetAuto(false);
909     getIDocumentState().SetModified();
910 
911     if (GetIDocumentUndoRedo().DoesUndo())
912     {
913         GetIDocumentUndoRedo().AppendUndo(
914             std::make_unique<SwUndoTextFormatCollCreate>(pFormatColl, pDerivedFrom,
915                                                     this));
916     }
917 
918     if (bBroadcast)
919         BroadcastStyleOperation(rFormatName, SfxStyleFamily::Para,
920                                 SfxHintId::StyleSheetCreated);
921 
922     return pFormatColl;
923 }
924 
925 SwFormat *SwDoc::MakeTextFormatColl_(const OUString &rFormatName,
926                             SwFormat *pDerivedFrom,
927                             bool bBroadcast, bool /*bAuto*/)
928 {
929     SwTextFormatColl *pTextFormatColl = dynamic_cast<SwTextFormatColl*>(pDerivedFrom);
930     pTextFormatColl = MakeTextFormatColl( rFormatName, pTextFormatColl, bBroadcast );
931     return dynamic_cast<SwFormat*>(pTextFormatColl);
932 }
933 
934 //FEATURE::CONDCOLL
935 SwConditionTextFormatColl* SwDoc::MakeCondTextFormatColl( const OUString &rFormatName,
936                                                   SwTextFormatColl *pDerivedFrom,
937                                                   bool bBroadcast)
938 {
939     SwConditionTextFormatColl*pFormatColl = new SwConditionTextFormatColl( GetAttrPool(),
940                                                     rFormatName, pDerivedFrom );
941     mpTextFormatCollTable->push_back(pFormatColl);
942     pFormatColl->SetAuto(false);
943     getIDocumentState().SetModified();
944 
945     if (GetIDocumentUndoRedo().DoesUndo())
946     {
947         GetIDocumentUndoRedo().AppendUndo(
948             std::make_unique<SwUndoCondTextFormatCollCreate>(pFormatColl, pDerivedFrom,
949                                                         this));
950     }
951 
952     if (bBroadcast)
953         BroadcastStyleOperation(rFormatName, SfxStyleFamily::Para,
954                                 SfxHintId::StyleSheetCreated);
955 
956     return pFormatColl;
957 }
958 //FEATURE::CONDCOLL
959 
960 // GRF
961 SwGrfFormatColl* SwDoc::MakeGrfFormatColl( const OUString &rFormatName,
962                                      SwGrfFormatColl *pDerivedFrom )
963 {
964     SwGrfFormatColl *pFormatColl = new SwGrfFormatColl( GetAttrPool(), rFormatName,
965                                                 pDerivedFrom );
966     mpGrfFormatCollTable->push_back( pFormatColl );
967     pFormatColl->SetAuto(false);
968     getIDocumentState().SetModified();
969     return pFormatColl;
970 }
971 
972 void SwDoc::DelTextFormatColl(size_t nFormatColl, bool bBroadcast)
973 {
974     OSL_ENSURE( nFormatColl, "Remove of Coll 0." );
975 
976     // Who has the to-be-deleted as their Next?
977     SwTextFormatColl *pDel = (*mpTextFormatCollTable)[nFormatColl];
978     if( mpDfltTextFormatColl.get() == pDel )
979         return;     // never delete default!
980 
981     if (bBroadcast)
982         BroadcastStyleOperation(pDel->GetName(), SfxStyleFamily::Para,
983                                 SfxHintId::StyleSheetErased);
984 
985     if (GetIDocumentUndoRedo().DoesUndo())
986     {
987         std::unique_ptr<SwUndoTextFormatCollDelete> pUndo;
988         if (RES_CONDTXTFMTCOLL == pDel->Which())
989         {
990             pUndo.reset(new SwUndoCondTextFormatCollDelete(pDel, this));
991         }
992         else
993         {
994             pUndo.reset(new SwUndoTextFormatCollDelete(pDel, this));
995         }
996 
997         GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
998     }
999 
1000     // Remove the FormatColl
1001     mpTextFormatCollTable->erase(mpTextFormatCollTable->begin() + nFormatColl);
1002     // Correct next
1003     for( SwTextFormatColls::const_iterator it = mpTextFormatCollTable->begin() + 1; it != mpTextFormatCollTable->end(); ++it )
1004         SetTextFormatCollNext( *it, pDel );
1005     delete pDel;
1006     getIDocumentState().SetModified();
1007 }
1008 
1009 void SwDoc::DelTextFormatColl( SwTextFormatColl const *pColl, bool bBroadcast )
1010 {
1011     size_t nFormat = mpTextFormatCollTable->GetPos( pColl );
1012     OSL_ENSURE( SIZE_MAX != nFormat, "Collection not found," );
1013     DelTextFormatColl( nFormat, bBroadcast );
1014 }
1015 
1016 static bool lcl_SetTextFormatColl( const SwNodePtr& rpNode, void* pArgs )
1017 {
1018     SwContentNode* pCNd = static_cast<SwContentNode*>(rpNode->GetTextNode());
1019 
1020     if( pCNd == nullptr)
1021         return true;
1022 
1023     sw::DocumentContentOperationsManager::ParaRstFormat* pPara = static_cast<sw::DocumentContentOperationsManager::ParaRstFormat*>(pArgs);
1024 
1025     if (pPara->pLayout && pPara->pLayout->IsHideRedlines())
1026     {
1027         if (pCNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)
1028         {
1029             return true;
1030         }
1031         if (pCNd->IsTextNode())
1032         {
1033             pCNd = sw::GetParaPropsNode(*pPara->pLayout, SwNodeIndex(*pCNd));
1034         }
1035     }
1036 
1037     SwTextFormatColl* pFormat = static_cast<SwTextFormatColl*>(pPara->pFormatColl);
1038     if ( pPara->bReset )
1039     {
1040         lcl_RstAttr(pCNd, pPara);
1041 
1042         // #i62675# check, if paragraph style has changed
1043         if ( pPara->bResetListAttrs &&
1044              pFormat != pCNd->GetFormatColl() &&
1045              pFormat->GetItemState( RES_PARATR_NUMRULE ) == SfxItemState::SET )
1046         {
1047             // Check, if the list style of the paragraph will change.
1048             bool bChangeOfListStyleAtParagraph( true );
1049             SwTextNode& rTNd(dynamic_cast<SwTextNode&>(*pCNd));
1050             {
1051                 SwNumRule* pNumRuleAtParagraph(rTNd.GetNumRule());
1052                 if ( pNumRuleAtParagraph )
1053                 {
1054                     const SwNumRuleItem& rNumRuleItemAtParagraphStyle =
1055                         pFormat->GetNumRule();
1056                     if ( rNumRuleItemAtParagraphStyle.GetValue() ==
1057                             pNumRuleAtParagraph->GetName() )
1058                     {
1059                         bChangeOfListStyleAtParagraph = false;
1060                     }
1061                 }
1062             }
1063 
1064             if ( bChangeOfListStyleAtParagraph )
1065             {
1066                 std::unique_ptr< SwRegHistory > pRegH;
1067                 if ( pPara->pHistory )
1068                 {
1069                     pRegH.reset(new SwRegHistory(&rTNd, rTNd, pPara->pHistory));
1070                 }
1071 
1072                 pCNd->ResetAttr( RES_PARATR_NUMRULE );
1073 
1074                 // reset all list attributes
1075                 pCNd->ResetAttr( RES_PARATR_LIST_LEVEL );
1076                 pCNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
1077                 pCNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
1078                 pCNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
1079                 pCNd->ResetAttr( RES_PARATR_LIST_ID );
1080             }
1081         }
1082     }
1083 
1084     // add to History so that old data is saved, if necessary
1085     if( pPara->pHistory )
1086         pPara->pHistory->Add( pCNd->GetFormatColl(), pCNd->GetIndex(),
1087                 SwNodeType::Text );
1088 
1089     pCNd->ChgFormatColl( pFormat );
1090 
1091     pPara->nWhich++;
1092 
1093     return true;
1094 }
1095 
1096 bool SwDoc::SetTextFormatColl(const SwPaM &rRg,
1097                           SwTextFormatColl *pFormat,
1098                           const bool bReset,
1099                           const bool bResetListAttrs,
1100                           SwRootFrame const*const pLayout)
1101 {
1102     SwDataChanged aTmp( rRg );
1103     const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
1104     SwHistory* pHst = nullptr;
1105     bool bRet = true;
1106 
1107     if (GetIDocumentUndoRedo().DoesUndo())
1108     {
1109         std::unique_ptr<SwUndoFormatColl> pUndo(new SwUndoFormatColl( rRg, pFormat,
1110                                                   bReset,
1111                                                   bResetListAttrs ));
1112         pHst = pUndo->GetHistory();
1113         GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
1114     }
1115 
1116     sw::DocumentContentOperationsManager::ParaRstFormat aPara(
1117             pStt, pEnd, pHst, nullptr, pLayout);
1118     aPara.pFormatColl = pFormat;
1119     aPara.bReset = bReset;
1120     // #i62675#
1121     aPara.bResetListAttrs = bResetListAttrs;
1122 
1123     GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1,
1124                         lcl_SetTextFormatColl, &aPara );
1125     if( !aPara.nWhich )
1126         bRet = false;           // didn't find a valid Node
1127 
1128     if (bRet)
1129     {
1130         getIDocumentState().SetModified();
1131     }
1132 
1133     return bRet;
1134 }
1135 
1136 /// Copy the formats to itself
1137 SwFormat* SwDoc::CopyFormat( const SwFormat& rFormat,
1138                         const SwFormatsBase& rFormatArr,
1139                         FNCopyFormat fnCopyFormat, const SwFormat& rDfltFormat )
1140 {
1141     // It's no autoformat, default format or collection format,
1142     // then search for it.
1143     if( !rFormat.IsAuto() || !rFormat.GetRegisteredIn() )
1144         for( size_t n = 0; n < rFormatArr.GetFormatCount(); ++n )
1145         {
1146             // Does the Doc already contain the template?
1147             if( rFormatArr.GetFormat(n)->GetName()==rFormat.GetName() )
1148                 return rFormatArr.GetFormat(n);
1149         }
1150 
1151     // Search for the "parent" first
1152     SwFormat* pParent = const_cast<SwFormat*>(&rDfltFormat);
1153     if( rFormat.DerivedFrom() && pParent != rFormat.DerivedFrom() )
1154         pParent = CopyFormat( *rFormat.DerivedFrom(), rFormatArr,
1155                                 fnCopyFormat, rDfltFormat );
1156 
1157     // Create the format and copy the attributes
1158     // #i40550#
1159     SwFormat* pNewFormat = (this->*fnCopyFormat)( rFormat.GetName(), pParent, false, true );
1160     pNewFormat->SetAuto( rFormat.IsAuto() );
1161     pNewFormat->CopyAttrs( rFormat );           // copy the attributes
1162 
1163     pNewFormat->SetPoolFormatId( rFormat.GetPoolFormatId() );
1164     pNewFormat->SetPoolHelpId( rFormat.GetPoolHelpId() );
1165 
1166     // Always set the HelpFile Id to default!
1167     pNewFormat->SetPoolHlpFileId( UCHAR_MAX );
1168 
1169     return pNewFormat;
1170 }
1171 
1172 /// copy the frame format
1173 SwFrameFormat* SwDoc::CopyFrameFormat( const SwFrameFormat& rFormat )
1174 {
1175     return static_cast<SwFrameFormat*>(CopyFormat( rFormat, *GetFrameFormats(), &SwDoc::MakeFrameFormat_,
1176                                 *GetDfltFrameFormat() ));
1177 }
1178 
1179 /// copy the char format
1180 SwCharFormat* SwDoc::CopyCharFormat( const SwCharFormat& rFormat )
1181 {
1182     return static_cast<SwCharFormat*>(CopyFormat( rFormat, *GetCharFormats(),
1183                                             &SwDoc::MakeCharFormat_,
1184                                             *GetDfltCharFormat() ));
1185 }
1186 
1187 /// copy TextNodes
1188 SwTextFormatColl* SwDoc::CopyTextColl( const SwTextFormatColl& rColl )
1189 {
1190     SwTextFormatColl* pNewColl = FindTextFormatCollByName( rColl.GetName() );
1191     if( pNewColl )
1192         return pNewColl;
1193 
1194     // search for the "parent" first
1195     SwTextFormatColl* pParent = mpDfltTextFormatColl.get();
1196     if( pParent != rColl.DerivedFrom() )
1197         pParent = CopyTextColl( *static_cast<SwTextFormatColl*>(rColl.DerivedFrom()) );
1198 
1199 //FEATURE::CONDCOLL
1200     if( RES_CONDTXTFMTCOLL == rColl.Which() )
1201     {
1202         pNewColl = new SwConditionTextFormatColl( GetAttrPool(), rColl.GetName(),
1203                                                 pParent);
1204         mpTextFormatCollTable->push_back( pNewColl );
1205         pNewColl->SetAuto(false);
1206         getIDocumentState().SetModified();
1207 
1208         // copy the conditions
1209         static_cast<SwConditionTextFormatColl*>(pNewColl)->SetConditions(
1210                             static_cast<const SwConditionTextFormatColl&>(rColl).GetCondColls() );
1211     }
1212     else
1213 //FEATURE::CONDCOLL
1214         pNewColl = MakeTextFormatColl( rColl.GetName(), pParent );
1215 
1216     // copy the auto formats or the attributes
1217     pNewColl->CopyAttrs( rColl );
1218 
1219     if(rColl.IsAssignedToListLevelOfOutlineStyle())
1220         pNewColl->AssignToListLevelOfOutlineStyle(rColl.GetAssignedOutlineStyleLevel());
1221     pNewColl->SetPoolFormatId( rColl.GetPoolFormatId() );
1222     pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() );
1223 
1224     // Always set the HelpFile Id to default!
1225     pNewColl->SetPoolHlpFileId( UCHAR_MAX );
1226 
1227     if( &rColl.GetNextTextFormatColl() != &rColl )
1228         pNewColl->SetNextTextFormatColl( *CopyTextColl( rColl.GetNextTextFormatColl() ));
1229 
1230     // create the NumRule if necessary
1231     if( this != rColl.GetDoc() )
1232     {
1233         const SfxPoolItem* pItem;
1234         if( SfxItemState::SET == pNewColl->GetItemState( RES_PARATR_NUMRULE,
1235             false, &pItem ))
1236         {
1237             const SwNumRule* pRule;
1238             const OUString& rName = static_cast<const SwNumRuleItem*>(pItem)->GetValue();
1239             if( !rName.isEmpty() &&
1240                 nullptr != ( pRule = rColl.GetDoc()->FindNumRulePtr( rName )) &&
1241                 !pRule->IsAutoRule() )
1242             {
1243                 SwNumRule* pDestRule = FindNumRulePtr( rName );
1244                 if( pDestRule )
1245                     pDestRule->SetInvalidRule( true );
1246                 else
1247                     MakeNumRule( rName, pRule );
1248             }
1249         }
1250     }
1251     return pNewColl;
1252 }
1253 
1254 /// copy the graphic nodes
1255 SwGrfFormatColl* SwDoc::CopyGrfColl( const SwGrfFormatColl& rColl )
1256 {
1257     SwGrfFormatColl* pNewColl = static_cast<SwGrfFormatColl*>(FindFormatByName( static_cast<SwFormatsBase const &>(*mpGrfFormatCollTable), rColl.GetName() ));
1258     if( pNewColl )
1259         return pNewColl;
1260 
1261      // Search for the "parent" first
1262     SwGrfFormatColl* pParent = mpDfltGrfFormatColl.get();
1263     if( pParent != rColl.DerivedFrom() )
1264         pParent = CopyGrfColl( *static_cast<SwGrfFormatColl*>(rColl.DerivedFrom()) );
1265 
1266     // if not, copy them
1267     pNewColl = MakeGrfFormatColl( rColl.GetName(), pParent );
1268 
1269     // copy the attributes
1270     pNewColl->CopyAttrs( rColl );
1271 
1272     pNewColl->SetPoolFormatId( rColl.GetPoolFormatId() );
1273     pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() );
1274 
1275     // Always set the HelpFile Id to default!
1276     pNewColl->SetPoolHlpFileId( UCHAR_MAX );
1277 
1278     return pNewColl;
1279 }
1280 
1281 void SwDoc::CopyFormatArr( const SwFormatsBase& rSourceArr,
1282                         SwFormatsBase const & rDestArr,
1283                         FNCopyFormat fnCopyFormat,
1284                         SwFormat& rDfltFormat )
1285 {
1286     SwFormat* pSrc, *pDest;
1287 
1288     // 1st step: Create all formats (skip the 0th - it's the default one)
1289     for( size_t nSrc = rSourceArr.GetFormatCount(); nSrc > 1; )
1290     {
1291         pSrc = rSourceArr.GetFormat( --nSrc );
1292         if( pSrc->IsDefault() || pSrc->IsAuto() )
1293             continue;
1294 
1295         if( nullptr == FindFormatByName( rDestArr, pSrc->GetName() ) )
1296         {
1297             if( RES_CONDTXTFMTCOLL == pSrc->Which() )
1298                 MakeCondTextFormatColl( pSrc->GetName(), static_cast<SwTextFormatColl*>(&rDfltFormat) );
1299             else
1300                 // #i40550#
1301                 (this->*fnCopyFormat)( pSrc->GetName(), &rDfltFormat, false, true );
1302         }
1303     }
1304 
1305     // 2nd step: Copy all attributes, set the right parents
1306     for( size_t nSrc = rSourceArr.GetFormatCount(); nSrc > 1; )
1307     {
1308         pSrc = rSourceArr.GetFormat( --nSrc );
1309         if( pSrc->IsDefault() || pSrc->IsAuto() )
1310             continue;
1311 
1312         pDest = FindFormatByName( rDestArr, pSrc->GetName() );
1313         pDest->SetAuto(false);
1314         pDest->DelDiffs( *pSrc );
1315 
1316         // #i94285#: existing <SwFormatPageDesc> instance, before copying attributes
1317         const SfxPoolItem* pItem;
1318         if( &GetAttrPool() != pSrc->GetAttrSet().GetPool() &&
1319             SfxItemState::SET == pSrc->GetAttrSet().GetItemState(
1320             RES_PAGEDESC, false, &pItem ) &&
1321             static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc() )
1322         {
1323             SwFormatPageDesc aPageDesc( *static_cast<const SwFormatPageDesc*>(pItem) );
1324             const OUString& rNm = aPageDesc.GetPageDesc()->GetName();
1325             SwPageDesc* pPageDesc = FindPageDesc( rNm );
1326             if( !pPageDesc )
1327             {
1328                 pPageDesc = MakePageDesc(rNm);
1329             }
1330             aPageDesc.RegisterToPageDesc( *pPageDesc );
1331             SwAttrSet aTmpAttrSet( pSrc->GetAttrSet() );
1332             aTmpAttrSet.Put( aPageDesc );
1333             pDest->SetFormatAttr( aTmpAttrSet );
1334         }
1335         else
1336         {
1337             pDest->SetFormatAttr( pSrc->GetAttrSet() );
1338         }
1339 
1340         pDest->SetPoolFormatId( pSrc->GetPoolFormatId() );
1341         pDest->SetPoolHelpId( pSrc->GetPoolHelpId() );
1342 
1343         // Always set the HelpFile Id to default!
1344         pDest->SetPoolHlpFileId( UCHAR_MAX );
1345 
1346         if( pSrc->DerivedFrom() )
1347             pDest->SetDerivedFrom( FindFormatByName( rDestArr,
1348                                         pSrc->DerivedFrom()->GetName() ) );
1349         if( RES_TXTFMTCOLL == pSrc->Which() ||
1350             RES_CONDTXTFMTCOLL == pSrc->Which() )
1351         {
1352             SwTextFormatColl* pSrcColl = static_cast<SwTextFormatColl*>(pSrc),
1353                         * pDstColl = static_cast<SwTextFormatColl*>(pDest);
1354             if( &pSrcColl->GetNextTextFormatColl() != pSrcColl )
1355                 pDstColl->SetNextTextFormatColl( *static_cast<SwTextFormatColl*>(FindFormatByName(
1356                     rDestArr, pSrcColl->GetNextTextFormatColl().GetName() ) ) );
1357 
1358             if(pSrcColl->IsAssignedToListLevelOfOutlineStyle())
1359                 pDstColl->AssignToListLevelOfOutlineStyle(pSrcColl->GetAssignedOutlineStyleLevel());
1360 
1361 //FEATURE::CONDCOLL
1362             if( RES_CONDTXTFMTCOLL == pSrc->Which() )
1363                 // Copy the conditions, but delete the old ones first!
1364                 static_cast<SwConditionTextFormatColl*>(pDstColl)->SetConditions(
1365                             static_cast<SwConditionTextFormatColl*>(pSrc)->GetCondColls() );
1366 //FEATURE::CONDCOLL
1367         }
1368     }
1369 }
1370 
1371 void SwDoc::CopyPageDescHeaderFooterImpl( bool bCpyHeader,
1372                                 const SwFrameFormat& rSrcFormat, SwFrameFormat& rDestFormat )
1373 {
1374     // Treat the header and footer attributes in the right way:
1375     // Copy content nodes across documents!
1376     sal_uInt16 nAttr = bCpyHeader ? sal_uInt16(RES_HEADER) : sal_uInt16(RES_FOOTER);
1377     const SfxPoolItem* pItem;
1378     if( SfxItemState::SET != rSrcFormat.GetAttrSet().GetItemState( nAttr, false, &pItem ))
1379         return ;
1380 
1381     // The header only contains the reference to the format from the other document!
1382     std::unique_ptr<SfxPoolItem> pNewItem(pItem->Clone());
1383 
1384     SwFrameFormat* pOldFormat;
1385     if( bCpyHeader )
1386          pOldFormat = static_cast<SwFormatHeader*>(pNewItem.get())->GetHeaderFormat();
1387     else
1388          pOldFormat = static_cast<SwFormatFooter*>(pNewItem.get())->GetFooterFormat();
1389 
1390     if( pOldFormat )
1391     {
1392         SwFrameFormat* pNewFormat = new SwFrameFormat( GetAttrPool(), "CpyDesc",
1393                                             GetDfltFrameFormat() );
1394         pNewFormat->CopyAttrs( *pOldFormat );
1395 
1396         if( SfxItemState::SET == pNewFormat->GetAttrSet().GetItemState(
1397             RES_CNTNT, false, &pItem ))
1398         {
1399             const SwFormatContent* pContent = static_cast<const SwFormatContent*>(pItem);
1400             if( pContent->GetContentIdx() )
1401             {
1402                 SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
1403                 const SwNodes& rSrcNds = rSrcFormat.GetDoc()->GetNodes();
1404                 SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmpIdx,
1405                                                 bCpyHeader
1406                                                     ? SwHeaderStartNode
1407                                                     : SwFooterStartNode );
1408                 const SwNode& rCSttNd = pContent->GetContentIdx()->GetNode();
1409                 SwNodeRange aRg( rCSttNd, 0, *rCSttNd.EndOfSectionNode() );
1410                 aTmpIdx = *pSttNd->EndOfSectionNode();
1411                 rSrcNds.Copy_( aRg, aTmpIdx );
1412                 aTmpIdx = *pSttNd;
1413                 rSrcFormat.GetDoc()->GetDocumentContentOperationsManager().CopyFlyInFlyImpl( aRg, 0, aTmpIdx );
1414                 pNewFormat->SetFormatAttr( SwFormatContent( pSttNd ));
1415             }
1416             else
1417                 pNewFormat->ResetFormatAttr( RES_CNTNT );
1418         }
1419         if( bCpyHeader )
1420             static_cast<SwFormatHeader*>(pNewItem.get())->RegisterToFormat(*pNewFormat);
1421         else
1422             static_cast<SwFormatFooter*>(pNewItem.get())->RegisterToFormat(*pNewFormat);
1423         rDestFormat.SetFormatAttr( *pNewItem );
1424     }
1425 }
1426 
1427 void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, SwPageDesc& rDstDesc,
1428                             bool bCopyPoolIds )
1429 {
1430     bool bNotifyLayout = false;
1431     SwRootFrame* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout();
1432 
1433     rDstDesc.SetLandscape( rSrcDesc.GetLandscape() );
1434     rDstDesc.SetNumType( rSrcDesc.GetNumType() );
1435     if( rDstDesc.ReadUseOn() != rSrcDesc.ReadUseOn() )
1436     {
1437         rDstDesc.WriteUseOn( rSrcDesc.ReadUseOn() );
1438         bNotifyLayout = true;
1439     }
1440 
1441     if( bCopyPoolIds )
1442     {
1443         rDstDesc.SetPoolFormatId( rSrcDesc.GetPoolFormatId() );
1444         rDstDesc.SetPoolHelpId( rSrcDesc.GetPoolHelpId() );
1445         // Always set the HelpFile Id to default!
1446         rDstDesc.SetPoolHlpFileId( UCHAR_MAX );
1447     }
1448 
1449     if( rSrcDesc.GetFollow() != &rSrcDesc )
1450     {
1451         const SwPageDesc* pSrcFollow = rSrcDesc.GetFollow();
1452         SwPageDesc* pFollow = FindPageDesc( pSrcFollow->GetName() );
1453         if( !pFollow )
1454         {
1455             // copy
1456             pFollow = MakePageDesc( pSrcFollow->GetName() );
1457             CopyPageDesc( *pSrcFollow, *pFollow );
1458         }
1459         rDstDesc.SetFollow( pFollow );
1460         bNotifyLayout = true;
1461     }
1462 
1463     // the header and footer attributes are copied separately
1464     // the content sections have to be copied in their entirety
1465     {
1466         SfxItemSet aAttrSet( rSrcDesc.GetMaster().GetAttrSet() );
1467         aAttrSet.ClearItem( RES_HEADER );
1468         aAttrSet.ClearItem( RES_FOOTER );
1469 
1470         rDstDesc.GetMaster().DelDiffs( aAttrSet );
1471         rDstDesc.GetMaster().SetFormatAttr( aAttrSet );
1472 
1473         aAttrSet.ClearItem();
1474         aAttrSet.Put( rSrcDesc.GetLeft().GetAttrSet() );
1475         aAttrSet.ClearItem( RES_HEADER );
1476         aAttrSet.ClearItem( RES_FOOTER );
1477 
1478         rDstDesc.GetLeft().DelDiffs( aAttrSet );
1479         rDstDesc.GetLeft().SetFormatAttr( aAttrSet );
1480 
1481         aAttrSet.ClearItem();
1482         aAttrSet.Put( rSrcDesc.GetFirstMaster().GetAttrSet() );
1483         aAttrSet.ClearItem( RES_HEADER );
1484         aAttrSet.ClearItem( RES_FOOTER );
1485 
1486         rDstDesc.GetFirstMaster().DelDiffs( aAttrSet );
1487         rDstDesc.GetFirstMaster().SetFormatAttr( aAttrSet );
1488 
1489         aAttrSet.ClearItem();
1490         aAttrSet.Put( rSrcDesc.GetFirstLeft().GetAttrSet() );
1491         aAttrSet.ClearItem( RES_HEADER );
1492         aAttrSet.ClearItem( RES_FOOTER );
1493 
1494         rDstDesc.GetFirstLeft().DelDiffs( aAttrSet );
1495         rDstDesc.GetFirstLeft().SetFormatAttr( aAttrSet );
1496     }
1497 
1498     CopyHeader( rSrcDesc.GetMaster(), rDstDesc.GetMaster() );
1499     CopyFooter( rSrcDesc.GetMaster(), rDstDesc.GetMaster() );
1500     if( !rDstDesc.IsHeaderShared() )
1501         CopyHeader( rSrcDesc.GetLeft(), rDstDesc.GetLeft() );
1502     else
1503         rDstDesc.GetLeft().SetFormatAttr( rDstDesc.GetMaster().GetHeader() );
1504     if( !rDstDesc.IsFirstShared() )
1505     {
1506         CopyHeader( rSrcDesc.GetFirstMaster(), rDstDesc.GetFirstMaster() );
1507         rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetFirstMaster().GetHeader());
1508     }
1509     else
1510     {
1511         rDstDesc.GetFirstMaster().SetFormatAttr( rDstDesc.GetMaster().GetHeader() );
1512         rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetLeft().GetHeader());
1513     }
1514 
1515     if( !rDstDesc.IsFooterShared() )
1516         CopyFooter( rSrcDesc.GetLeft(), rDstDesc.GetLeft() );
1517     else
1518         rDstDesc.GetLeft().SetFormatAttr( rDstDesc.GetMaster().GetFooter() );
1519     if( !rDstDesc.IsFirstShared() )
1520     {
1521         CopyFooter( rSrcDesc.GetFirstMaster(), rDstDesc.GetFirstMaster() );
1522         rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetFirstMaster().GetFooter());
1523     }
1524     else
1525     {
1526         rDstDesc.GetFirstMaster().SetFormatAttr( rDstDesc.GetMaster().GetFooter() );
1527         rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetLeft().GetFooter());
1528     }
1529 
1530     if( bNotifyLayout && pTmpRoot )
1531     {
1532         for( auto aLayout : GetAllLayouts() )
1533             aLayout->AllCheckPageDescs();
1534     }
1535 
1536     // If foot notes change the pages have to be triggered
1537     if( !(rDstDesc.GetFootnoteInfo() == rSrcDesc.GetFootnoteInfo()) )
1538     {
1539         sw::PageFootnoteHint aHint;
1540         rDstDesc.SetFootnoteInfo( rSrcDesc.GetFootnoteInfo() );
1541         rDstDesc.GetMaster().CallSwClientNotify(aHint);
1542         rDstDesc.GetLeft().CallSwClientNotify(aHint);
1543         rDstDesc.GetFirstMaster().CallSwClientNotify(aHint);
1544         rDstDesc.GetFirstLeft().CallSwClientNotify(aHint);
1545     }
1546 }
1547 
1548 void SwDoc::ReplaceStyles( const SwDoc& rSource, bool bIncludePageStyles )
1549 {
1550     ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1551 
1552     CopyFormatArr( *rSource.mpCharFormatTable, *mpCharFormatTable,
1553                 &SwDoc::MakeCharFormat_, *mpDfltCharFormat );
1554     CopyFormatArr( *rSource.mpFrameFormatTable, *mpFrameFormatTable,
1555                 &SwDoc::MakeFrameFormat_, *mpDfltFrameFormat );
1556     CopyFormatArr( *rSource.mpTextFormatCollTable, *mpTextFormatCollTable,
1557                 &SwDoc::MakeTextFormatColl_, *mpDfltTextFormatColl );
1558 
1559     //To-Do:
1560     //  a) in rtf export don't export our hideous pgdsctbl
1561     //  extension to rtf anymore
1562     //  b) in sd rtf import (View::InsertData) don't use
1563     //  a super-fragile test for mere presence of \trowd to
1564     //  indicate import of rtf into a table
1565     //  c) then drop use of bIncludePageStyles
1566     if (bIncludePageStyles)
1567     {
1568         // and now the page templates
1569         SwPageDescs::size_type nCnt = rSource.m_PageDescs.size();
1570         if( nCnt )
1571         {
1572             // a different Doc -> Number formatter needs to be merged
1573             SwTableNumFormatMerge aTNFM( rSource, *this );
1574 
1575             // 1st step: Create all formats (skip the 0th - it's the default!)
1576             while( nCnt )
1577             {
1578                 const SwPageDesc &rSrc = *rSource.m_PageDescs[ --nCnt ];
1579                 if( nullptr == FindPageDesc( rSrc.GetName() ) )
1580                     MakePageDesc( rSrc.GetName() );
1581             }
1582 
1583             // 2nd step: Copy all attributes, set the right parents
1584             for (SwPageDescs::size_type i = rSource.m_PageDescs.size(); i; )
1585             {
1586                 const SwPageDesc &rSrc = *rSource.m_PageDescs[ --i ];
1587                 SwPageDesc* pDesc = FindPageDesc( rSrc.GetName() );
1588                 CopyPageDesc( rSrc, *pDesc);
1589             }
1590         }
1591     }
1592 
1593     // then there are the numbering templates
1594     const SwNumRuleTable::size_type nCnt = rSource.GetNumRuleTable().size();
1595     if( nCnt )
1596     {
1597         const SwNumRuleTable& rArr = rSource.GetNumRuleTable();
1598         for( SwNumRuleTable::size_type n = 0; n < nCnt; ++n )
1599         {
1600             const SwNumRule& rR = *rArr[ n ];
1601             SwNumRule* pNew = FindNumRulePtr( rR.GetName());
1602             if( pNew )
1603                 pNew->CopyNumRule( this, rR );
1604             else
1605             {
1606                 if( !rR.IsAutoRule() )
1607                     MakeNumRule( rR.GetName(), &rR );
1608                 else
1609                 {
1610                     // as we reset all styles, there shouldn't be any unknown
1611                     // automatic SwNumRules, because all should have been
1612                     // created by the style copying!
1613                     // So just warn and ignore.
1614                     SAL_WARN( "sw.core", "Found unknown auto SwNumRule during reset!" );
1615                 }
1616             }
1617         }
1618     }
1619 
1620     if (undoGuard.UndoWasEnabled())
1621     {
1622         // nodes array was modified!
1623         GetIDocumentUndoRedo().DelAllUndoObj();
1624     }
1625 
1626     getIDocumentState().SetModified();
1627 }
1628 
1629 SwFormat* SwDoc::FindFormatByName( const SwFormatsBase& rFormatArr,
1630                                    const OUString& rName )
1631 {
1632     SwFormat* pFnd = nullptr;
1633     for( size_t n = 0; n < rFormatArr.GetFormatCount(); ++n )
1634     {
1635         // Does the Doc already contain the template?
1636         if( rFormatArr.GetFormat(n)->HasName( rName ) )
1637         {
1638             pFnd = rFormatArr.GetFormat(n);
1639             break;
1640         }
1641     }
1642     return pFnd;
1643 }
1644 
1645 void SwDoc::MoveLeftMargin(const SwPaM& rPam, bool bRight, bool bModulus,
1646         SwRootFrame const*const pLayout)
1647 {
1648     SwHistory* pHistory = nullptr;
1649     if (GetIDocumentUndoRedo().DoesUndo())
1650     {
1651         std::unique_ptr<SwUndoMoveLeftMargin> pUndo(new SwUndoMoveLeftMargin( rPam, bRight,
1652                                                                 bModulus ));
1653         pHistory = &pUndo->GetHistory();
1654         GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
1655     }
1656 
1657     const SvxTabStopItem& rTabItem = GetDefault( RES_PARATR_TABSTOP );
1658     const sal_Int32 nDefDist = rTabItem.Count() ? rTabItem[0].GetTabPos() : 1134;
1659     const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
1660     SwNodeIndex aIdx( rStt.nNode );
1661     while( aIdx <= rEnd.nNode )
1662     {
1663         SwTextNode* pTNd = aIdx.GetNode().GetTextNode();
1664         if( pTNd )
1665         {
1666             pTNd = sw::GetParaPropsNode(*pLayout, aIdx);
1667             SvxLRSpaceItem aLS( static_cast<const SvxLRSpaceItem&>(pTNd->SwContentNode::GetAttr( RES_LR_SPACE )) );
1668 
1669             // #i93873# See also lcl_MergeListLevelIndentAsLRSpaceItem in thints.cxx
1670             if ( pTNd->AreListLevelIndentsApplicable() )
1671             {
1672                 const SwNumRule* pRule = pTNd->GetNumRule();
1673                 if ( pRule )
1674                 {
1675                     const int nListLevel = pTNd->GetActualListLevel();
1676                     if ( nListLevel >= 0 )
1677                     {
1678                         const SwNumFormat& rFormat = pRule->Get(static_cast<sal_uInt16>(nListLevel));
1679                         if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1680                         {
1681                             aLS.SetTextLeft( rFormat.GetIndentAt() );
1682                             aLS.SetTextFirstLineOfst( static_cast<short>(rFormat.GetFirstLineIndent()) );
1683                         }
1684                     }
1685                 }
1686             }
1687 
1688             long nNext = aLS.GetTextLeft();
1689             if( bModulus )
1690                 nNext = ( nNext / nDefDist ) * nDefDist;
1691 
1692             if( bRight )
1693                 nNext += nDefDist;
1694             else
1695                 if(nNext >0) // fdo#75936 set limit for decreasing indent
1696                     nNext -= nDefDist;
1697 
1698             aLS.SetTextLeft( nNext );
1699 
1700             SwRegHistory aRegH( pTNd, *pTNd, pHistory );
1701             pTNd->SetAttr( aLS );
1702             aIdx = *sw::GetFirstAndLastNode(*pLayout, aIdx).second;
1703         }
1704         ++aIdx;
1705     }
1706     getIDocumentState().SetModified();
1707 }
1708 
1709 bool SwDoc::DontExpandFormat( const SwPosition& rPos, bool bFlag )
1710 {
1711     bool bRet = false;
1712     SwTextNode* pTextNd = rPos.nNode.GetNode().GetTextNode();
1713     if( pTextNd )
1714     {
1715         bRet = pTextNd->DontExpandFormat( rPos.nContent, bFlag );
1716         if( bRet && GetIDocumentUndoRedo().DoesUndo() )
1717         {
1718             GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoDontExpandFormat>(rPos) );
1719         }
1720     }
1721     return bRet;
1722 }
1723 
1724 SwTableBoxFormat* SwDoc::MakeTableBoxFormat()
1725 {
1726     SwTableBoxFormat* pFormat = new SwTableBoxFormat( GetAttrPool(), mpDfltFrameFormat.get() );
1727     getIDocumentState().SetModified();
1728     return pFormat;
1729 }
1730 
1731 SwTableLineFormat* SwDoc::MakeTableLineFormat()
1732 {
1733     SwTableLineFormat* pFormat = new SwTableLineFormat( GetAttrPool(), mpDfltFrameFormat.get() );
1734     getIDocumentState().SetModified();
1735     return pFormat;
1736 }
1737 
1738 void SwDoc::EnsureNumberFormatter()
1739 {
1740     comphelper::doubleCheckedInit(mpNumberFormatter, []()
1741     {
1742         LanguageType eLang = LANGUAGE_SYSTEM;
1743         SvNumberFormatter* pRet = new SvNumberFormatter(comphelper::getProcessComponentContext(), eLang);
1744         pRet->SetEvalDateFormat( NF_EVALDATEFORMAT_FORMAT_INTL );
1745         if (!utl::ConfigManager::IsFuzzing())
1746             pRet->SetYear2000(static_cast<sal_uInt16>(::utl::MiscCfg().GetYear2000()));
1747         return pRet;
1748     });
1749 }
1750 
1751 SwTableNumFormatMerge::SwTableNumFormatMerge( const SwDoc& rSrc, SwDoc& rDest )
1752     : pNFormat( nullptr )
1753 {
1754     // a different Doc -> Number formatter needs to be merged
1755     SvNumberFormatter* pN;
1756     if( &rSrc != &rDest && nullptr != ( pN = const_cast<SwDoc&>(rSrc).GetNumberFormatter( false ) ))
1757     {
1758         pNFormat = rDest.GetNumberFormatter();
1759         pNFormat->MergeFormatter( *pN );
1760     }
1761 
1762     if( &rSrc != &rDest )
1763         static_cast<SwGetRefFieldType*>(rSrc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::GetRef ))->
1764             MergeWithOtherDoc( rDest );
1765 }
1766 
1767 SwTableNumFormatMerge::~SwTableNumFormatMerge()
1768 {
1769     if( pNFormat )
1770         pNFormat->ClearMergeTable();
1771 }
1772 
1773 void SwDoc::SetTextFormatCollByAutoFormat( const SwPosition& rPos, sal_uInt16 nPoolId,
1774                                     const SfxItemSet* pSet )
1775 {
1776     SwPaM aPam( rPos );
1777     SwTextNode* pTNd = rPos.nNode.GetNode().GetTextNode();
1778     assert(pTNd);
1779 
1780     if (mbIsAutoFormatRedline)
1781     {
1782         // create the redline object
1783         const SwTextFormatColl& rColl = *pTNd->GetTextColl();
1784         SwRangeRedline* pRedl = new SwRangeRedline( RedlineType::FmtColl, aPam );
1785         pRedl->SetMark();
1786 
1787         // Only those items that are not set by the Set again in the Node
1788         // are of interest. Thus, we take the difference.
1789         SwRedlineExtraData_FormatColl aExtraData( rColl.GetName(),
1790                                                 rColl.GetPoolFormatId() );
1791         if( pSet && pTNd->HasSwAttrSet() )
1792         {
1793             SfxItemSet aTmp( *pTNd->GetpSwAttrSet() );
1794             aTmp.Differentiate( *pSet );
1795             // we handle the adjust item separately
1796             const SfxPoolItem* pItem;
1797             if( SfxItemState::SET == pTNd->GetpSwAttrSet()->GetItemState(
1798                     RES_PARATR_ADJUST, false, &pItem ))
1799                 aTmp.Put( *pItem );
1800             aExtraData.SetItemSet( aTmp );
1801         }
1802         pRedl->SetExtraData( &aExtraData );
1803 
1804         //TODO: Undo is still missing!
1805         getIDocumentRedlineAccess().AppendRedline( pRedl, true );
1806     }
1807 
1808     SetTextFormatColl( aPam, getIDocumentStylePoolAccess().GetTextCollFromPool( nPoolId ) );
1809 
1810     if (pSet && pSet->Count())
1811     {
1812         aPam.SetMark();
1813         aPam.GetMark()->nContent.Assign(pTNd, pTNd->GetText().getLength());
1814         // sw_redlinehide: don't need layout currently because the only caller
1815         // passes in the properties node
1816         assert(static_cast<SwTextFrame const*>(pTNd->getLayoutFrame(nullptr))->GetTextNodeForParaProps() == pTNd);
1817         getIDocumentContentOperations().InsertItemSet( aPam, *pSet );
1818     }
1819 }
1820 
1821 void SwDoc::SetFormatItemByAutoFormat( const SwPaM& rPam, const SfxItemSet& rSet )
1822 {
1823     SwTextNode* pTNd = rPam.GetPoint()->nNode.GetNode().GetTextNode();
1824     assert(pTNd);
1825 
1826     RedlineFlags eOld = getIDocumentRedlineAccess().GetRedlineFlags();
1827 
1828     if (mbIsAutoFormatRedline)
1829     {
1830         // create the redline object
1831         SwRangeRedline* pRedl = new SwRangeRedline( RedlineType::Format, rPam );
1832         if( !pRedl->HasMark() )
1833             pRedl->SetMark();
1834 
1835         // Only those items that are not set by the Set again in the Node
1836         // are of interest. Thus, we take the difference.
1837         SwRedlineExtraData_Format aExtraData( rSet );
1838 
1839         pRedl->SetExtraData( &aExtraData );
1840 
1841         //TODO: Undo is still missing!
1842         getIDocumentRedlineAccess().AppendRedline( pRedl, true );
1843 
1844         getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld | RedlineFlags::Ignore );
1845     }
1846 
1847     const sal_Int32 nEnd(rPam.End()->nContent.GetIndex());
1848     std::vector<sal_uInt16> whichIds;
1849     SfxItemIter iter(rSet);
1850     for (SfxPoolItem const* pItem = iter.FirstItem();
1851             pItem; pItem = iter.NextItem())
1852     {
1853         whichIds.push_back(pItem->Which());
1854         whichIds.push_back(pItem->Which());
1855     }
1856     whichIds.push_back(0);
1857     SfxItemSet currentSet(GetAttrPool(), whichIds.data());
1858     pTNd->GetParaAttr(currentSet, nEnd, nEnd);
1859     for (size_t i = 0; whichIds[i]; i += 2)
1860     {   // yuk - want to explicitly set the pool defaults too :-/
1861         currentSet.Put(currentSet.Get(whichIds[i]));
1862     }
1863 
1864     getIDocumentContentOperations().InsertItemSet( rPam, rSet, SetAttrMode::DONTEXPAND );
1865 
1866     // fdo#62536: DONTEXPAND does not work when there is already an AUTOFMT
1867     // here, so insert the old attributes as an empty hint to stop expand
1868     SwPaM endPam(*pTNd, nEnd);
1869     endPam.SetMark();
1870     getIDocumentContentOperations().InsertItemSet(endPam, currentSet);
1871 
1872     getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
1873 }
1874 
1875 void SwDoc::ChgFormat(SwFormat & rFormat, const SfxItemSet & rSet)
1876 {
1877     if (GetIDocumentUndoRedo().DoesUndo())
1878     {
1879         // copying <rSet> to <aSet>
1880         SfxItemSet aSet(rSet);
1881         // remove from <aSet> all items, which are already set at the format
1882         aSet.Differentiate(rFormat.GetAttrSet());
1883         // <aSet> contains now all *new* items for the format
1884 
1885         // copying current format item set to <aOldSet>
1886         SfxItemSet aOldSet(rFormat.GetAttrSet());
1887         // insert new items into <aOldSet>
1888         aOldSet.Put(aSet);
1889         // invalidate all new items in <aOldSet> in order to clear these items,
1890         // if the undo action is triggered.
1891         {
1892             SfxItemIter aIter(aSet);
1893 
1894             const SfxPoolItem * pItem = aIter.FirstItem();
1895             while (pItem != nullptr)
1896             {
1897                 aOldSet.InvalidateItem(pItem->Which());
1898 
1899                 pItem = aIter.NextItem();
1900             }
1901         }
1902 
1903         GetIDocumentUndoRedo().AppendUndo(
1904             std::make_unique<SwUndoFormatAttr>(aOldSet, rFormat, /*bSaveDrawPt*/true));
1905     }
1906 
1907     rFormat.SetFormatAttr(rSet);
1908 }
1909 
1910 void SwDoc::RenameFormat(SwFormat & rFormat, const OUString & sNewName,
1911                       bool bBroadcast)
1912 {
1913     SfxStyleFamily eFamily = SfxStyleFamily::All;
1914 
1915     if (GetIDocumentUndoRedo().DoesUndo())
1916     {
1917         std::unique_ptr<SwUndo> pUndo;
1918 
1919         switch (rFormat.Which())
1920         {
1921         case RES_CHRFMT:
1922             pUndo.reset(new SwUndoRenameCharFormat(rFormat.GetName(), sNewName, this));
1923             eFamily = SfxStyleFamily::Char;
1924             break;
1925         case RES_TXTFMTCOLL:
1926             pUndo.reset(new SwUndoRenameFormatColl(rFormat.GetName(), sNewName, this));
1927             eFamily = SfxStyleFamily::Para;
1928             break;
1929         case RES_FRMFMT:
1930             pUndo.reset(new SwUndoRenameFrameFormat(rFormat.GetName(), sNewName, this));
1931             eFamily = SfxStyleFamily::Frame;
1932             break;
1933 
1934         default:
1935             break;
1936         }
1937 
1938         if (pUndo)
1939         {
1940             GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
1941         }
1942     }
1943 
1944     rFormat.SetName(sNewName);
1945 
1946     if (bBroadcast)
1947         BroadcastStyleOperation(sNewName, eFamily, SfxHintId::StyleSheetModified);
1948 }
1949 
1950 void SwDoc::dumpAsXml(xmlTextWriterPtr pWriter) const
1951 {
1952     bool bOwns = false;
1953     if (!pWriter)
1954     {
1955         pWriter = xmlNewTextWriterFilename("nodes.xml", 0);
1956         xmlTextWriterSetIndent(pWriter,1);
1957         xmlTextWriterSetIndentString(pWriter, BAD_CAST("  "));
1958         xmlTextWriterStartDocument(pWriter, nullptr, nullptr, nullptr);
1959         bOwns = true;
1960     }
1961     xmlTextWriterStartElement(pWriter, BAD_CAST("SwDoc"));
1962     xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1963 
1964     m_pNodes->dumpAsXml(pWriter);
1965     maDBData.dumpAsXml(pWriter);
1966     mpMarkManager->dumpAsXml(pWriter);
1967     m_pUndoManager->dumpAsXml(pWriter);
1968     getIDocumentFieldsAccess().GetFieldTypes()->dumpAsXml(pWriter);
1969     mpTextFormatCollTable->dumpAsXml(pWriter);
1970     mpCharFormatTable->dumpAsXml(pWriter);
1971     mpFrameFormatTable->dumpAsXml(pWriter, "frmFormatTable");
1972     mpSpzFrameFormatTable->dumpAsXml(pWriter, "spzFrameFormatTable");
1973     mpSectionFormatTable->dumpAsXml(pWriter);
1974     mpNumRuleTable->dumpAsXml(pWriter);
1975     getIDocumentRedlineAccess().GetRedlineTable().dumpAsXml(pWriter);
1976     getIDocumentRedlineAccess().GetExtraRedlineTable().dumpAsXml(pWriter);
1977     if (const SdrModel* pModel = getIDocumentDrawModelAccess().GetDrawModel())
1978         pModel->dumpAsXml(pWriter);
1979 
1980     xmlTextWriterStartElement(pWriter, BAD_CAST("mbModified"));
1981     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(getIDocumentState().IsModified()).getStr()));
1982     xmlTextWriterEndElement(pWriter);
1983 
1984     xmlTextWriterEndElement(pWriter);
1985     if (bOwns)
1986     {
1987         xmlTextWriterEndDocument(pWriter);
1988         xmlFreeTextWriter(pWriter);
1989     }
1990 }
1991 
1992 void SwDBData::dumpAsXml(xmlTextWriterPtr pWriter) const
1993 {
1994     xmlTextWriterStartElement(pWriter, BAD_CAST("SwDBData"));
1995 
1996     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("sDataSource"), BAD_CAST(sDataSource.toUtf8().getStr()));
1997     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("sCommand"), BAD_CAST(sCommand.toUtf8().getStr()));
1998     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nCommandType"), BAD_CAST(OString::number(nCommandType).getStr()));
1999 
2000     xmlTextWriterEndElement(pWriter);
2001 }
2002 
2003 std::set<Color> SwDoc::GetDocColors()
2004 {
2005     std::set<Color> aDocColors;
2006     SwAttrPool& rPool = GetAttrPool();
2007     const sal_uInt16 pAttribs[] = {RES_CHRATR_COLOR, RES_CHRATR_HIGHLIGHT, RES_BACKGROUND};
2008     for (sal_uInt16 nAttrib : pAttribs)
2009     {
2010         for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(nAttrib))
2011         {
2012             auto pColorItem = static_cast<const SvxColorItem*>(pItem);
2013             Color aColor( pColorItem->GetValue() );
2014             if (COL_AUTO != aColor)
2015                 aDocColors.insert(aColor);
2016         }
2017     }
2018     return aDocColors;
2019 }
2020 
2021 // #i69627#
2022 namespace docfunc
2023 {
2024     bool HasOutlineStyleToBeWrittenAsNormalListStyle( SwDoc& rDoc )
2025     {
2026         // If a parent paragraph style of one of the paragraph styles, which
2027         // are assigned to the list levels of the outline style, has a list style
2028         // set or inherits a list style from its parent style, the outline style
2029         // has to be written as a normal list style to the OpenDocument file
2030         // format or the OpenOffice.org file format.
2031         bool bRet( false );
2032 
2033         const SwTextFormatColls* pTextFormatColls( rDoc.GetTextFormatColls() );
2034         if ( pTextFormatColls )
2035         {
2036             for ( auto pTextFormatColl : *pTextFormatColls )
2037             {
2038                 if ( pTextFormatColl->IsDefault() ||
2039                     ! pTextFormatColl->IsAssignedToListLevelOfOutlineStyle() )
2040                 {
2041                     continue;
2042                 }
2043 
2044                 const SwTextFormatColl* pParentTextFormatColl =
2045                    dynamic_cast<const SwTextFormatColl*>( pTextFormatColl->DerivedFrom());
2046                 if ( !pParentTextFormatColl )
2047                     continue;
2048 
2049                 if ( SfxItemState::SET == pParentTextFormatColl->GetItemState( RES_PARATR_NUMRULE ) )
2050                 {
2051                     // #i106218# consider that the outline style is set
2052                     const SwNumRuleItem& rDirectItem = pParentTextFormatColl->GetNumRule();
2053                     if ( rDirectItem.GetValue() != rDoc.GetOutlineNumRule()->GetName() )
2054                     {
2055                         bRet = true;
2056                         break;
2057                     }
2058                 }
2059             }
2060 
2061         }
2062         return bRet;
2063     }
2064 }
2065 
2066 SwFrameFormats::SwFrameFormats()
2067     : m_PosIndex( m_Array.get<0>() )
2068     , m_TypeAndNameIndex( m_Array.get<1>() )
2069 {
2070 }
2071 
2072 SwFrameFormats::~SwFrameFormats()
2073 {
2074     DeleteAndDestroyAll();
2075 }
2076 
2077 SwFrameFormats::const_iterator SwFrameFormats::find( const value_type& x ) const
2078 {
2079     ByTypeAndName::iterator it = m_TypeAndNameIndex.find(
2080         boost::make_tuple(x->Which(), x->GetName(), x) );
2081     return m_Array.project<0>( it );
2082 }
2083 
2084 std::pair<SwFrameFormats::const_range_iterator,SwFrameFormats::const_range_iterator>
2085 SwFrameFormats::rangeFind( sal_uInt16 type, const OUString& name ) const
2086 {
2087     return m_TypeAndNameIndex.equal_range( boost::make_tuple(type, name) );
2088 }
2089 
2090 std::pair<SwFrameFormats::const_range_iterator,SwFrameFormats::const_range_iterator>
2091 SwFrameFormats::rangeFind( const value_type& x ) const
2092 {
2093     return rangeFind( x->Which(), x->GetName() );
2094 }
2095 
2096 void SwFrameFormats::DeleteAndDestroyAll( bool keepDefault )
2097 {
2098     if ( empty() )
2099         return;
2100     const int _offset = keepDefault ? 1 : 0;
2101     for( const_iterator it = begin() + _offset; it != end(); ++it )
2102         delete *it;
2103     if ( _offset )
2104         m_PosIndex.erase( begin() + _offset, end() );
2105     else
2106         m_Array.clear();
2107 }
2108 
2109 std::pair<SwFrameFormats::const_iterator,bool> SwFrameFormats::push_back( const value_type& x )
2110 {
2111     SAL_WARN_IF(x->m_ffList != nullptr, "sw.core", "Inserting already assigned item");
2112     assert(x->m_ffList == nullptr);
2113     x->m_ffList = this;
2114     return m_PosIndex.push_back( x );
2115 }
2116 
2117 bool SwFrameFormats::erase( const value_type& x )
2118 {
2119     const_iterator const ret = find( x );
2120     SAL_WARN_IF(x->m_ffList != this, "sw.core", "Removing invalid / unassigned item");
2121     if (ret != end()) {
2122         assert( x == *ret );
2123         m_PosIndex.erase( ret );
2124         x->m_ffList = nullptr;
2125         return true;
2126     }
2127     return false;
2128 }
2129 
2130 void SwFrameFormats::erase( size_type index_ )
2131 {
2132     erase( begin() + index_ );
2133 }
2134 
2135 void SwFrameFormats::erase( const_iterator const& position )
2136 {
2137     (*position)->m_ffList = nullptr;
2138     m_PosIndex.erase( begin() + (position - begin()) );
2139 }
2140 
2141 bool SwFrameFormats::ContainsFormat(const SwFrameFormat& x) const
2142 {
2143     return (x.m_ffList == this);
2144 }
2145 
2146 bool SwFrameFormats::IsAlive(SwFrameFormat const*const p) const
2147 {
2148     return find(const_cast<SwFrameFormat*>(p)) != end();
2149 }
2150 
2151 bool SwFrameFormats::newDefault( const value_type& x )
2152 {
2153     std::pair<iterator,bool> res = m_PosIndex.push_front( x );
2154     if( ! res.second )
2155         newDefault( res.first );
2156     return res.second;
2157 }
2158 
2159 void SwFrameFormats::newDefault( const_iterator const& position )
2160 {
2161     if (position == begin())
2162         return;
2163     m_PosIndex.relocate( begin(), position );
2164 }
2165 
2166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2167