xref: /trunk/main/editeng/source/editeng/editundo.cxx (revision 2407af082dace66c1b57237797ea1e24af5fe607)
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_editeng.hxx"
26 
27 #include <eeng_pch.hxx>
28 
29 #include <impedit.hxx>
30 #include <editundo.hxx>
31 #include <editeng/editview.hxx>
32 #include <editeng/editeng.hxx>
33 
34 DBG_NAME( EditUndo )
35 
36 #define MAX_UNDOS   100     // ab dieser Menge darf geloescht werden....
37 #define MIN_UNDOS   50      // soviel muss stehen bleiben...
38 
39 #define NO_UNDO         0xFFFF
40 #define GROUP_NOTFOUND  0xFFFF
41 
42 TYPEINIT1( EditUndo, SfxUndoAction );
43 TYPEINIT1( EditUndoDelContent, EditUndo );
44 TYPEINIT1( EditUndoConnectParas, EditUndo );
45 TYPEINIT1( EditUndoSplitPara, EditUndo );
46 TYPEINIT1( EditUndoInsertChars, EditUndo );
47 TYPEINIT1( EditUndoRemoveChars, EditUndo );
48 TYPEINIT1( EditUndoInsertFeature, EditUndo );
49 TYPEINIT1( EditUndoMoveParagraphs, EditUndo );
50 TYPEINIT1( EditUndoSetStyleSheet, EditUndo );
51 TYPEINIT1( EditUndoSetParaAttribs, EditUndo );
52 TYPEINIT1( EditUndoSetAttribs, EditUndo );
53 TYPEINIT1( EditUndoTransliteration, EditUndo );
54 TYPEINIT1( EditUndoMarkSelection, EditUndo );
55 
56 void lcl_DoSetSelection( EditView* pView, sal_uInt16 nPara )
57 {
58     EPaM aEPaM( nPara, 0 );
59     EditPaM aPaM( pView->GetImpEditEngine()->CreateEditPaM( aEPaM ) );
60     aPaM.SetIndex( aPaM.GetNode()->Len() );
61     EditSelection aSel( aPaM, aPaM );
62     pView->GetImpEditView()->SetEditSelection( aSel );
63 }
64 
65 // -----------------------------------------------------------------------
66 // EditUndoManager
67 // ------------------------------------------------------------------------
68 EditUndoManager::EditUndoManager( ImpEditEngine* p )
69 {
70     pImpEE = p;
71 }
72 
73 sal_Bool __EXPORT EditUndoManager::Undo()
74 {
75     if ( GetUndoActionCount() == 0 )
76         return sal_False;
77 
78     DBG_ASSERT( pImpEE->GetActiveView(), "Active View?" );
79 
80     if ( !pImpEE->GetActiveView() )
81     {
82         if ( pImpEE->GetEditViews().Count() )
83             pImpEE->SetActiveView( pImpEE->GetEditViews().GetObject(0) );
84         else
85         {
86             DBG_ERROR( "Undo in Engine ohne View nicht moeglich!" );
87             return sal_False;
88         }
89     }
90 
91     pImpEE->GetActiveView()->GetImpEditView()->DrawSelection(); // alte Selektion entfernen
92 
93     pImpEE->SetUndoMode( sal_True );
94     sal_Bool bDone = SfxUndoManager::Undo();
95     pImpEE->SetUndoMode( sal_False );
96 
97     EditSelection aNewSel( pImpEE->GetActiveView()->GetImpEditView()->GetEditSelection() );
98     DBG_ASSERT( !aNewSel.IsInvalid(), "Ungueltige Selektion nach Undo()" );
99     DBG_ASSERT( !aNewSel.DbgIsBuggy( pImpEE->GetEditDoc() ), "Kaputte Selektion nach Undo()" );
100 
101     aNewSel.Min() = aNewSel.Max();
102     pImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
103     pImpEE->FormatAndUpdate( pImpEE->GetActiveView() );
104 
105     return bDone;
106 }
107 
108 sal_Bool __EXPORT EditUndoManager::Redo()
109 {
110     if ( GetRedoActionCount() == 0 )
111         return sal_False;
112 
113     DBG_ASSERT( pImpEE->GetActiveView(), "Active View?" );
114 
115     if ( !pImpEE->GetActiveView() )
116     {
117         if ( pImpEE->GetEditViews().Count() )
118             pImpEE->SetActiveView( pImpEE->GetEditViews().GetObject(0) );
119         else
120         {
121             DBG_ERROR( "Redo in Engine ohne View nicht moeglich!" );
122             return sal_False;
123         }
124     }
125 
126     pImpEE->GetActiveView()->GetImpEditView()->DrawSelection(); // alte Selektion entfernen
127 
128     pImpEE->SetUndoMode( sal_True );
129     sal_Bool bDone = SfxUndoManager::Redo();
130     pImpEE->SetUndoMode( sal_False );
131 
132     EditSelection aNewSel( pImpEE->GetActiveView()->GetImpEditView()->GetEditSelection() );
133     DBG_ASSERT( !aNewSel.IsInvalid(), "Ungueltige Selektion nach Undo()" );
134     DBG_ASSERT( !aNewSel.DbgIsBuggy( pImpEE->GetEditDoc() ), "Kaputte Selektion nach Redo()" );
135 
136     aNewSel.Min() = aNewSel.Max();
137     pImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
138     pImpEE->FormatAndUpdate( pImpEE->GetActiveView() );
139 
140     return bDone;
141 }
142 
143 // -----------------------------------------------------------------------
144 // EditUndo
145 // ------------------------------------------------------------------------
146 EditUndo::EditUndo( sal_uInt16 nI, ImpEditEngine* p )
147 {
148     DBG_CTOR( EditUndo, 0 );
149     nId = nI;
150     pImpEE = p;
151 }
152 
153 EditUndo::~EditUndo()
154 {
155     DBG_DTOR( EditUndo, 0 );
156 }
157 
158 sal_uInt16 __EXPORT EditUndo::GetId() const
159 {
160     DBG_CHKTHIS( EditUndo, 0 );
161     return nId;
162 }
163 
164 sal_Bool __EXPORT EditUndo::CanRepeat(SfxRepeatTarget&) const
165 {
166     return sal_False;
167 }
168 
169 XubString __EXPORT EditUndo::GetComment() const
170 {
171     XubString aComment;
172     if ( pImpEE )
173     {
174         EditEngine* pEditEng = pImpEE->GetEditEnginePtr();
175         aComment = pEditEng->GetUndoComment( GetId() );
176     }
177     return aComment;
178 }
179 
180 // -----------------------------------------------------------------------
181 // EditUndoDelContent
182 // ------------------------------------------------------------------------
183 EditUndoDelContent::EditUndoDelContent( ImpEditEngine* _pImpEE, ContentNode* pNode, sal_uInt16 n )
184                     : EditUndo( EDITUNDO_DELCONTENT, _pImpEE )
185 {
186     pContentNode = pNode;
187     nNode = n;
188     bDelObject = sal_True;
189 }
190 
191 EditUndoDelContent::~EditUndoDelContent()
192 {
193     if ( bDelObject )
194         delete pContentNode;
195 }
196 
197 void __EXPORT EditUndoDelContent::Undo()
198 {
199     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
200     GetImpEditEngine()->InsertContent( pContentNode, nNode );
201     bDelObject = sal_False; // gehoert wieder der Engine
202     EditSelection aSel( EditPaM( pContentNode, 0 ), EditPaM( pContentNode, pContentNode->Len() ) );
203     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
204 }
205 
206 void __EXPORT EditUndoDelContent::Redo()
207 {
208     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
209 
210     ImpEditEngine* _pImpEE = GetImpEditEngine();
211 
212     // pNode stimmt nicht mehr, falls zwischendurch Undos, in denen
213     // Absaetze verschmolzen sind.
214     pContentNode = _pImpEE->GetEditDoc().SaveGetObject( nNode );
215     DBG_ASSERT( pContentNode, "EditUndoDelContent::Redo(): Node?!" );
216 
217     delete _pImpEE->GetParaPortions()[nNode];
218     _pImpEE->GetParaPortions().Remove( nNode );
219 
220     // Node nicht loeschen, haengt im Undo!
221     _pImpEE->GetEditDoc().Remove( nNode );
222     if( _pImpEE->IsCallParaInsertedOrDeleted() )
223         _pImpEE->GetEditEnginePtr()->ParagraphDeleted( nNode );
224 
225     DeletedNodeInfo* pInf = new DeletedNodeInfo( (sal_uLong)pContentNode, nNode );
226     _pImpEE->aDeletedNodes.Insert( pInf, _pImpEE->aDeletedNodes.Count() );
227     _pImpEE->UpdateSelections();
228 
229     ContentNode* pN = ( nNode < _pImpEE->GetEditDoc().Count() )
230         ? _pImpEE->GetEditDoc().SaveGetObject( nNode )
231         : _pImpEE->GetEditDoc().SaveGetObject( nNode-1 );
232     DBG_ASSERT( pN && ( pN != pContentNode ), "?! RemoveContent !? " );
233     EditPaM aPaM( pN, pN->Len() );
234 
235     bDelObject = sal_True;  // gehoert wieder dem Undo
236 
237     _pImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
238 }
239 
240 // -----------------------------------------------------------------------
241 // EditUndoConnectParas
242 // ------------------------------------------------------------------------
243 EditUndoConnectParas::EditUndoConnectParas( ImpEditEngine* _pImpEE, sal_uInt16 nN, sal_uInt16 nSP,
244                                             const SfxItemSet& rLeftParaAttribs, const SfxItemSet& rRightParaAttribs,
245                                             const SfxStyleSheet* pLeftStyle, const SfxStyleSheet* pRightStyle, sal_Bool bBkwrd )
246                     :   EditUndo( EDITUNDO_CONNECTPARAS, _pImpEE ),
247                         aLeftParaAttribs( rLeftParaAttribs ),
248                         aRightParaAttribs( rRightParaAttribs )
249 {
250     nNode   = nN;
251     nSepPos = nSP;
252 
253     if ( pLeftStyle )
254     {
255         aLeftStyleName = pLeftStyle->GetName();
256         eLeftStyleFamily = pLeftStyle->GetFamily();
257     }
258     if ( pRightStyle )
259     {
260         aRightStyleName = pRightStyle->GetName();
261         eRightStyleFamily = pRightStyle->GetFamily();
262     }
263 
264     bBackward = bBkwrd;
265 }
266 
267 EditUndoConnectParas::~EditUndoConnectParas()
268 {
269 }
270 
271 void __EXPORT EditUndoConnectParas::Undo()
272 {
273     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
274 
275     // Bei SplitContent darf noch kein ParagraphInserted gerufen werden,
276     // weil der Outliner sich auf die Attribute verlaesst um die Tiefe
277     // des Absatzes zu initialisieren
278 
279     sal_Bool bCall = GetImpEditEngine()->IsCallParaInsertedOrDeleted();
280     GetImpEditEngine()->SetCallParaInsertedOrDeleted( sal_False );
281 
282     EditPaM aPaM = GetImpEditEngine()->SplitContent( nNode, nSepPos );
283     GetImpEditEngine()->SetParaAttribs( nNode, aLeftParaAttribs );
284     GetImpEditEngine()->SetParaAttribs( nNode+1, aRightParaAttribs );
285 
286     GetImpEditEngine()->SetCallParaInsertedOrDeleted( bCall );
287     if ( GetImpEditEngine()->IsCallParaInsertedOrDeleted() )
288         GetImpEditEngine()->GetEditEnginePtr()->ParagraphInserted( nNode+1 );
289 
290     if ( GetImpEditEngine()->GetStyleSheetPool() )
291     {
292         if ( aLeftStyleName.Len() )
293             GetImpEditEngine()->SetStyleSheet( (sal_uInt16)nNode, (SfxStyleSheet*)GetImpEditEngine()->GetStyleSheetPool()->Find( aLeftStyleName, eLeftStyleFamily ) );
294         if ( aRightStyleName.Len() )
295             GetImpEditEngine()->SetStyleSheet( nNode+1, (SfxStyleSheet*)GetImpEditEngine()->GetStyleSheetPool()->Find( aRightStyleName, eRightStyleFamily ) );
296     }
297 
298     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
299 }
300 
301 void __EXPORT EditUndoConnectParas::Redo()
302 {
303     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
304     EditPaM aPaM = GetImpEditEngine()->ConnectContents( nNode, bBackward );
305 
306     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
307 }
308 
309 // -----------------------------------------------------------------------
310 // EditUndoSplitPara
311 // ------------------------------------------------------------------------
312 EditUndoSplitPara::EditUndoSplitPara( ImpEditEngine* _pImpEE, sal_uInt16 nN, sal_uInt16 nSP )
313                     : EditUndo( EDITUNDO_SPLITPARA, _pImpEE )
314 {
315     nNode   = nN;
316     nSepPos = nSP;
317 }
318 
319 EditUndoSplitPara::~EditUndoSplitPara()
320 {
321 }
322 
323 void __EXPORT EditUndoSplitPara::Undo()
324 {
325     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
326     EditPaM aPaM = GetImpEditEngine()->ConnectContents( nNode, sal_False );
327     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
328 }
329 
330 void __EXPORT EditUndoSplitPara::Redo()
331 {
332     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
333     EditPaM aPaM = GetImpEditEngine()->SplitContent( nNode, nSepPos );
334     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
335 }
336 
337 // -----------------------------------------------------------------------
338 // EditUndoInsertChars
339 // ------------------------------------------------------------------------
340 EditUndoInsertChars::EditUndoInsertChars( ImpEditEngine* _pImpEE, const EPaM& rEPaM, const XubString& rStr )
341                     : EditUndo( EDITUNDO_INSERTCHARS, _pImpEE ),
342                         aEPaM( rEPaM ), aText( rStr )
343 {
344 }
345 
346 void __EXPORT EditUndoInsertChars::Undo()
347 {
348     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
349     EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
350     EditSelection aSel( aPaM, aPaM );
351     aSel.Max().GetIndex() = aSel.Max().GetIndex() + aText.Len();
352     EditPaM aNewPaM( GetImpEditEngine()->ImpDeleteSelection( aSel ) );
353     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aNewPaM, aNewPaM ) );
354 }
355 
356 void __EXPORT EditUndoInsertChars::Redo()
357 {
358     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
359     EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
360     GetImpEditEngine()->ImpInsertText( EditSelection( aPaM, aPaM ), aText );
361     EditPaM aNewPaM( aPaM );
362     aNewPaM.GetIndex() = aNewPaM.GetIndex() + aText.Len();
363     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aNewPaM ) );
364 }
365 
366 sal_Bool __EXPORT EditUndoInsertChars::Merge( SfxUndoAction* pNextAction )
367 {
368     if ( !pNextAction->ISA( EditUndoInsertChars ) )
369         return sal_False;
370 
371     EditUndoInsertChars* pNext = (EditUndoInsertChars*)pNextAction;
372 
373     if ( aEPaM.nPara != pNext->aEPaM.nPara )
374         return sal_False;
375 
376     if ( ( aEPaM.nIndex + aText.Len() ) == pNext->aEPaM.nIndex )
377     {
378         aText += pNext->aText;
379         return sal_True;
380     }
381     return sal_False;
382 }
383 
384 // -----------------------------------------------------------------------
385 // EditUndoRemoveChars
386 // ------------------------------------------------------------------------
387 EditUndoRemoveChars::EditUndoRemoveChars( ImpEditEngine* _pImpEE, const EPaM& rEPaM, const XubString& rStr )
388                     : EditUndo( EDITUNDO_REMOVECHARS, _pImpEE ),
389                         aEPaM( rEPaM ), aText( rStr )
390 {
391 }
392 
393 void __EXPORT EditUndoRemoveChars::Undo()
394 {
395     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
396     EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
397     EditSelection aSel( aPaM, aPaM );
398     GetImpEditEngine()->ImpInsertText( aSel, aText );
399     aSel.Max().GetIndex() = aSel.Max().GetIndex() + aText.Len();
400     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
401 }
402 
403 void __EXPORT EditUndoRemoveChars::Redo()
404 {
405     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
406     EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
407     EditSelection aSel( aPaM, aPaM );
408     aSel.Max().GetIndex() = aSel.Max().GetIndex() + aText.Len();
409     EditPaM aNewPaM = GetImpEditEngine()->ImpDeleteSelection( aSel );
410     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewPaM );
411 }
412 
413 // -----------------------------------------------------------------------
414 // EditUndoInsertFeature
415 // ------------------------------------------------------------------------
416 EditUndoInsertFeature::EditUndoInsertFeature( ImpEditEngine* _pImpEE, const EPaM& rEPaM, const SfxPoolItem& rFeature)
417                     : EditUndo( EDITUNDO_INSERTFEATURE, _pImpEE ), aEPaM( rEPaM )
418 {
419     pFeature = rFeature.Clone();
420     DBG_ASSERT( pFeature, "Feature konnte nicht dupliziert werden: EditUndoInsertFeature" );
421 }
422 
423 EditUndoInsertFeature::~EditUndoInsertFeature()
424 {
425     delete pFeature;
426 }
427 
428 void __EXPORT EditUndoInsertFeature::Undo()
429 {
430     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
431     EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
432     EditSelection aSel( aPaM, aPaM );
433     // Attribute werden dort implizit vom Dokument korrigiert...
434     aSel.Max().GetIndex()++;
435     EditPaM aNewPaM = GetImpEditEngine()->ImpDeleteSelection( aSel );
436     aSel.Max().GetIndex()--;    // Fuer Selektion
437     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
438 }
439 
440 void __EXPORT EditUndoInsertFeature::Redo()
441 {
442     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
443     EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
444     EditSelection aSel( aPaM, aPaM );
445     GetImpEditEngine()->ImpInsertFeature( aSel, *pFeature );
446     if ( pFeature->Which() == EE_FEATURE_FIELD )
447         GetImpEditEngine()->UpdateFields();
448     aSel.Max().GetIndex()++;
449     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
450 }
451 
452 // -----------------------------------------------------------------------
453 // EditUndoMoveParagraphs
454 // ------------------------------------------------------------------------
455 EditUndoMoveParagraphs::EditUndoMoveParagraphs
456                             ( ImpEditEngine* _pImpEE, const Range& rParas, sal_uInt16 n )
457                             :   EditUndo( EDITUNDO_MOVEPARAGRAPHS, _pImpEE ),
458                                 nParagraphs( rParas )
459 {
460     nDest = n;
461 }
462 
463 EditUndoMoveParagraphs::~EditUndoMoveParagraphs()
464 {
465 }
466 
467 void __EXPORT EditUndoMoveParagraphs::Undo()
468 {
469     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
470     Range aTmpRange( nParagraphs );
471     long nTmpDest = aTmpRange.Min();
472 
473     long nDiff = ( nDest - aTmpRange.Min() );
474     aTmpRange.Min() += nDiff;
475     aTmpRange.Max() += nDiff;
476 
477     if ( nParagraphs.Min() < (long)nDest )
478     {
479         long nLen = aTmpRange.Len();
480         aTmpRange.Min() -= nLen;
481         aTmpRange.Max() -= nLen;
482     }
483     else
484         nTmpDest += aTmpRange.Len();
485 
486     EditSelection aNewSel( GetImpEditEngine()->MoveParagraphs( aTmpRange, (sal_uInt16)nTmpDest, 0 ) );
487     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
488 }
489 
490 void __EXPORT EditUndoMoveParagraphs::Redo()
491 {
492     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
493     EditSelection aNewSel( GetImpEditEngine()->MoveParagraphs( nParagraphs, nDest, 0 ) );
494     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
495 }
496 
497 // -----------------------------------------------------------------------
498 // EditUndoSetStyleSheet
499 // ------------------------------------------------------------------------
500 EditUndoSetStyleSheet::EditUndoSetStyleSheet( ImpEditEngine* _pImpEE, sal_uInt16 nP,
501                         const XubString& rPrevName, SfxStyleFamily ePrevFam,
502                         const XubString& rNewName, SfxStyleFamily eNewFam,
503                         const SfxItemSet& rPrevParaAttribs )
504     : EditUndo( EDITUNDO_STYLESHEET, _pImpEE ), aPrevName( rPrevName ), aNewName( rNewName ),
505       aPrevParaAttribs( rPrevParaAttribs )
506 {
507     ePrevFamily = ePrevFam;
508     eNewFamily = eNewFam;
509     nPara = nP;
510 }
511 
512 EditUndoSetStyleSheet::~EditUndoSetStyleSheet()
513 {
514 }
515 
516 void __EXPORT EditUndoSetStyleSheet::Undo()
517 {
518     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
519     GetImpEditEngine()->SetStyleSheet( nPara, (SfxStyleSheet*)GetImpEditEngine()->GetStyleSheetPool()->Find( aPrevName, ePrevFamily ) );
520     GetImpEditEngine()->SetParaAttribs( nPara, aPrevParaAttribs );
521     lcl_DoSetSelection( GetImpEditEngine()->GetActiveView(), nPara );
522 }
523 
524 void __EXPORT EditUndoSetStyleSheet::Redo()
525 {
526     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
527     GetImpEditEngine()->SetStyleSheet( nPara, (SfxStyleSheet*)GetImpEditEngine()->GetStyleSheetPool()->Find( aNewName, eNewFamily ) );
528     lcl_DoSetSelection( GetImpEditEngine()->GetActiveView(), nPara );
529 }
530 
531 // -----------------------------------------------------------------------
532 // EditUndoSetParaAttribs
533 // ------------------------------------------------------------------------
534 EditUndoSetParaAttribs::EditUndoSetParaAttribs( ImpEditEngine* _pImpEE, sal_uInt16 nP, const SfxItemSet& rPrevItems, const SfxItemSet& rNewItems )
535     : EditUndo( EDITUNDO_PARAATTRIBS, _pImpEE ),
536       aPrevItems( rPrevItems ),
537       aNewItems(rNewItems )
538 {
539     nPara = nP;
540 }
541 
542 EditUndoSetParaAttribs::~EditUndoSetParaAttribs()
543 {
544 }
545 
546 void __EXPORT EditUndoSetParaAttribs::Undo()
547 {
548     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
549     GetImpEditEngine()->SetParaAttribs( nPara, aPrevItems );
550     lcl_DoSetSelection( GetImpEditEngine()->GetActiveView(), nPara );
551 }
552 
553 void __EXPORT EditUndoSetParaAttribs::Redo()
554 {
555     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
556     GetImpEditEngine()->SetParaAttribs( nPara, aNewItems );
557     lcl_DoSetSelection( GetImpEditEngine()->GetActiveView(), nPara );
558 }
559 
560 // -----------------------------------------------------------------------
561 // EditUndoSetAttribs
562 // ------------------------------------------------------------------------
563 EditUndoSetAttribs::EditUndoSetAttribs( ImpEditEngine* _pImpEE, const ESelection& rESel, const SfxItemSet& rNewItems )
564     : EditUndo( EDITUNDO_ATTRIBS, _pImpEE ),
565       aESel( rESel ),
566       aNewAttribs( rNewItems )
567 {
568     // Wenn das EditUndoSetAttribs eigentlich ein RemoveAttribs ist, koennte
569     // man das eigentlich an einem leeren ItemSet erkennen, aber dann muesste
570     // an einigen Stellen abgefangen werden, das ggf. ein SetAttribs mit einem
571     // leeren ItemSet gemacht wird.
572     // => Ich habe lieber diesen Member spendiert...
573     bSetIsRemove = sal_False;
574     bRemoveParaAttribs = sal_False;
575     nRemoveWhich = 0;
576     nSpecial = 0;
577 }
578 
579 EditUndoSetAttribs::~EditUndoSetAttribs()
580 {
581     // Items aus Pool holen...
582     SfxItemPool* pPool = aNewAttribs.GetPool();
583     sal_uInt16 nContents = aPrevAttribs.Count();
584     for ( sal_uInt16 n = 0; n < nContents; n++ )
585     {
586         ContentAttribsInfo* pInf = aPrevAttribs[n];
587         DBG_ASSERT( pInf, "Undo_DTOR (SetAttribs): pInf = NULL!" );
588         for ( sal_uInt16 nAttr = 0; nAttr < pInf->GetPrevCharAttribs().Count(); nAttr++ )
589         {
590             EditCharAttrib* pX = pInf->GetPrevCharAttribs()[nAttr];
591             DBG_ASSERT( pX, "Undo_DTOR (SetAttribs): pX = NULL!" );
592             pPool->Remove( *pX->GetItem() );
593             delete pX;
594         }
595         delete pInf;
596     }
597 }
598 
599 void __EXPORT EditUndoSetAttribs::Undo()
600 {
601     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
602     ImpEditEngine* _pImpEE = GetImpEditEngine();
603     sal_Bool bFields = sal_False;
604     for ( sal_uInt16 nPara = aESel.nStartPara; nPara <= aESel.nEndPara; nPara++ )
605     {
606         ContentAttribsInfo* pInf = aPrevAttribs[ (sal_uInt16)(nPara-aESel.nStartPara) ];
607         DBG_ASSERT( pInf, "Undo (SetAttribs): pInf = NULL!" );
608 
609         // erstmal die Absatzattribute...
610         _pImpEE->SetParaAttribs( nPara, pInf->GetPrevParaAttribs() );
611 
612         // Dann die Zeichenattribute...
613         // Alle Attribute inkl. Features entfernen, werden wieder neu eingestellt.
614         _pImpEE->RemoveCharAttribs( nPara, 0, sal_True );
615         DBG_ASSERT( _pImpEE->GetEditDoc().SaveGetObject( nPara ), "Undo (SetAttribs): pNode = NULL!" );
616         ContentNode* pNode = _pImpEE->GetEditDoc().GetObject( nPara );
617         for ( sal_uInt16 nAttr = 0; nAttr < pInf->GetPrevCharAttribs().Count(); nAttr++ )
618         {
619             EditCharAttrib* pX = pInf->GetPrevCharAttribs()[nAttr];
620             DBG_ASSERT( pX, "Redo (SetAttribs): pX = NULL!" );
621             // wird autom. 'eingepoolt'.
622             _pImpEE->GetEditDoc().InsertAttrib( pNode, pX->GetStart(), pX->GetEnd(), *pX->GetItem() );
623             if ( pX->Which() == EE_FEATURE_FIELD )
624                 bFields = sal_True;
625         }
626     }
627     if ( bFields )
628         _pImpEE->UpdateFields();
629     ImpSetSelection( GetImpEditEngine()->GetActiveView() );
630 }
631 
632 void __EXPORT EditUndoSetAttribs::Redo()
633 {
634     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
635     ImpEditEngine* _pImpEE = GetImpEditEngine();
636 
637     EditSelection aSel( _pImpEE->CreateSel( aESel ) );
638     if ( !bSetIsRemove )
639         _pImpEE->SetAttribs( aSel, aNewAttribs, nSpecial );
640     else
641         _pImpEE->RemoveCharAttribs( aSel, bRemoveParaAttribs, nRemoveWhich );
642 
643     ImpSetSelection( GetImpEditEngine()->GetActiveView() );
644 }
645 
646 void EditUndoSetAttribs::ImpSetSelection( EditView* /*pView*/ )
647 {
648     ImpEditEngine* _pImpEE = GetImpEditEngine();
649     EditSelection aSel( _pImpEE->CreateSel( aESel ) );
650     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
651 }
652 
653 // -----------------------------------------------------------------------
654 // EditUndoTransliteration
655 // ------------------------------------------------------------------------
656 EditUndoTransliteration::EditUndoTransliteration( ImpEditEngine* _pImpEE, const ESelection& rESel, sal_Int32 nM )
657     : EditUndo( EDITUNDO_TRANSLITERATE, _pImpEE ), aOldESel( rESel )
658 {
659     nMode = nM;
660     pTxtObj = NULL;
661 }
662 
663 EditUndoTransliteration::~EditUndoTransliteration()
664 {
665     delete pTxtObj;
666 }
667 
668 void __EXPORT EditUndoTransliteration::Undo()
669 {
670     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
671 
672     ImpEditEngine* _pImpEE = GetImpEditEngine();
673 
674     EditSelection aSel( _pImpEE->CreateSel( aNewESel ) );
675 
676     // Insert text, but don't expand Atribs at the current position:
677     aSel = _pImpEE->DeleteSelected( aSel );
678     EditSelection aDelSel( aSel );
679     aSel = _pImpEE->InsertParaBreak( aSel );
680     aDelSel.Max() = aSel.Min();
681     aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs( _pImpEE->GetEditDoc().GetItemPool() );
682     EditSelection aNewSel;
683     if ( pTxtObj )
684     {
685         aNewSel = _pImpEE->InsertText( *pTxtObj, aSel );
686     }
687     else
688     {
689         aNewSel = _pImpEE->InsertText( aSel, aText );
690     }
691     if ( aNewSel.Min().GetNode() == aDelSel.Max().GetNode() )
692     {
693         aNewSel.Min().SetNode( aDelSel.Min().GetNode() );
694         aNewSel.Min().GetIndex() =
695             aNewSel.Min().GetIndex() + aDelSel.Min().GetIndex();
696     }
697     if ( aNewSel.Max().GetNode() == aDelSel.Max().GetNode() )
698     {
699         aNewSel.Max().SetNode( aDelSel.Min().GetNode() );
700         aNewSel.Max().GetIndex() =
701             aNewSel.Max().GetIndex() + aDelSel.Min().GetIndex();
702     }
703     _pImpEE->DeleteSelected( aDelSel );
704 
705     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
706 }
707 
708 void __EXPORT EditUndoTransliteration::Redo()
709 {
710     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
711     ImpEditEngine* _pImpEE = GetImpEditEngine();
712 
713     EditSelection aSel( _pImpEE->CreateSel( aOldESel ) );
714     EditSelection aNewSel = _pImpEE->TransliterateText( aSel, nMode );
715     GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
716 }
717 
718 // -----------------------------------------------------------------------
719 // EditUndoMarkSelection
720 // ------------------------------------------------------------------------
721 EditUndoMarkSelection::EditUndoMarkSelection( ImpEditEngine* _pImpEE, const ESelection& rSel )
722     : EditUndo( EDITUNDO_MARKSELECTION, _pImpEE ), aSelection( rSel )
723 {
724 }
725 
726 EditUndoMarkSelection::~EditUndoMarkSelection()
727 {
728 }
729 
730 void __EXPORT EditUndoMarkSelection::Undo()
731 {
732     DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
733     if ( GetImpEditEngine()->GetActiveView() )
734     {
735         if ( GetImpEditEngine()->IsFormatted() )
736             GetImpEditEngine()->GetActiveView()->SetSelection( aSelection );
737         else
738             GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( GetImpEditEngine()->CreateSel( aSelection ) );
739     }
740 }
741 
742 void __EXPORT EditUndoMarkSelection::Redo()
743 {
744     // Fuer Redo unwichtig, weil am Anfang der Undo-Klammerung
745 }
746 
747