1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include <hintids.hxx>
28 #include <fmtanchr.hxx>
29 #include <frmfmt.hxx>
30 #include <doc.hxx>
31 #include <IDocumentUndoRedo.hxx>
32 #include <IShellCursorSupplier.hxx>
33 #include <docary.hxx>
34 #include <swundo.hxx> // fuer die UndoIds
35 #include <pam.hxx>
36 #include <ndtxt.hxx>
37 #include <UndoCore.hxx>
38 #include <rolbck.hxx>
39 #include <redline.hxx>
40
41
42
SwUndoInserts(SwUndoId nUndoId,const SwPaM & rPam)43 SwUndoInserts::SwUndoInserts( SwUndoId nUndoId, const SwPaM& rPam )
44 : SwUndo( nUndoId ), SwUndRng( rPam ),
45 pTxtFmtColl( 0 ), pLastNdColl(0), pFrmFmts( 0 ), pRedlData( 0 ),
46 bSttWasTxtNd( sal_True ), nNdDiff( 0 ), pPos( 0 ), nSetPos( 0 )
47 {
48 pHistory = new SwHistory;
49 SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
50
51 SwTxtNode* pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
52 if( pTxtNd )
53 {
54 pTxtFmtColl = pTxtNd->GetTxtColl();
55 pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
56 0, pTxtNd->GetTxt().Len(), false );
57 if( pTxtNd->HasSwAttrSet() )
58 pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
59
60 if( !nSttCntnt ) // dann werden Flys mitgenommen !!
61 {
62 sal_uInt16 nArrLen = pDoc->GetSpzFrmFmts()->Count();
63 for( sal_uInt16 n = 0; n < nArrLen; ++n )
64 {
65 SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
66 SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
67 const SwPosition* pAPos = pAnchor->GetCntntAnchor();
68 if (pAPos &&
69 (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
70 nSttNode == pAPos->nNode.GetIndex() )
71 {
72 if( !pFrmFmts )
73 pFrmFmts = new SvPtrarr;
74 pFrmFmts->Insert( pFmt, pFrmFmts->Count() );
75 }
76 }
77 }
78 }
79 // Redline beachten
80 if( pDoc->IsRedlineOn() )
81 {
82 pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->GetRedlineAuthor() );
83 SetRedlineMode( pDoc->GetRedlineMode() );
84 }
85 }
86
87 // setze den Destination-Bereich nach dem Einlesen.
88
SetInsertRange(const SwPaM & rPam,sal_Bool bScanFlys,sal_Bool bSttIsTxtNd)89 void SwUndoInserts::SetInsertRange( const SwPaM& rPam, sal_Bool bScanFlys,
90 sal_Bool bSttIsTxtNd )
91 {
92 const SwPosition* pTmpPos = rPam.End();
93 nEndNode = pTmpPos->nNode.GetIndex();
94 nEndCntnt = pTmpPos->nContent.GetIndex();
95 if( rPam.HasMark() )
96 {
97 if( pTmpPos == rPam.GetPoint() )
98 pTmpPos = rPam.GetMark();
99 else
100 pTmpPos = rPam.GetPoint();
101
102 nSttNode = pTmpPos->nNode.GetIndex();
103 nSttCntnt = pTmpPos->nContent.GetIndex();
104
105 if( !bSttIsTxtNd ) // wird eine Tabellenselektion eingefuegt,
106 {
107 ++nSttNode; // dann stimmt der CopyPam nicht ganz
108 bSttWasTxtNd = sal_False;
109 }
110 }
111
112 if( bScanFlys && !nSttCntnt )
113 {
114 // dann alle neuen Flys zusammen sammeln !!
115 SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
116 sal_uInt16 nFndPos, nArrLen = pDoc->GetSpzFrmFmts()->Count();
117 for( sal_uInt16 n = 0; n < nArrLen; ++n )
118 {
119 SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
120 SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
121 SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
122 if (pAPos &&
123 (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
124 nSttNode == pAPos->nNode.GetIndex() )
125 {
126 if( !pFrmFmts ||
127 USHRT_MAX == ( nFndPos = pFrmFmts->GetPos( pFmt ) ) )
128 {
129 ::boost::shared_ptr<SwUndoInsLayFmt> const pFlyUndo(
130 new SwUndoInsLayFmt(pFmt, 0, 0));
131 m_FlyUndos.push_back(pFlyUndo);
132 }
133 else
134 pFrmFmts->Remove( nFndPos );
135 }
136 }
137 delete pFrmFmts, pFrmFmts = 0;
138 }
139 }
140
141
~SwUndoInserts()142 SwUndoInserts::~SwUndoInserts()
143 {
144 if( pPos ) // loesche noch den Bereich aus dem UndoNodes Array
145 {
146 // Insert speichert den Inhalt in der IconSection
147 SwNodes& rUNds = pPos->nNode.GetNodes();
148 if( pPos->nContent.GetIndex() ) // nicht den gesamten Node loeschen
149 {
150 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
151 ASSERT( pTxtNd, "kein TextNode, aus dem geloescht werden soll" );
152 if( pTxtNd ) // Robust
153 {
154 pTxtNd->EraseText( pPos->nContent );
155 }
156 pPos->nNode++;
157 }
158 pPos->nContent.Assign( 0, 0 );
159 rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() -
160 pPos->nNode.GetIndex() );
161 delete pPos;
162 }
163 delete pFrmFmts;
164 delete pRedlData;
165 }
166
167
UndoImpl(::sw::UndoRedoContext & rContext)168 void SwUndoInserts::UndoImpl(::sw::UndoRedoContext & rContext)
169 {
170 SwDoc *const pDoc = & rContext.GetDoc();
171 SwPaM *const pPam = & AddUndoRedoPaM(rContext);
172
173 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
174 pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
175
176 // sind an Point/Mark 2 unterschiedliche TextNodes, dann muss ein
177 // JoinNext ausgefuehrt werden.
178 sal_Bool bJoinNext = nSttNode != nEndNode &&
179 pPam->GetMark()->nNode.GetNode().GetTxtNode() &&
180 pPam->GetPoint()->nNode.GetNode().GetTxtNode();
181
182
183 // gibts ueberhaupt Inhalt ? (laden von Zeichenvorlagen hat kein Inhalt!)
184 if( nSttNode != nEndNode || nSttCntnt != nEndCntnt )
185 {
186 if( nSttNode != nEndNode )
187 {
188 SwTxtNode* pTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
189 if( pTxtNd && pTxtNd->GetTxt().Len() == nEndCntnt )
190 pLastNdColl = pTxtNd->GetTxtColl();
191 }
192
193 RemoveIdxFromRange( *pPam, sal_False );
194 SetPaM(*pPam);
195
196 // sind Fussnoten oder CntntFlyFrames im Text ??
197 nSetPos = pHistory->Count();
198 nNdDiff = pPam->GetMark()->nNode.GetIndex();
199 DelCntntIndex( *pPam->GetMark(), *pPam->GetPoint() );
200 nNdDiff -= pPam->GetMark()->nNode.GetIndex();
201
202 if( *pPam->GetPoint() != *pPam->GetMark() )
203 {
204 pPos = new SwPosition( *pPam->GetPoint() );
205 MoveToUndoNds( *pPam, &pPos->nNode, &pPos->nContent );
206
207 if( !bSttWasTxtNd )
208 pPam->Move( fnMoveBackward, fnGoCntnt );
209 }
210 }
211
212 if (m_FlyUndos.size())
213 {
214 sal_uLong nTmp = pPam->GetPoint()->nNode.GetIndex();
215 for (size_t n = m_FlyUndos.size(); 0 < n; --n)
216 {
217 m_FlyUndos[ n-1 ]->UndoImpl(rContext);
218 }
219 nNdDiff += nTmp - pPam->GetPoint()->nNode.GetIndex();
220 }
221
222 SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
223 SwTxtNode* pTxtNode = rIdx.GetNode().GetTxtNode();
224 if( pTxtNode )
225 {
226 if( !pTxtFmtColl ) // falls 0, dann war hier auch kein TextNode,
227 { // dann muss dieser geloescht werden,
228 SwNodeIndex aDelIdx( rIdx );
229 rIdx++;
230 SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
231 xub_StrLen nCnt = 0; if( pCNd ) nCnt = pCNd->Len();
232 pPam->GetPoint()->nContent.Assign( pCNd, nCnt );
233 pPam->SetMark();
234 pPam->DeleteMark();
235
236 RemoveIdxRel( aDelIdx.GetIndex(), *pPam->GetPoint() );
237
238 pDoc->GetNodes().Delete( aDelIdx, 1 );
239 }
240 else
241 {
242 if( bJoinNext && pTxtNode->CanJoinNext())
243 {
244 {
245 RemoveIdxRel( rIdx.GetIndex()+1, SwPosition( rIdx,
246 SwIndex( pTxtNode, pTxtNode->GetTxt().Len() )));
247 }
248 pTxtNode->JoinNext();
249 }
250 // reset all text attributes in the paragraph!
251 pTxtNode->RstTxtAttr( SwIndex(pTxtNode, 0), pTxtNode->Len(), 0, 0, true );
252
253 // setze alle Attribute im Node zurueck
254 pTxtNode->ResetAllAttr();
255
256 if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
257 pTxtFmtColl = (SwTxtFmtColl*)pTxtNode->ChgFmtColl( pTxtFmtColl );
258
259 pHistory->SetTmpEnd( nSetPos );
260 pHistory->TmpRollback( pDoc, 0, false );
261 }
262 }
263 }
264
RedoImpl(::sw::UndoRedoContext & rContext)265 void SwUndoInserts::RedoImpl(::sw::UndoRedoContext & rContext)
266 {
267 // setze noch den Cursor auf den Redo-Bereich
268 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
269 SwDoc* pDoc = pPam->GetDoc();
270 pPam->DeleteMark();
271 pPam->GetPoint()->nNode = nSttNode - nNdDiff;
272 SwCntntNode* pCNd = pPam->GetCntntNode();
273 pPam->GetPoint()->nContent.Assign( pCNd, nSttCntnt );
274
275 SwTxtFmtColl* pSavTxtFmtColl = pTxtFmtColl;
276 if( pTxtFmtColl && pCNd && pCNd->IsTxtNode() )
277 pSavTxtFmtColl = ((SwTxtNode*)pCNd)->GetTxtColl();
278
279 pHistory->SetTmpEnd( nSetPos );
280
281 // alte Anfangs-Position fuers Rollback zurueckholen
282 if( ( nSttNode != nEndNode || nSttCntnt != nEndCntnt ) && pPos )
283 {
284 sal_Bool bMvBkwrd = MovePtBackward( *pPam );
285
286 // Inhalt wieder einfuegen. (erst pPos abmelden !!)
287 sal_uLong nMvNd = pPos->nNode.GetIndex();
288 xub_StrLen nMvCnt = pPos->nContent.GetIndex();
289 DELETEZ( pPos );
290 MoveFromUndoNds( *pDoc, nMvNd, nMvCnt, *pPam->GetMark() );
291 if( bSttWasTxtNd )
292 MovePtForward( *pPam, bMvBkwrd );
293 pPam->Exchange();
294 }
295
296 if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
297 {
298 SwTxtNode* pTxtNd = pPam->GetMark()->nNode.GetNode().GetTxtNode();
299 if( pTxtNd )
300 pTxtNd->ChgFmtColl( pTxtFmtColl );
301 }
302 pTxtFmtColl = pSavTxtFmtColl;
303
304 if( pLastNdColl && USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pLastNdColl ) &&
305 pPam->GetPoint()->nNode != pPam->GetMark()->nNode )
306 {
307 SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode();
308 if( pTxtNd )
309 pTxtNd->ChgFmtColl( pLastNdColl );
310 }
311
312 for (size_t n = m_FlyUndos.size(); 0 < n; --n)
313 {
314 m_FlyUndos[ n-1 ]->RedoImpl(rContext);
315 }
316
317 pHistory->Rollback( pDoc, nSetPos );
318
319 if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
320 {
321 RedlineMode_t eOld = pDoc->GetRedlineMode();
322 pDoc->SetRedlineMode_intern((RedlineMode_t)( eOld & ~nsRedlineMode_t::REDLINE_IGNORE ));
323 pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
324 pDoc->SetRedlineMode_intern( eOld );
325 }
326 else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
327 pDoc->GetRedlineTbl().Count() )
328 pDoc->SplitRedline( *pPam );
329 }
330
RepeatImpl(::sw::RepeatContext & rContext)331 void SwUndoInserts::RepeatImpl(::sw::RepeatContext & rContext)
332 {
333 SwPaM aPam( rContext.GetDoc().GetNodes().GetEndOfContent() );
334 SetPaM( aPam );
335 SwPaM & rRepeatPaM( rContext.GetRepeatPaM() );
336 aPam.GetDoc()->CopyRange( aPam, *rRepeatPaM.GetPoint(), false );
337 }
338
339
340 //////////////////////////////////////////////////////////////////////////
341
SwUndoInsDoc(const SwPaM & rPam)342 SwUndoInsDoc::SwUndoInsDoc( const SwPaM& rPam )
343 : SwUndoInserts( UNDO_INSDOKUMENT, rPam )
344 {
345 }
346
SwUndoCpyDoc(const SwPaM & rPam)347 SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM& rPam )
348 : SwUndoInserts( UNDO_COPY, rPam )
349 {
350 }
351
352