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 <hintids.hxx>
21 #include <fmtanchr.hxx>
24 #include <IDocumentUndoRedo.hxx>
25 #include <IShellCursorSupplier.hxx>
30 #include <UndoCore.hxx>
32 #include <redline.hxx>
34 SwUndoInserts::SwUndoInserts( SwUndoId nUndoId
, const SwPaM
& rPam
)
35 : SwUndo( nUndoId
), SwUndRng( rPam
),
36 pTxtFmtColl( 0 ), pLastNdColl(0), pFrmFmts( 0 ), pRedlData( 0 ),
37 bSttWasTxtNd( sal_True
), nNdDiff( 0 ), nSetPos( 0 )
39 pHistory
= new SwHistory
;
40 SwDoc
* pDoc
= (SwDoc
*)rPam
.GetDoc();
42 SwTxtNode
* pTxtNd
= rPam
.GetPoint()->nNode
.GetNode().GetTxtNode();
45 pTxtFmtColl
= pTxtNd
->GetTxtColl();
46 pHistory
->CopyAttr( pTxtNd
->GetpSwpHints(), nSttNode
,
47 0, pTxtNd
->GetTxt().getLength(), false );
48 if( pTxtNd
->HasSwAttrSet() )
49 pHistory
->CopyFmtAttr( *pTxtNd
->GetpSwAttrSet(), nSttNode
);
51 if( !nSttCntnt
) // than take the Flys along
53 sal_uInt16 nArrLen
= pDoc
->GetSpzFrmFmts()->size();
54 for( sal_uInt16 n
= 0; n
< nArrLen
; ++n
)
56 SwFrmFmt
* pFmt
= (*pDoc
->GetSpzFrmFmts())[n
];
57 SwFmtAnchor
const*const pAnchor
= &pFmt
->GetAnchor();
58 const SwPosition
* pAPos
= pAnchor
->GetCntntAnchor();
60 (pAnchor
->GetAnchorId() == FLY_AT_PARA
) &&
61 nSttNode
== pAPos
->nNode
.GetIndex() )
64 pFrmFmts
= new std::vector
<SwFrmFmt
*>;
65 pFrmFmts
->push_back( pFmt
);
71 if( pDoc
->IsRedlineOn() )
73 pRedlData
= new SwRedlineData( nsRedlineType_t::REDLINE_INSERT
, pDoc
->GetRedlineAuthor() );
74 SetRedlineMode( pDoc
->GetRedlineMode() );
78 // set destination after reading input
79 void SwUndoInserts::SetInsertRange( const SwPaM
& rPam
, sal_Bool bScanFlys
,
80 sal_Bool bSttIsTxtNd
)
82 const SwPosition
* pTmpPos
= rPam
.End();
83 nEndNode
= pTmpPos
->nNode
.GetIndex();
84 nEndCntnt
= pTmpPos
->nContent
.GetIndex();
87 if( pTmpPos
== rPam
.GetPoint() )
88 pTmpPos
= rPam
.GetMark();
90 pTmpPos
= rPam
.GetPoint();
92 nSttNode
= pTmpPos
->nNode
.GetIndex();
93 nSttCntnt
= pTmpPos
->nContent
.GetIndex();
95 if( !bSttIsTxtNd
) // if a table selection is added ...
97 ++nSttNode
; // ... than the CopyPam is not fully correct
98 bSttWasTxtNd
= sal_False
;
102 if( bScanFlys
&& !nSttCntnt
)
104 // than collect all new Flys
105 SwDoc
* pDoc
= (SwDoc
*)rPam
.GetDoc();
106 sal_uInt16 nArrLen
= pDoc
->GetSpzFrmFmts()->size();
107 for( sal_uInt16 n
= 0; n
< nArrLen
; ++n
)
109 SwFrmFmt
* pFmt
= (*pDoc
->GetSpzFrmFmts())[n
];
110 SwFmtAnchor
const*const pAnchor
= &pFmt
->GetAnchor();
111 SwPosition
const*const pAPos
= pAnchor
->GetCntntAnchor();
113 (pAnchor
->GetAnchorId() == FLY_AT_PARA
) &&
114 nSttNode
== pAPos
->nNode
.GetIndex() )
116 std::vector
<SwFrmFmt
*>::iterator it
;
118 pFrmFmts
->end() == ( it
= std::find( pFrmFmts
->begin(), pFrmFmts
->end(), pFmt
) ) )
120 ::boost::shared_ptr
<SwUndoInsLayFmt
> const pFlyUndo(
121 new SwUndoInsLayFmt(pFmt
, 0, 0));
122 m_FlyUndos
.push_back(pFlyUndo
);
125 pFrmFmts
->erase( it
);
128 delete pFrmFmts
, pFrmFmts
= 0;
132 SwUndoInserts::~SwUndoInserts()
134 if (m_pUndoNodeIndex
) // delete also the section from UndoNodes array
136 // Insert saves content in IconSection
137 SwNodes
& rUNds
= m_pUndoNodeIndex
->GetNodes();
138 rUNds
.Delete(*m_pUndoNodeIndex
,
139 rUNds
.GetEndOfExtras().GetIndex() - m_pUndoNodeIndex
->GetIndex());
140 m_pUndoNodeIndex
.reset();
146 void SwUndoInserts::UndoImpl(::sw::UndoRedoContext
& rContext
)
148 SwDoc
*const pDoc
= & rContext
.GetDoc();
149 SwPaM
*const pPam
= & AddUndoRedoPaM(rContext
);
151 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
152 pDoc
->DeleteRedline( *pPam
, true, USHRT_MAX
);
154 // if Point and Mark are different text nodes so a JoinNext has to be done
155 bool bJoinNext
= nSttNode
!= nEndNode
&&
156 pPam
->GetMark()->nNode
.GetNode().GetTxtNode() &&
157 pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
160 // Is there any content? (loading from template does not have content)
161 if( nSttNode
!= nEndNode
|| nSttCntnt
!= nEndCntnt
)
163 if( nSttNode
!= nEndNode
)
165 SwTxtNode
* pTxtNd
= pDoc
->GetNodes()[ nEndNode
]->GetTxtNode();
166 if (pTxtNd
&& pTxtNd
->GetTxt().getLength() == nEndCntnt
)
167 pLastNdColl
= pTxtNd
->GetTxtColl();
170 RemoveIdxFromRange( *pPam
, sal_False
);
173 // are there Footnotes or CntntFlyFrames in text?
174 nSetPos
= pHistory
->Count();
175 nNdDiff
= pPam
->GetMark()->nNode
.GetIndex();
176 DelCntntIndex( *pPam
->GetMark(), *pPam
->GetPoint() );
177 nNdDiff
-= pPam
->GetMark()->nNode
.GetIndex();
179 if( *pPam
->GetPoint() != *pPam
->GetMark() )
181 m_pUndoNodeIndex
.reset(
182 new SwNodeIndex(pDoc
->GetNodes().GetEndOfContent()));
183 MoveToUndoNds(*pPam
, m_pUndoNodeIndex
.get());
186 pPam
->Move( fnMoveBackward
, fnGoCntnt
);
190 if (m_FlyUndos
.size())
192 sal_uLong nTmp
= pPam
->GetPoint()->nNode
.GetIndex();
193 for (size_t n
= m_FlyUndos
.size(); 0 < n
; --n
)
195 m_FlyUndos
[ n
-1 ]->UndoImpl(rContext
);
197 nNdDiff
+= nTmp
- pPam
->GetPoint()->nNode
.GetIndex();
200 SwNodeIndex
& rIdx
= pPam
->GetPoint()->nNode
;
201 SwTxtNode
* pTxtNode
= rIdx
.GetNode().GetTxtNode();
204 if( !pTxtFmtColl
) // if 0 than it's no TextNode -> delete
206 SwNodeIndex
aDelIdx( rIdx
);
208 SwCntntNode
* pCNd
= rIdx
.GetNode().GetCntntNode();
212 pPam
->GetPoint()->nContent
.Assign( pCNd
, nCnt
);
216 RemoveIdxRel( aDelIdx
.GetIndex(), *pPam
->GetPoint() );
218 pDoc
->GetNodes().Delete( aDelIdx
, 1 );
222 if( bJoinNext
&& pTxtNode
->CanJoinNext())
225 RemoveIdxRel( rIdx
.GetIndex()+1, SwPosition( rIdx
,
226 SwIndex(pTxtNode
, pTxtNode
->GetTxt().getLength())));
228 pTxtNode
->JoinNext();
230 // reset all text attributes in the paragraph!
231 pTxtNode
->RstAttr( SwIndex(pTxtNode
, 0), pTxtNode
->Len(),
234 pTxtNode
->ResetAllAttr();
236 if( USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pTxtFmtColl
))
237 pTxtFmtColl
= (SwTxtFmtColl
*)pTxtNode
->ChgFmtColl( pTxtFmtColl
);
239 pHistory
->SetTmpEnd( nSetPos
);
240 pHistory
->TmpRollback( pDoc
, 0, false );
245 void SwUndoInserts::RedoImpl(::sw::UndoRedoContext
& rContext
)
247 // position cursor onto REDO section
248 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
249 SwDoc
* pDoc
= pPam
->GetDoc();
251 pPam
->GetPoint()->nNode
= nSttNode
- nNdDiff
;
252 SwCntntNode
* pCNd
= pPam
->GetCntntNode();
253 pPam
->GetPoint()->nContent
.Assign( pCNd
, nSttCntnt
);
255 SwTxtFmtColl
* pSavTxtFmtColl
= pTxtFmtColl
;
256 if( pTxtFmtColl
&& pCNd
&& pCNd
->IsTxtNode() )
257 pSavTxtFmtColl
= ((SwTxtNode
*)pCNd
)->GetTxtColl();
259 pHistory
->SetTmpEnd( nSetPos
);
261 // retrieve start position for rollback
262 if( ( nSttNode
!= nEndNode
|| nSttCntnt
!= nEndCntnt
) && m_pUndoNodeIndex
)
264 sal_Bool bMvBkwrd
= MovePtBackward( *pPam
);
266 // re-insert content again (first detach m_pUndoNodeIndex!)
267 sal_uLong
const nMvNd
= m_pUndoNodeIndex
->GetIndex();
268 m_pUndoNodeIndex
.reset();
269 MoveFromUndoNds(*pDoc
, nMvNd
, *pPam
->GetMark());
271 MovePtForward( *pPam
, bMvBkwrd
);
275 if( USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pTxtFmtColl
))
277 SwTxtNode
* pTxtNd
= pPam
->GetMark()->nNode
.GetNode().GetTxtNode();
279 pTxtNd
->ChgFmtColl( pTxtFmtColl
);
281 pTxtFmtColl
= pSavTxtFmtColl
;
283 if( pLastNdColl
&& USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pLastNdColl
) &&
284 pPam
->GetPoint()->nNode
!= pPam
->GetMark()->nNode
)
286 SwTxtNode
* pTxtNd
= pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
288 pTxtNd
->ChgFmtColl( pLastNdColl
);
291 for (size_t n
= m_FlyUndos
.size(); 0 < n
; --n
)
293 m_FlyUndos
[ n
-1 ]->RedoImpl(rContext
);
296 pHistory
->Rollback( pDoc
, nSetPos
);
298 if( pRedlData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
300 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
301 pDoc
->SetRedlineMode_intern((RedlineMode_t
)( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
));
302 pDoc
->AppendRedline( new SwRedline( *pRedlData
, *pPam
), true);
303 pDoc
->SetRedlineMode_intern( eOld
);
305 else if( !( nsRedlineMode_t::REDLINE_IGNORE
& GetRedlineMode() ) &&
306 !pDoc
->GetRedlineTbl().empty() )
307 pDoc
->SplitRedline( *pPam
);
310 void SwUndoInserts::RepeatImpl(::sw::RepeatContext
& rContext
)
312 SwPaM
aPam( rContext
.GetDoc().GetNodes().GetEndOfContent() );
314 SwPaM
& rRepeatPaM( rContext
.GetRepeatPaM() );
315 aPam
.GetDoc()->CopyRange( aPam
, *rRepeatPaM
.GetPoint(), false );
318 SwUndoInsDoc::SwUndoInsDoc( const SwPaM
& rPam
)
319 : SwUndoInserts( UNDO_INSDOKUMENT
, rPam
)
323 SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM
& rPam
)
324 : SwUndoInserts( UNDO_COPY
, rPam
)
328 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */