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: docundo.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"
34 #include <svx/svdmodel.hxx>
36 #include <vcl/wrkwin.hxx>
40 #include <swundo.hxx> // fuer die UndoIds
49 using namespace ::com::sun::star
;
52 USHORT
SwDoc::nUndoActions
= UNDO_ACTION_COUNT
; // anzahl von Undo-Action
54 // the undo array should never grow beyond this limit:
55 #define UNDO_ACTION_LIMIT (USHRT_MAX - 1000)
58 SV_IMPL_PTRARR( SwUndoIds
, SwUndoIdAndNamePtr
)
60 //#define _SHOW_UNDORANGE
61 #ifdef _SHOW_UNDORANGE
64 class UndoArrStatus
: public WorkWindow
66 USHORT nUndo
, nUndoNds
;
67 virtual void Paint( const Rectangle
& );
70 void Set( USHORT
, USHORT
);
72 static UndoArrStatus
* pUndoMsgWin
= 0;
75 UndoArrStatus::UndoArrStatus()
76 : WorkWindow( APP_GETAPPWINDOW() ), nUndo(0), nUndoNds(0)
78 SetSizePixel( Size( 200, 100 ));
79 SetFont( Font( "Courier", Size( 0, 10 )) );
84 void UndoArrStatus::Set( USHORT n1
, USHORT n2
)
86 nUndo
= n1
; nUndoNds
= n2
;
91 void UndoArrStatus::Paint( const Rectangle
& )
94 DrawRect( Rectangle( Point(0,0), GetOutputSize() ));
95 ( s
= "Undos: " ) += nUndo
;
96 DrawText( Point( 0, 0 ), s
);
97 ( s
= "UndoNodes: " ) += nUndoNds
;
98 DrawText( Point( 0, 15 ), s
);
103 void SwDoc::SetUndoNoResetModified()
105 nUndoSavePos
= USHRT_MAX
;
108 bool SwDoc::IsUndoNoResetModified() const
110 return USHRT_MAX
== nUndoSavePos
;
113 void SwDoc::DoUndo(bool bUn
)
117 SdrModel
* pSdrModel
= GetDrawModel();
119 pSdrModel
->EnableUndo(bUn
);
122 bool SwDoc::DoesUndo() const
127 void SwDoc::DoGroupUndo(bool bUn
)
132 bool SwDoc::DoesGroupUndo() const
137 sal_uInt16
SwDoc::GetUndoActionCount()
142 void SwDoc::SetUndoActionCount( sal_uInt16 nNew
)
147 const SwNodes
* SwDoc::GetUndoNds() const
152 void SwDoc::AppendUndo( SwUndo
* pUndo
)
154 if( nsRedlineMode_t::REDLINE_NONE
== pUndo
->GetRedlineMode() )
155 pUndo
->SetRedlineMode( GetRedlineMode() );
157 // Unfortunately, the silly SvPtrArr can only store a little less than
158 // USHRT_MAX elements. Of course it doesn't see any necessity for asserting
159 // or even doing error handling. pUndos should definitely be replaced by an
160 // STL container that doesn't have this problem. cf #95884#
161 DBG_ASSERT( pUndos
->Count() < USHRT_MAX
- 16,
162 "Writer will crash soon. I apologize for the inconvenience." );
164 pUndos
->Insert( pUndo
, nUndoPos
);
166 switch( pUndo
->GetId() )
168 case UNDO_START
: ++nUndoSttEnd
;
171 case UNDO_END
: ASSERT( nUndoSttEnd
, "Undo-Ende ohne Start" );
175 if( pUndos
->Count() != nUndoPos
&& UNDO_END
!= pUndo
->GetId() )
178 ASSERT( pUndos
->Count() == nUndoPos
|| UNDO_END
== pUndo
->GetId(),
179 "Redo history not deleted!" );
186 #ifdef _SHOW_UNDORANGE
187 // zur Anzeige der aktuellen Undo-Groessen
189 pUndoMsgWin
= new UndoArrStatus
;
190 pUndoMsgWin
->Set( pUndos
->Count(), aUndoNodes
.Count() );
193 // noch eine offene Klammerung, kann man sich den Rest schenken
197 // folgende Array-Grenzen muessen ueberwacht werden:
198 // - Undo, Grenze: fester Wert oder USHRT_MAX - 1000
199 // - UndoNodes, Grenze: USHRT_MAX - 1000
200 // - AttrHistory Grenze: USHRT_MAX - 1000
201 // (defined in UNDO_ACTION_LIMIT at the top of this file)
203 USHORT nEnde
= UNDO_ACTION_LIMIT
;
205 // nur zum Testen der neuen DOC-Member
208 SwUndoId nId
= UNDO_EMPTY
;
209 USHORT nUndosCnt
= 0, nSttEndCnt
= 0;
210 for( USHORT nCnt
= 0; nCnt
< nUndoPos
; ++nCnt
)
212 if( UNDO_START
== ( nId
= (*pUndos
)[ nCnt
]->GetId()) )
214 else if( UNDO_END
== nId
)
219 ASSERT( nSttEndCnt
== nUndoSttEnd
, "Start-Ende Count ungleich" );
220 ASSERT( nUndosCnt
== nUndoCnt
, "Undo Count ungleich" );
224 if( SwDoc::nUndoActions
< nUndoCnt
)
225 // immer 1/10 loeschen
226 //JP 23.09.95: oder wenn neu eingestellt wurde um die Differenz
227 //JP 29.5.2001: Task #83891#: remove only the overlapping actions
228 DelUndoObj( nUndoCnt
- SwDoc::nUndoActions
);
231 USHORT nUndosCnt
= nUndoCnt
;
232 // immer 1/10 loeschen bis der "Ausloeser" behoben ist
233 while( aUndoNodes
.Count() && nEnde
< aUndoNodes
.Count() )
234 DelUndoObj( nUndosCnt
/ 10 );
240 void SwDoc::ClearRedo()
242 if( DoesUndo() && nUndoPos
!= pUndos
->Count() )
244 //?? why ?? if( !nUndoSttEnd )
246 // setze UndoCnt auf den neuen Wert
248 for( USHORT nCnt
= pUndos
->Count(); nUndoPos
< nCnt
; --nUndoCnt
)
249 // Klammerung ueberspringen
250 if( UNDO_END
== (pUndo
= (*pUndos
)[ --nCnt
])->GetId() )
251 nCnt
= nCnt
- ((SwUndoEnd
*)pUndo
)->GetSttOffset();
254 // loesche die Undo-Aktionen (immer von hinten !)
255 pUndos
->DeleteAndDestroy( nUndoPos
, pUndos
->Count() - nUndoPos
);
260 // loescht die gesamten UndoObjecte
261 void SwDoc::DelAllUndoObj()
267 // Offene Undo-Klammerungen erhalten !!
269 USHORT nSize
= pUndos
->Count();
271 if( UNDO_START
!= ( pUndo
= (*pUndos
)[ --nSize
] )->GetId() ||
272 ((SwUndoStart
*)pUndo
)->GetEndOffset() )
273 // keine offenen Gruppierung ?
274 pUndos
->DeleteAndDestroy( nSize
, 1 );
277 nUndoPos
= pUndos
->Count();
281 aUndos.DelDtor( --nUndoPos, 1 );
282 nUndoCnt = nUndoSttEnd = nUndoPos = 0;
284 nUndoSavePos
= USHRT_MAX
;
289 // loescht alle UndoObjecte vom Anfang bis zum angegebenen Ende
290 BOOL
SwDoc::DelUndoObj( USHORT nEnde
)
292 if( !nEnde
) // sollte mal 0 uebergeben werden,
294 if( !pUndos
->Count() )
296 ++nEnde
; // dann korrigiere es auf 1
301 // pruefe erstmal, wo das Ende steht
302 SwUndoId nId
= UNDO_EMPTY
;
303 USHORT nSttEndCnt
= 0;
306 for( nCnt
= 0; nEnde
&& nCnt
< nUndoPos
; ++nCnt
)
308 if( UNDO_START
== ( nId
= (*pUndos
)[ nCnt
]->GetId() ))
310 else if( UNDO_END
== nId
)
316 ASSERT( nCnt
< nUndoPos
|| nUndoPos
== pUndos
->Count(),
317 "Undo-Del-Ende liegt in einer Redo-Aktion" );
319 // dann setze ab Ende bis Undo-Ende bei allen Undo-Objecte die Werte um
320 nSttEndCnt
= nCnt
; // Position merken
321 if( nUndoSavePos
< nSttEndCnt
) // SavePos wird aufgegeben
322 nUndoSavePos
= USHRT_MAX
;
323 else if( nUndoSavePos
!= USHRT_MAX
)
324 nUndoSavePos
= nUndoSavePos
- nSttEndCnt
;
327 pUndos
->DeleteAndDestroy( --nSttEndCnt
, 1 );
328 nUndoPos
= pUndos
->Count();
334 /**************** UNDO ******************/
336 void SwDoc::setUndoNoModifiedPosition( SwUndoNoModifiedPosition nNew
)
339 if( !pUndos
->Count() || nUndoSavePos
> pUndos
->Count() - 1 )
340 nUndoSavePos
= USHRT_MAX
;
343 SwUndoNoModifiedPosition
SwDoc::getUndoNoModifiedPosition() const
349 bool SwDoc::HasUndoId(SwUndoId eId
) const
351 USHORT nSize
= nUndoPos
;
354 if( ( pUndo
= (*pUndos
)[nSize
])->GetId() == eId
||
355 ( UNDO_START
== pUndo
->GetId() &&
356 ((SwUndoStart
*)pUndo
)->GetUserId() == eId
)
357 || ( UNDO_END
== pUndo
->GetId() &&
358 ((SwUndoEnd
*)pUndo
)->GetUserId() == eId
) )
367 bool SwDoc::Undo( SwUndoIter
& rUndoIter
)
369 if ( (rUndoIter
.GetId()!=0) && (!HasUndoId(rUndoIter
.GetId())) )
371 rUndoIter
.bWeiter
= FALSE
;
376 rUndoIter
.bWeiter
= FALSE
;
380 SwUndo
*pUndo
= (*pUndos
)[ --nUndoPos
];
382 RedlineMode_t eOld
= GetRedlineMode();
383 RedlineMode_t eTmpMode
= (RedlineMode_t
)pUndo
->GetRedlineMode();
384 if( (nsRedlineMode_t::REDLINE_SHOW_MASK
& eTmpMode
) != (nsRedlineMode_t::REDLINE_SHOW_MASK
& eOld
) &&
385 UNDO_START
!= pUndo
->GetId() && UNDO_END
!= pUndo
->GetId() )
386 SetRedlineMode( eTmpMode
);
388 SetRedlineMode_intern((RedlineMode_t
)(eTmpMode
| nsRedlineMode_t::REDLINE_IGNORE
));
391 // zum spaeteren ueberpruefen
392 SwUndoId nAktId
= pUndo
->GetId();
393 //JP 11.05.98: FlyFormate ueber die EditShell selektieren, nicht aus dem
399 case UNDO_INSDRAWFMT
:
403 rUndoIter
.ClearSelections();
406 pUndo
->Undo( rUndoIter
);
408 SetRedlineMode( eOld
);
410 // Besonderheit von Undo-Replace (interne History)
411 if( UNDO_REPLACE
== nAktId
&& ((SwUndoReplace
*)pUndo
)->nAktPos
)
417 // Objekt aus History entfernen und zerstoeren
418 if( nUndoPos
&& !rUndoIter
.bWeiter
&&
419 UNDO_START
== ( pUndo
= (*pUndos
)[ nUndoPos
-1 ] )->GetId() )
422 // JP 29.10.96: Start und End setzen kein Modify-Flag.
423 // Sonst gibt es Probleme mit der autom. Aufnahme von Ausnahmen
424 // bei der Autokorrektur
425 if( UNDO_START
!= nAktId
&& UNDO_END
!= nAktId
)
426 SetModified(); // default: immer setzen, kann zurueck gesetzt werden
428 // ist die History leer und wurde nicht wegen Speichermangel
429 // verworfen, so kann das Dokument als unveraendert gelten
430 if( nUndoSavePos
== nUndoPos
)
437 // setzt Undoklammerung auf, liefert nUndoId der Klammerung
440 SwUndoId
SwDoc::StartUndo( SwUndoId eUndoId
, const SwRewriter
* pRewriter
)
446 eUndoId
= UNDO_START
;
448 SwUndoStart
* pUndo
= new SwUndoStart( eUndoId
);
451 pUndo
->SetRewriter(*pRewriter
);
457 // schliesst Klammerung der nUndoId, nicht vom UI benutzt
460 SwUndoId
SwDoc::EndUndo(SwUndoId eUndoId
, const SwRewriter
* pRewriter
)
462 USHORT nSize
= nUndoPos
;
463 if( !mbUndo
|| !nSize
-- )
466 if( UNDO_START
== eUndoId
|| !eUndoId
)
469 SwUndo
* pUndo
= (*pUndos
)[ nSize
];
470 if( UNDO_START
== pUndo
->GetId() )
472 // leere Start/End-Klammerung ??
473 pUndos
->DeleteAndDestroy( nSize
);
479 // exist above any redo objects? If yes, delete them
480 if( nUndoPos
!= pUndos
->Count() )
482 // setze UndoCnt auf den neuen Wert
483 for( USHORT nCnt
= pUndos
->Count(); nUndoPos
< nCnt
; --nUndoCnt
)
484 // Klammerung ueberspringen
485 if( UNDO_END
== (pUndo
= (*pUndos
)[ --nCnt
])->GetId() )
486 nCnt
= nCnt
- ((SwUndoEnd
*)pUndo
)->GetSttOffset();
488 pUndos
->DeleteAndDestroy( nUndoPos
, pUndos
->Count() - nUndoPos
);
491 // suche den Anfang dieser Klammerung
492 SwUndoId nId
= UNDO_EMPTY
;
494 if( UNDO_START
== ( nId
= (pUndo
= (*pUndos
)[ --nSize
] )->GetId()) &&
495 !((SwUndoStart
*)pUndo
)->GetEndOffset() )
496 break; // Start gefunden
498 if( nId
!= UNDO_START
)
500 // kann eigentlich nur beim Abspielen von Macros passieren, die
501 // Undo/Redo/Repeat benutzen und die eine exitierende Selection
502 // durch Einfuegen loeschen
503 ASSERT( !this, "kein entsprechendes Ende gefunden" );
504 // kein entsprechenden Start gefunden -> Ende nicht einfuegen
505 // und die Member am Doc updaten
509 // setze UndoCnt auf den neuen Wert
511 for( USHORT nCnt
= 0; nCnt
< pUndos
->Count(); ++nCnt
, ++nUndoCnt
)
512 // Klammerung ueberspringen
513 if( UNDO_START
== (pTmpUndo
= (*pUndos
)[ nCnt
])->GetId() )
514 nCnt
= nCnt
+ ((SwUndoStart
*)pTmpUndo
)->GetEndOffset();
519 // Klammerung um eine einzelne Action muss nicht sein!
520 // Aussnahme: es ist eine eigene ID definiert
521 if( 2 == pUndos
->Count() - nSize
&&
522 (UNDO_END
== eUndoId
|| eUndoId
== (*pUndos
)[ nSize
+1 ]->GetId() ))
524 pUndos
->DeleteAndDestroy( nSize
);
525 nUndoPos
= pUndos
->Count();
529 if( SwDoc::nUndoActions
< nUndoCnt
)
530 // immer 1/10 loeschen
531 //JP 23.09.95: oder wenn neu eingestellt wurde um die Differenz
532 //JP 29.5.2001: Task #83891#: remove only the overlapping actions
533 DelUndoObj( nUndoCnt
- SwDoc::nUndoActions
);
536 USHORT nEnde
= USHRT_MAX
- 1000;
537 USHORT nUndosCnt
= nUndoCnt
;
538 // immer 1/10 loeschen bis der "Ausloeser" behoben ist
539 while( aUndoNodes
.Count() && nEnde
< aUndoNodes
.Count() )
540 DelUndoObj( nUndosCnt
/ 10 );
546 // setze die Klammerung am Start/End-Undo
547 nSize
= pUndos
->Count() - nSize
;
548 ((SwUndoStart
*)pUndo
)->SetEndOffset( nSize
);
550 SwUndoEnd
* pUndoEnd
= new SwUndoEnd( eUndoId
);
551 pUndoEnd
->SetSttOffset( nSize
);
553 // nur zum Testen der Start/End-Verpointerung vom Start/End Undo
556 USHORT nEndCnt
= 1, nCnt
= pUndos
->Count();
557 SwUndoId nTmpId
= UNDO_EMPTY
;
560 if( UNDO_START
== ( nTmpId
= (*pUndos
)[ --nCnt
]->GetId()) )
562 if( !nEndCnt
) // falls mal ein Start ohne Ende vorhanden ist
565 if( !nEndCnt
) // hier ist der Anfang
568 else if( UNDO_END
== nTmpId
)
573 ASSERT( nCnt
== pUndos
->Count() - nSize
,
574 "Start-Ende falsch geklammert" );
580 ((SwUndoStart
*) pUndo
)->SetRewriter(*pRewriter
);
581 pUndoEnd
->SetRewriter(*pRewriter
);
584 pUndoEnd
->SetRewriter(((SwUndoStart
*) pUndo
)->GetRewriter());
586 AppendUndo( pUndoEnd
);
590 // liefert die Id der letzten Undofaehigen Aktion zurueck oder 0
591 // fuellt ggf. VARARR mit User-UndoIds
593 String
SwDoc::GetUndoIdsStr( String
* pStr
, SwUndoIds
*pUndoIds
) const
599 GetUndoIds( pStr
, pUndoIds
);
603 GetUndoIds( &aTmpStr
, pUndoIds
);
608 /*-- 24.11.2004 16:11:21---------------------------------------------------
610 -----------------------------------------------------------------------*/
611 sal_Bool
SwDoc::RestoreInvisibleContent()
613 sal_Bool bRet
= sal_False
;
616 SwUndo
* pUndo
= (*pUndos
)[ nUndoPos
- 1 ];
617 if( ( pUndo
->GetId() == UNDO_END
&&
618 static_cast<SwUndoEnd
*>(pUndo
)->GetUserId() == UNDO_UI_DELETE_INVISIBLECNTNT
) )
620 SwPaM
aPam( GetNodes().GetEndOfPostIts() );
621 SwUndoIter
aUndoIter( &aPam
);
626 while ( aUndoIter
.IsNextUndo() );
636 Returns id and comment for a certain undo object in an undo stack.
638 Remark: In the following the object type referred to is always the
639 effective object type. If an UNDO_START or UNDO_END has a user type
640 it is referred to as this type.
642 If the queried object is an UNDO_END and has no user id the result
643 is taken from the first object that is not an UNDO_END nor an
644 UNDO_START preceeding the queried object.
646 If the queried object is an UNDO_START and has no user id the
647 result is taken from the first object that is not an UNDO_END nor
648 an UNDO_START preceeding the UNDO_END object belonging to the
651 In all other cases the result is taken from the queried object.
653 @param rUndos the undo stack
654 @param nPos position of the undo object to query
656 @return SwUndoIdAndName object containing the query result
658 SwUndoIdAndName
* lcl_GetUndoIdAndName(const SwUndos
& rUndos
, sal_uInt16 nPos
)
660 SwUndo
* pUndo
= rUndos
[ nPos
];
661 SwUndoId nId
= UNDO_EMPTY
;
662 String
sStr("??", RTL_TEXTENCODING_ASCII_US
);
664 ASSERT( nPos
< rUndos
.Count(), "nPos out of range");
666 switch (pUndo
->GetId())
670 SwUndoStart
* pUndoStart
= (SwUndoStart
*) pUndo
;
671 nId
= pUndoStart
->GetUserId();
676 Start at the according UNDO_END. Search backwards
677 for first objects that is not a UNDO_END.
679 int nTmpPos
= nPos
+ pUndoStart
->GetEndOffset();
680 int nSubstitute
= -1;
686 pTmpUndo
= rUndos
[ static_cast<USHORT
>(nTmpPos
) ];
688 if (pTmpUndo
->GetEffectiveId() > UNDO_END
)
689 nSubstitute
= nTmpPos
;
691 while (nSubstitute
< 0 && nTmpPos
> nPos
);
693 if (nSubstitute
>= 0)
695 SwUndo
* pSubUndo
= rUndos
[ static_cast<USHORT
>(nSubstitute
) ];
696 nId
= pSubUndo
->GetEffectiveId();
697 sStr
= pSubUndo
->GetComment();
701 sStr
= pUndo
->GetComment();
708 SwUndoEnd
* pUndoEnd
= (SwUndoEnd
*) pUndo
;
709 nId
= pUndoEnd
->GetUserId();
714 Start at this UNDO_END. Search backwards
715 for first objects that is not a UNDO_END.
719 int nUndoStart
= nTmpPos
- pUndoEnd
->GetSttOffset();
720 int nSubstitute
= -1;
729 pTmpUndo
= rUndos
[ static_cast<USHORT
>(nTmpPos
) ];
731 if (pTmpUndo
->GetEffectiveId() > UNDO_END
)
732 nSubstitute
= nTmpPos
;
734 while (nSubstitute
< 0 && nTmpPos
> nUndoStart
);
736 if (nSubstitute
>= 0)
738 SwUndo
* pSubUndo
= rUndos
[ static_cast<USHORT
>(nSubstitute
) ];
739 nId
= pSubUndo
->GetEffectiveId();
740 sStr
= pSubUndo
->GetComment();
745 sStr
= pUndo
->GetComment();
751 nId
= pUndo
->GetId();
752 sStr
= pUndo
->GetComment();
755 return new SwUndoIdAndName(nId
, &sStr
);
758 SwUndoId
SwDoc::GetUndoIds( String
* pStr
, SwUndoIds
*pUndoIds
) const
760 int nTmpPos
= nUndoPos
- 1;
761 SwUndoId nId
= UNDO_EMPTY
;
765 SwUndo
* pUndo
= (*pUndos
)[ static_cast<USHORT
>(nTmpPos
) ];
767 SwUndoIdAndName
* pIdAndName
= lcl_GetUndoIdAndName( *pUndos
, static_cast<sal_uInt16
>(nTmpPos
) );
769 if (nTmpPos
== nUndoPos
- 1)
771 nId
= pIdAndName
->GetUndoId();
774 *pStr
= *pIdAndName
->GetUndoStr();
778 pUndoIds
->Insert(pIdAndName
, pUndoIds
->Count());
782 if (pUndo
->GetId() == UNDO_END
)
783 nTmpPos
-= ((SwUndoEnd
*) pUndo
)->GetSttOffset();
791 bool SwDoc::HasTooManyUndos() const
793 // AppendUndo checks the UNDO_ACTION_LIMIT, unless there's a nested undo.
794 // So HasTooManyUndos() may only occur when undos are nested; else
795 // AppendUndo has some sort of bug.
796 DBG_ASSERT( (nUndoSttEnd
!= 0) || (pUndos
->Count() < UNDO_ACTION_LIMIT
),
797 "non-nested undos should have been handled in AppendUndo" );
798 return (pUndos
->Count() >= UNDO_ACTION_LIMIT
);
802 /**************** REDO ******************/
805 bool SwDoc::Redo( SwUndoIter
& rUndoIter
)
807 if( rUndoIter
.GetId() && !HasUndoId( rUndoIter
.GetId() ) )
809 rUndoIter
.bWeiter
= FALSE
;
812 if( nUndoPos
== pUndos
->Count() )
814 rUndoIter
.bWeiter
= FALSE
;
818 SwUndo
*pUndo
= (*pUndos
)[ nUndoPos
++ ];
820 RedlineMode_t eOld
= GetRedlineMode();
821 RedlineMode_t eTmpMode
= (RedlineMode_t
)pUndo
->GetRedlineMode();
822 if( (nsRedlineMode_t::REDLINE_SHOW_MASK
& eTmpMode
) != (nsRedlineMode_t::REDLINE_SHOW_MASK
& eOld
) &&
823 UNDO_START
!= pUndo
->GetId() && UNDO_END
!= pUndo
->GetId() )
824 SetRedlineMode( eTmpMode
);
825 SetRedlineMode_intern( (RedlineMode_t
)(eTmpMode
| nsRedlineMode_t::REDLINE_IGNORE
));
827 //JP 11.05.98: FlyFormate ueber die EditShell selektieren, nicht aus dem
829 if( UNDO_START
!= pUndo
->GetId() && UNDO_END
!= pUndo
->GetId() )
830 rUndoIter
.ClearSelections();
832 pUndo
->Redo( rUndoIter
);
834 SetRedlineMode( eOld
);
836 // Besonderheit von Undo-Replace (interne History)
837 if( UNDO_REPLACE
== pUndo
->GetId() &&
838 USHRT_MAX
!= ((SwUndoReplace
*)pUndo
)->nAktPos
)
844 if( rUndoIter
.bWeiter
&& nUndoPos
>= pUndos
->Count() )
845 rUndoIter
.bWeiter
= FALSE
;
847 // ist die History leer und wurde nicht wegen Speichermangel
848 // verworfen, so kann das Dokument als unveraendert gelten
849 if( nUndoSavePos
== nUndoPos
)
857 // liefert die Id der letzten Redofaehigen Aktion zurueck oder 0
858 // fuellt ggf. VARARR mit User-RedoIds
860 String
SwDoc::GetRedoIdsStr( String
* pStr
, SwUndoIds
*pRedoIds
) const
866 GetRedoIds( pStr
, pRedoIds
);
870 GetRedoIds( &aTmpStr
, pRedoIds
);
877 SwUndoId
SwDoc::GetRedoIds( String
* pStr
, SwUndoIds
*pRedoIds
) const
879 sal_uInt16 nTmpPos
= nUndoPos
;
880 SwUndoId nId
= UNDO_EMPTY
;
882 while (nTmpPos
< pUndos
->Count())
884 SwUndo
* pUndo
= (*pUndos
)[nTmpPos
];
886 SwUndoIdAndName
* pIdAndName
= lcl_GetUndoIdAndName(*pUndos
, nTmpPos
);
888 if (nTmpPos
== nUndoPos
)
890 nId
= pIdAndName
->GetUndoId();
893 *pStr
= *pIdAndName
->GetUndoStr();
897 pRedoIds
->Insert(pIdAndName
, pRedoIds
->Count());
901 if (pUndo
->GetId() == UNDO_START
)
902 nTmpPos
= nTmpPos
+ ((SwUndoStart
*) pUndo
)->GetEndOffset();
910 /**************** REPEAT ******************/
913 bool SwDoc::Repeat( SwUndoIter
& rUndoIter
, sal_uInt16 nRepeatCnt
)
915 if( rUndoIter
.GetId() && !HasUndoId( rUndoIter
.GetId() ) )
917 rUndoIter
.bWeiter
= FALSE
;
920 USHORT nSize
= nUndoPos
;
923 rUndoIter
.bWeiter
= FALSE
;
927 // dann suche jetzt ueber die End/Start-Gruppen die gueltige Repeat-Aktion
928 SwUndo
*pUndo
= (*pUndos
)[ --nSize
];
929 if( UNDO_END
== pUndo
->GetId() )
930 nSize
= nSize
- ((SwUndoEnd
*)pUndo
)->GetSttOffset();
932 USHORT nEndCnt
= nUndoPos
;
933 BOOL bOneUndo
= nSize
+ 1 == nUndoPos
;
935 SwPaM
* pTmpCrsr
= rUndoIter
.pAktPam
;
936 SwUndoId nId
= UNDO_EMPTY
;
938 if( pTmpCrsr
!= pTmpCrsr
->GetNext() || !bOneUndo
) // Undo-Klammerung aufbauen
940 if (pUndo
->GetId() == UNDO_END
)
942 SwUndoStart
* pStartUndo
=
943 (SwUndoStart
*) (*pUndos
)[nSize
];
945 nId
= pStartUndo
->GetUserId();
948 StartUndo( nId
, NULL
);
950 do { // dann durchlaufe mal den gesamten Ring
951 for( USHORT nRptCnt
= nRepeatCnt
; nRptCnt
> 0; --nRptCnt
)
953 rUndoIter
.pLastUndoObj
= 0;
954 for( USHORT nCnt
= nSize
; nCnt
< nEndCnt
; ++nCnt
)
955 (*pUndos
)[ nCnt
]->Repeat( rUndoIter
); // Repeat ausfuehren
958 ( rUndoIter
.pAktPam
= (SwPaM
*)rUndoIter
.pAktPam
->GetNext() ));
959 if( pTmpCrsr
!= pTmpCrsr
->GetNext() || !bOneUndo
)
960 EndUndo( nId
, NULL
);
965 // liefert die Id der letzten Repeatfaehigen Aktion zurueck oder 0
966 // fuellt ggf. VARARR mit User-RedoIds
968 String
SwDoc::GetRepeatIdsStr(String
* pStr
, SwUndoIds
*pRepeatIds
) const
975 nId
= GetRepeatIds(pStr
, pRepeatIds
);
979 nId
= GetRepeatIds(&aTmpStr
, pRepeatIds
);
987 SwUndoId
SwDoc::GetRepeatIds(String
* pStr
, SwUndoIds
*pRepeatIds
) const
989 SwUndoId nRepeatId
= GetUndoIds( pStr
, pRepeatIds
);
990 if( REPEAT_START
<= nRepeatId
&& REPEAT_END
> nRepeatId
)
996 SwUndo
* SwDoc::RemoveLastUndo( SwUndoId eUndoId
)
998 SwUndo
* pUndo
= (*pUndos
)[ nUndoPos
- 1 ];
999 if( eUndoId
== pUndo
->GetId() && nUndoPos
== pUndos
->Count() )
1004 pUndos
->Remove( nUndoPos
, 1 );
1009 ASSERT( !this, "falsches Undo-Object" );
1014 SwUndoIdAndName::SwUndoIdAndName( SwUndoId nId
, const String
* pStr
)
1015 : eUndoId( nId
), pUndoStr( pStr
? new String( *pStr
) : 0 )
1019 SwUndoIdAndName::~SwUndoIdAndName()