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
162 pTxtNd
->EraseText( pPos
->nContent
);
166 pPos
->nContent
.Assign( 0, 0 );
167 rUNds
.Delete( pPos
->nNode
, rUNds
.GetEndOfExtras().GetIndex() -
168 pPos
->nNode
.GetIndex() );
177 void SwUndoInserts::Undo( SwUndoIter
& rUndoIter
)
179 SwPaM
* pPam
= rUndoIter
.pAktPam
;
180 SwDoc
* pDoc
= pPam
->GetDoc();
182 BOOL bUndo
= pDoc
->DoesUndo();
183 pDoc
->DoUndo( FALSE
);
185 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
186 pDoc
->DeleteRedline( *pPam
, true, USHRT_MAX
);
188 // sind an Point/Mark 2 unterschiedliche TextNodes, dann muss ein
189 // JoinNext ausgefuehrt werden.
190 BOOL bJoinNext
= nSttNode
!= nEndNode
&&
191 pPam
->GetMark()->nNode
.GetNode().GetTxtNode() &&
192 pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
195 // gibts ueberhaupt Inhalt ? (laden von Zeichenvorlagen hat kein Inhalt!)
196 if( nSttNode
!= nEndNode
|| nSttCntnt
!= nEndCntnt
)
198 if( nSttNode
!= nEndNode
)
200 SwTxtNode
* pTxtNd
= pDoc
->GetNodes()[ nEndNode
]->GetTxtNode();
201 if( pTxtNd
&& pTxtNd
->GetTxt().Len() == nEndCntnt
)
202 pLastNdColl
= pTxtNd
->GetTxtColl();
205 RemoveIdxFromRange( *pPam
, FALSE
);
208 // sind Fussnoten oder CntntFlyFrames im Text ??
209 nSetPos
= pHistory
->Count();
210 nNdDiff
= pPam
->GetMark()->nNode
.GetIndex();
211 DelCntntIndex( *pPam
->GetMark(), *pPam
->GetPoint() );
212 nNdDiff
-= pPam
->GetMark()->nNode
.GetIndex();
214 if( *pPam
->GetPoint() != *pPam
->GetMark() )
216 pPos
= new SwPosition( *pPam
->GetPoint() );
217 MoveToUndoNds( *pPam
, &pPos
->nNode
, &pPos
->nContent
);
220 pPam
->Move( fnMoveBackward
, fnGoCntnt
);
226 ULONG nTmp
= pPam
->GetPoint()->nNode
.GetIndex();
227 for( USHORT n
= pFlyUndos
->Count(); n
; )
228 (*pFlyUndos
)[ --n
]->Undo( rUndoIter
);
229 nNdDiff
+= nTmp
- pPam
->GetPoint()->nNode
.GetIndex();
232 SwNodeIndex
& rIdx
= pPam
->GetPoint()->nNode
;
233 SwTxtNode
* pTxtNode
= rIdx
.GetNode().GetTxtNode();
236 if( !pTxtFmtColl
) // falls 0, dann war hier auch kein TextNode,
237 { // dann muss dieser geloescht werden,
238 SwNodeIndex
aDelIdx( rIdx
);
240 SwCntntNode
* pCNd
= rIdx
.GetNode().GetCntntNode();
241 xub_StrLen nCnt
= 0; if( pCNd
) nCnt
= pCNd
->Len();
242 pPam
->GetPoint()->nContent
.Assign( pCNd
, nCnt
);
246 RemoveIdxRel( aDelIdx
.GetIndex(), *pPam
->GetPoint() );
248 pDoc
->GetNodes().Delete( aDelIdx
, 1 );
252 if( bJoinNext
&& pTxtNode
->CanJoinNext())
255 RemoveIdxRel( rIdx
.GetIndex()+1, SwPosition( rIdx
,
256 SwIndex( pTxtNode
, pTxtNode
->GetTxt().Len() )));
258 pTxtNode
->JoinNext();
260 // reset all text attributes in the paragraph!
261 pTxtNode
->RstAttr( SwIndex(pTxtNode
, 0), pTxtNode
->Len(),
264 // setze alle Attribute im Node zurueck
265 pTxtNode
->ResetAllAttr();
267 if( USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pTxtFmtColl
))
268 pTxtFmtColl
= (SwTxtFmtColl
*)pTxtNode
->ChgFmtColl( pTxtFmtColl
);
270 pHistory
->SetTmpEnd( nSetPos
);
271 pHistory
->TmpRollback( pDoc
, 0, false );
275 pDoc
->DoUndo( bUndo
);
276 if( pPam
!= rUndoIter
.pAktPam
)
280 void SwUndoInserts::Redo( SwUndoIter
& rUndoIter
)
282 // setze noch den Cursor auf den Redo-Bereich
283 SwPaM
* pPam
= rUndoIter
.pAktPam
;
284 SwDoc
* pDoc
= pPam
->GetDoc();
286 pPam
->GetPoint()->nNode
= nSttNode
- nNdDiff
;
287 SwCntntNode
* pCNd
= pPam
->GetCntntNode();
288 pPam
->GetPoint()->nContent
.Assign( pCNd
, nSttCntnt
);
290 SwTxtFmtColl
* pSavTxtFmtColl
= pTxtFmtColl
;
291 if( pTxtFmtColl
&& pCNd
&& pCNd
->IsTxtNode() )
292 pSavTxtFmtColl
= ((SwTxtNode
*)pCNd
)->GetTxtColl();
294 pHistory
->SetTmpEnd( nSetPos
);
296 // alte Anfangs-Position fuers Rollback zurueckholen
297 if( ( nSttNode
!= nEndNode
|| nSttCntnt
!= nEndCntnt
) && pPos
)
299 BOOL bMvBkwrd
= MovePtBackward( *pPam
);
301 // Inhalt wieder einfuegen. (erst pPos abmelden !!)
302 ULONG nMvNd
= pPos
->nNode
.GetIndex();
303 xub_StrLen nMvCnt
= pPos
->nContent
.GetIndex();
305 MoveFromUndoNds( *pDoc
, nMvNd
, nMvCnt
, *pPam
->GetMark() );
307 MovePtForward( *pPam
, bMvBkwrd
);
311 if( USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pTxtFmtColl
))
313 SwTxtNode
* pTxtNd
= pPam
->GetMark()->nNode
.GetNode().GetTxtNode();
315 pTxtNd
->ChgFmtColl( pTxtFmtColl
);
317 pTxtFmtColl
= pSavTxtFmtColl
;
319 if( pLastNdColl
&& USHRT_MAX
!= pDoc
->GetTxtFmtColls()->GetPos( pLastNdColl
) &&
320 pPam
->GetPoint()->nNode
!= pPam
->GetMark()->nNode
)
322 SwTxtNode
* pTxtNd
= pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
324 pTxtNd
->ChgFmtColl( pLastNdColl
);
328 for( USHORT n
= pFlyUndos
->Count(); n
; )
329 (*pFlyUndos
)[ --n
]->Redo( rUndoIter
);
331 pHistory
->Rollback( pDoc
, nSetPos
);
333 if( pRedlData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
335 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
336 pDoc
->SetRedlineMode_intern((RedlineMode_t
)( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
));
337 pDoc
->AppendRedline( new SwRedline( *pRedlData
, *pPam
), true);
338 pDoc
->SetRedlineMode_intern( eOld
);
340 else if( !( nsRedlineMode_t::REDLINE_IGNORE
& GetRedlineMode() ) &&
341 pDoc
->GetRedlineTbl().Count() )
342 pDoc
->SplitRedline( *pPam
);
345 void SwUndoInserts::Repeat( SwUndoIter
& rUndoIter
)
347 if( GetId() == rUndoIter
.GetLastUndoId() )
350 SwPaM
aPam( *rUndoIter
.pAktPam
->GetPoint() );
352 aPam
.GetDoc()->CopyRange( aPam
, *rUndoIter
.pAktPam
->GetPoint(), false );
354 rUndoIter
.pLastUndoObj
= this;
361 SwUndoInsDoc::SwUndoInsDoc( const SwPaM
& rPam
)
362 : SwUndoInserts( UNDO_INSDOKUMENT
, rPam
)
366 SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM
& rPam
)
367 : SwUndoInserts( UNDO_COPY
, rPam
)