1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: untblk.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <fmtanchr.hxx>
40 #include <swundo.hxx> // fuer die UndoIds
45 #include <redline.hxx>
49 SwUndoInserts::SwUndoInserts( SwUndoId nUndoId
, const SwPaM
& rPam
)
50 : SwUndo( nUndoId
), SwUndRng( rPam
),
51 pTxtFmtColl( 0 ), pLastNdColl(0), pFrmFmts( 0 ), pFlyUndos(0), pRedlData( 0 ),
52 bSttWasTxtNd( TRUE
), nNdDiff( 0 ), pPos( 0 ), nSetPos( 0 )
54 pHistory
= new SwHistory
;
55 SwDoc
* pDoc
= (SwDoc
*)rPam
.GetDoc();
57 SwTxtNode
* pTxtNd
= rPam
.GetPoint()->nNode
.GetNode().GetTxtNode();
60 pTxtFmtColl
= pTxtNd
->GetTxtColl();
61 pHistory
->CopyAttr( pTxtNd
->GetpSwpHints(), nSttNode
,
62 0, pTxtNd
->GetTxt().Len(), false );
63 if( pTxtNd
->HasSwAttrSet() )
64 pHistory
->CopyFmtAttr( *pTxtNd
->GetpSwAttrSet(), nSttNode
);
66 if( !nSttCntnt
) // dann werden Flys mitgenommen !!
68 USHORT nArrLen
= pDoc
->GetSpzFrmFmts()->Count();
69 for( USHORT n
= 0; n
< nArrLen
; ++n
)
71 SwFrmFmt
* pFmt
= (*pDoc
->GetSpzFrmFmts())[n
];
72 const SwFmtAnchor
* pAnchor
= &pFmt
->GetAnchor();
73 const SwPosition
* pAPos
;
74 if ( pAnchor
->GetAnchorId() == FLY_AT_CNTNT
&&
75 0 != ( pAPos
= pAnchor
->GetCntntAnchor()) &&
76 nSttNode
== pAPos
->nNode
.GetIndex() )
79 pFrmFmts
= new SvPtrarr
;
80 pFrmFmts
->Insert( pFmt
, pFrmFmts
->Count() );
86 if( pDoc
->IsRedlineOn() )
88 pRedlData
= new SwRedlineData( nsRedlineType_t::REDLINE_INSERT
, pDoc
->GetRedlineAuthor() );
89 SetRedlineMode( pDoc
->GetRedlineMode() );
93 // setze den Destination-Bereich nach dem Einlesen.
95 void SwUndoInserts::SetInsertRange( const SwPaM
& rPam
, BOOL bScanFlys
,
98 const SwPosition
* pTmpPos
= rPam
.End();
99 nEndNode
= pTmpPos
->nNode
.GetIndex();
100 nEndCntnt
= pTmpPos
->nContent
.GetIndex();
103 if( pTmpPos
== rPam
.GetPoint() )
104 pTmpPos
= rPam
.GetMark();
106 pTmpPos
= rPam
.GetPoint();
108 nSttNode
= pTmpPos
->nNode
.GetIndex();
109 nSttCntnt
= pTmpPos
->nContent
.GetIndex();
111 if( !bSttIsTxtNd
) // wird eine Tabellenselektion eingefuegt,
113 ++nSttNode
; // dann stimmt der CopyPam nicht ganz
114 bSttWasTxtNd
= FALSE
;
118 if( bScanFlys
&& !nSttCntnt
)
120 // dann alle neuen Flys zusammen sammeln !!
121 SwDoc
* pDoc
= (SwDoc
*)rPam
.GetDoc();
122 pFlyUndos
= new SwUndos();
123 USHORT nFndPos
, nArrLen
= pDoc
->GetSpzFrmFmts()->Count();
124 for( USHORT n
= 0; n
< nArrLen
; ++n
)
126 SwFrmFmt
* pFmt
= (*pDoc
->GetSpzFrmFmts())[n
];
127 const SwFmtAnchor
* pAnchor
= &pFmt
->GetAnchor();
128 const SwPosition
* pAPos
;
129 if( pAnchor
->GetAnchorId() == FLY_AT_CNTNT
&&
130 0 != ( pAPos
= pAnchor
->GetCntntAnchor()) &&
131 nSttNode
== pAPos
->nNode
.GetIndex() )
134 USHRT_MAX
== ( nFndPos
= pFrmFmts
->GetPos( pFmt
) ) )
136 SwUndoInsLayFmt
* pFlyUndo
= new SwUndoInsLayFmt( pFmt
,0,0 );
137 pFlyUndos
->Insert( pFlyUndo
, pFlyUndos
->Count() );
140 pFrmFmts
->Remove( nFndPos
);
143 delete pFrmFmts
, pFrmFmts
= 0;
144 if( !pFlyUndos
->Count() )
145 delete pFlyUndos
, pFlyUndos
= 0;
150 SwUndoInserts::~SwUndoInserts()
152 if( pPos
) // loesche noch den Bereich aus dem UndoNodes Array
154 // Insert speichert den Inhalt in der IconSection
155 SwNodes
& rUNds
= pPos
->nNode
.GetNodes();
156 if( pPos
->nContent
.GetIndex() ) // nicht den gesamten Node loeschen
158 SwTxtNode
* pTxtNd
= pPos
->nNode
.GetNode().GetTxtNode();
159 ASSERT( pTxtNd
, "kein TextNode, aus dem geloescht werden soll" );
160 if( pTxtNd
) // Robust
161 pTxtNd
->Erase( pPos
->nContent
);
164 pPos
->nContent
.Assign( 0, 0 );
165 rUNds
.Delete( pPos
->nNode
, rUNds
.GetEndOfExtras().GetIndex() -
166 pPos
->nNode
.GetIndex() );
175 void SwUndoInserts::Undo( SwUndoIter
& rUndoIter
)
177 SwPaM
* pPam
= rUndoIter
.pAktPam
;
178 SwDoc
* pDoc
= pPam
->GetDoc();
180 BOOL bUndo
= pDoc
->DoesUndo();
181 pDoc
->DoUndo( FALSE
);
183 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
184 pDoc
->DeleteRedline( *pPam
, true, USHRT_MAX
);
186 // sind an Point/Mark 2 unterschiedliche TextNodes, dann muss ein
187 // JoinNext ausgefuehrt werden.
188 BOOL bJoinNext
= nSttNode
!= nEndNode
&&
189 pPam
->GetMark()->nNode
.GetNode().GetTxtNode() &&
190 pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
193 // gibts ueberhaupt Inhalt ? (laden von Zeichenvorlagen hat kein Inhalt!)
194 if( nSttNode
!= nEndNode
|| nSttCntnt
!= nEndCntnt
)
196 if( nSttNode
!= nEndNode
)
198 SwTxtNode
* pTxtNd
= pDoc
->GetNodes()[ nEndNode
]->GetTxtNode();
199 if( pTxtNd
&& pTxtNd
->GetTxt().Len() == nEndCntnt
)
200 pLastNdColl
= pTxtNd
->GetTxtColl();
203 RemoveIdxFromRange( *pPam
, FALSE
);
206 // sind Fussnoten oder CntntFlyFrames im Text ??
207 nSetPos
= pHistory
->Count();
208 nNdDiff
= pPam
->GetMark()->nNode
.GetIndex();
209 DelCntntIndex( *pPam
->GetMark(), *pPam
->GetPoint() );
210 nNdDiff
-= pPam
->GetMark()->nNode
.GetIndex();
212 if( *pPam
->GetPoint() != *pPam
->GetMark() )
214 pPos
= new SwPosition( *pPam
->GetPoint() );
215 MoveToUndoNds( *pPam
, &pPos
->nNode
, &pPos
->nContent
);
218 pPam
->Move( fnMoveBackward
, fnGoCntnt
);
224 ULONG nTmp
= pPam
->GetPoint()->nNode
.GetIndex();
225 for( USHORT n
= pFlyUndos
->Count(); n
; )
226 (*pFlyUndos
)[ --n
]->Undo( rUndoIter
);
227 nNdDiff
+= nTmp
- pPam
->GetPoint()->nNode
.GetIndex();
230 SwNodeIndex
& rIdx
= pPam
->GetPoint()->nNode
;
231 SwTxtNode
* pTxtNode
= rIdx
.GetNode().GetTxtNode();
234 if( !pTxtFmtColl
) // falls 0, dann war hier auch kein TextNode,
235 { // dann muss dieser geloescht werden,
236 SwNodeIndex
aDelIdx( rIdx
);
238 SwCntntNode
* pCNd
= rIdx
.GetNode().GetCntntNode();
239 xub_StrLen nCnt
= 0; if( pCNd
) nCnt
= pCNd
->Len();
240 pPam
->GetPoint()->nContent
.Assign( pCNd
, nCnt
);
244 RemoveIdxRel( aDelIdx
.GetIndex(), *pPam
->GetPoint() );
246 pDoc
->GetNodes().Delete( aDelIdx
, 1 );
250 pDoc
->RstTxtAttrs( *pPam
, TRUE
);
251 if( bJoinNext
&& pTxtNode
->CanJoinNext())
254 RemoveIdxRel( rIdx
.GetIndex()+1, SwPosition( rIdx
,
255 SwIndex( pTxtNode
, pTxtNode
->GetTxt().Len() )));
257 pTxtNode
->JoinNext();
260 // setze alle Attribute im Node zurueck
261 pTxtNode
->ResetAllAttr();
263 if( USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pTxtFmtColl
))
264 pTxtFmtColl
= (SwTxtFmtColl
*)pTxtNode
->ChgFmtColl( pTxtFmtColl
);
266 pHistory
->SetTmpEnd( nSetPos
);
267 pHistory
->TmpRollback( pDoc
, 0, false );
271 pDoc
->DoUndo( bUndo
);
272 if( pPam
!= rUndoIter
.pAktPam
)
276 void SwUndoInserts::Redo( SwUndoIter
& rUndoIter
)
278 // setze noch den Cursor auf den Redo-Bereich
279 SwPaM
* pPam
= rUndoIter
.pAktPam
;
280 SwDoc
* pDoc
= pPam
->GetDoc();
282 pPam
->GetPoint()->nNode
= nSttNode
- nNdDiff
;
283 SwCntntNode
* pCNd
= pPam
->GetCntntNode();
284 pPam
->GetPoint()->nContent
.Assign( pCNd
, nSttCntnt
);
286 SwTxtFmtColl
* pSavTxtFmtColl
= pTxtFmtColl
;
287 if( pTxtFmtColl
&& pCNd
&& pCNd
->IsTxtNode() )
288 pSavTxtFmtColl
= ((SwTxtNode
*)pCNd
)->GetTxtColl();
290 pHistory
->SetTmpEnd( nSetPos
);
291 pHistory
->TmpRollback( pDoc
, 0, false );
293 // alte Anfangs-Position fuers Rollback zurueckholen
294 if( ( nSttNode
!= nEndNode
|| nSttCntnt
!= nEndCntnt
) && pPos
)
296 BOOL bMvBkwrd
= MovePtBackward( *pPam
);
298 // Inhalt wieder einfuegen. (erst pPos abmelden !!)
299 ULONG nMvNd
= pPos
->nNode
.GetIndex();
300 xub_StrLen nMvCnt
= pPos
->nContent
.GetIndex();
302 MoveFromUndoNds( *pDoc
, nMvNd
, nMvCnt
, *pPam
->GetMark() );
304 MovePtForward( *pPam
, bMvBkwrd
);
308 if( USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pTxtFmtColl
))
310 SwTxtNode
* pTxtNd
= pPam
->GetMark()->nNode
.GetNode().GetTxtNode();
312 pTxtNd
->ChgFmtColl( pTxtFmtColl
);
314 pTxtFmtColl
= pSavTxtFmtColl
;
316 if( pLastNdColl
&& USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pLastNdColl
) &&
317 pPam
->GetPoint()->nNode
!= pPam
->GetMark()->nNode
)
319 SwTxtNode
* pTxtNd
= pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
321 pTxtNd
->ChgFmtColl( pLastNdColl
);
325 for( USHORT n
= pFlyUndos
->Count(); n
; )
326 (*pFlyUndos
)[ --n
]->Redo( rUndoIter
);
328 pHistory
->Rollback( pDoc
, nSetPos
);
330 if( pRedlData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
332 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
333 pDoc
->SetRedlineMode_intern((RedlineMode_t
)( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
));
334 pDoc
->AppendRedline( new SwRedline( *pRedlData
, *pPam
), true);
335 pDoc
->SetRedlineMode_intern( eOld
);
337 else if( !( nsRedlineMode_t::REDLINE_IGNORE
& GetRedlineMode() ) &&
338 pDoc
->GetRedlineTbl().Count() )
339 pDoc
->SplitRedline( *pPam
);
342 void SwUndoInserts::Repeat( SwUndoIter
& rUndoIter
)
344 if( GetId() == rUndoIter
.GetLastUndoId() )
347 SwPaM
aPam( *rUndoIter
.pAktPam
->GetPoint() );
349 aPam
.GetDoc()->Copy( aPam
, *rUndoIter
.pAktPam
->GetPoint(), false );
351 rUndoIter
.pLastUndoObj
= this;
358 SwUndoInsDoc::SwUndoInsDoc( const SwPaM
& rPam
)
359 : SwUndoInserts( UNDO_INSDOKUMENT
, rPam
)
363 SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM
& rPam
)
364 : SwUndoInserts( UNDO_COPY
, rPam
)