1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <UndoInsert.hxx>
22 #include <hintids.hxx>
23 #include <unotools/charclass.hxx>
24 #include <editeng/keepitem.hxx>
25 #include <svx/svdobj.hxx>
26 #include <osl/diagnose.h>
28 #include <fmtcntnt.hxx>
31 #include <IDocumentUndoRedo.hxx>
32 #include <IDocumentDrawModelAccess.hxx>
33 #include <IDocumentRedlineAccess.hxx>
34 #include <IDocumentLayoutAccess.hxx>
35 #include <IShellCursorSupplier.hxx>
39 #include <UndoCore.hxx>
40 #include <UndoDelete.hxx>
41 #include <UndoAttribute.hxx>
49 #include <swtable.hxx>
50 #include <redline.hxx>
52 #include <acorrect.hxx>
54 #include <strings.hrc>
57 using namespace ::com::sun::star
;
61 std::optional
<OUString
> SwUndoInsert::GetTextFromDoc() const
63 std::optional
<OUString
> aResult
;
65 SwNodeIndex
aNd( m_pDoc
->GetNodes(), m_nNode
);
66 SwContentNode
* pCNd
= aNd
.GetNode().GetContentNode();
68 if( pCNd
->IsTextNode() )
70 OUString sText
= pCNd
->GetTextNode()->GetText();
72 sal_Int32 nStart
= m_nContent
-m_nLen
;
73 sal_Int32 nLength
= m_nLen
;
81 aResult
= sText
.copy(nStart
, nLength
);
87 void SwUndoInsert::Init(const SwNode
& rNd
)
90 m_pDoc
= const_cast<SwDoc
*>(&rNd
.GetDoc());
91 if( m_pDoc
->getIDocumentRedlineAccess().IsRedlineOn() )
93 m_pRedlData
.reset( new SwRedlineData( RedlineType::Insert
,
94 m_pDoc
->getIDocumentRedlineAccess().GetRedlineAuthor() ) );
95 SetRedlineFlags( m_pDoc
->getIDocumentRedlineAccess().GetRedlineFlags() );
98 maUndoText
= GetTextFromDoc();
100 m_bCacheComment
= false;
103 SwUndoInsert::SwUndoInsert( const SwNode
& rNd
, sal_Int32 nCnt
,
105 const SwInsertFlags nInsertFlags
,
107 : SwUndo(SwUndoId::TYPING
, &rNd
.GetDoc()),
108 m_nNode( rNd
.GetIndex() ), m_nContent(nCnt
), m_nLen(nL
),
109 m_bIsWordDelim( bWDelim
), m_bIsAppend( false )
111 , m_nInsertFlags(nInsertFlags
)
116 SwUndoInsert::SwUndoInsert( const SwNode
& rNd
)
117 : SwUndo(SwUndoId::SPLITNODE
, &rNd
.GetDoc()),
118 m_nNode( rNd
.GetIndex() ), m_nContent(0), m_nLen(1),
119 m_bIsWordDelim( false ), m_bIsAppend( true )
121 , m_nInsertFlags(SwInsertFlags::EMPTYEXPAND
)
126 // Check if the next Insert can be combined with the current one. If so
127 // change the length and InsPos. As a result, SwDoc::Insert will not add a
128 // new object into the Undo list.
130 bool SwUndoInsert::CanGrouping( sal_Unicode cIns
)
132 if( !m_bIsAppend
&& m_bIsWordDelim
==
133 !GetAppCharClass().isLetterNumeric( OUString( cIns
)) )
139 (*maUndoText
) += OUStringChar(cIns
);
146 bool SwUndoInsert::CanGrouping( const SwPosition
& rPos
)
149 if( m_nNode
== rPos
.GetNodeIndex() &&
150 m_nContent
== rPos
.GetContentIndex() )
153 SwDoc
& rDoc
= rPos
.GetNode().GetDoc();
154 if( ( ~RedlineFlags::ShowMask
& rDoc
.getIDocumentRedlineAccess().GetRedlineFlags() ) ==
155 ( ~RedlineFlags::ShowMask
& GetRedlineFlags() ) )
159 // then there is or was still an active Redline:
160 // Check if there is another Redline at the InsPosition. If the
161 // same exists only once, it can be combined.
162 const SwRedlineTable
& rTable
= rDoc
.getIDocumentRedlineAccess().GetRedlineTable();
163 if( !rTable
.empty() )
165 SwRedlineData
aRData( RedlineType::Insert
, rDoc
.getIDocumentRedlineAccess().GetRedlineAuthor() );
166 const SwContentNode
* pIReg
= rPos
.GetContentNode();
167 for(SwRangeRedline
* pRedl
: rTable
)
169 const SwPosition
& rIdx
= *pRedl
->End();
170 if( pIReg
== rIdx
.GetContentNode() &&
171 m_nContent
== rIdx
.GetContentIndex() )
173 if( !pRedl
->HasMark() || !m_pRedlData
||
174 *pRedl
!= *m_pRedlData
|| *pRedl
!= aRData
)
187 SwUndoInsert::~SwUndoInsert()
189 if (m_oUndoNodeIndex
) // delete the section from UndoNodes array
191 // Insert saves the content in IconSection
192 SwNodes
& rUNds
= m_oUndoNodeIndex
->GetNodes();
193 rUNds
.Delete(*m_oUndoNodeIndex
,
194 rUNds
.GetEndOfExtras().GetIndex() - m_oUndoNodeIndex
->GetIndex());
195 m_oUndoNodeIndex
.reset();
197 else // the inserted text
204 void SwUndoInsert::UndoImpl(::sw::UndoRedoContext
& rContext
)
206 SwDoc
*const pTmpDoc
= & rContext
.GetDoc();
207 SwCursor
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
211 pPam
->GetPoint()->Assign(m_nNode
);
213 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
216 pPam
->Move( fnMoveBackward
);
218 pTmpDoc
->getIDocumentRedlineAccess().DeleteRedline( *pPam
, true, RedlineType::Any
);
221 pTmpDoc
->getIDocumentContentOperations().DelFullPara( *pPam
);
222 pPam
->GetPoint()->SetContent( 0 );
226 SwNodeOffset nNd
= m_nNode
;
227 sal_Int32 nCnt
= m_nContent
;
230 SwNodeIndex
aNd( pTmpDoc
->GetNodes(), m_nNode
);
231 SwContentNode
* pCNd
= aNd
.GetNode().GetContentNode();
232 SwPaM
aPaM( *pCNd
, m_nContent
);
236 SwTextNode
* const pTextNode( pCNd
->GetTextNode() );
239 aPaM
.GetPoint()->AdjustContent( - m_nLen
);
240 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
241 pTmpDoc
->getIDocumentRedlineAccess().DeleteRedline( aPaM
, true, RedlineType::Any
);
244 // RSID was added: remove any CHARFMT/AUTOFMT that may be
245 // set on the deleted text; EraseText will leave empty
246 // ones behind otherwise
247 pTextNode
->DeleteAttributes(RES_TXTATR_AUTOFMT
,
248 aPaM
.GetPoint()->GetContentIndex(),
249 aPaM
.GetMark()->GetContentIndex());
250 pTextNode
->DeleteAttributes(RES_TXTATR_CHARFMT
,
251 aPaM
.GetPoint()->GetContentIndex(),
252 aPaM
.GetMark()->GetContentIndex());
254 RemoveIdxFromRange( aPaM
, false );
255 maText
= pTextNode
->GetText().copy(m_nContent
-m_nLen
, m_nLen
);
256 pTextNode
->EraseText( *aPaM
.GetPoint(), m_nLen
);
258 else // otherwise Graphics/OLE/Text/...
260 aPaM
.Move(fnMoveBackward
);
261 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
262 pTmpDoc
->getIDocumentRedlineAccess().DeleteRedline( aPaM
, true, RedlineType::Any
);
263 RemoveIdxFromRange( aPaM
, false );
266 nNd
= aPaM
.GetPoint()->GetNodeIndex();
267 nCnt
= aPaM
.GetPoint()->GetContentIndex();
271 m_oUndoNodeIndex
.emplace(m_pDoc
->GetNodes().GetEndOfContent());
272 MoveToUndoNds(aPaM
, &*m_oUndoNodeIndex
);
274 m_nNode
= aPaM
.GetPoint()->GetNodeIndex();
275 m_nContent
= aPaM
.GetPoint()->GetContentIndex();
278 // set cursor to Undo range
281 pPam
->GetPoint()->Assign( nNd
, nCnt
);
287 void SwUndoInsert::RedoImpl(::sw::UndoRedoContext
& rContext
)
289 SwDoc
*const pTmpDoc
= & rContext
.GetDoc();
290 SwCursor
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
295 pPam
->GetPoint()->Assign( m_nNode
- 1 );
296 pTmpDoc
->getIDocumentContentOperations().AppendTextNode( *pPam
->GetPoint() );
299 pPam
->Move( fnMoveBackward
);
302 if( m_pRedlData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
304 RedlineFlags eOld
= pTmpDoc
->getIDocumentRedlineAccess().GetRedlineFlags();
305 pTmpDoc
->getIDocumentRedlineAccess().SetRedlineFlags_intern(eOld
& ~RedlineFlags::Ignore
);
306 pTmpDoc
->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlData
, *pPam
), true);
307 pTmpDoc
->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
);
309 else if( !( RedlineFlags::Ignore
& GetRedlineFlags() ) &&
310 !pTmpDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty() )
311 pTmpDoc
->getIDocumentRedlineAccess().SplitRedline( *pPam
);
317 pPam
->GetPoint()->Assign( m_nNode
);
318 SwContentNode
*const pCNd
=
319 pPam
->GetPoint()->GetNode().GetContentNode();
320 pPam
->GetPoint()->SetContent( m_nContent
);
324 ::std::optional
<SwNodeIndex
> oMvBkwrd
= MovePtBackward(*pPam
);
328 SwTextNode
*const pTextNode
= pCNd
->GetTextNode();
329 OSL_ENSURE( pTextNode
, "where is my textnode ?" );
331 pTextNode
->InsertText( *maText
, *pPam
->GetMark(),
333 assert(ins
.getLength() == maText
->getLength()); // must succeed
335 if (m_bWithRsid
) // re-insert RSID
337 SwPaM
pam(*pPam
->GetMark(), nullptr); // mark -> point
338 pTmpDoc
->UpdateRsid(pam
, ins
.getLength());
343 // re-insert content again (first detach m_oUndoNodeIndex!)
344 SwNodeOffset
const nMvNd
= m_oUndoNodeIndex
->GetIndex();
345 m_oUndoNodeIndex
.reset();
346 MoveFromUndoNds(*pTmpDoc
, nMvNd
, *pPam
->GetMark());
348 m_nNode
= pPam
->GetMark()->GetNodeIndex();
349 m_nContent
= pPam
->GetMark()->GetContentIndex();
351 MovePtForward(*pPam
, ::std::move(oMvBkwrd
));
353 if( m_pRedlData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
355 RedlineFlags eOld
= pTmpDoc
->getIDocumentRedlineAccess().GetRedlineFlags();
356 pTmpDoc
->getIDocumentRedlineAccess().SetRedlineFlags_intern(eOld
& ~RedlineFlags::Ignore
);
357 pTmpDoc
->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlData
,
359 pTmpDoc
->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
);
361 else if( !( RedlineFlags::Ignore
& GetRedlineFlags() ) &&
362 !pTmpDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty() )
363 pTmpDoc
->getIDocumentRedlineAccess().SplitRedline(*pPam
);
367 maUndoText
= GetTextFromDoc();
370 void SwUndoInsert::RepeatImpl(::sw::RepeatContext
& rContext
)
375 SwDoc
& rDoc
= rContext
.GetDoc();
376 SwNodeIndex
aNd( rDoc
.GetNodes(), m_nNode
);
377 SwContentNode
* pCNd
= aNd
.GetNode().GetContentNode();
379 if( !m_bIsAppend
&& 1 == m_nLen
) // >1 than always Text, otherwise Graphics/OLE/Text/...
381 SwPaM
aPaM( *pCNd
, m_nContent
);
383 aPaM
.Move(fnMoveBackward
);
384 pCNd
= aPaM
.GetPointContentNode();
387 // What happens with the possible selected range ???
389 switch( pCNd
->GetNodeType() )
391 case SwNodeType::Text
:
394 rDoc
.getIDocumentContentOperations().AppendTextNode( *rContext
.GetRepeatPaM().GetPoint() );
398 OUString
const aText( pCNd
->GetTextNode()->GetText() );
399 ::sw::GroupUndoGuard
const undoGuard(rDoc
.GetIDocumentUndoRedo());
400 rDoc
.getIDocumentContentOperations().InsertString( rContext
.GetRepeatPaM(),
401 aText
.copy(m_nContent
- m_nLen
, m_nLen
) );
404 case SwNodeType::Grf
:
406 SwGrfNode
* pGrfNd
= static_cast<SwGrfNode
*>(pCNd
);
409 if( pGrfNd
->IsGrfLink() )
410 pGrfNd
->GetFileFilterNms( &sFile
, &sFilter
);
412 rDoc
.getIDocumentContentOperations().InsertGraphic(
413 rContext
.GetRepeatPaM(), sFile
, sFilter
,
415 nullptr/* Graphics collection*/, nullptr, nullptr );
419 case SwNodeType::Ole
:
421 // StarView does not yet provide an option to copy a StarOBJ
422 SwOLEObj
& rSwOLE
= static_cast<SwOLENode
*>(pCNd
)->GetOLEObj();
424 // temporary storage until object is inserted
425 // TODO/MBA: seems that here a physical copy is done - not as in drawing layer! Testing!
426 // TODO/LATER: Copying through the container would copy the replacement image as well
427 comphelper::EmbeddedObjectContainer aCnt
;
428 OUString aName
= aCnt
.CreateUniqueObjectName();
429 if (aCnt
.StoreEmbeddedObject(rSwOLE
.GetOleRef(), aName
, true, OUString(), OUString()))
431 uno::Reference
< embed::XEmbeddedObject
> aNew
= aCnt
.GetEmbeddedObject( aName
);
432 rDoc
.getIDocumentContentOperations().InsertEmbObject(
433 rContext
.GetRepeatPaM(),
434 svt::EmbeddedObjectRef( aNew
,
435 static_cast<SwOLENode
*>(pCNd
)->GetAspect() ),
446 SwRewriter
SwUndoInsert::GetRewriter() const
449 std::optional
<OUString
> aStr
;
459 OUString aString
= ShortenString(DenoteSpecialCharacters(*aStr
),
463 aResult
.AddRule(UndoArg1
, aString
);
470 aResult
.AddRule(UndoArg1
, "??");
476 bool SwUndoInsert::IsIndependent(const SwUndoInsert
& rOther
) const
478 return m_nNode
!= rOther
.m_nNode
;
481 class SwUndoReplace::Impl
482 : private SwUndoSaveContent
486 SwNodeOffset m_nSttNd
, m_nEndNd
, m_nOffset
;
487 sal_Int32 m_nSttCnt
, m_nEndCnt
, m_nSetPos
, m_nSelEnd
;
488 bool m_bSplitNext
: 1;
490 // metadata references for paragraph and following para (if m_bSplitNext)
491 std::shared_ptr
< ::sfx2::MetadatableUndo
> m_pMetadataUndoStart
;
492 std::shared_ptr
< ::sfx2::MetadatableUndo
> m_pMetadataUndoEnd
;
495 Impl(SwPaM
const& rPam
, OUString aIns
, bool const bRegExp
);
497 void UndoImpl( ::sw::UndoRedoContext
& );
498 void RedoImpl( ::sw::UndoRedoContext
& );
500 void SetEnd(SwPaM
const& rPam
);
502 OUString
const& GetOld() const { return m_sOld
; }
503 OUString
const& GetIns() const { return m_sIns
; }
506 SwUndoReplace::SwUndoReplace(SwPaM
const& rPam
,
507 OUString
const& rIns
, bool const bRegExp
)
508 : SwUndo( SwUndoId::REPLACE
, &rPam
.GetDoc() )
509 , m_pImpl(std::make_unique
<Impl
>(rPam
, rIns
, bRegExp
))
513 SwUndoReplace::~SwUndoReplace()
517 void SwUndoReplace::UndoImpl(::sw::UndoRedoContext
& rContext
)
519 m_pImpl
->UndoImpl(rContext
);
522 void SwUndoReplace::RedoImpl(::sw::UndoRedoContext
& rContext
)
524 m_pImpl
->RedoImpl(rContext
);
528 MakeUndoReplaceRewriter(sal_uLong
const occurrences
,
529 OUString
const& sOld
, OUString
const& sNew
)
535 aResult
.AddRule(UndoArg1
, OUString::number(occurrences
));
536 aResult
.AddRule(UndoArg2
, SwResId(STR_OCCURRENCES_OF
));
539 SwResId(STR_START_QUOTE
)
540 + ShortenString(sOld
, nUndoStringLength
, SwResId(STR_LDOTS
))
541 + SwResId(STR_END_QUOTE
);
542 aResult
.AddRule(UndoArg3
, aTmpStr
);
544 else if (1 == occurrences
)
549 SwResId(STR_START_QUOTE
)
550 + ShortenString(sOld
, nUndoStringLength
, SwResId(STR_LDOTS
))
551 + SwResId(STR_END_QUOTE
);
552 aResult
.AddRule(UndoArg1
, aTmpStr
);
555 aResult
.AddRule(UndoArg2
, SwResId(STR_YIELDS
));
560 SwResId(STR_START_QUOTE
)
561 + ShortenString(sNew
, nUndoStringLength
, SwResId(STR_LDOTS
))
562 + SwResId(STR_END_QUOTE
);
563 aResult
.AddRule(UndoArg3
, aTmpStr
);
570 SwRewriter
SwUndoReplace::GetRewriter() const
572 return MakeUndoReplaceRewriter(1, m_pImpl
->GetOld(), m_pImpl
->GetIns());
575 void SwUndoReplace::SetEnd(SwPaM
const& rPam
)
577 m_pImpl
->SetEnd(rPam
);
580 SwUndoReplace::Impl::Impl(
581 SwPaM
const& rPam
, OUString aIns
, bool const bRegExp
)
582 : m_sIns(std::move( aIns
))
587 auto [pStt
, pEnd
] = rPam
.StartEnd(); // SwPosition*
589 m_nSttNd
= m_nEndNd
= pStt
->GetNodeIndex();
590 m_nSttCnt
= pStt
->GetContentIndex();
591 m_nSelEnd
= m_nEndCnt
= pEnd
->GetContentIndex();
593 m_bSplitNext
= m_nSttNd
!= pEnd
->GetNodeIndex();
595 SwTextNode
* pNd
= pStt
->GetNode().GetTextNode();
596 OSL_ENSURE( pNd
, "Dude, where's my TextNode?" );
598 m_pHistory
.reset( new SwHistory
);
599 DelContentIndex(*rPam
.GetMark(), *rPam
.GetPoint(), DelContentType::AllMask
| DelContentType::Replace
);
601 m_nSetPos
= m_pHistory
->Count();
603 SwNodeOffset nNewPos
= pStt
->GetNodeIndex();
604 m_nOffset
= m_nSttNd
- nNewPos
;
606 if ( pNd
->GetpSwpHints() )
608 m_pHistory
->CopyAttr( pNd
->GetpSwpHints(), nNewPos
, 0,
609 pNd
->GetText().getLength(), true );
614 if( pNd
->HasSwAttrSet() )
615 m_pHistory
->CopyFormatAttr( *pNd
->GetpSwAttrSet(), nNewPos
);
616 m_pHistory
->Add( pNd
->GetTextColl(), nNewPos
, SwNodeType::Text
);
618 SwTextNode
* pNext
= pEnd
->GetNode().GetTextNode();
619 SwNodeOffset nTmp
= pNext
->GetIndex();
620 m_pHistory
->CopyAttr( pNext
->GetpSwpHints(), nTmp
, 0,
621 pNext
->GetText().getLength(), true );
622 if( pNext
->HasSwAttrSet() )
623 m_pHistory
->CopyFormatAttr( *pNext
->GetpSwAttrSet(), nTmp
);
624 m_pHistory
->Add( pNext
->GetTextColl(),nTmp
, SwNodeType::Text
);
626 m_pMetadataUndoStart
= pNd
->CreateUndo();
627 m_pMetadataUndoEnd
= pNext
->CreateUndo();
630 if( !m_pHistory
->Count() )
635 const sal_Int32 nECnt
= m_bSplitNext
? pNd
->GetText().getLength()
636 : pEnd
->GetContentIndex();
637 m_sOld
= pNd
->GetText().copy( m_nSttCnt
, nECnt
- m_nSttCnt
);
640 void SwUndoReplace::Impl::UndoImpl(::sw::UndoRedoContext
& rContext
)
642 SwDoc
*const pDoc
= & rContext
.GetDoc();
643 SwCursor
& rPam(rContext
.GetCursorSupplier().CreateNewShellCursor());
646 SwTextNode
* pNd
= pDoc
->GetNodes()[ m_nSttNd
- m_nOffset
]->GetTextNode();
647 OSL_ENSURE( pNd
, "Dude, where's my TextNode?" );
649 SwAutoCorrExceptWord
* pACEWord
= pDoc
->GetAutoCorrExceptWord();
652 if ((1 == m_sIns
.getLength()) && (1 == m_sOld
.getLength()))
654 SwPosition
aPos( *pNd
, m_nSttCnt
);
655 pACEWord
->CheckChar( aPos
, m_sOld
[ 0 ] );
657 pDoc
->SetAutoCorrExceptWord( nullptr );
660 // don't look at m_sIns for deletion, maybe it was not completely inserted
662 rPam
.GetPoint()->Assign(*pNd
, m_nSttCnt
);
664 rPam
.GetPoint()->Assign( m_nSttNd
- m_nOffset
, m_nSttNd
== m_nEndNd
? m_nEndCnt
: pNd
->Len());
666 // replace only in start node, without regex
667 bool const ret
= pDoc
->getIDocumentContentOperations().ReplaceRange(rPam
, m_sOld
, false);
668 assert(ret
); (void)ret
;
669 if (m_nSttNd
!= m_nEndNd
)
670 { // in case of regex inserting paragraph breaks, join nodes...
671 assert(rPam
.GetMark()->GetContentIndex() == rPam
.GetMark()->GetNode().GetTextNode()->Len());
672 rPam
.GetPoint()->Assign( m_nEndNd
- m_nOffset
, m_nEndCnt
);
673 pDoc
->getIDocumentContentOperations().DeleteAndJoin(rPam
);
676 pNd
= pDoc
->GetNodes()[ m_nSttNd
- m_nOffset
]->GetTextNode();
677 OSL_ENSURE( pNd
, "Dude, where's my TextNode?" );
682 assert(m_nSttCnt
+ m_sOld
.getLength() <= pNd
->Len());
683 SwPosition
aPos(*pNd
, m_nSttCnt
+ m_sOld
.getLength());
684 pDoc
->getIDocumentContentOperations().SplitNode( aPos
, false );
685 pNd
->RestoreMetadata(m_pMetadataUndoEnd
);
686 pNd
= pDoc
->GetNodes()[ m_nSttNd
- m_nOffset
]->GetTextNode();
688 pNd
->RestoreMetadata(m_pMetadataUndoStart
);
693 if( pNd
->GetpSwpHints() )
694 pNd
->ClearSwpHintsArr( true );
696 m_pHistory
->TmpRollback( pDoc
, m_nSetPos
, false );
697 if ( m_nSetPos
) // there were footnotes/FlyFrames
699 // are there others than these?
700 if( m_nSetPos
< m_pHistory
->Count() )
702 // than save those attributes as well
704 aHstr
.Move( 0, m_pHistory
.get(), m_nSetPos
);
705 m_pHistory
->Rollback( pDoc
);
706 m_pHistory
->Move( 0, &aHstr
);
710 m_pHistory
->Rollback( pDoc
);
716 rPam
.GetPoint()->Assign( m_nSttNd
, m_nSttCnt
);
719 void SwUndoReplace::Impl::RedoImpl(::sw::UndoRedoContext
& rContext
)
721 SwDoc
& rDoc
= rContext
.GetDoc();
722 SwCursor
& rPam(rContext
.GetCursorSupplier().CreateNewShellCursor());
724 rPam
.GetPoint()->Assign( m_nSttNd
, m_nSttCnt
);
728 rPam
.GetPoint()->Assign( m_nSttNd
+ 1 );
729 rPam
.GetPoint()->SetContent( m_nSelEnd
);
733 auto xSave
= std::make_unique
<SwHistory
>();
734 std::swap(m_pHistory
, xSave
);
736 DelContentIndex(*rPam
.GetMark(), *rPam
.GetPoint(), DelContentType::AllMask
| DelContentType::Replace
);
737 m_nSetPos
= m_pHistory
->Count();
739 std::swap(xSave
, m_pHistory
);
740 m_pHistory
->Move(0, xSave
.get());
744 m_pHistory
.reset( new SwHistory
);
745 DelContentIndex(*rPam
.GetMark(), *rPam
.GetPoint(), DelContentType::AllMask
| DelContentType::Replace
);
746 m_nSetPos
= m_pHistory
->Count();
753 rDoc
.getIDocumentContentOperations().ReplaceRange( rPam
, m_sIns
, m_bRegExp
);
757 void SwUndoReplace::Impl::SetEnd(SwPaM
const& rPam
)
759 const SwPosition
* pEnd
= rPam
.End();
760 m_nEndNd
= m_nOffset
+ pEnd
->GetNodeIndex();
761 m_nEndCnt
= pEnd
->GetContentIndex();
764 SwUndoReRead::SwUndoReRead( const SwPaM
& rPam
, const SwGrfNode
& rGrfNd
)
765 : SwUndo( SwUndoId::REREAD
, &rPam
.GetDoc() ), mnPosition( rPam
.GetPoint()->GetNodeIndex() )
767 SaveGraphicData( rGrfNd
);
770 SwUndoReRead::~SwUndoReRead()
774 void SwUndoReRead::SetAndSave(::sw::UndoRedoContext
& rContext
)
776 SwDoc
& rDoc
= rContext
.GetDoc();
777 SwGrfNode
* pGrfNd
= rDoc
.GetNodes()[ mnPosition
]->GetGrfNode();
782 // cache the old values
783 std::optional
<Graphic
> oOldGrf(moGraphic
);
784 std::optional
<OUString
> aOldNm
= maNm
;
785 MirrorGraph nOldMirr
= mnMirror
;
786 // since all of them are cleared/modified by SaveGraphicData:
787 SaveGraphicData( *pGrfNd
);
791 pGrfNd
->ReRead( *aOldNm
, maFltr
? *maFltr
: OUString() );
795 pGrfNd
->ReRead( OUString(), OUString(), oOldGrf
? &*oOldGrf
: nullptr );
798 if( MirrorGraph::Dont
!= nOldMirr
)
799 pGrfNd
->SetAttr( SwMirrorGrf() );
801 rContext
.SetSelections(pGrfNd
->GetFlyFormat(), nullptr);
804 void SwUndoReRead::UndoImpl(::sw::UndoRedoContext
& rContext
)
806 SetAndSave(rContext
);
809 void SwUndoReRead::RedoImpl(::sw::UndoRedoContext
& rContext
)
811 SetAndSave(rContext
);
814 void SwUndoReRead::SaveGraphicData( const SwGrfNode
& rGrfNd
)
816 if( rGrfNd
.IsGrfLink() )
820 rGrfNd
.GetFileFilterNms(&*maNm
, &*maFltr
);
825 moGraphic
.emplace( rGrfNd
.GetGrf(true) );
829 mnMirror
= rGrfNd
.GetSwAttrSet().GetMirrorGrf().GetValue();
832 SwUndoInsertLabel::SwUndoInsertLabel( const SwLabelType eTyp
,
835 OUString aNumberSeparator
,
837 const sal_uInt16 nInitId
,
838 OUString aCharacterStyle
,
839 const bool bCpyBorder
,
841 : SwUndo( SwUndoId::INSERTLABEL
, pDoc
),
842 m_sText(std::move( aText
)),
843 m_sSeparator(std::move( aSeparator
)),
844 m_sNumberSeparator(std::move( aNumberSeparator
)),//#i61007# order of captions
845 m_sCharacterStyle(std::move( aCharacterStyle
)),
846 m_nFieldId( nInitId
),
850 m_bCopyBorder( bCpyBorder
)
853 OBJECT
.pUndoFly
= nullptr;
854 OBJECT
.pUndoAttr
= nullptr;
857 SwUndoInsertLabel::~SwUndoInsertLabel()
859 if( SwLabelType::Object
== m_eType
|| SwLabelType::Draw
== m_eType
)
861 delete OBJECT
.pUndoFly
;
862 delete OBJECT
.pUndoAttr
;
865 delete NODE
.pUndoInsNd
;
868 void SwUndoInsertLabel::UndoImpl(::sw::UndoRedoContext
& rContext
)
870 SwDoc
& rDoc
= rContext
.GetDoc();
872 if( SwLabelType::Object
== m_eType
|| SwLabelType::Draw
== m_eType
)
874 OSL_ENSURE( OBJECT
.pUndoAttr
&& OBJECT
.pUndoFly
, "Pointer not initialized" );
875 SwFrameFormat
* pFormat
;
876 SdrObject
*pSdrObj
= nullptr;
877 if( OBJECT
.pUndoAttr
&&
878 nullptr != (pFormat
= static_cast<SwFrameFormat
*>(OBJECT
.pUndoAttr
->GetFormat( rDoc
))) &&
879 ( SwLabelType::Draw
!= m_eType
||
880 nullptr != (pSdrObj
= pFormat
->FindSdrObject()) ) )
882 OBJECT
.pUndoAttr
->UndoImpl(rContext
);
883 OBJECT
.pUndoFly
->UndoImpl(rContext
);
884 if( SwLabelType::Draw
== m_eType
)
886 pSdrObj
->SetLayer( m_nLayerId
);
890 else if( NODE
.nNode
)
892 if ( m_eType
== SwLabelType::Table
&& m_bUndoKeep
)
894 SwTableNode
*pNd
= rDoc
.GetNodes()[
895 rDoc
.GetNodes()[NODE
.nNode
-1]->StartOfSectionIndex()]->GetTableNode();
897 pNd
->GetTable().GetFrameFormat()->ResetFormatAttr( RES_KEEP
);
899 SwPaM
aPam( rDoc
.GetNodes().GetEndOfContent() );
900 aPam
.GetPoint()->Assign( NODE
.nNode
);
902 aPam
.GetPoint()->Assign( NODE
.nNode
+ 1 );
903 NODE
.pUndoInsNd
= new SwUndoDelete(aPam
, SwDeleteFlags::Default
, true);
907 void SwUndoInsertLabel::RedoImpl(::sw::UndoRedoContext
& rContext
)
909 SwDoc
& rDoc
= rContext
.GetDoc();
911 if( SwLabelType::Object
== m_eType
|| SwLabelType::Draw
== m_eType
)
913 OSL_ENSURE( OBJECT
.pUndoAttr
&& OBJECT
.pUndoFly
, "Pointer not initialized" );
914 SwFrameFormat
* pFormat
;
915 SdrObject
*pSdrObj
= nullptr;
916 if( OBJECT
.pUndoAttr
&&
917 nullptr != (pFormat
= static_cast<SwFrameFormat
*>(OBJECT
.pUndoAttr
->GetFormat( rDoc
))) &&
918 ( SwLabelType::Draw
!= m_eType
||
919 nullptr != (pSdrObj
= pFormat
->FindSdrObject()) ) )
921 OBJECT
.pUndoFly
->RedoImpl(rContext
);
922 OBJECT
.pUndoAttr
->RedoImpl(rContext
);
923 if( SwLabelType::Draw
== m_eType
)
925 pSdrObj
->SetLayer( m_nLayerId
);
926 if( pSdrObj
->GetLayer() == rDoc
.getIDocumentDrawModelAccess().GetHellId() )
927 pSdrObj
->SetLayer( rDoc
.getIDocumentDrawModelAccess().GetHeavenId() );
928 // OD 02.07.2003 #108784#
929 else if( pSdrObj
->GetLayer() == rDoc
.getIDocumentDrawModelAccess().GetInvisibleHellId() )
930 pSdrObj
->SetLayer( rDoc
.getIDocumentDrawModelAccess().GetInvisibleHeavenId() );
934 else if( NODE
.pUndoInsNd
)
936 if ( m_eType
== SwLabelType::Table
&& m_bUndoKeep
)
938 SwTableNode
*pNd
= rDoc
.GetNodes()[
939 rDoc
.GetNodes()[NODE
.nNode
-1]->StartOfSectionIndex()]->GetTableNode();
941 pNd
->GetTable().GetFrameFormat()->SetFormatAttr( SvxFormatKeepItem(true, RES_KEEP
) );
943 NODE
.pUndoInsNd
->UndoImpl(rContext
);
944 delete NODE
.pUndoInsNd
;
945 NODE
.pUndoInsNd
= nullptr;
949 void SwUndoInsertLabel::RepeatImpl(::sw::RepeatContext
& rContext
)
951 SwDoc
& rDoc
= rContext
.GetDoc();
952 const SwPosition
& rPos
= *rContext
.GetRepeatPaM().GetPoint();
954 SwNodeOffset
nIdx(0);
956 SwContentNode
* pCNd
= rPos
.GetNode().GetContentNode();
960 case SwLabelType::Table
:
962 const SwTableNode
* pTNd
= pCNd
->FindTableNode();
964 nIdx
= pTNd
->GetIndex();
968 case SwLabelType::Fly
:
969 case SwLabelType::Object
:
972 SwContentFrame
*pCnt
= pCNd
->getLayoutFrame( rDoc
.getIDocumentLayoutAccess().GetCurrentLayout() );
973 if( pCnt
&& nullptr != ( pFly
= pCnt
->FindFlyFrame() ) )
974 nIdx
= pFly
->GetFormat()->GetContent().GetContentIdx()->GetIndex();
977 case SwLabelType::Draw
:
983 rDoc
.InsertLabel( m_eType
, m_sText
, m_sSeparator
, m_sNumberSeparator
, m_bBefore
,
984 m_nFieldId
, nIdx
, m_sCharacterStyle
, m_bCopyBorder
);
988 SwRewriter
SwUndoInsertLabel::GetRewriter() const
990 return CreateRewriter(m_sText
);
993 SwRewriter
SwUndoInsertLabel::CreateRewriter(const OUString
&rStr
)
995 SwRewriter aRewriter
;
1002 SwResId(STR_START_QUOTE
)
1003 + ShortenString(rStr
, nUndoStringLength
, SwResId(STR_LDOTS
))
1004 + SwResId(STR_END_QUOTE
);
1007 aRewriter
.AddRule(UndoArg1
, aTmpStr
);
1012 void SwUndoInsertLabel::SetFlys( SwFrameFormat
& rOldFly
, SfxItemSet
const & rChgSet
,
1013 SwFrameFormat
& rNewFly
)
1015 if( SwLabelType::Object
== m_eType
|| SwLabelType::Draw
== m_eType
)
1017 SwUndoFormatAttrHelper
aTmp( rOldFly
, false );
1018 rOldFly
.SetFormatAttr( rChgSet
);
1019 if ( aTmp
.GetUndo() )
1021 OBJECT
.pUndoAttr
= aTmp
.ReleaseUndo().release();
1023 OBJECT
.pUndoFly
= new SwUndoInsLayFormat( &rNewFly
, SwNodeOffset(0), 0 );
1027 void SwUndoInsertLabel::SetDrawObj( SdrLayerID nLId
)
1029 if( SwLabelType::Draw
== m_eType
)
1035 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */