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 ), pPos( 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().Len(), 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( pPos
) // delete also the section from UndoNodes array
136 // Insert saves content in IconSection
137 SwNodes
& rUNds
= pPos
->nNode
.GetNodes();
138 if( pPos
->nContent
.GetIndex() ) // do not delete complete Node
140 SwTxtNode
* pTxtNd
= pPos
->nNode
.GetNode().GetTxtNode();
141 OSL_ENSURE( pTxtNd
, "no TextNode to delete from" );
142 if( pTxtNd
) // robust
144 pTxtNd
->EraseText( pPos
->nContent
);
148 pPos
->nContent
.Assign( 0, 0 );
149 rUNds
.Delete( pPos
->nNode
, rUNds
.GetEndOfExtras().GetIndex() -
150 pPos
->nNode
.GetIndex() );
157 void SwUndoInserts::UndoImpl(::sw::UndoRedoContext
& rContext
)
159 SwDoc
*const pDoc
= & rContext
.GetDoc();
160 SwPaM
*const pPam
= & AddUndoRedoPaM(rContext
);
162 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
163 pDoc
->DeleteRedline( *pPam
, true, USHRT_MAX
);
165 // if Point and Mark are different text nodes so a JoinNext has to be done
166 sal_Bool bJoinNext
= nSttNode
!= nEndNode
&&
167 pPam
->GetMark()->nNode
.GetNode().GetTxtNode() &&
168 pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
171 // Is there any content? (loading from template does not have content)
172 if( nSttNode
!= nEndNode
|| nSttCntnt
!= nEndCntnt
)
174 if( nSttNode
!= nEndNode
)
176 SwTxtNode
* pTxtNd
= pDoc
->GetNodes()[ nEndNode
]->GetTxtNode();
177 if( pTxtNd
&& pTxtNd
->GetTxt().Len() == nEndCntnt
)
178 pLastNdColl
= pTxtNd
->GetTxtColl();
181 RemoveIdxFromRange( *pPam
, sal_False
);
184 // are there Footnotes or CntntFlyFrames in text?
185 nSetPos
= pHistory
->Count();
186 nNdDiff
= pPam
->GetMark()->nNode
.GetIndex();
187 DelCntntIndex( *pPam
->GetMark(), *pPam
->GetPoint() );
188 nNdDiff
-= pPam
->GetMark()->nNode
.GetIndex();
190 if( *pPam
->GetPoint() != *pPam
->GetMark() )
192 pPos
= new SwPosition( *pPam
->GetPoint() );
193 MoveToUndoNds( *pPam
, &pPos
->nNode
, &pPos
->nContent
);
196 pPam
->Move( fnMoveBackward
, fnGoCntnt
);
200 if (m_FlyUndos
.size())
202 sal_uLong nTmp
= pPam
->GetPoint()->nNode
.GetIndex();
203 for (size_t n
= m_FlyUndos
.size(); 0 < n
; --n
)
205 m_FlyUndos
[ n
-1 ]->UndoImpl(rContext
);
207 nNdDiff
+= nTmp
- pPam
->GetPoint()->nNode
.GetIndex();
210 SwNodeIndex
& rIdx
= pPam
->GetPoint()->nNode
;
211 SwTxtNode
* pTxtNode
= rIdx
.GetNode().GetTxtNode();
214 if( !pTxtFmtColl
) // if 0 than it's no TextNode -> delete
216 SwNodeIndex
aDelIdx( rIdx
);
218 SwCntntNode
* pCNd
= rIdx
.GetNode().GetCntntNode();
222 pPam
->GetPoint()->nContent
.Assign( pCNd
, nCnt
);
226 RemoveIdxRel( aDelIdx
.GetIndex(), *pPam
->GetPoint() );
228 pDoc
->GetNodes().Delete( aDelIdx
, 1 );
232 if( bJoinNext
&& pTxtNode
->CanJoinNext())
235 RemoveIdxRel( rIdx
.GetIndex()+1, SwPosition( rIdx
,
236 SwIndex( pTxtNode
, pTxtNode
->GetTxt().Len() )));
238 pTxtNode
->JoinNext();
240 // reset all text attributes in the paragraph!
241 pTxtNode
->RstAttr( SwIndex(pTxtNode
, 0), pTxtNode
->Len(),
244 pTxtNode
->ResetAllAttr();
246 if( USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pTxtFmtColl
))
247 pTxtFmtColl
= (SwTxtFmtColl
*)pTxtNode
->ChgFmtColl( pTxtFmtColl
);
249 pHistory
->SetTmpEnd( nSetPos
);
250 pHistory
->TmpRollback( pDoc
, 0, false );
255 void SwUndoInserts::RedoImpl(::sw::UndoRedoContext
& rContext
)
257 // position cursor onto REDO section
258 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
259 SwDoc
* pDoc
= pPam
->GetDoc();
261 pPam
->GetPoint()->nNode
= nSttNode
- nNdDiff
;
262 SwCntntNode
* pCNd
= pPam
->GetCntntNode();
263 pPam
->GetPoint()->nContent
.Assign( pCNd
, nSttCntnt
);
265 SwTxtFmtColl
* pSavTxtFmtColl
= pTxtFmtColl
;
266 if( pTxtFmtColl
&& pCNd
&& pCNd
->IsTxtNode() )
267 pSavTxtFmtColl
= ((SwTxtNode
*)pCNd
)->GetTxtColl();
269 pHistory
->SetTmpEnd( nSetPos
);
271 // retrieve start position for rollback
272 if( ( nSttNode
!= nEndNode
|| nSttCntnt
!= nEndCntnt
) && pPos
)
274 sal_Bool bMvBkwrd
= MovePtBackward( *pPam
);
276 // re-insert content again (first detach pPos!)
277 sal_uLong nMvNd
= pPos
->nNode
.GetIndex();
278 xub_StrLen nMvCnt
= pPos
->nContent
.GetIndex();
280 MoveFromUndoNds( *pDoc
, nMvNd
, nMvCnt
, *pPam
->GetMark() );
282 MovePtForward( *pPam
, bMvBkwrd
);
286 if( USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pTxtFmtColl
))
288 SwTxtNode
* pTxtNd
= pPam
->GetMark()->nNode
.GetNode().GetTxtNode();
290 pTxtNd
->ChgFmtColl( pTxtFmtColl
);
292 pTxtFmtColl
= pSavTxtFmtColl
;
294 if( pLastNdColl
&& USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pLastNdColl
) &&
295 pPam
->GetPoint()->nNode
!= pPam
->GetMark()->nNode
)
297 SwTxtNode
* pTxtNd
= pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
299 pTxtNd
->ChgFmtColl( pLastNdColl
);
302 for (size_t n
= m_FlyUndos
.size(); 0 < n
; --n
)
304 m_FlyUndos
[ n
-1 ]->RedoImpl(rContext
);
307 pHistory
->Rollback( pDoc
, nSetPos
);
309 if( pRedlData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
311 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
312 pDoc
->SetRedlineMode_intern((RedlineMode_t
)( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
));
313 pDoc
->AppendRedline( new SwRedline( *pRedlData
, *pPam
), true);
314 pDoc
->SetRedlineMode_intern( eOld
);
316 else if( !( nsRedlineMode_t::REDLINE_IGNORE
& GetRedlineMode() ) &&
317 !pDoc
->GetRedlineTbl().empty() )
318 pDoc
->SplitRedline( *pPam
);
321 void SwUndoInserts::RepeatImpl(::sw::RepeatContext
& rContext
)
323 SwPaM
aPam( rContext
.GetDoc().GetNodes().GetEndOfContent() );
325 SwPaM
& rRepeatPaM( rContext
.GetRepeatPaM() );
326 aPam
.GetDoc()->CopyRange( aPam
, *rRepeatPaM
.GetPoint(), false );
329 SwUndoInsDoc::SwUndoInsDoc( const SwPaM
& rPam
)
330 : SwUndoInserts( UNDO_INSDOKUMENT
, rPam
)
334 SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM
& rPam
)
335 : SwUndoInserts( UNDO_COPY
, rPam
)
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */