1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <libxml/xmlwriter.h>
24 #include <svl/itemiter.hxx>
25 #include <editeng/formatbreakitem.hxx>
27 #include <hintids.hxx>
29 #include <fchrfmt.hxx>
30 #include <fmtflcnt.hxx>
31 #include <fmtrfmrk.hxx>
33 #include <fmtpdsc.hxx>
35 #include <txtrfmrk.hxx>
36 #include <txttxmrk.hxx>
38 #include <txtflcnt.hxx>
39 #include <fmtanchr.hxx>
40 #include <fmtcnct.hxx>
44 #include <IDocumentUndoRedo.hxx>
45 #include <IDocumentFieldsAccess.hxx>
46 #include <IDocumentLayoutAccess.hxx>
50 #include <cellatr.hxx>
53 #include <swtable.hxx>
54 #include <UndoCore.hxx>
56 #include <charfmt.hxx>
57 #include <strings.hrc>
58 #include <bookmark.hxx>
59 #include <frameformats.hxx>
63 OUString
SwHistoryHint::GetDescription() const
68 void SwHistoryHint::dumpAsXml(xmlTextWriterPtr pWriter
) const
70 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwHistoryHint"));
71 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
72 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("symbol"), BAD_CAST(typeid(*this).name()));
73 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("m_eWhichId"),
74 BAD_CAST(OString::number(m_eWhichId
).getStr()));
75 (void)xmlTextWriterEndElement(pWriter
);
78 SwHistorySetFormat::SwHistorySetFormat( const SfxPoolItem
* pFormatHt
, SwNodeOffset nNd
)
79 : SwHistoryHint( HSTRY_SETFMTHNT
)
80 , m_pAttr( pFormatHt
->Clone() )
83 switch ( m_pAttr
->Which() )
86 static_cast<SwFormatPageDesc
&>(*m_pAttr
).ChgDefinedIn( nullptr );
89 static_cast<SwFormatDrop
&>(*m_pAttr
).ChgDefinedIn(nullptr);
91 case RES_BOXATR_FORMULA
:
93 // save formulas always in plain text
94 SwTableBoxFormula
& rNew
= static_cast<SwTableBoxFormula
&>(*m_pAttr
);
95 if ( rNew
.IsIntrnlName() )
97 const SwTableBoxFormula
& rOld
=
98 *static_cast<const SwTableBoxFormula
*>(pFormatHt
);
99 const SwNode
* pNd
= rOld
.GetNodeOfFormula();
102 const SwTableNode
* pTableNode
= pNd
->FindTableNode();
105 auto pCpyTable
= const_cast<SwTable
*>(&pTableNode
->GetTable());
106 pCpyTable
->SwitchFormulasToExternalRepresentation();
107 rNew
.ChgDefinedIn(rOld
.GetDefinedIn());
108 rNew
.ToRelBoxNm(pCpyTable
);
112 rNew
.ChgDefinedIn( nullptr );
118 OUString
SwHistorySetFormat::GetDescription() const
122 switch (m_pAttr
->Which())
125 switch (static_cast<SvxFormatBreakItem
&>(*m_pAttr
).GetBreak())
127 case SvxBreak::PageBefore
:
128 case SvxBreak::PageAfter
:
129 case SvxBreak::PageBoth
:
130 aResult
= SwResId(STR_UNDO_PAGEBREAKS
);
133 case SvxBreak::ColumnBefore
:
134 case SvxBreak::ColumnAfter
:
135 case SvxBreak::ColumnBoth
:
136 aResult
= SwResId(STR_UNDO_COLBRKS
);
150 void SwHistorySetFormat::dumpAsXml(xmlTextWriterPtr pWriter
) const
152 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwHistorySetFormat"));
153 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("m_nNodeIndex"),
154 BAD_CAST(OString::number(sal_Int32(m_nNodeIndex
)).getStr()));
155 SwHistoryHint::dumpAsXml(pWriter
);
159 m_pAttr
->dumpAsXml(pWriter
);
162 (void)xmlTextWriterEndElement(pWriter
);
165 void SwHistorySetFormat::SetInDoc( SwDoc
* pDoc
, bool bTmpSet
)
167 SwNode
* pNode
= pDoc
->GetNodes()[ m_nNodeIndex
];
168 if ( pNode
->IsContentNode() )
170 static_cast<SwContentNode
*>(pNode
)->SetAttr( *m_pAttr
);
172 else if ( pNode
->IsTableNode() )
174 static_cast<SwTableNode
*>(pNode
)->GetTable().GetFrameFormat()->SetFormatAttr(
177 else if ( pNode
->IsStartNode() && (SwTableBoxStartNode
==
178 static_cast<SwStartNode
*>(pNode
)->GetStartNodeType()) )
180 SwTableNode
* pTNd
= pNode
->FindTableNode();
183 SwTableBox
* pBox
= pTNd
->GetTable().GetTableBox( m_nNodeIndex
);
186 pBox
->ClaimFrameFormat()->SetFormatAttr( *m_pAttr
);
197 SwHistorySetFormat::~SwHistorySetFormat()
201 SwHistoryResetFormat::SwHistoryResetFormat(const SfxPoolItem
* pFormatHt
, SwNodeOffset nNodeIdx
)
202 : SwHistoryHint( HSTRY_RESETFMTHNT
)
203 , m_nNodeIndex( nNodeIdx
)
204 , m_nWhich( pFormatHt
->Which() )
208 void SwHistoryResetFormat::SetInDoc( SwDoc
* pDoc
, bool )
210 SwNode
* pNode
= pDoc
->GetNodes()[ m_nNodeIndex
];
211 if ( pNode
->IsContentNode() )
213 static_cast<SwContentNode
*>(pNode
)->ResetAttr( m_nWhich
);
215 else if ( pNode
->IsTableNode() )
217 static_cast<SwTableNode
*>(pNode
)->GetTable().GetFrameFormat()->
218 ResetFormatAttr( m_nWhich
);
222 SwHistorySetText::SwHistorySetText( SwTextAttr
* pTextHt
, SwNodeOffset nNodePos
)
223 : SwHistoryHint( HSTRY_SETTXTHNT
)
224 , m_nNodeIndex( nNodePos
)
225 , m_nStart( pTextHt
->GetStart() )
226 , m_nEnd( pTextHt
->GetAnyEnd() )
227 , m_bFormatIgnoreStart(pTextHt
->IsFormatIgnoreStart())
228 , m_bFormatIgnoreEnd (pTextHt
->IsFormatIgnoreEnd ())
230 // Caution: the following attributes generate no format attributes:
231 // - NoLineBreak, NoHyphen, Inserted, Deleted
232 // These cases must be handled separately !!!
234 // a little bit complicated but works: first assign a copy of the
235 // default value and afterwards the values from text attribute
236 if ( RES_TXTATR_CHARFMT
== pTextHt
->Which() )
238 m_pAttr
.reset( new SwFormatCharFormat( pTextHt
->GetCharFormat().GetCharFormat() ) );
242 m_pAttr
.reset( pTextHt
->GetAttr().Clone() );
246 SwHistorySetText::~SwHistorySetText()
250 void SwHistorySetText::SetInDoc( SwDoc
* pDoc
, bool )
255 if ( RES_TXTATR_CHARFMT
== m_pAttr
->Which() )
257 // ask the Doc if the CharFormat still exists
258 if (!pDoc
->GetCharFormats()->ContainsFormat(static_cast<SwFormatCharFormat
&>(*m_pAttr
).GetCharFormat()))
259 return; // do not set, format does not exist
262 SwTextNode
* pTextNd
= pDoc
->GetNodes()[ m_nNodeIndex
]->GetTextNode();
263 OSL_ENSURE( pTextNd
, "SwHistorySetText::SetInDoc: not a TextNode" );
268 SwTextAttr
*const pAttr
= pTextNd
->InsertItem(*m_pAttr
, m_nStart
, m_nEnd
,
269 SetAttrMode::NOTXTATRCHR
|
270 SetAttrMode::NOHINTADJUST
);
271 // shouldn't be possible to hit any error/merging path from here
273 if (m_bFormatIgnoreStart
)
275 pAttr
->SetFormatIgnoreStart(true);
277 if (m_bFormatIgnoreEnd
)
279 pAttr
->SetFormatIgnoreEnd(true);
283 SwHistorySetTextField::SwHistorySetTextField( const SwTextField
* pTextField
, SwNodeOffset nNodePos
)
284 : SwHistoryHint( HSTRY_SETTXTFLDHNT
)
285 , m_pField( new SwFormatField( *pTextField
->GetFormatField().GetField() ) )
287 // only copy if not Sys-FieldType
288 SwDoc
& rDoc
= pTextField
->GetTextNode().GetDoc();
290 m_nFieldWhich
= m_pField
->GetField()->GetTyp()->Which();
291 if (m_nFieldWhich
== SwFieldIds::Database
||
292 m_nFieldWhich
== SwFieldIds::User
||
293 m_nFieldWhich
== SwFieldIds::SetExp
||
294 m_nFieldWhich
== SwFieldIds::Dde
||
295 !rDoc
.getIDocumentFieldsAccess().GetSysFieldType( m_nFieldWhich
))
297 m_pFieldType
= m_pField
->GetField()->GetTyp()->Copy();
298 m_pField
->GetField()->ChgTyp( m_pFieldType
.get() ); // change field type
300 m_nNodeIndex
= nNodePos
;
301 m_nPos
= pTextField
->GetStart();
304 OUString
SwHistorySetTextField::GetDescription() const
306 return m_pField
->GetField()->GetDescription();
309 SwHistorySetTextField::~SwHistorySetTextField()
313 void SwHistorySetTextField::SetInDoc( SwDoc
* pDoc
, bool )
318 SwFieldType
* pNewFieldType
= m_pFieldType
.get();
319 if ( !pNewFieldType
)
321 pNewFieldType
= pDoc
->getIDocumentFieldsAccess().GetSysFieldType( m_nFieldWhich
);
325 // register type with the document
326 pNewFieldType
= pDoc
->getIDocumentFieldsAccess().InsertFieldType( *m_pFieldType
);
329 m_pField
->GetField()->ChgTyp( pNewFieldType
); // change field type
331 SwTextNode
* pTextNd
= pDoc
->GetNodes()[ m_nNodeIndex
]->GetTextNode();
332 OSL_ENSURE( pTextNd
, "SwHistorySetTextField: no TextNode" );
336 pTextNd
->InsertItem( *m_pField
, m_nPos
, m_nPos
,
337 SetAttrMode::NOTXTATRCHR
);
341 SwHistorySetRefMark::SwHistorySetRefMark( const SwTextRefMark
* pTextHt
, SwNodeOffset nNodePos
)
342 : SwHistoryHint( HSTRY_SETREFMARKHNT
)
343 , m_RefName( pTextHt
->GetRefMark().GetRefName() )
344 , m_nNodeIndex( nNodePos
)
345 , m_nStart( pTextHt
->GetStart() )
346 , m_nEnd( pTextHt
->GetAnyEnd() )
350 void SwHistorySetRefMark::SetInDoc( SwDoc
* pDoc
, bool )
352 SwTextNode
* pTextNd
= pDoc
->GetNodes()[ m_nNodeIndex
]->GetTextNode();
353 OSL_ENSURE( pTextNd
, "SwHistorySetRefMark: no TextNode" );
357 SwFormatRefMark
aRefMark( m_RefName
);
359 // if a reference mark without an end already exists here: must not insert!
360 if ( m_nStart
!= m_nEnd
||
361 !pTextNd
->GetTextAttrForCharAt( m_nStart
, RES_TXTATR_REFMARK
) )
363 pTextNd
->InsertItem( aRefMark
, m_nStart
, m_nEnd
,
364 SetAttrMode::NOTXTATRCHR
);
368 SwHistorySetTOXMark::SwHistorySetTOXMark( const SwTextTOXMark
* pTextHt
, SwNodeOffset nNodePos
)
369 : SwHistoryHint( HSTRY_SETTOXMARKHNT
)
370 , m_TOXMark( pTextHt
->GetTOXMark() )
371 , m_TOXName( m_TOXMark
.GetTOXType()->GetTypeName() )
372 , m_eTOXTypes( m_TOXMark
.GetTOXType()->GetType() )
373 , m_nNodeIndex( nNodePos
)
374 , m_nStart( pTextHt
->GetStart() )
375 , m_nEnd( pTextHt
->GetAnyEnd() )
377 static_cast<SvtListener
*>(&m_TOXMark
)->EndListeningAll();
380 SwTOXType
* SwHistorySetTOXMark::GetSwTOXType(SwDoc
& rDoc
, TOXTypes eTOXTypes
, const OUString
& rTOXName
)
382 // search for respective TOX type
383 const sal_uInt16 nCnt
= rDoc
.GetTOXTypeCount(eTOXTypes
);
384 SwTOXType
* pToxType
= nullptr;
385 for ( sal_uInt16 n
= 0; n
< nCnt
; ++n
)
387 pToxType
= const_cast<SwTOXType
*>(rDoc
.GetTOXType(eTOXTypes
, n
));
388 if (pToxType
->GetTypeName() == rTOXName
)
393 if ( !pToxType
) // TOX type not found, create new
395 pToxType
= const_cast<SwTOXType
*>(
396 rDoc
.InsertTOXType(SwTOXType(rDoc
, eTOXTypes
, rTOXName
)));
402 void SwHistorySetTOXMark::SetInDoc( SwDoc
* pDoc
, bool )
404 SwTextNode
* pTextNd
= pDoc
->GetNodes()[ m_nNodeIndex
]->GetTextNode();
405 OSL_ENSURE( pTextNd
, "SwHistorySetTOXMark: no TextNode" );
409 SwTOXType
* pToxType
= GetSwTOXType(*pDoc
, m_eTOXTypes
, m_TOXName
);
411 SwTOXMark
aNew( m_TOXMark
);
412 aNew
.RegisterToTOXType( *pToxType
);
414 pTextNd
->InsertItem( aNew
, m_nStart
, m_nEnd
,
415 SetAttrMode::NOTXTATRCHR
);
418 bool SwHistorySetTOXMark::IsEqual( const SwTOXMark
& rCmp
) const
420 return m_TOXName
== rCmp
.GetTOXType()->GetTypeName() &&
421 m_eTOXTypes
== rCmp
.GetTOXType()->GetType() &&
422 m_TOXMark
.GetAlternativeText() == rCmp
.GetAlternativeText() &&
423 ( (TOX_INDEX
== m_eTOXTypes
)
424 ? ( m_TOXMark
.GetPrimaryKey() == rCmp
.GetPrimaryKey() &&
425 m_TOXMark
.GetSecondaryKey() == rCmp
.GetSecondaryKey() )
426 : m_TOXMark
.GetLevel() == rCmp
.GetLevel()
430 SwHistoryResetText::SwHistoryResetText( sal_uInt16 nWhich
,
431 sal_Int32 nAttrStart
, sal_Int32 nAttrEnd
, SwNodeOffset nNodePos
)
432 : SwHistoryHint( HSTRY_RESETTXTHNT
)
433 , m_nNodeIndex( nNodePos
), m_nStart( nAttrStart
), m_nEnd( nAttrEnd
)
438 void SwHistoryResetText::SetInDoc( SwDoc
* pDoc
, bool )
440 SwTextNode
* pTextNd
= pDoc
->GetNodes()[ m_nNodeIndex
]->GetTextNode();
441 OSL_ENSURE( pTextNd
, "SwHistoryResetText: no TextNode" );
444 pTextNd
->DeleteAttributes( m_nAttr
, m_nStart
, m_nEnd
);
448 SwHistorySetFootnote::SwHistorySetFootnote( SwTextFootnote
* pTextFootnote
, SwNodeOffset nNodePos
)
449 : SwHistoryHint( HSTRY_SETFTNHNT
)
450 , m_pUndo( new SwUndoSaveSection
)
451 , m_FootnoteNumber( pTextFootnote
->GetFootnote().GetNumStr() )
452 , m_nNodeIndex( nNodePos
)
453 , m_nStart( pTextFootnote
->GetStart() )
454 , m_bEndNote( pTextFootnote
->GetFootnote().IsEndNote() )
456 OSL_ENSURE( pTextFootnote
->GetStartNode(),
457 "SwHistorySetFootnote: Footnote without Section" );
459 // keep the old NodePos (because who knows what later will be saved/deleted
461 SwDoc
& rDoc
= const_cast<SwDoc
&>(pTextFootnote
->GetTextNode().GetDoc());
462 SwNode
* pSaveNd
= rDoc
.GetNodes()[ m_nNodeIndex
];
464 // keep pointer to StartNode of FootnoteSection and reset its attribute for now
465 // (as a result, its/all Frames will be deleted automatically)
466 SwNodeIndex
aSttIdx( *pTextFootnote
->GetStartNode() );
467 pTextFootnote
->SetStartNode( nullptr, false );
469 m_pUndo
->SaveSection( aSttIdx
);
470 m_nNodeIndex
= pSaveNd
->GetIndex();
473 SwHistorySetFootnote::SwHistorySetFootnote( const SwTextFootnote
&rTextFootnote
)
474 : SwHistoryHint( HSTRY_SETFTNHNT
)
475 , m_FootnoteNumber( rTextFootnote
.GetFootnote().GetNumStr() )
476 , m_nNodeIndex( SwTextFootnote_GetIndex( (&rTextFootnote
) ) )
477 , m_nStart( rTextFootnote
.GetStart() )
478 , m_bEndNote( rTextFootnote
.GetFootnote().IsEndNote() )
480 OSL_ENSURE( rTextFootnote
.GetStartNode(),
481 "SwHistorySetFootnote: Footnote without Section" );
484 OUString
SwHistorySetFootnote::GetDescription() const
486 return SwResId(STR_FOOTNOTE
);
489 SwHistorySetFootnote::~SwHistorySetFootnote()
493 void SwHistorySetFootnote::SetInDoc( SwDoc
* pDoc
, bool )
495 SwTextNode
* pTextNd
= pDoc
->GetNodes()[ m_nNodeIndex
]->GetTextNode();
496 OSL_ENSURE( pTextNd
, "SwHistorySetFootnote: no TextNode" );
502 // set the footnote in the TextNode
503 SwFormatFootnote
aTemp( m_bEndNote
);
504 SwFormatFootnote
& rNew
= const_cast<SwFormatFootnote
&>(
505 pDoc
->GetAttrPool().Put(aTemp
) );
506 if ( !m_FootnoteNumber
.isEmpty() )
508 rNew
.SetNumStr( m_FootnoteNumber
);
510 SwTextFootnote
* pTextFootnote
= new SwTextFootnote( rNew
, m_nStart
);
512 // create the section of the Footnote
513 SwNodeIndex
aIdx( *pTextNd
);
514 m_pUndo
->RestoreSection( pDoc
, &aIdx
, SwFootnoteStartNode
);
515 pTextFootnote
->SetStartNode( &aIdx
);
516 if ( m_pUndo
->GetHistory() )
518 // create frames only now
519 m_pUndo
->GetHistory()->Rollback( pDoc
);
522 pTextNd
->InsertHint( pTextFootnote
);
526 SwTextFootnote
* const pFootnote
=
527 static_cast<SwTextFootnote
*>(
528 pTextNd
->GetTextAttrForCharAt( m_nStart
));
530 SwFormatFootnote
&rFootnote
= const_cast<SwFormatFootnote
&>(pFootnote
->GetFootnote());
531 rFootnote
.SetNumStr( m_FootnoteNumber
);
532 if ( rFootnote
.IsEndNote() != m_bEndNote
)
534 rFootnote
.SetEndNote( m_bEndNote
);
535 pFootnote
->CheckCondColl();
540 SwHistoryChangeFormatColl::SwHistoryChangeFormatColl( SwFormatColl
* pFormatColl
, SwNodeOffset nNd
,
541 SwNodeType nNodeWhich
)
542 : SwHistoryHint( HSTRY_CHGFMTCOLL
)
543 , m_pColl( pFormatColl
)
544 , m_nNodeIndex( nNd
)
545 , m_nNodeType( nNodeWhich
)
549 void SwHistoryChangeFormatColl::SetInDoc( SwDoc
* pDoc
, bool )
551 SwContentNode
* pContentNd
= pDoc
->GetNodes()[ m_nNodeIndex
]->GetContentNode();
552 OSL_ENSURE( pContentNd
, "SwHistoryChangeFormatColl: no ContentNode" );
554 // before setting the format, check if it is still available in the
555 // document. if it has been deleted, there is no undo!
556 if ( !(pContentNd
&& m_nNodeType
== pContentNd
->GetNodeType()) )
559 if ( SwNodeType::Text
== m_nNodeType
)
561 if (pDoc
->GetTextFormatColls()->IsAlive(static_cast<SwTextFormatColl
*>(m_pColl
)))
563 pContentNd
->ChgFormatColl( m_pColl
);
566 else if (pDoc
->GetGrfFormatColls()->IsAlive(static_cast<SwGrfFormatColl
*>(m_pColl
)))
568 pContentNd
->ChgFormatColl( m_pColl
);
572 SwHistoryTextFlyCnt::SwHistoryTextFlyCnt( SwFrameFormat
* const pFlyFormat
)
573 : SwHistoryHint( HSTRY_FLYCNT
)
574 , m_pUndo( new SwUndoDelLayFormat( pFlyFormat
) )
576 OSL_ENSURE( pFlyFormat
, "SwHistoryTextFlyCnt: no Format" );
577 m_pUndo
->ChgShowSel( false );
580 SwHistoryTextFlyCnt::~SwHistoryTextFlyCnt()
584 void SwHistoryTextFlyCnt::SetInDoc( SwDoc
* pDoc
, bool )
586 ::sw::IShellCursorSupplier
*const pISCS(pDoc
->GetIShellCursorSupplier());
588 ::sw::UndoRedoContext
context(*pDoc
, *pISCS
);
589 m_pUndo
->UndoImpl(context
);
592 void SwHistoryTextFlyCnt::dumpAsXml(xmlTextWriterPtr pWriter
) const
594 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwHistoryTextFlyCnt"));
595 SwHistoryHint::dumpAsXml(pWriter
);
599 m_pUndo
->dumpAsXml(pWriter
);
602 (void)xmlTextWriterEndElement(pWriter
);
605 SwHistoryBookmark::SwHistoryBookmark(
606 const ::sw::mark::IMark
& rBkmk
,
609 : SwHistoryHint(HSTRY_BOOKMARK
)
610 , m_aName(rBkmk
.GetName())
613 rBkmk
.GetMarkPos().GetNodeIndex() : SwNodeOffset(0))
614 , m_nOtherNode(bSaveOtherPos
?
615 rBkmk
.GetOtherMarkPos().GetNodeIndex() : SwNodeOffset(0))
616 , m_nContent(bSavePos
?
617 rBkmk
.GetMarkPos().GetContentIndex() : 0)
618 , m_nOtherContent(bSaveOtherPos
?
619 rBkmk
.GetOtherMarkPos().GetContentIndex() :0)
620 , m_bSavePos(bSavePos
)
621 , m_bSaveOtherPos(bSaveOtherPos
)
622 , m_bHadOtherPos(rBkmk
.IsExpanded())
623 , m_eBkmkType(IDocumentMarkAccess::GetType(rBkmk
))
625 const ::sw::mark::IBookmark
* const pBookmark
= dynamic_cast< const ::sw::mark::IBookmark
* >(&rBkmk
);
629 m_aKeycode
= pBookmark
->GetKeyCode();
630 m_aShortName
= pBookmark
->GetShortName();
631 m_bHidden
= pBookmark
->IsHidden();
632 m_aHideCondition
= pBookmark
->GetHideCondition();
634 ::sfx2::Metadatable
const*const pMetadatable(
635 dynamic_cast< ::sfx2::Metadatable
const* >(pBookmark
));
638 m_pMetadataUndo
= pMetadatable
->CreateUndo();
642 void SwHistoryBookmark::SetInDoc( SwDoc
* pDoc
, bool )
644 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
646 SwNodes
& rNds
= pDoc
->GetNodes();
647 IDocumentMarkAccess
* pMarkAccess
= pDoc
->getIDocumentMarkAccess();
648 std::optional
<SwPaM
> pPam
;
649 ::sw::mark::IMark
* pMark
= nullptr;
653 SwContentNode
* const pContentNd
= rNds
[m_nNode
]->GetContentNode();
654 OSL_ENSURE(pContentNd
,
655 "<SwHistoryBookmark::SetInDoc(..)>"
656 " - wrong node for a mark");
658 // #111660# don't crash when nNode1 doesn't point to content node.
660 pPam
.emplace(*pContentNd
, m_nContent
);
664 pMark
= *pMarkAccess
->findMark(m_aName
);
665 pPam
.emplace(pMark
->GetMarkPos());
670 SwContentNode
* const pContentNd
= rNds
[m_nOtherNode
]->GetContentNode();
671 OSL_ENSURE(pContentNd
,
672 "<SwHistoryBookmark::SetInDoc(..)>"
673 " - wrong node for a mark");
675 if (pPam
&& pContentNd
)
678 pPam
->GetMark()->Assign(*pContentNd
, m_nOtherContent
);
681 else if(m_bHadOtherPos
)
684 pMark
= *pMarkAccess
->findMark(m_aName
);
685 OSL_ENSURE(pMark
->IsExpanded(),
686 "<SwHistoryBookmark::SetInDoc(..)>"
687 " - missing pos on old mark");
689 *pPam
->GetMark() = pMark
->GetOtherMarkPos();
695 if ( pMark
!= nullptr )
697 pMarkAccess
->deleteMark( pMark
);
699 ::sw::mark::IBookmark
* const pBookmark
=
700 dynamic_cast<::sw::mark::IBookmark
*>(
701 pMarkAccess
->makeMark(*pPam
, m_aName
, m_eBkmkType
, sw::mark::InsertMode::New
));
702 if ( pBookmark
== nullptr )
705 pBookmark
->SetKeyCode(m_aKeycode
);
706 pBookmark
->SetShortName(m_aShortName
);
707 pBookmark
->Hide(m_bHidden
);
708 pBookmark
->SetHideCondition(m_aHideCondition
);
712 ::sfx2::Metadatable
* const pMeta(
713 dynamic_cast< ::sfx2::Metadatable
* >(pBookmark
));
714 OSL_ENSURE(pMeta
, "metadata undo, but not metadatable?");
717 pMeta
->RestoreMetadata(m_pMetadataUndo
);
722 bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark
& rBkmk
)
724 return m_nNode
== rBkmk
.GetMarkPos().GetNodeIndex()
725 && m_nContent
== rBkmk
.GetMarkPos().GetContentIndex()
726 && m_aName
== rBkmk
.GetName();
729 SwHistoryNoTextFieldmark::SwHistoryNoTextFieldmark(const ::sw::mark::IFieldmark
& rFieldMark
)
730 : SwHistoryHint(HSTRY_NOTEXTFIELDMARK
)
731 , m_sType(rFieldMark
.GetFieldname())
732 , m_nNode(rFieldMark
.GetMarkStart().GetNodeIndex())
733 , m_nContent(rFieldMark
.GetMarkStart().GetContentIndex())
737 void SwHistoryNoTextFieldmark::SetInDoc(SwDoc
* pDoc
, bool)
739 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
741 SwNodes
& rNds
= pDoc
->GetNodes();
742 std::optional
<SwPaM
> pPam
;
744 const SwContentNode
* pContentNd
= rNds
[m_nNode
]->GetContentNode();
746 pPam
.emplace(*pContentNd
, m_nContent
);
750 IDocumentMarkAccess
* pMarkAccess
= pDoc
->getIDocumentMarkAccess();
751 pMarkAccess
->makeNoTextFieldBookmark(*pPam
, OUString(), m_sType
);
755 void SwHistoryNoTextFieldmark::ResetInDoc(SwDoc
& rDoc
)
757 ::sw::UndoGuard
const undoGuard(rDoc
.GetIDocumentUndoRedo());
759 SwNodes
& rNds
= rDoc
.GetNodes();
760 std::optional
<SwPaM
> pPam
;
762 const SwContentNode
* pContentNd
= rNds
[m_nNode
]->GetContentNode();
764 pPam
.emplace(*pContentNd
, m_nContent
);
768 IDocumentMarkAccess
* pMarkAccess
= rDoc
.getIDocumentMarkAccess();
769 pMarkAccess
->deleteFieldmarkAt(*pPam
->GetPoint());
773 SwHistoryTextFieldmark::SwHistoryTextFieldmark(const ::sw::mark::IFieldmark
& rFieldMark
)
774 : SwHistoryHint(HSTRY_TEXTFIELDMARK
)
775 , m_sName(rFieldMark
.GetName())
776 , m_sType(rFieldMark
.GetFieldname())
777 , m_nStartNode(rFieldMark
.GetMarkStart().GetNodeIndex())
778 , m_nStartContent(rFieldMark
.GetMarkStart().GetContentIndex())
779 , m_nEndNode(rFieldMark
.GetMarkEnd().GetNodeIndex())
780 , m_nEndContent(rFieldMark
.GetMarkEnd().GetContentIndex())
782 SwPosition
const sepPos(sw::mark::FindFieldSep(rFieldMark
));
783 m_nSepNode
= sepPos
.GetNodeIndex();
784 m_nSepContent
= sepPos
.GetContentIndex();
787 void SwHistoryTextFieldmark::SetInDoc(SwDoc
* pDoc
, bool)
789 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
791 SwNodes
& rNds
= pDoc
->GetNodes();
793 assert(rNds
[m_nStartNode
]->IsContentNode());
794 assert(rNds
[m_nEndNode
]->IsContentNode());
795 assert(rNds
[m_nSepNode
]->IsContentNode());
797 SwPaM
const pam(*rNds
[m_nStartNode
]->GetContentNode(), m_nStartContent
,
798 *rNds
[m_nEndNode
]->GetContentNode(),
799 // subtract 1 for the CH_TXT_ATR_FIELDEND itself,
800 // plus more if same node as other CH_TXT_ATR
801 m_nStartNode
== m_nEndNode
802 ? (m_nEndContent
- 3)
803 : m_nSepNode
== m_nEndNode
804 ? (m_nEndContent
- 2)
805 : (m_nEndContent
- 1));
806 SwPosition
const sepPos(*rNds
[m_nSepNode
]->GetContentNode(),
807 m_nStartNode
== m_nSepNode
? (m_nSepContent
- 1) : m_nSepContent
);
809 IDocumentMarkAccess
& rMarksAccess(*pDoc
->getIDocumentMarkAccess());
810 rMarksAccess
.makeFieldBookmark(pam
, m_sName
, m_sType
, &sepPos
);
813 void SwHistoryTextFieldmark::ResetInDoc(SwDoc
& rDoc
)
815 ::sw::UndoGuard
const undoGuard(rDoc
.GetIDocumentUndoRedo());
817 SwNodes
& rNds
= rDoc
.GetNodes();
819 assert(rNds
[m_nStartNode
]->IsContentNode());
820 assert(rNds
[m_nEndNode
]->IsContentNode());
821 assert(rNds
[m_nSepNode
]->IsContentNode());
823 SwPosition
const pos(*rNds
[m_nStartNode
]->GetContentNode(), m_nStartContent
);
825 IDocumentMarkAccess
& rMarksAccess(*rDoc
.getIDocumentMarkAccess());
826 rMarksAccess
.deleteFieldmarkAt(pos
);
829 SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet
& rSet
,
830 SwNodeOffset nNodePos
, const o3tl::sorted_vector
<sal_uInt16
> &rSetArr
)
831 : SwHistoryHint( HSTRY_SETATTRSET
)
833 , m_ResetArray( 0, 4 )
834 , m_nNodeIndex( nNodePos
)
836 SfxItemIter
aIter( m_OldSet
), aOrigIter( rSet
);
837 const SfxPoolItem
* pItem
= aIter
.GetCurItem(),
838 * pOrigItem
= aOrigIter
.GetCurItem();
839 while (pItem
&& pOrigItem
)
841 if( !rSetArr
.count( pOrigItem
->Which() ))
843 m_ResetArray
.push_back( pOrigItem
->Which() );
844 m_OldSet
.ClearItem( pOrigItem
->Which() );
848 switch ( pItem
->Which() )
851 static_cast<SwFormatPageDesc
*>(
852 const_cast<SfxPoolItem
*>(pItem
))->ChgDefinedIn( nullptr );
855 case RES_PARATR_DROP
:
856 static_cast<SwFormatDrop
*>(
857 const_cast<SfxPoolItem
*>(pItem
))->ChgDefinedIn(nullptr);
860 case RES_BOXATR_FORMULA
:
862 // When a formula is set, never save the value. It
863 // possibly must be recalculated!
864 // Save formulas always in plain text
865 m_OldSet
.ClearItem( RES_BOXATR_VALUE
);
867 SwTableBoxFormula
& rNew
=
868 *static_cast<SwTableBoxFormula
*>(
869 const_cast<SfxPoolItem
*>(pItem
));
870 if ( rNew
.IsIntrnlName() )
872 const SwTableBoxFormula
& rOld
=
873 rSet
.Get( RES_BOXATR_FORMULA
);
874 const SwNode
* pNd
= rOld
.GetNodeOfFormula();
877 const SwTableNode
* pTableNode
878 = pNd
->FindTableNode();
881 auto pCpyTable
= const_cast<SwTable
*>(&pTableNode
->GetTable());
882 pCpyTable
->SwitchFormulasToExternalRepresentation();
883 rNew
.ChgDefinedIn(rOld
.GetDefinedIn());
884 rNew
.PtrToBoxNm(pCpyTable
);
888 rNew
.ChgDefinedIn( nullptr );
894 pItem
= aIter
.NextItem();
895 pOrigItem
= aOrigIter
.NextItem();
899 void SwHistorySetAttrSet::SetInDoc( SwDoc
* pDoc
, bool )
901 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
903 SwNode
* pNode
= pDoc
->GetNodes()[ m_nNodeIndex
];
904 if ( pNode
->IsContentNode() )
906 static_cast<SwContentNode
*>(pNode
)->SetAttr( m_OldSet
);
907 if ( !m_ResetArray
.empty() )
909 static_cast<SwContentNode
*>(pNode
)->ResetAttr( m_ResetArray
);
912 else if ( pNode
->IsTableNode() )
915 *static_cast<SwTableNode
*>(pNode
)->GetTable().GetFrameFormat();
916 rFormat
.SetFormatAttr( m_OldSet
);
917 if ( !m_ResetArray
.empty() )
919 rFormat
.ResetFormatAttr( m_ResetArray
.front() );
924 SwHistoryChangeFlyAnchor::SwHistoryChangeFlyAnchor(sw::SpzFrameFormat
& rFormat
)
925 : SwHistoryHint( HSTRY_CHGFLYANCHOR
)
927 , m_nOldNodeIndex( rFormat
.GetAnchor().GetAnchorNode()->GetIndex() )
928 , m_nOldContentIndex( (RndStdIds::FLY_AT_CHAR
== rFormat
.GetAnchor().GetAnchorId())
929 ? rFormat
.GetAnchor().GetAnchorContentOffset()
934 void SwHistoryChangeFlyAnchor::SetInDoc( SwDoc
* pDoc
, bool )
936 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
938 // One would expect m_rFormat to only contain FlyFormats, given the name of
939 // this class, but apparently it is also used for DrawFormats.
940 if (!pDoc
->GetSpzFrameFormats()->IsAlive(&m_rFormat
)) // Format does still exist
943 SwFormatAnchor
aTmp( m_rFormat
.GetAnchor() );
945 SwNode
* pNd
= pDoc
->GetNodes()[ m_nOldNodeIndex
];
946 SwContentNode
* pCNd
= pNd
->GetContentNode();
947 SwPosition
aPos( *pNd
);
948 if ( COMPLETE_STRING
!= m_nOldContentIndex
)
949 aPos
.SetContent( m_nOldContentIndex
);
950 aTmp
.SetAnchor( &aPos
);
952 // so the Layout does not get confused
953 if (!pCNd
->getLayoutFrame(pDoc
->getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, nullptr))
955 m_rFormat
.DelFrames();
958 m_rFormat
.SetFormatAttr( aTmp
);
961 SwHistoryChangeFlyChain::SwHistoryChangeFlyChain( SwFlyFrameFormat
& rFormat
,
962 const SwFormatChain
& rAttr
)
963 : SwHistoryHint( HSTRY_CHGFLYCHAIN
)
964 , m_pPrevFormat( rAttr
.GetPrev() )
965 , m_pNextFormat( rAttr
.GetNext() )
966 , m_pFlyFormat( &rFormat
)
970 void SwHistoryChangeFlyChain::SetInDoc( SwDoc
* pDoc
, bool )
972 if (!pDoc
->GetSpzFrameFormats()->IsAlive(m_pFlyFormat
))
975 SwFormatChain aChain
;
978 pDoc
->GetSpzFrameFormats()->IsAlive(m_pPrevFormat
))
980 aChain
.SetPrev( m_pPrevFormat
);
981 SwFormatChain
aTmp( m_pPrevFormat
->GetChain() );
982 aTmp
.SetNext( m_pFlyFormat
);
983 m_pPrevFormat
->SetFormatAttr( aTmp
);
987 pDoc
->GetSpzFrameFormats()->IsAlive(m_pNextFormat
))
989 aChain
.SetNext( m_pNextFormat
);
990 SwFormatChain
aTmp( m_pNextFormat
->GetChain() );
991 aTmp
.SetPrev( m_pFlyFormat
);
992 m_pNextFormat
->SetFormatAttr( aTmp
);
995 if ( aChain
.GetNext() || aChain
.GetPrev() )
997 m_pFlyFormat
->SetFormatAttr( aChain
);
1002 SwHistoryChangeCharFormat::SwHistoryChangeCharFormat(SfxItemSet aSet
,
1004 : SwHistoryHint(HSTRY_CHGCHARFMT
)
1005 , m_OldSet(std::move(aSet
)), m_Format(std::move(sFormat
))
1009 void SwHistoryChangeCharFormat::SetInDoc(SwDoc
* pDoc
, bool )
1011 SwCharFormat
* pCharFormat
= pDoc
->FindCharFormatByName(m_Format
);
1015 pCharFormat
->SetFormatAttr(m_OldSet
);
1020 SwHistory::SwHistory()
1025 SwHistory::~SwHistory()
1029 void SwHistory::Add(
1030 const SfxPoolItem
* pOldValue
,
1031 const SfxPoolItem
* pNewValue
,
1032 SwNodeOffset nNodeIdx
)
1034 OSL_ENSURE( !m_nEndDiff
, "History was not deleted after REDO" );
1035 const sal_uInt16
nWhich(pNewValue
->Which());
1038 if(nWhich
== RES_TXTATR_FIELD
|| nWhich
== RES_TXTATR_ANNOTATION
)
1043 // no default Attribute?
1044 std::unique_ptr
<SwHistoryHint
> pHt
;
1046 // To be able to include the DrawingLayer FillItems something more
1047 // general has to be done to check if an Item is default than to check
1048 // if its pointer equals that in Writer's global PoolDefaults (held in
1049 // aAttrTab and used to fill the pool defaults in Writer - looks as if
1050 // Writer is *older* than the SfxItemPool ?). I checked the possibility to
1051 // get the SfxItemPool here (works), but decided to use the SfxPoolItem's
1052 // global tooling aka IsDefaultItem(const SfxPoolItem*) for now
1053 if(pOldValue
&& !IsDefaultItem(pOldValue
))
1055 pHt
.reset( new SwHistorySetFormat( pOldValue
, nNodeIdx
) );
1059 pHt
.reset( new SwHistoryResetFormat( pNewValue
, nNodeIdx
) );
1062 m_SwpHstry
.push_back( std::move(pHt
) );
1065 // FIXME: refactor the following "Add" methods (DRY)?
1066 void SwHistory::Add( SwTextAttr
* pHint
, SwNodeOffset nNodeIdx
, bool bNewAttr
)
1068 OSL_ENSURE( !m_nEndDiff
, "History was not deleted after REDO" );
1070 std::unique_ptr
<SwHistoryHint
> pHt
;
1073 switch ( pHint
->Which() )
1075 case RES_TXTATR_FTN
:
1076 pHt
.reset( new SwHistorySetFootnote(
1077 static_cast<SwTextFootnote
*>(pHint
), nNodeIdx
) );
1079 case RES_TXTATR_FLYCNT
:
1080 pHt
.reset( new SwHistoryTextFlyCnt( static_cast<SwTextFlyCnt
*>(pHint
)
1081 ->GetFlyCnt().GetFrameFormat() ) );
1083 case RES_TXTATR_FIELD
:
1084 case RES_TXTATR_ANNOTATION
:
1085 pHt
.reset( new SwHistorySetTextField(
1086 static_txtattr_cast
<SwTextField
*>(pHint
), nNodeIdx
) );
1088 case RES_TXTATR_TOXMARK
:
1089 pHt
.reset( new SwHistorySetTOXMark(
1090 static_txtattr_cast
<SwTextTOXMark
*>(pHint
), nNodeIdx
) );
1092 case RES_TXTATR_REFMARK
:
1093 pHt
.reset( new SwHistorySetRefMark(
1094 static_txtattr_cast
<SwTextRefMark
*>(pHint
), nNodeIdx
) );
1097 pHt
.reset( new SwHistorySetText( pHint
, nNodeIdx
) );
1102 pHt
.reset( new SwHistoryResetText( pHint
->Which(), pHint
->GetStart(),
1103 pHint
->GetAnyEnd(), nNodeIdx
) );
1105 m_SwpHstry
.push_back( std::move(pHt
) );
1108 void SwHistory::Add( SwFormatColl
* pColl
, SwNodeOffset nNodeIdx
, SwNodeType nWhichNd
)
1110 OSL_ENSURE( !m_nEndDiff
, "History was not deleted after REDO" );
1112 std::unique_ptr
<SwHistoryHint
> pHt(
1113 new SwHistoryChangeFormatColl( pColl
, nNodeIdx
, nWhichNd
));
1114 m_SwpHstry
.push_back( std::move(pHt
) );
1117 void SwHistory::Add(const ::sw::mark::IMark
& rBkmk
, bool bSavePos
, bool bSaveOtherPos
)
1119 OSL_ENSURE( !m_nEndDiff
, "History was not deleted after REDO" );
1121 std::unique_ptr
<SwHistoryHint
> pHt
;
1123 switch (IDocumentMarkAccess::GetType(rBkmk
))
1125 case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK
:
1126 case IDocumentMarkAccess::MarkType::DATE_FIELDMARK
:
1127 assert(bSavePos
&& bSaveOtherPos
); // must be deleted completely!
1128 pHt
.reset(new SwHistoryTextFieldmark(dynamic_cast<sw::mark::IFieldmark
const&>(rBkmk
)));
1130 case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK
:
1131 case IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK
:
1132 assert(bSavePos
&& bSaveOtherPos
); // must be deleted completely!
1133 pHt
.reset(new SwHistoryNoTextFieldmark(dynamic_cast<sw::mark::IFieldmark
const&>(rBkmk
)));
1136 pHt
.reset(new SwHistoryBookmark(rBkmk
, bSavePos
, bSaveOtherPos
));
1141 m_SwpHstry
.push_back( std::move(pHt
) );
1144 void SwHistory::AddChangeFlyAnchor(sw::SpzFrameFormat
& rFormat
)
1146 std::unique_ptr
<SwHistoryHint
> pHt(new SwHistoryChangeFlyAnchor(rFormat
));
1147 m_SwpHstry
.push_back( std::move(pHt
) );
1150 void SwHistory::AddDeleteFly(SwFrameFormat
& rFormat
, sal_uInt16
& rSetPos
)
1152 OSL_ENSURE( !m_nEndDiff
, "History was not deleted after REDO" );
1154 const sal_uInt16 nWh
= rFormat
.Which();
1157 assert((RES_FLYFRMFMT
== nWh
&& dynamic_cast<SwFlyFrameFormat
*>(&rFormat
))
1158 || (RES_DRAWFRMFMT
== nWh
&& dynamic_cast<SwDrawFrameFormat
*>(&rFormat
)));
1160 std::unique_ptr
<SwHistoryHint
> pHint(new SwHistoryTextFlyCnt( &rFormat
));
1161 m_SwpHstry
.push_back( std::move(pHint
) );
1163 if( const SwFormatChain
* pChainItem
= rFormat
.GetItemIfSet( RES_CHAIN
, false ) )
1165 assert(RES_FLYFRMFMT
== nWh
); // not supported on SdrObjects
1166 if( pChainItem
->GetNext() || pChainItem
->GetPrev() )
1168 std::unique_ptr
<SwHistoryHint
> pHt(
1169 new SwHistoryChangeFlyChain(static_cast<SwFlyFrameFormat
&>(rFormat
), *pChainItem
));
1170 m_SwpHstry
.insert( m_SwpHstry
.begin() + rSetPos
++, std::move(pHt
) );
1171 if ( pChainItem
->GetNext() )
1173 SwFormatChain
aTmp( pChainItem
->GetNext()->GetChain() );
1174 aTmp
.SetPrev( nullptr );
1175 pChainItem
->GetNext()->SetFormatAttr( aTmp
);
1177 if ( pChainItem
->GetPrev() )
1179 SwFormatChain
aTmp( pChainItem
->GetPrev()->GetChain() );
1180 aTmp
.SetNext( nullptr );
1181 pChainItem
->GetPrev()->SetFormatAttr( aTmp
);
1184 rFormat
.ResetFormatAttr( RES_CHAIN
);
1189 void SwHistory::Add( const SwTextFootnote
& rFootnote
)
1191 std::unique_ptr
<SwHistoryHint
> pHt(new SwHistorySetFootnote( rFootnote
));
1192 m_SwpHstry
.push_back( std::move(pHt
) );
1196 void SwHistory::Add(const SfxItemSet
& rSet
, const SwCharFormat
& rFormat
)
1198 std::unique_ptr
<SwHistoryHint
> pHt(new SwHistoryChangeCharFormat(rSet
, rFormat
.GetName()));
1199 m_SwpHstry
.push_back( std::move(pHt
) );
1202 bool SwHistory::Rollback( SwDoc
* pDoc
, sal_uInt16 nStart
)
1207 for ( sal_uInt16 i
= Count(); i
> nStart
; )
1209 SwHistoryHint
* pHHt
= m_SwpHstry
[ --i
].get();
1210 pHHt
->SetInDoc( pDoc
, false );
1212 m_SwpHstry
.erase( m_SwpHstry
.begin() + nStart
, m_SwpHstry
.end() );
1217 bool SwHistory::TmpRollback( SwDoc
* pDoc
, sal_uInt16 nStart
, bool bToFirst
)
1219 sal_uInt16 nEnd
= Count() - m_nEndDiff
;
1220 if ( !Count() || !nEnd
|| nStart
>= nEnd
)
1225 for ( ; nEnd
> nStart
; ++m_nEndDiff
)
1227 SwHistoryHint
* pHHt
= m_SwpHstry
[ --nEnd
].get();
1228 pHHt
->SetInDoc( pDoc
, true );
1233 for ( ; nStart
< nEnd
; ++m_nEndDiff
, ++nStart
)
1235 SwHistoryHint
* pHHt
= m_SwpHstry
[ nStart
].get();
1236 pHHt
->SetInDoc( pDoc
, true );
1242 sal_uInt16
SwHistory::SetTmpEnd( sal_uInt16 nNewTmpEnd
)
1244 OSL_ENSURE( nNewTmpEnd
<= Count(), "SwHistory::SetTmpEnd: out of bounds" );
1246 const sal_uInt16 nOld
= Count() - m_nEndDiff
;
1247 m_nEndDiff
= Count() - nNewTmpEnd
;
1249 // for every SwHistoryFlyCnt, call the Redo of its UndoObject.
1250 // this saves the formats of the flys!
1251 for ( sal_uInt16 n
= nOld
; n
< nNewTmpEnd
; n
++ )
1253 if ( HSTRY_FLYCNT
== (*this)[ n
]->Which() )
1255 static_cast<SwHistoryTextFlyCnt
*>((*this)[ n
])
1256 ->GetUDelLFormat()->RedoForRollback();
1263 void SwHistory::CopyFormatAttr(
1264 const SfxItemSet
& rSet
,
1265 SwNodeOffset nNodeIdx
)
1270 SfxItemIter
aIter(rSet
);
1271 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1274 if(!IsInvalidItem(pItem
))
1276 Add(pItem
, pItem
, nNodeIdx
);
1279 pItem
= aIter
.NextItem();
1284 void SwHistory::dumpAsXml(xmlTextWriterPtr pWriter
) const
1286 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwHistory"));
1287 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1289 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("m_SwpHstry"));
1290 for (const auto& pHistory
: m_SwpHstry
)
1292 pHistory
->dumpAsXml(pWriter
);
1294 (void)xmlTextWriterEndElement(pWriter
);
1296 (void)xmlTextWriterEndElement(pWriter
);
1299 void SwHistory::CopyAttr(
1300 SwpHints
const * pHts
,
1301 const SwNodeOffset nNodeIdx
,
1302 const sal_Int32 nStart
,
1303 const sal_Int32 nEnd
,
1304 const bool bCopyFields
)
1309 // copy all attributes of the TextNode in the area from nStart to nEnd
1311 for( size_t n
= 0; n
< pHts
->Count(); ++n
)
1313 // nAttrStt must even be set when !pEndIdx
1315 const sal_Int32 nAttrStt
= pHt
->GetStart();
1316 const sal_Int32
* pEndIdx
= pHt
->GetEnd();
1317 if( nullptr != pEndIdx
&& nAttrStt
> nEnd
)
1320 // never copy Flys and Footnote !!
1321 bool bNextAttr
= false;
1322 switch( pHt
->Which() )
1324 case RES_TXTATR_FIELD
:
1325 case RES_TXTATR_ANNOTATION
:
1326 case RES_TXTATR_INPUTFIELD
:
1330 case RES_TXTATR_FLYCNT
:
1331 case RES_TXTATR_FTN
:
1339 // save all attributes that are somehow in this area
1340 if ( nStart
<= nAttrStt
)
1342 if ( nEnd
> nAttrStt
)
1344 Add( pHt
, nNodeIdx
, false );
1347 else if ( pEndIdx
&& nStart
< *pEndIdx
)
1349 Add( pHt
, nNodeIdx
, false );
1354 // Class to register the history at a Node, Format, HintsArray, ...
1355 SwRegHistory::SwRegHistory( SwHistory
* pHst
)
1356 : SwClient( nullptr )
1357 , m_pHistory( pHst
)
1358 , m_nNodeIndex( NODE_OFFSET_MAX
)
1363 SwRegHistory::SwRegHistory( sw::BroadcastingModify
* pRegIn
, const SwNode
& rNd
,
1365 : SwClient( pRegIn
)
1366 , m_pHistory( pHst
)
1367 , m_nNodeIndex( rNd
.GetIndex() )
1372 SwRegHistory::SwRegHistory( const SwNode
& rNd
, SwHistory
* pHst
)
1373 : SwClient( nullptr )
1374 , m_pHistory( pHst
)
1375 , m_nNodeIndex( rNd
.GetIndex() )
1380 void SwRegHistory::SwClientNotify(const SwModify
&, const SfxHint
& rHint
)
1382 if (rHint
.GetId() != SfxHintId::SwLegacyModify
)
1384 auto pLegacyHint
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
1385 if ( !(m_pHistory
&& pLegacyHint
->m_pNew
&& pLegacyHint
->m_pOld
!= pLegacyHint
->m_pNew
) )
1388 if ( pLegacyHint
->m_pNew
->Which() < POOLATTR_END
)
1390 if(RES_UPDATE_ATTR
== pLegacyHint
->m_pNew
->Which())
1392 m_pHistory
->Add(pLegacyHint
->m_pOld
, pLegacyHint
->m_pNew
, m_nNodeIndex
);
1396 OSL_ENSURE(false, "Unexpected update attribute (!)");
1399 else if (pLegacyHint
->m_pOld
&& RES_ATTRSET_CHG
== pLegacyHint
->m_pNew
->Which())
1401 std::unique_ptr
<SwHistoryHint
> pNewHstr
;
1402 const SfxItemSet
& rSet
= *static_cast< const SwAttrSetChg
* >(pLegacyHint
->m_pOld
)->GetChgSet();
1404 if ( 1 < rSet
.Count() )
1406 pNewHstr
.reset( new SwHistorySetAttrSet( rSet
, m_nNodeIndex
, m_WhichIdSet
) );
1408 else if (const SfxPoolItem
* pItem
= SfxItemIter(rSet
).GetCurItem())
1410 if ( m_WhichIdSet
.count( pItem
->Which() ) )
1412 pNewHstr
.reset( new SwHistorySetFormat( pItem
, m_nNodeIndex
) );
1416 pNewHstr
.reset( new SwHistoryResetFormat( pItem
, m_nNodeIndex
) );
1421 m_pHistory
->m_SwpHstry
.push_back( std::move(pNewHstr
) );
1425 void SwRegHistory::AddHint( SwTextAttr
* pHt
, const bool bNew
)
1427 m_pHistory
->Add( pHt
, m_nNodeIndex
, bNew
);
1430 bool SwRegHistory::InsertItems( const SfxItemSet
& rSet
,
1431 sal_Int32
const nStart
, sal_Int32
const nEnd
, SetAttrMode
const nFlags
,
1432 SwTextAttr
**ppNewTextAttr
)
1437 SwTextNode
* const pTextNode
=
1438 dynamic_cast<SwTextNode
*>(GetRegisteredIn());
1440 OSL_ENSURE(pTextNode
, "SwRegHistory not registered at text node?");
1446 pTextNode
->GetOrCreateSwpHints().Register(this);
1449 const bool bInserted
= pTextNode
->SetAttr( rSet
, nStart
, nEnd
, nFlags
, ppNewTextAttr
);
1451 // Caution: The array can be deleted when inserting an attribute!
1452 // This can happen when the value that should be added first deletes
1453 // an existing attribute but does not need to be added itself because
1454 // the paragraph attributes are identical
1455 // ( -> bForgetAttr in SwpHints::Insert )
1456 if ( pTextNode
->GetpSwpHints() && m_pHistory
)
1458 pTextNode
->GetpSwpHints()->DeRegister();
1462 if ( m_pHistory
&& bInserted
)
1464 SfxItemIter
aIter(rSet
);
1465 for (SfxPoolItem
const* pItem
= aIter
.GetCurItem(); pItem
; pItem
= aIter
.NextItem())
1466 { // check that the history recorded a hint to reset every item
1467 sal_uInt16
const nWhich(pItem
->Which());
1468 sal_uInt16
const nExpected(
1469 (isCHRATR(nWhich
) || RES_TXTATR_UNKNOWN_CONTAINER
== nWhich
)
1470 ? RES_TXTATR_AUTOFMT
1472 if (RES_TXTATR_AUTOFMT
== nExpected
)
1473 continue; // special case, may get set on text node itself
1474 // tdf#105077 even worse, node's set could cause
1475 // nothing at all to be inserted
1477 m_pHistory
->m_SwpHstry
.begin(), m_pHistory
->m_SwpHstry
.end(),
1478 [nExpected
](std::unique_ptr
<SwHistoryHint
> const& pHint
) -> bool {
1479 SwHistoryResetText
const*const pReset(
1480 dynamic_cast<SwHistoryResetText
const*>(pHint
.get()));
1481 return pReset
&& (pReset
->GetWhich() == nExpected
);
1490 void SwRegHistory::RegisterInModify( sw::BroadcastingModify
* pRegIn
, const SwNode
& rNd
)
1492 if ( m_pHistory
&& pRegIn
)
1494 pRegIn
->Add( this );
1495 m_nNodeIndex
= rNd
.GetIndex();
1500 m_WhichIdSet
.clear();
1504 void SwRegHistory::MakeSetWhichIds()
1506 if (!m_pHistory
) return;
1508 m_WhichIdSet
.clear();
1510 if( !GetRegisteredIn() )
1513 const SfxItemSet
* pSet
= nullptr;
1514 if( auto pContentNode
= dynamic_cast< const SwContentNode
*>( GetRegisteredIn() ) )
1516 pSet
= pContentNode
->GetpSwAttrSet();
1518 else if ( auto pSwFormat
= dynamic_cast< const SwFormat
*>( GetRegisteredIn() ) )
1520 pSet
= &pSwFormat
->GetAttrSet();
1522 if( pSet
&& pSet
->Count() )
1524 SfxItemIter
aIter( *pSet
);
1525 for (const SfxPoolItem
* pItem
= aIter
.GetCurItem(); pItem
; pItem
= aIter
.NextItem())
1527 sal_uInt16 nW
= pItem
->Which();
1528 m_WhichIdSet
.insert( nW
);
1532 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */