LCOV - code coverage report
Current view: top level - svl/source/undo - undo.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 453 581 78.0 %
Date: 2012-08-25 Functions: 89 133 66.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 342 746 45.8 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : 
      21                 :            : #include <com/sun/star/uno/Exception.hpp>
      22                 :            : 
      23                 :            : #include <comphelper/flagguard.hxx>
      24                 :            : #include <tools/debug.hxx>
      25                 :            : #include <tools/diagnose_ex.h>
      26                 :            : 
      27                 :            : #include <svl/undo.hxx>
      28                 :            : 
      29                 :            : #include <vector>
      30                 :            : #include <list>
      31                 :            : #include <limits>
      32                 :            : 
      33                 :            : using ::com::sun::star::uno::Exception;
      34                 :            : 
      35                 :            : // STATIC DATA -----------------------------------------------------------
      36                 :            : 
      37                 :            : DBG_NAME(SfxUndoAction)
      38                 :            : 
      39                 :            : //========================================================================
      40                 :            : 
      41         [ #  # ]:          0 : TYPEINIT0(SfxUndoAction);
      42         [ #  # ]:          0 : TYPEINIT0(SfxListUndoAction);
      43         [ #  # ]:          0 : TYPEINIT0(SfxLinkUndoAction);
      44         [ -  + ]:         36 : TYPEINIT0(SfxRepeatTarget);
      45                 :            : 
      46                 :            : //------------------------------------------------------------------------
      47                 :            : 
      48                 :       5351 : SfxRepeatTarget::~SfxRepeatTarget()
      49                 :            : {
      50         [ -  + ]:       5351 : }
      51                 :            : 
      52                 :            : //------------------------------------------------------------------------
      53                 :            : 
      54                 :         52 : SfxUndoContext::~SfxUndoContext()
      55                 :            : {
      56         [ -  + ]:         52 : }
      57                 :            : 
      58                 :            : //------------------------------------------------------------------------
      59                 :            : 
      60                 :      12551 : sal_Bool SfxUndoAction::IsLinked()
      61                 :            : {
      62                 :      12551 :     return bLinked;
      63                 :            : }
      64                 :            : 
      65                 :            : //------------------------------------------------------------------------
      66                 :            : 
      67                 :     784063 : void SfxUndoAction::SetLinked( sal_Bool bIsLinked )
      68                 :            : {
      69                 :     784063 :     bLinked = bIsLinked;
      70                 :     784063 : }
      71                 :            : 
      72                 :            : //------------------------------------------------------------------------
      73                 :            : 
      74                 :     783874 : SfxUndoAction::~SfxUndoAction()
      75                 :            : {
      76                 :            :     DBG_DTOR(SfxUndoAction, 0);
      77                 :            :     DBG_ASSERT( !IsLinked(), "Gelinkte Action geloescht" );
      78         [ -  + ]:     783874 : }
      79                 :            : 
      80                 :            : 
      81                 :     784063 : SfxUndoAction::SfxUndoAction()
      82                 :            : {
      83                 :            :     DBG_CTOR(SfxUndoAction, 0);
      84                 :     784063 :     SetLinked( sal_False );
      85                 :     784063 : }
      86                 :            : 
      87                 :            : //------------------------------------------------------------------------
      88                 :            : 
      89                 :          0 : sal_Bool SfxUndoAction::Merge( SfxUndoAction * )
      90                 :            : {
      91                 :            :     DBG_CHKTHIS(SfxUndoAction, 0);
      92                 :          0 :     return sal_False;
      93                 :            : }
      94                 :            : 
      95                 :            : //------------------------------------------------------------------------
      96                 :            : 
      97                 :        186 : rtl::OUString SfxUndoAction::GetComment() const
      98                 :            : {
      99                 :            :     DBG_CHKTHIS(SfxUndoAction, 0);
     100                 :        186 :     return rtl::OUString();
     101                 :            : }
     102                 :            : 
     103                 :            : //------------------------------------------------------------------------
     104                 :            : 
     105                 :            : 
     106                 :          4 : sal_uInt16 SfxUndoAction::GetId() const
     107                 :            : {
     108                 :            :     DBG_CHKTHIS(SfxUndoAction, 0);
     109                 :          4 :     return 0;
     110                 :            : }
     111                 :            : 
     112                 :            : //------------------------------------------------------------------------
     113                 :            : 
     114                 :        150 : XubString SfxUndoAction::GetRepeatComment(SfxRepeatTarget&) const
     115                 :            : {
     116                 :            :     DBG_CHKTHIS(SfxUndoAction, 0);
     117         [ +  - ]:        150 :     return GetComment();
     118                 :            : }
     119                 :            : 
     120                 :            : //------------------------------------------------------------------------
     121                 :            : 
     122                 :          0 : void SfxUndoAction::Undo()
     123                 :            : {
     124                 :            :     // die sind nur konzeptuell pure virtual
     125                 :            :     OSL_FAIL( "pure virtual function called: SfxUndoAction::Undo()" );
     126                 :          0 : }
     127                 :            : 
     128                 :            : //------------------------------------------------------------------------
     129                 :            : 
     130                 :         50 : void SfxUndoAction::UndoWithContext( SfxUndoContext& i_context )
     131                 :            : {
     132                 :            :     (void)i_context;
     133                 :         50 :     Undo();
     134                 :         46 : }
     135                 :            : 
     136                 :            : //------------------------------------------------------------------------
     137                 :            : 
     138                 :          0 : void SfxUndoAction::Redo()
     139                 :            : {
     140                 :            :     // die sind nur konzeptuell pure virtual
     141                 :            :     OSL_FAIL( "pure virtual function called: SfxUndoAction::Redo()" );
     142                 :          0 : }
     143                 :            : 
     144                 :            : //------------------------------------------------------------------------
     145                 :            : 
     146                 :          4 : void SfxUndoAction::RedoWithContext( SfxUndoContext& i_context )
     147                 :            : {
     148                 :            :     (void)i_context;
     149                 :          4 :     Redo();
     150                 :          0 : }
     151                 :            : 
     152                 :            : //------------------------------------------------------------------------
     153                 :            : 
     154                 :          0 : void SfxUndoAction::Repeat(SfxRepeatTarget&)
     155                 :            : {
     156                 :            :     // die sind nur konzeptuell pure virtual
     157                 :            :     OSL_FAIL( "pure virtual function called: SfxUndoAction::Repeat()" );
     158                 :          0 : }
     159                 :            : 
     160                 :            : //------------------------------------------------------------------------
     161                 :            : 
     162                 :            : 
     163                 :          0 : sal_Bool SfxUndoAction::CanRepeat(SfxRepeatTarget&) const
     164                 :            : {
     165                 :          0 :     return sal_True;
     166                 :            : }
     167                 :            : 
     168                 :            : //========================================================================
     169                 :            : 
     170                 :            : typedef ::std::vector< SfxUndoListener* >   UndoListeners;
     171                 :            : 
     172                 :            : struct SVL_DLLPRIVATE SfxUndoManager_Data
     173                 :            : {
     174                 :            :     ::osl::Mutex    aMutex;
     175                 :            :     SfxUndoArray*   pUndoArray;
     176                 :            :     SfxUndoArray*   pActUndoArray;
     177                 :            :     SfxUndoArray*   pFatherUndoArray;
     178                 :            : 
     179                 :            :     sal_Int32       mnMarks;
     180                 :            :     sal_Int32       mnEmptyMark;
     181                 :            :     bool            mbUndoEnabled;
     182                 :            :     bool            mbDoing;
     183                 :            :     bool            mbClearUntilTopLevel;
     184                 :            : 
     185                 :            :     UndoListeners   aListeners;
     186                 :            : 
     187                 :      27894 :     SfxUndoManager_Data( size_t i_nMaxUndoActionCount )
     188         [ +  - ]:      27894 :         :pUndoArray( new SfxUndoArray( i_nMaxUndoActionCount ) )
     189                 :            :         ,pActUndoArray( NULL )
     190                 :            :         ,pFatherUndoArray( NULL )
     191                 :            :         ,mnMarks( 0 )
     192                 :      27894 :         ,mnEmptyMark(MARK_INVALID)
     193                 :            :         ,mbUndoEnabled( true )
     194                 :            :         ,mbDoing( false )
     195   [ +  -  +  - ]:      55788 :         ,mbClearUntilTopLevel( false )
     196                 :            :     {
     197                 :      27894 :         pActUndoArray = pUndoArray;
     198                 :      27894 :     }
     199                 :            : 
     200                 :      27315 :     ~SfxUndoManager_Data()
     201                 :      27315 :     {
     202 [ +  - ][ +  - ]:      27315 :         delete pUndoArray;
     203                 :      27315 :     }
     204                 :            : };
     205                 :            : 
     206                 :            : //========================================================================
     207                 :            : 
     208                 :            : namespace svl { namespace undo { namespace impl
     209                 :            : {
     210                 :            :     //--------------------------------------------------------------------
     211                 :            :     class SVL_DLLPRIVATE LockGuard
     212                 :            :     {
     213                 :            :     public:
     214                 :        408 :         LockGuard( SfxUndoManager& i_manager )
     215                 :        408 :             :m_manager( i_manager )
     216                 :            :         {
     217                 :        408 :             m_manager.ImplEnableUndo_Lock( false );
     218                 :        408 :         }
     219                 :            : 
     220                 :        408 :         ~LockGuard()
     221                 :            :         {
     222                 :        408 :             m_manager.ImplEnableUndo_Lock( true );
     223                 :        408 :         }
     224                 :            : 
     225                 :            :     private:
     226                 :            :         SfxUndoManager& m_manager;
     227                 :            :     };
     228                 :            : 
     229                 :            :     //--------------------------------------------------------------------
     230                 :            :     typedef void ( SfxUndoListener::*UndoListenerVoidMethod )();
     231                 :            :     typedef void ( SfxUndoListener::*UndoListenerStringMethod )( const String& );
     232                 :            : 
     233                 :            :     //--------------------------------------------------------------------
     234                 :   17607882 :     struct SVL_DLLPRIVATE NotifyUndoListener : public ::std::unary_function< SfxUndoListener*, void >
     235                 :            :     {
     236                 :            :         NotifyUndoListener()
     237                 :            :             :m_notificationMethod( NULL )
     238                 :            :             ,m_altNotificationMethod( NULL )
     239                 :            :             ,m_sActionComment()
     240                 :            :         {
     241                 :            :         }
     242                 :            : 
     243                 :    1542124 :         NotifyUndoListener( UndoListenerVoidMethod i_notificationMethod )
     244                 :            :             :m_notificationMethod( i_notificationMethod )
     245                 :            :             ,m_altNotificationMethod( NULL )
     246                 :    1542124 :             ,m_sActionComment()
     247                 :            :         {
     248                 :    1542124 :         }
     249                 :            : 
     250                 :     988910 :         NotifyUndoListener( UndoListenerStringMethod i_notificationMethod, const String& i_actionComment )
     251                 :            :             :m_notificationMethod( NULL )
     252                 :            :             ,m_altNotificationMethod( i_notificationMethod )
     253                 :     988910 :             ,m_sActionComment( i_actionComment )
     254                 :            :         {
     255                 :     988910 :         }
     256                 :            : 
     257                 :    2503695 :         bool is() const
     258                 :            :         {
     259 [ +  + ][ +  - ]:    2503695 :             return ( m_notificationMethod != 0 ) || ( m_altNotificationMethod != 0 );
     260                 :            :         }
     261                 :            : 
     262                 :       1419 :         void operator()( SfxUndoListener* i_listener ) const
     263                 :            :         {
     264                 :            :             OSL_PRECOND( is(), "NotifyUndoListener: this will crash!" );
     265         [ +  + ]:       1419 :             if ( m_altNotificationMethod != 0 )
     266                 :            :             {
     267         [ -  + ]:       1207 :                 ( i_listener->*m_altNotificationMethod )( m_sActionComment );
     268                 :            :             }
     269                 :            :             else
     270                 :            :             {
     271         [ -  + ]:        212 :                 ( i_listener->*m_notificationMethod )();
     272                 :            :             }
     273                 :       1419 :         }
     274                 :            : 
     275                 :            :     private:
     276                 :            :         UndoListenerVoidMethod      m_notificationMethod;
     277                 :            :         UndoListenerStringMethod    m_altNotificationMethod;
     278                 :            :         String                      m_sActionComment;
     279                 :            :     };
     280                 :            : 
     281                 :            :     //--------------------------------------------------------------------
     282                 :            :     class SVL_DLLPRIVATE UndoManagerGuard
     283                 :            :     {
     284                 :            :     public:
     285                 :    3171778 :         UndoManagerGuard( SfxUndoManager_Data& i_managerData )
     286                 :            :             :m_rManagerData( i_managerData )
     287                 :            :             ,m_aGuard( i_managerData.aMutex )
     288 [ +  - ][ +  - ]:    3171778 :             ,m_notifiers()
     289                 :            :         {
     290                 :    3171778 :         }
     291                 :            : 
     292                 :            :         ~UndoManagerGuard();
     293                 :            : 
     294                 :        408 :         void clear()
     295                 :            :         {
     296                 :        408 :             m_aGuard.clear();
     297                 :        408 :         }
     298                 :            : 
     299                 :        408 :         void reset()
     300                 :            :         {
     301                 :        408 :             m_aGuard.reset();
     302                 :        408 :         }
     303                 :            : 
     304                 :        128 :         void cancelNotifications()
     305                 :            :         {
     306                 :        128 :             m_notifiers.clear();
     307                 :        128 :         }
     308                 :            : 
     309                 :            :         /** marks the given Undo action for deletion
     310                 :            : 
     311                 :            :             The Undo action will be put into a list, whose members will be deleted from within the destructor of the
     312                 :            :             UndoManagerGuard. This deletion will happen without the UndoManager's mutex locked.
     313                 :            :         */
     314                 :     529779 :         void    markForDeletion( SfxUndoAction* i_action )
     315                 :            :         {
     316                 :            :             // remember
     317         [ +  - ]:     529779 :             if ( i_action )
     318                 :     529779 :                 m_aUndoActionsCleanup.push_back( i_action );
     319                 :     529779 :         }
     320                 :            : 
     321                 :            :         /** schedules the given SfxUndoListener method to be called for all registered listeners.
     322                 :            : 
     323                 :            :             The notification will happen after the Undo manager's mutex has been released, and after all pending
     324                 :            :             deletions of Undo actions are done.
     325                 :            :         */
     326                 :    1514809 :         void    scheduleNotification( UndoListenerVoidMethod i_notificationMethod )
     327                 :            :         {
     328         [ +  - ]:    1514809 :             m_notifiers.push_back( NotifyUndoListener( i_notificationMethod ) );
     329                 :    1514809 :         }
     330                 :            : 
     331                 :     988910 :         void    scheduleNotification( UndoListenerStringMethod i_notificationMethod, const String& i_actionComment )
     332                 :            :         {
     333         [ +  - ]:     988910 :             m_notifiers.push_back( NotifyUndoListener( i_notificationMethod, i_actionComment ) );
     334                 :     988910 :         }
     335                 :            : 
     336                 :            :     private:
     337                 :            :         SfxUndoManager_Data&                m_rManagerData;
     338                 :            :         ::osl::ResettableMutexGuard         m_aGuard;
     339                 :            :         ::std::list< SfxUndoAction* >       m_aUndoActionsCleanup;
     340                 :            :         ::std::list< NotifyUndoListener >   m_notifiers;
     341                 :            :     };
     342                 :            : 
     343                 :    3171778 :     UndoManagerGuard::~UndoManagerGuard()
     344                 :            :     {
     345                 :            :         // copy members
     346         [ +  - ]:    3171778 :         UndoListeners aListenersCopy( m_rManagerData.aListeners );
     347                 :            : 
     348                 :            :         // release mutex
     349         [ +  - ]:    3171778 :         m_aGuard.clear();
     350                 :            : 
     351                 :            :         // delete all actions
     352         [ +  + ]:    3701557 :         while ( !m_aUndoActionsCleanup.empty() )
     353                 :            :         {
     354         [ +  - ]:     529779 :             SfxUndoAction* pAction = m_aUndoActionsCleanup.front();
     355         [ +  - ]:     529779 :             m_aUndoActionsCleanup.pop_front();
     356                 :            :             try
     357                 :            :             {
     358 [ +  - ][ +  - ]:     529779 :                 delete pAction;
     359                 :            :             }
     360         [ #  # ]:          0 :             catch( const Exception& )
     361                 :            :             {
     362                 :            :                 DBG_UNHANDLED_EXCEPTION();
     363                 :            :             }
     364                 :            :         }
     365                 :            : 
     366                 :            :         // handle scheduled notification
     367         [ +  + ]:   11350946 :         for (   ::std::list< NotifyUndoListener >::const_iterator notifier = m_notifiers.begin();
     368                 :    5675473 :                 notifier != m_notifiers.end();
     369                 :            :                 ++notifier
     370                 :            :              )
     371                 :            :         {
     372         [ +  - ]:    2503695 :             if ( notifier->is() )
     373 [ +  - ][ +  - ]:    2503695 :                 ::std::for_each( aListenersCopy.begin(), aListenersCopy.end(), *notifier );
         [ +  - ][ +  - ]
     374                 :    3171778 :         }
     375         [ #  # ]:    3171778 :     }
     376                 :            : } } }
     377                 :            : 
     378                 :            : using namespace ::svl::undo::impl;
     379                 :            : 
     380                 :            : //========================================================================
     381                 :            : 
     382                 :      27894 : SfxUndoManager::SfxUndoManager( size_t nMaxUndoActionCount )
     383 [ +  - ][ +  - ]:      27894 :     :m_pData( new SfxUndoManager_Data( nMaxUndoActionCount ) )
     384                 :            : {
     385                 :      27894 : }
     386                 :            : 
     387                 :            : //------------------------------------------------------------------------
     388                 :            : 
     389         [ +  - ]:      27315 : SfxUndoManager::~SfxUndoManager()
     390                 :            : {
     391         [ +  - ]:      27315 :     UndoListeners aListenersCopy;
     392                 :            :     {
     393         [ +  - ]:      27315 :         UndoManagerGuard aGuard( *m_pData );
     394 [ +  - ][ +  - ]:      27315 :         aListenersCopy = m_pData->aListeners;
     395                 :            :     }
     396                 :            : 
     397                 :            :     ::std::for_each( aListenersCopy.begin(), aListenersCopy.end(),
     398 [ +  - ][ +  - ]:      27315 :         NotifyUndoListener( &SfxUndoListener::undoManagerDying ) );
         [ +  - ][ +  - ]
     399         [ -  + ]:      27808 : }
     400                 :            : 
     401                 :            : //------------------------------------------------------------------------
     402                 :            : 
     403                 :      44165 : void SfxUndoManager::EnableUndo( bool i_enable )
     404                 :            : {
     405         [ +  - ]:      44165 :     UndoManagerGuard aGuard( *m_pData );
     406 [ +  - ][ +  - ]:      44165 :     ImplEnableUndo_Lock( i_enable );
     407                 :            : 
     408                 :      44165 : }
     409                 :            : 
     410                 :            : //------------------------------------------------------------------------
     411                 :            : 
     412                 :      44981 : void SfxUndoManager::ImplEnableUndo_Lock( bool const i_enable )
     413                 :            : {
     414         [ +  + ]:      44981 :     if ( m_pData->mbUndoEnabled == i_enable )
     415                 :      44981 :         return;
     416                 :      17898 :     m_pData->mbUndoEnabled = i_enable;
     417                 :            : }
     418                 :            : 
     419                 :            : //------------------------------------------------------------------------
     420                 :            : 
     421                 :     529985 : bool SfxUndoManager::IsUndoEnabled() const
     422                 :            : {
     423         [ +  - ]:     529985 :     UndoManagerGuard aGuard( *m_pData );
     424 [ +  - ][ +  - ]:     529985 :     return ImplIsUndoEnabled_Lock();
     425                 :            : }
     426                 :            : 
     427                 :            : //------------------------------------------------------------------------
     428                 :            : 
     429                 :    2338832 : bool SfxUndoManager::ImplIsUndoEnabled_Lock() const
     430                 :            : {
     431                 :    2338832 :     return m_pData->mbUndoEnabled;
     432                 :            : }
     433                 :            : 
     434                 :            : //------------------------------------------------------------------------
     435                 :            : 
     436                 :       3312 : void SfxUndoManager::SetMaxUndoActionCount( size_t nMaxUndoActionCount )
     437                 :            : {
     438         [ +  - ]:       3312 :     UndoManagerGuard aGuard( *m_pData );
     439                 :            : 
     440                 :            :     // Remove entries from the pActUndoArray when we have to reduce
     441                 :            :     // the number of entries due to a lower nMaxUndoActionCount.
     442                 :            :     // Both redo and undo action entries will be removed until we reached the
     443                 :            :     // new nMaxUndoActionCount.
     444                 :            : 
     445                 :       3312 :     long nNumToDelete = m_pData->pActUndoArray->aUndoActions.size() - nMaxUndoActionCount;
     446         [ +  + ]:       3320 :     while ( nNumToDelete > 0 )
     447                 :            :     {
     448                 :          8 :         size_t nPos = m_pData->pActUndoArray->aUndoActions.size();
     449         [ -  + ]:          8 :         if ( nPos > m_pData->pActUndoArray->nCurUndoAction )
     450                 :            :         {
     451         [ #  # ]:          0 :             SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[nPos-1].pAction;
     452 [ #  # ][ #  # ]:          0 :             if ( !pAction->IsLinked() )
     453                 :            :             {
     454         [ #  # ]:          0 :                 aGuard.markForDeletion( pAction );
     455         [ #  # ]:          0 :                 m_pData->pActUndoArray->aUndoActions.Remove( nPos-1 );
     456                 :          0 :                 --nNumToDelete;
     457                 :            :             }
     458                 :            :         }
     459                 :            : 
     460 [ +  - ][ +  - ]:          8 :         if ( nNumToDelete > 0 && m_pData->pActUndoArray->nCurUndoAction > 0 )
                 [ +  - ]
     461                 :            :         {
     462         [ +  - ]:          8 :             SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[0].pAction;
     463 [ +  - ][ +  - ]:          8 :             if ( !pAction->IsLinked() )
     464                 :            :             {
     465         [ +  - ]:          8 :                 aGuard.markForDeletion( pAction );
     466         [ +  - ]:          8 :                 m_pData->pActUndoArray->aUndoActions.Remove(0);
     467                 :          8 :                 --m_pData->pActUndoArray->nCurUndoAction;
     468                 :          8 :                 --nNumToDelete;
     469                 :            :             }
     470                 :            :         }
     471                 :            : 
     472         [ -  + ]:          8 :         if ( nPos == m_pData->pActUndoArray->aUndoActions.size() )
     473                 :          0 :             break; // Cannot delete more entries
     474                 :            :     }
     475                 :            : 
     476         [ +  - ]:       3312 :     m_pData->pActUndoArray->nMaxUndoActions = nMaxUndoActionCount;
     477                 :       3312 : }
     478                 :            : 
     479                 :            : //------------------------------------------------------------------------
     480                 :            : 
     481                 :          0 : size_t SfxUndoManager::GetMaxUndoActionCount() const
     482                 :            : {
     483         [ #  # ]:          0 :     UndoManagerGuard aGuard( *m_pData );
     484         [ #  # ]:          0 :     return m_pData->pActUndoArray->nMaxUndoActions;
     485                 :            : }
     486                 :            : 
     487                 :            : //------------------------------------------------------------------------
     488                 :            : 
     489                 :    1200756 : void SfxUndoManager::ImplClearCurrentLevel_NoNotify( UndoManagerGuard& i_guard )
     490                 :            : {
     491                 :            :     // clear array
     492         [ +  + ]:    1416034 :     while ( !m_pData->pActUndoArray->aUndoActions.empty() )
     493                 :            :     {
     494                 :     215278 :         size_t deletePos = m_pData->pActUndoArray->aUndoActions.size() - 1;
     495                 :     215278 :         SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[ deletePos ].pAction;
     496                 :     215278 :         i_guard.markForDeletion( pAction );
     497                 :     215278 :         m_pData->pActUndoArray->aUndoActions.Remove( deletePos );
     498                 :            :     }
     499                 :            : 
     500                 :    1200756 :     m_pData->pActUndoArray->nCurUndoAction = 0;
     501                 :            : 
     502                 :    1200756 :     m_pData->mnMarks = 0;
     503                 :    1200756 :     m_pData->mnEmptyMark = MARK_INVALID;
     504                 :    1200756 : }
     505                 :            : 
     506                 :            : //------------------------------------------------------------------------
     507                 :            : 
     508                 :    1198766 : void SfxUndoManager::Clear()
     509                 :            : {
     510         [ +  - ]:    1198766 :     UndoManagerGuard aGuard( *m_pData );
     511                 :            : 
     512                 :            :     OSL_ENSURE( !ImplIsInListAction_Lock(), "SfxUndoManager::Clear: suspicious call - do you really wish to clear the current level?" );
     513         [ +  - ]:    1198766 :     ImplClearCurrentLevel_NoNotify( aGuard );
     514                 :            : 
     515                 :            :     // notify listeners
     516 [ +  - ][ +  - ]:    1198766 :     aGuard.scheduleNotification( &SfxUndoListener::cleared );
     517                 :    1198766 : }
     518                 :            : 
     519                 :            : //------------------------------------------------------------------------
     520                 :            : 
     521                 :       1862 : void SfxUndoManager::ClearAllLevels()
     522                 :            : {
     523         [ +  - ]:       1862 :     UndoManagerGuard aGuard( *m_pData );
     524         [ +  - ]:       1862 :     ImplClearCurrentLevel_NoNotify( aGuard );
     525                 :            : 
     526 [ +  - ][ -  + ]:       1862 :     if ( ImplIsInListAction_Lock() )
     527                 :            :     {
     528                 :          0 :         m_pData->mbClearUntilTopLevel = true;
     529                 :            :     }
     530                 :            :     else
     531                 :            :     {
     532         [ +  - ]:       1862 :         aGuard.scheduleNotification( &SfxUndoListener::cleared );
     533         [ +  - ]:       1862 :     }
     534                 :       1862 : }
     535                 :            : 
     536                 :            : //------------------------------------------------------------------------
     537                 :            : 
     538                 :      12240 : void SfxUndoManager::ImplClearRedo_NoLock( bool const i_currentLevel )
     539                 :            : {
     540         [ +  - ]:      12240 :     UndoManagerGuard aGuard( *m_pData );
     541 [ +  - ][ +  - ]:      12240 :     ImplClearRedo( aGuard, i_currentLevel );
     542                 :      12240 : }
     543                 :            : 
     544                 :            : //------------------------------------------------------------------------
     545                 :            : 
     546                 :          6 : void SfxUndoManager::ClearRedo()
     547                 :            : {
     548                 :            :     OSL_ENSURE( !IsInListAction(), "SfxUndoManager::ClearRedo: suspicious call - do you really wish to clear the current level?" );
     549                 :          6 :     ImplClearRedo_NoLock( CurrentLevel );
     550                 :          6 : }
     551                 :            : 
     552                 :            : //------------------------------------------------------------------------
     553                 :            : 
     554                 :        128 : void SfxUndoManager::Reset()
     555                 :            : {
     556         [ +  - ]:        128 :     UndoManagerGuard aGuard( *m_pData );
     557                 :            : 
     558                 :            :     // clear all locks
     559 [ +  - ][ -  + ]:        128 :     while ( !ImplIsUndoEnabled_Lock() )
     560         [ #  # ]:          0 :         ImplEnableUndo_Lock( true );
     561                 :            : 
     562                 :            :     // cancel all list actions
     563 [ +  - ][ +  + ]:        152 :     while ( IsInListAction() )
     564         [ +  - ]:         24 :         ImplLeaveListAction( false, aGuard );
     565                 :            : 
     566                 :            :     // clear both stacks
     567         [ +  - ]:        128 :     ImplClearCurrentLevel_NoNotify( aGuard );
     568                 :            : 
     569                 :            :     // cancel the notifications scheduled by ImplLeaveListAction,
     570                 :            :     // as we want to do an own, dedicated notification
     571                 :        128 :     aGuard.cancelNotifications();
     572                 :            : 
     573                 :            :     // schedule notification
     574 [ +  - ][ +  - ]:        128 :     aGuard.scheduleNotification( &SfxUndoListener::resetAll );
     575                 :        128 : }
     576                 :            : 
     577                 :            : //------------------------------------------------------------------------
     578                 :            : 
     579                 :         16 : void SfxUndoManager::ImplClearUndo( UndoManagerGuard& i_guard )
     580                 :            : {
     581         [ +  + ]:         32 :     while ( m_pData->pActUndoArray->nCurUndoAction > 0 )
     582                 :            :     {
     583                 :         16 :         SfxUndoAction* pUndoAction = m_pData->pActUndoArray->aUndoActions[0].pAction;
     584                 :         16 :         m_pData->pActUndoArray->aUndoActions.Remove( 0 );
     585                 :         16 :         i_guard.markForDeletion( pUndoAction );
     586                 :         16 :         --m_pData->pActUndoArray->nCurUndoAction;
     587                 :            :     }
     588                 :            :     // TODO: notifications? We don't have clearedUndo, only cleared and clearedRedo at the SfxUndoListener
     589                 :         16 : }
     590                 :            : 
     591                 :            : //------------------------------------------------------------------------
     592                 :            : 
     593                 :     228762 : void SfxUndoManager::ImplClearRedo( UndoManagerGuard& i_guard, bool const i_currentLevel )
     594                 :            : {
     595         [ +  + ]:     228762 :     SfxUndoArray* pUndoArray = ( i_currentLevel == IUndoManager::CurrentLevel ) ? m_pData->pActUndoArray : m_pData->pUndoArray;
     596                 :            : 
     597                 :            :     // clearance
     598         [ +  + ]:     228820 :     while ( pUndoArray->aUndoActions.size() > pUndoArray->nCurUndoAction )
     599                 :            :     {
     600                 :         58 :         size_t deletePos = pUndoArray->aUndoActions.size() - 1;
     601                 :         58 :         SfxUndoAction* pAction = pUndoArray->aUndoActions[ deletePos ].pAction;
     602                 :         58 :         pUndoArray->aUndoActions.Remove( deletePos );
     603                 :         58 :         i_guard.markForDeletion( pAction );
     604                 :            :     }
     605                 :            : 
     606                 :            :     // notification - only if the top level's stack was cleared
     607         [ +  + ]:     228762 :     if ( i_currentLevel == IUndoManager::TopLevel )
     608                 :      12234 :         i_guard.scheduleNotification( &SfxUndoListener::clearedRedo );
     609                 :     228762 : }
     610                 :            : 
     611                 :            : //------------------------------------------------------------------------
     612                 :            : 
     613                 :     772103 : bool SfxUndoManager::ImplAddUndoAction_NoNotify( SfxUndoAction *pAction, bool bTryMerge, bool bClearRedo, UndoManagerGuard& i_guard )
     614                 :            : {
     615 [ +  + ][ -  + ]:     772103 :     if ( !ImplIsUndoEnabled_Lock() || ( m_pData->pActUndoArray->nMaxUndoActions == 0 ) )
                 [ +  + ]
     616                 :            :     {
     617                 :         55 :         i_guard.markForDeletion( pAction );
     618                 :         55 :         return false;
     619                 :            :     }
     620                 :            : 
     621                 :            :     // merge, if required
     622                 :     772048 :     SfxUndoAction* pMergeWithAction = m_pData->pActUndoArray->nCurUndoAction ?
     623         [ +  + ]:     772048 :         m_pData->pActUndoArray->aUndoActions[m_pData->pActUndoArray->nCurUndoAction-1].pAction : NULL;
     624 [ +  + ][ +  - ]:     772048 :     if ( bTryMerge && pMergeWithAction )
     625                 :            :     {
     626                 :          2 :         bool bMerged = pMergeWithAction->Merge( pAction );
     627         [ +  - ]:          2 :         if ( bMerged )
     628                 :            :         {
     629                 :          2 :             i_guard.markForDeletion( pAction );
     630                 :          2 :             return false;
     631                 :            :         }
     632                 :            :     }
     633                 :            : 
     634                 :            :     // clear redo stack, if requested
     635 [ +  + ][ +  + ]:     772046 :     if ( bClearRedo && ( ImplGetRedoActionCount_Lock( CurrentLevel ) > 0 ) )
                 [ +  + ]
     636                 :         18 :         ImplClearRedo( i_guard, IUndoManager::CurrentLevel );
     637                 :            : 
     638                 :            :     // respect max number
     639         [ +  + ]:     772046 :     if( m_pData->pActUndoArray == m_pData->pUndoArray )
     640                 :            :     {
     641   [ +  +  +  - ]:    1094315 :         while( m_pData->pActUndoArray->aUndoActions.size() >=
                 [ +  + ]
     642                 :     540886 :                m_pData->pActUndoArray->nMaxUndoActions &&
     643                 :      12543 :                !m_pData->pActUndoArray->aUndoActions[0].pAction->IsLinked() )
     644                 :            :         {
     645                 :      12543 :             i_guard.markForDeletion( m_pData->pActUndoArray->aUndoActions[0].pAction );
     646                 :      12543 :             m_pData->pActUndoArray->aUndoActions.Remove(0);
     647         [ +  - ]:      12543 :             if (m_pData->pActUndoArray->nCurUndoAction > 0)
     648                 :            :             {
     649                 :      12543 :                 --m_pData->pActUndoArray->nCurUndoAction;
     650                 :            :             }
     651                 :            :         }
     652                 :            :     }
     653                 :            : 
     654                 :            :     // append new action
     655                 :     772046 :     m_pData->pActUndoArray->aUndoActions.Insert( pAction, m_pData->pActUndoArray->nCurUndoAction++ );
     656                 :     772103 :     return true;
     657                 :            : }
     658                 :            : 
     659                 :            : //------------------------------------------------------------------------
     660                 :            : 
     661                 :     253794 : void SfxUndoManager::AddUndoAction( SfxUndoAction *pAction, sal_Bool bTryMerge )
     662                 :            : {
     663         [ +  - ]:     253794 :     UndoManagerGuard aGuard( *m_pData );
     664                 :            : 
     665                 :            :     // add
     666 [ +  - ][ +  + ]:     253794 :     if ( ImplAddUndoAction_NoNotify( pAction, bTryMerge, true, aGuard ) )
     667                 :            :     {
     668                 :            :         // notify listeners
     669 [ +  - ][ +  - ]:     253737 :         aGuard.scheduleNotification( &SfxUndoListener::undoActionAdded, pAction->GetComment() );
         [ +  - ][ +  - ]
     670         [ +  - ]:     253794 :     }
     671                 :     253794 : }
     672                 :            : 
     673                 :            : //------------------------------------------------------------------------
     674                 :            : 
     675                 :      14248 : size_t SfxUndoManager::GetUndoActionCount( bool const i_currentLevel ) const
     676                 :            : {
     677         [ +  - ]:      14248 :     UndoManagerGuard aGuard( *m_pData );
     678         [ +  + ]:      14248 :     const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray;
     679         [ +  - ]:      14248 :     return pUndoArray->nCurUndoAction;
     680                 :            : }
     681                 :            : 
     682                 :            : //------------------------------------------------------------------------
     683                 :            : 
     684                 :        645 : rtl::OUString SfxUndoManager::GetUndoActionComment( size_t nNo, bool const i_currentLevel ) const
     685                 :            : {
     686         [ +  - ]:        645 :     UndoManagerGuard aGuard( *m_pData );
     687                 :            : 
     688                 :        645 :     rtl::OUString sComment;
     689         [ +  + ]:        645 :     const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray;
     690                 :            :     DBG_ASSERT( nNo < pUndoArray->nCurUndoAction, "svl::SfxUndoManager::GetUndoActionComment: illegal index!" );
     691         [ +  - ]:        645 :     if( nNo < pUndoArray->nCurUndoAction )
     692 [ +  - ][ +  - ]:        645 :         sComment = pUndoArray->aUndoActions[ pUndoArray->nCurUndoAction - 1 - nNo ].pAction->GetComment();
     693         [ +  - ]:        645 :     return sComment;
     694                 :            : }
     695                 :            : 
     696                 :            : //------------------------------------------------------------------------
     697                 :            : 
     698                 :          0 : sal_uInt16 SfxUndoManager::GetUndoActionId() const
     699                 :            : {
     700         [ #  # ]:          0 :     UndoManagerGuard aGuard( *m_pData );
     701                 :            : 
     702                 :            :     DBG_ASSERT( m_pData->pActUndoArray->nCurUndoAction > 0, "svl::SfxUndoManager::GetUndoActionId(), illegal id!" );
     703         [ #  # ]:          0 :     if ( m_pData->pActUndoArray->nCurUndoAction == 0 )
     704                 :          0 :         return 0;
     705 [ #  # ][ #  # ]:          0 :     return m_pData->pActUndoArray->aUndoActions[m_pData->pActUndoArray->nCurUndoAction-1].pAction->GetId();
                 [ #  # ]
     706                 :            : }
     707                 :            : 
     708                 :            : //------------------------------------------------------------------------
     709                 :            : 
     710                 :      16082 : SfxUndoAction* SfxUndoManager::GetUndoAction( size_t nNo ) const
     711                 :            : {
     712         [ +  - ]:      16082 :     UndoManagerGuard aGuard( *m_pData );
     713                 :            : 
     714                 :            :     DBG_ASSERT( nNo < m_pData->pActUndoArray->nCurUndoAction, "svl::SfxUndoManager::GetUndoAction(), illegal id!" );
     715         [ -  + ]:      16082 :     if( nNo >= m_pData->pActUndoArray->nCurUndoAction )
     716                 :          0 :         return NULL;
     717 [ +  - ][ +  - ]:      16082 :     return m_pData->pActUndoArray->aUndoActions[m_pData->pActUndoArray->nCurUndoAction-1-nNo].pAction;
     718                 :            : }
     719                 :            : 
     720                 :            : //------------------------------------------------------------------------
     721                 :            : 
     722                 :            : /** clears the redo stack and removes the top undo action */
     723                 :          0 : void SfxUndoManager::RemoveLastUndoAction()
     724                 :            : {
     725         [ #  # ]:          0 :     UndoManagerGuard aGuard( *m_pData );
     726                 :            : 
     727         [ #  # ]:          0 :     ENSURE_OR_RETURN_VOID( m_pData->pActUndoArray->nCurUndoAction, "svl::SfxUndoManager::RemoveLastUndoAction(), no action to remove?!" );
     728                 :            : 
     729                 :          0 :     m_pData->pActUndoArray->nCurUndoAction--;
     730                 :            : 
     731                 :            :     // delete redo-actions and top action
     732         [ #  # ]:          0 :     for ( size_t nPos = m_pData->pActUndoArray->aUndoActions.size(); nPos > m_pData->pActUndoArray->nCurUndoAction; --nPos )
     733                 :            :     {
     734 [ #  # ][ #  # ]:          0 :         aGuard.markForDeletion( m_pData->pActUndoArray->aUndoActions[nPos-1].pAction );
     735                 :            :     }
     736                 :            : 
     737                 :          0 :     m_pData->pActUndoArray->aUndoActions.Remove(
     738                 :          0 :         m_pData->pActUndoArray->nCurUndoAction,
     739 [ #  # ][ #  # ]:          0 :         m_pData->pActUndoArray->aUndoActions.size() - m_pData->pActUndoArray->nCurUndoAction );
                 [ #  # ]
     740                 :            : }
     741                 :            : 
     742                 :            : //------------------------------------------------------------------------
     743                 :            : 
     744                 :        914 : bool SfxUndoManager::IsDoing() const
     745                 :            : {
     746         [ +  - ]:        914 :     UndoManagerGuard aGuard( *m_pData );
     747         [ +  - ]:        914 :     return m_pData->mbDoing;
     748                 :            : }
     749                 :            : 
     750                 :            : //------------------------------------------------------------------------
     751                 :            : 
     752                 :        338 : sal_Bool SfxUndoManager::Undo()
     753                 :            : {
     754                 :        338 :     return ImplUndo( NULL );
     755                 :            : }
     756                 :            : 
     757                 :            : //------------------------------------------------------------------------
     758                 :            : 
     759                 :         46 : sal_Bool SfxUndoManager::UndoWithContext( SfxUndoContext& i_context )
     760                 :            : {
     761                 :         46 :     return ImplUndo( &i_context );
     762                 :            : }
     763                 :            : 
     764                 :            : //------------------------------------------------------------------------
     765                 :            : 
     766                 :        384 : sal_Bool SfxUndoManager::ImplUndo( SfxUndoContext* i_contextOrNull )
     767                 :            : {
     768         [ +  - ]:        384 :     UndoManagerGuard aGuard( *m_pData );
     769                 :            :     OSL_ENSURE( !IsDoing(), "SfxUndoManager::Undo: *nested* Undo/Redo actions? How this?" );
     770                 :            : 
     771         [ +  - ]:        384 :     ::comphelper::FlagGuard aDoingGuard( m_pData->mbDoing );
     772         [ +  - ]:        384 :     LockGuard aLockGuard( *this );
     773                 :            : 
     774 [ +  - ][ -  + ]:        384 :     if ( ImplIsInListAction_Lock() )
     775                 :            :     {
     776                 :            :         OSL_ENSURE( false, "SfxUndoManager::Undo: not possible when within a list action!" );
     777                 :          0 :         return sal_False;
     778                 :            :     }
     779                 :            : 
     780         [ -  + ]:        384 :     if ( m_pData->pActUndoArray->nCurUndoAction == 0 )
     781                 :            :     {
     782                 :            :         OSL_ENSURE( false, "SfxUndoManager::Undo: undo stack is empty!" );
     783                 :          0 :         return sal_False;
     784                 :            :     }
     785                 :            : 
     786         [ +  - ]:        384 :     SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[ --m_pData->pActUndoArray->nCurUndoAction ].pAction;
     787 [ +  - ][ +  - ]:        384 :     const String sActionComment = pAction->GetComment();
     788                 :            :     try
     789                 :            :     {
     790                 :            :         // clear the guard/mutex before calling into the SfxUndoAction - this can be an extension-implemented UNO component
     791                 :            :         // nowadays ...
     792         [ +  - ]:        384 :         aGuard.clear();
     793         [ +  + ]:        384 :         if ( i_contextOrNull != NULL )
     794         [ +  + ]:         46 :             pAction->UndoWithContext( *i_contextOrNull );
     795                 :            :         else
     796         [ +  + ]:        338 :             pAction->Undo();
     797         [ +  - ]:        368 :         aGuard.reset();
     798                 :            :     }
     799                 :         32 :     catch( ... )
     800                 :            :     {
     801         [ -  + ]:         16 :         aGuard.reset();
     802                 :            : 
     803                 :            :         // in theory, somebody might have tampered with all of *m_pData while the mutex was unlocked. So, see if
     804                 :            :         // we still find pAction in our current Undo array
     805                 :         16 :         size_t nCurAction = 0;
     806         [ +  - ]:         32 :         while ( nCurAction < m_pData->pActUndoArray->aUndoActions.size() )
     807                 :            :         {
     808 [ -  + ][ +  + ]:         32 :             if ( m_pData->pActUndoArray->aUndoActions[ nCurAction++ ].pAction == pAction )
     809                 :            :             {
     810                 :            :                 // the Undo action is still there ...
     811                 :            :                 // assume the error is a permanent failure, and clear the Undo stack
     812         [ -  + ]:         16 :                 ImplClearUndo( aGuard );
     813                 :         16 :                 throw;
     814                 :            :             }
     815                 :            :         }
     816                 :            :         OSL_ENSURE( false, "SfxUndoManager::Undo: can't clear the Undo stack after the failure - some other party was faster ..." );
     817                 :          0 :         throw;
     818                 :            :     }
     819                 :            : 
     820         [ +  - ]:        368 :     aGuard.scheduleNotification( &SfxUndoListener::actionUndone, sActionComment );
     821                 :            : 
     822 [ +  - ][ +  - ]:        384 :     return sal_True;
         [ +  - ][ +  - ]
     823                 :            : }
     824                 :            : 
     825                 :            : //------------------------------------------------------------------------
     826                 :            : 
     827                 :       4784 : size_t SfxUndoManager::GetRedoActionCount( bool const i_currentLevel ) const
     828                 :            : {
     829         [ +  - ]:       4784 :     UndoManagerGuard aGuard( *m_pData );
     830 [ +  - ][ +  - ]:       4784 :     return ImplGetRedoActionCount_Lock( i_currentLevel );
     831                 :            : }
     832                 :            : 
     833                 :            : //------------------------------------------------------------------------
     834                 :            : 
     835                 :     258521 : size_t SfxUndoManager::ImplGetRedoActionCount_Lock( bool const i_currentLevel ) const
     836                 :            : {
     837         [ +  + ]:     258521 :     const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray;
     838                 :     258521 :     return pUndoArray->aUndoActions.size() - pUndoArray->nCurUndoAction;
     839                 :            : }
     840                 :            : 
     841                 :            : //------------------------------------------------------------------------
     842                 :            : 
     843                 :        110 : rtl::OUString SfxUndoManager::GetRedoActionComment( size_t nNo, bool const i_currentLevel ) const
     844                 :            : {
     845         [ +  - ]:        110 :     UndoManagerGuard aGuard( *m_pData );
     846         [ +  + ]:        110 :     const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray;
     847 [ +  - ][ +  - ]:        110 :     return pUndoArray->aUndoActions[ pUndoArray->nCurUndoAction + nNo ].pAction->GetComment();
                 [ +  - ]
     848                 :            : }
     849                 :            : 
     850                 :            : //------------------------------------------------------------------------
     851                 :            : 
     852                 :         18 : sal_Bool SfxUndoManager::Redo()
     853                 :            : {
     854                 :         18 :     return ImplRedo( NULL );
     855                 :            : }
     856                 :            : 
     857                 :            : //------------------------------------------------------------------------
     858                 :            : 
     859                 :          6 : sal_Bool SfxUndoManager::RedoWithContext( SfxUndoContext& i_context )
     860                 :            : {
     861                 :          6 :     return ImplRedo( &i_context );
     862                 :            : }
     863                 :            : 
     864                 :            : //------------------------------------------------------------------------
     865                 :            : 
     866                 :         24 : sal_Bool SfxUndoManager::ImplRedo( SfxUndoContext* i_contextOrNull )
     867                 :            : {
     868         [ +  - ]:         24 :     UndoManagerGuard aGuard( *m_pData );
     869                 :            :     OSL_ENSURE( !IsDoing(), "SfxUndoManager::Redo: *nested* Undo/Redo actions? How this?" );
     870                 :            : 
     871         [ +  - ]:         24 :     ::comphelper::FlagGuard aDoingGuard( m_pData->mbDoing );
     872         [ +  - ]:         24 :     LockGuard aLockGuard( *this );
     873                 :            : 
     874 [ +  - ][ -  + ]:         24 :     if ( ImplIsInListAction_Lock() )
     875                 :            :     {
     876                 :            :         OSL_ENSURE( false, "SfxUndoManager::Redo: not possible when within a list action!" );
     877                 :          0 :         return sal_False;
     878                 :            :     }
     879                 :            : 
     880         [ -  + ]:         24 :     if ( m_pData->pActUndoArray->nCurUndoAction >= m_pData->pActUndoArray->aUndoActions.size() )
     881                 :            :     {
     882                 :            :         OSL_ENSURE( false, "SfxUndoManager::Redo: redo stack is empty!" );
     883                 :          0 :         return sal_False;
     884                 :            :     }
     885                 :            : 
     886         [ +  - ]:         24 :     SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction++ ].pAction;
     887 [ +  - ][ +  - ]:         24 :     const String sActionComment = pAction->GetComment();
     888                 :            :     try
     889                 :            :     {
     890                 :            :         // clear the guard/mutex before calling into the SfxUndoAction - this can be a extension-implemented UNO component
     891                 :            :         // nowadays ...
     892         [ +  - ]:         24 :         aGuard.clear();
     893         [ +  + ]:         24 :         if ( i_contextOrNull != NULL )
     894         [ +  + ]:          6 :             pAction->RedoWithContext( *i_contextOrNull );
     895                 :            :         else
     896         [ +  + ]:         18 :             pAction->Redo();
     897         [ +  - ]:          8 :         aGuard.reset();
     898                 :            :     }
     899                 :         32 :     catch( ... )
     900                 :            :     {
     901         [ -  + ]:         16 :         aGuard.reset();
     902                 :            : 
     903                 :            :         // in theory, somebody might have tampered with all of *m_pData while the mutex was unlocked. So, see if
     904                 :            :         // we still find pAction in our current Undo array
     905                 :         16 :         size_t nCurAction = 0;
     906         [ +  - ]:         32 :         while ( nCurAction < m_pData->pActUndoArray->aUndoActions.size() )
     907                 :            :         {
     908 [ -  + ][ +  + ]:         32 :             if ( m_pData->pActUndoArray->aUndoActions[ nCurAction ].pAction == pAction )
     909                 :            :             {
     910                 :            :                 // the Undo action is still there ...
     911                 :            :                 // assume the error is a permanent failure, and clear the Undo stack
     912         [ -  + ]:         16 :                 ImplClearRedo( aGuard, IUndoManager::CurrentLevel );
     913                 :         16 :                 throw;
     914                 :            :             }
     915                 :         16 :             ++nCurAction;
     916                 :            :         }
     917                 :            :         OSL_ENSURE( false, "SfxUndoManager::Redo: can't clear the Undo stack after the failure - some other party was faster ..." );
     918                 :          0 :         throw;
     919                 :            :     }
     920                 :            : 
     921         [ +  - ]:          8 :     aGuard.scheduleNotification( &SfxUndoListener::actionRedone, sActionComment );
     922                 :            : 
     923 [ +  - ][ +  - ]:         24 :     return sal_True;
         [ +  - ][ +  - ]
     924                 :            : }
     925                 :            : 
     926                 :            : //------------------------------------------------------------------------
     927                 :            : 
     928                 :       1000 : size_t SfxUndoManager::GetRepeatActionCount() const
     929                 :            : {
     930         [ +  - ]:       1000 :     UndoManagerGuard aGuard( *m_pData );
     931         [ +  - ]:       1000 :     return m_pData->pActUndoArray->aUndoActions.size();
     932                 :            : }
     933                 :            : 
     934                 :            : //------------------------------------------------------------------------
     935                 :            : 
     936                 :        158 : XubString SfxUndoManager::GetRepeatActionComment( SfxRepeatTarget &rTarget) const
     937                 :            : {
     938         [ +  - ]:        158 :     UndoManagerGuard aGuard( *m_pData );
     939         [ +  - ]:        158 :     return m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->aUndoActions.size() - 1 ].pAction
     940 [ +  - ][ +  - ]:        158 :         ->GetRepeatComment(rTarget);
     941                 :            : }
     942                 :            : 
     943                 :            : //------------------------------------------------------------------------
     944                 :            : 
     945                 :          0 : sal_Bool SfxUndoManager::Repeat( SfxRepeatTarget &rTarget )
     946                 :            : {
     947         [ #  # ]:          0 :     UndoManagerGuard aGuard( *m_pData );
     948         [ #  # ]:          0 :     if ( !m_pData->pActUndoArray->aUndoActions.empty() )
     949                 :            :     {
     950         [ #  # ]:          0 :         SfxUndoAction* pAction = m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->aUndoActions.size() - 1 ].pAction;
     951         [ #  # ]:          0 :         aGuard.clear();
     952 [ #  # ][ #  # ]:          0 :         if ( pAction->CanRepeat( rTarget ) )
     953         [ #  # ]:          0 :             pAction->Repeat( rTarget );
     954                 :          0 :         return sal_True;
     955                 :            :     }
     956                 :            : 
     957         [ #  # ]:          0 :     return sal_False;
     958                 :            : }
     959                 :            : 
     960                 :            : //------------------------------------------------------------------------
     961                 :            : 
     962                 :        360 : sal_Bool SfxUndoManager::CanRepeat( SfxRepeatTarget &rTarget ) const
     963                 :            : {
     964         [ +  - ]:        360 :     UndoManagerGuard aGuard( *m_pData );
     965         [ +  - ]:        360 :     if ( !m_pData->pActUndoArray->aUndoActions.empty() )
     966                 :            :     {
     967                 :        360 :         size_t nActionNo = m_pData->pActUndoArray->aUndoActions.size() - 1;
     968 [ +  - ][ +  - ]:        360 :         return m_pData->pActUndoArray->aUndoActions[nActionNo].pAction->CanRepeat(rTarget);
     969                 :            :     }
     970         [ +  - ]:        360 :     return sal_False;
     971                 :            : }
     972                 :            : 
     973                 :            : //------------------------------------------------------------------------
     974                 :            : 
     975                 :         57 : void SfxUndoManager::AddUndoListener( SfxUndoListener& i_listener )
     976                 :            : {
     977         [ +  - ]:         57 :     UndoManagerGuard aGuard( *m_pData );
     978 [ +  - ][ +  - ]:         57 :     m_pData->aListeners.push_back( &i_listener );
     979                 :         57 : }
     980                 :            : 
     981                 :            : //------------------------------------------------------------------------
     982                 :            : 
     983                 :         57 : void SfxUndoManager::RemoveUndoListener( SfxUndoListener& i_listener )
     984                 :            : {
     985         [ +  - ]:         57 :     UndoManagerGuard aGuard( *m_pData );
     986 [ +  - ][ +  - ]:        114 :     for (   UndoListeners::iterator lookup = m_pData->aListeners.begin();
     987                 :         57 :             lookup != m_pData->aListeners.end();
     988                 :            :             ++lookup
     989                 :            :         )
     990                 :            :     {
     991         [ +  - ]:         57 :         if ( (*lookup) == &i_listener )
     992                 :            :         {
     993         [ +  - ]:         57 :             m_pData->aListeners.erase( lookup );
     994                 :         57 :             break;
     995                 :            :         }
     996         [ +  - ]:         57 :     }
     997                 :         57 : }
     998                 :            : 
     999                 :            : //------------------------------------------------------------------------
    1000                 :            : 
    1001                 :     518309 : void SfxUndoManager::EnterListAction(
    1002                 :            :     const XubString& rComment, const XubString &rRepeatComment, sal_uInt16 nId )
    1003                 :            : 
    1004                 :            : /*  [Beschreibung]
    1005                 :            : 
    1006                 :            :     Fuegt eine ListUndoAction ein und setzt dessen UndoArray als aktuelles.
    1007                 :            : */
    1008                 :            : 
    1009                 :            : {
    1010         [ +  - ]:     518309 :     UndoManagerGuard aGuard( *m_pData );
    1011                 :            : 
    1012 [ +  - ][ -  + ]:     518309 :     if( !ImplIsUndoEnabled_Lock() )
    1013                 :            :         return;
    1014                 :            : 
    1015         [ -  + ]:     518309 :     if ( !m_pData->pUndoArray->nMaxUndoActions )
    1016                 :            :         return;
    1017                 :            : 
    1018                 :     518309 :     m_pData->pFatherUndoArray = m_pData->pActUndoArray;
    1019 [ +  - ][ +  - ]:     518309 :     SfxListUndoAction* pAction = new SfxListUndoAction( rComment, rRepeatComment, nId, m_pData->pActUndoArray );
         [ +  - ][ +  - ]
    1020         [ +  - ]:     518309 :     OSL_VERIFY( ImplAddUndoAction_NoNotify( pAction, false, false, aGuard ) );
    1021                 :            :         // expected to succeed: all conditions under which it could fail should have been checked already
    1022         [ +  - ]:     518309 :     m_pData->pActUndoArray = pAction;
    1023                 :            : 
    1024                 :            :     // notification
    1025 [ +  - ][ +  - ]:     518309 :     aGuard.scheduleNotification( &SfxUndoListener::listActionEntered, rComment );
                 [ +  - ]
    1026                 :            : }
    1027                 :            : 
    1028                 :            : //------------------------------------------------------------------------
    1029                 :            : 
    1030                 :       6602 : bool SfxUndoManager::IsInListAction() const
    1031                 :            : {
    1032         [ +  - ]:       6602 :     UndoManagerGuard aGuard( *m_pData );
    1033 [ +  - ][ +  - ]:       6602 :     return ImplIsInListAction_Lock();
    1034                 :            : }
    1035                 :            : 
    1036                 :            : //------------------------------------------------------------------------
    1037                 :            : 
    1038                 :     527179 : bool SfxUndoManager::ImplIsInListAction_Lock() const
    1039                 :            : {
    1040                 :     527179 :     return ( m_pData->pActUndoArray != m_pData->pUndoArray );
    1041                 :            : }
    1042                 :            : 
    1043                 :            : //------------------------------------------------------------------------
    1044                 :            : 
    1045                 :        869 : size_t SfxUndoManager::GetListActionDepth() const
    1046                 :            : {
    1047         [ +  - ]:        869 :     UndoManagerGuard aGuard( *m_pData );
    1048                 :        869 :     size_t nDepth(0);
    1049                 :            : 
    1050                 :        869 :     SfxUndoArray* pLookup( m_pData->pActUndoArray );
    1051         [ +  + ]:       1371 :     while ( pLookup != m_pData->pUndoArray )
    1052                 :            :     {
    1053                 :        502 :         pLookup = pLookup->pFatherUndoArray;
    1054                 :        502 :         ++nDepth;
    1055                 :            :     }
    1056                 :            : 
    1057         [ +  - ]:        869 :     return nDepth;
    1058                 :            : }
    1059                 :            : 
    1060                 :            : //------------------------------------------------------------------------
    1061                 :            : 
    1062                 :     518251 : size_t SfxUndoManager::LeaveListAction()
    1063                 :            : {
    1064         [ +  - ]:     518251 :     UndoManagerGuard aGuard( *m_pData );
    1065         [ +  - ]:     518251 :     size_t nCount = ImplLeaveListAction( false, aGuard );
    1066                 :            : 
    1067         [ -  + ]:     518251 :     if ( m_pData->mbClearUntilTopLevel )
    1068                 :            :     {
    1069         [ #  # ]:          0 :         ImplClearCurrentLevel_NoNotify( aGuard );
    1070 [ #  # ][ #  # ]:          0 :         if ( !ImplIsInListAction_Lock() )
    1071                 :            :         {
    1072                 :          0 :             m_pData->mbClearUntilTopLevel = false;
    1073         [ #  # ]:          0 :             aGuard.scheduleNotification( &SfxUndoListener::cleared );
    1074                 :            :         }
    1075                 :          0 :         nCount = 0;
    1076                 :            :     }
    1077                 :            : 
    1078         [ +  - ]:     518251 :     return nCount;
    1079                 :            : }
    1080                 :            : 
    1081                 :            : //------------------------------------------------------------------------
    1082                 :            : 
    1083                 :         32 : size_t SfxUndoManager::LeaveAndMergeListAction()
    1084                 :            : {
    1085         [ +  - ]:         32 :     UndoManagerGuard aGuard( *m_pData );
    1086 [ +  - ][ +  - ]:         32 :     return ImplLeaveListAction( true, aGuard );
    1087                 :            : }
    1088                 :            : 
    1089                 :            : //------------------------------------------------------------------------
    1090                 :            : 
    1091                 :     518307 : size_t SfxUndoManager::ImplLeaveListAction( const bool i_merge, UndoManagerGuard& i_guard )
    1092                 :            : {
    1093         [ -  + ]:     518307 :     if ( !ImplIsUndoEnabled_Lock() )
    1094                 :          0 :         return 0;
    1095                 :            : 
    1096         [ -  + ]:     518307 :     if ( !m_pData->pUndoArray->nMaxUndoActions )
    1097                 :          0 :         return 0;
    1098                 :            : 
    1099         [ -  + ]:     518307 :     if( !ImplIsInListAction_Lock() )
    1100                 :            :     {
    1101                 :            :         OSL_TRACE( "svl::SfxUndoManager::ImplLeaveListAction, called without calling EnterListAction()!" );
    1102                 :          0 :         return 0;
    1103                 :            :     }
    1104                 :            : 
    1105                 :            :     DBG_ASSERT( m_pData->pActUndoArray->pFatherUndoArray, "SfxUndoManager::ImplLeaveListAction, no father undo array!?" );
    1106                 :            : 
    1107                 :            :     // the array/level which we're about to leave
    1108                 :     518307 :     SfxUndoArray* pArrayToLeave = m_pData->pActUndoArray;
    1109                 :            :     // one step up
    1110                 :     518307 :     m_pData->pActUndoArray = m_pData->pActUndoArray->pFatherUndoArray;
    1111                 :            : 
    1112                 :            :     // If no undo actions were added to the list, delete the list action
    1113                 :     518307 :     const size_t nListActionElements = pArrayToLeave->nCurUndoAction;
    1114         [ +  + ]:     518307 :     if ( nListActionElements == 0 )
    1115                 :            :     {
    1116                 :     301819 :         SfxUndoAction* pCurrentAction= m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction-1 ].pAction;
    1117                 :     301819 :         m_pData->pActUndoArray->aUndoActions.Remove( --m_pData->pActUndoArray->nCurUndoAction );
    1118                 :     301819 :         i_guard.markForDeletion( pCurrentAction );
    1119                 :            : 
    1120                 :     301819 :         i_guard.scheduleNotification( &SfxUndoListener::listActionCancelled );
    1121                 :     301819 :         return 0;
    1122                 :            :     }
    1123                 :            : 
    1124                 :            :     // now that it is finally clear the list action is non-trivial, and does participate in the Undo stack, clear
    1125                 :            :     // the redo stack
    1126                 :     216488 :     ImplClearRedo( i_guard, IUndoManager::CurrentLevel );
    1127                 :            : 
    1128                 :     216488 :     SfxUndoAction* pCurrentAction= m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction-1 ].pAction;
    1129         [ -  + ]:     216488 :     SfxListUndoAction* pListAction = dynamic_cast< SfxListUndoAction * >( pCurrentAction );
    1130         [ -  + ]:     216488 :     ENSURE_OR_RETURN( pListAction, "SfxUndoManager::ImplLeaveListAction: list action expected at this position!", nListActionElements );
    1131                 :            : 
    1132         [ +  + ]:     216488 :     if ( i_merge )
    1133                 :            :     {
    1134                 :            :         // merge the list action with its predecessor on the same level
    1135                 :            :         OSL_ENSURE( m_pData->pActUndoArray->nCurUndoAction > 1,
    1136                 :            :             "SfxUndoManager::ImplLeaveListAction: cannot merge the list action if there's no other action on the same level - check this beforehand!" );
    1137         [ +  - ]:         16 :         if ( m_pData->pActUndoArray->nCurUndoAction > 1 )
    1138                 :            :         {
    1139                 :         16 :             SfxUndoAction* pPreviousAction = m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction - 2 ].pAction;
    1140                 :         16 :             m_pData->pActUndoArray->aUndoActions.Remove( m_pData->pActUndoArray->nCurUndoAction - 2 );
    1141                 :         16 :             --m_pData->pActUndoArray->nCurUndoAction;
    1142                 :         16 :             pListAction->aUndoActions.Insert( pPreviousAction, 0 );
    1143                 :         16 :             ++pListAction->nCurUndoAction;
    1144                 :            : 
    1145 [ +  - ][ +  - ]:         16 :             pListAction->SetComment( pPreviousAction->GetComment() );
                 [ +  - ]
    1146                 :            :         }
    1147                 :            :     }
    1148                 :            : 
    1149                 :            :     // if the undo array has no comment, try to get it from its children
    1150         [ +  + ]:     216488 :     if ( pListAction->GetComment().isEmpty() )
    1151                 :            :     {
    1152         [ +  - ]:        124 :         for( size_t n = 0; n < pListAction->aUndoActions.size(); n++ )
    1153                 :            :         {
    1154         [ +  + ]:         82 :             if (!pListAction->aUndoActions[n].pAction->GetComment().isEmpty())
    1155                 :            :             {
    1156 [ +  - ][ +  - ]:         42 :                 pListAction->SetComment( pListAction->aUndoActions[n].pAction->GetComment() );
                 [ +  - ]
    1157                 :         42 :                 break;
    1158                 :            :             }
    1159                 :            :         }
    1160                 :            :     }
    1161                 :            : 
    1162                 :            :     // notify listeners
    1163 [ +  - ][ +  - ]:     216488 :     i_guard.scheduleNotification( &SfxUndoListener::listActionLeft, pListAction->GetComment() );
                 [ +  - ]
    1164                 :            : 
    1165                 :            :     // outta here
    1166                 :     518307 :     return nListActionElements;
    1167                 :            : }
    1168                 :            : 
    1169                 :            : //------------------------------------------------------------------------
    1170                 :      17216 : UndoStackMark SfxUndoManager::MarkTopUndoAction()
    1171                 :            : {
    1172         [ +  - ]:      17216 :     UndoManagerGuard aGuard( *m_pData );
    1173                 :            : 
    1174                 :            :     OSL_ENSURE( !IsInListAction(),
    1175                 :            :             "SfxUndoManager::MarkTopUndoAction(): suspicious call!" );
    1176                 :            :     OSL_ENSURE((m_pData->mnMarks + 1) < (m_pData->mnEmptyMark - 1),
    1177                 :            :             "SfxUndoManager::MarkTopUndoAction(): mark overflow!");
    1178                 :            : 
    1179                 :      17216 :     size_t const nActionPos = m_pData->pUndoArray->nCurUndoAction;
    1180         [ +  + ]:      17216 :     if (0 == nActionPos)
    1181                 :            :     {
    1182                 :      16832 :         --m_pData->mnEmptyMark;
    1183                 :      16832 :         return m_pData->mnEmptyMark;
    1184                 :            :     }
    1185                 :            : 
    1186         [ +  - ]:        384 :     m_pData->pUndoArray->aUndoActions[ nActionPos-1 ].aMarks.push_back(
    1187         [ +  - ]:        768 :             ++m_pData->mnMarks );
    1188         [ +  - ]:      17216 :     return m_pData->mnMarks;
    1189                 :            : }
    1190                 :            : 
    1191                 :            : //------------------------------------------------------------------------
    1192                 :         65 : void SfxUndoManager::RemoveMark( UndoStackMark const i_mark )
    1193                 :            : {
    1194         [ +  - ]:         65 :     UndoManagerGuard aGuard( *m_pData );
    1195                 :            : 
    1196 [ +  - ][ -  + ]:         65 :     if ((m_pData->mnEmptyMark < i_mark) || (MARK_INVALID == i_mark))
                 [ -  + ]
    1197                 :            :     {
    1198                 :            :         return; // nothing to remove
    1199                 :            :     }
    1200         [ +  + ]:         65 :     else if (i_mark == m_pData->mnEmptyMark)
    1201                 :            :     {
    1202                 :         63 :         --m_pData->mnEmptyMark; // never returned from MarkTop => invalid
    1203                 :            :         return;
    1204                 :            :     }
    1205                 :            : 
    1206         [ +  - ]:        134 :     for ( size_t i=0; i<m_pData->pUndoArray->aUndoActions.size(); ++i )
    1207                 :            :     {
    1208         [ +  - ]:        134 :         MarkedUndoAction& rAction = m_pData->pUndoArray->aUndoActions[i];
    1209   [ #  #  +  - ]:        268 :         for (   ::std::vector< UndoStackMark >::iterator markPos = rAction.aMarks.begin();
                 [ +  + ]
    1210                 :        134 :                 markPos != rAction.aMarks.end();
    1211                 :            :                 ++markPos
    1212                 :            :             )
    1213                 :            :         {
    1214 [ +  - ][ +  - ]:          2 :             if ( *markPos == i_mark )
    1215                 :            :             {
    1216         [ +  - ]:          2 :                 rAction.aMarks.erase( markPos );
    1217                 :            :                 return;
    1218                 :            :             }
    1219                 :            :         }
    1220                 :            :     }
    1221 [ +  - ][ -  + ]:         65 :     OSL_ENSURE( false, "SfxUndoManager::RemoveMark: mark not found!" );
    1222                 :            :         // TODO: this might be too offensive. There are situations where we implicitly remove marks
    1223                 :            :         // without our clients, in particular the client which created the mark, having a chance to know
    1224                 :            :         // about this.
    1225                 :            : }
    1226                 :            : 
    1227                 :            : //------------------------------------------------------------------------
    1228                 :         44 : bool SfxUndoManager::HasTopUndoActionMark( UndoStackMark const i_mark )
    1229                 :            : {
    1230         [ +  - ]:         44 :     UndoManagerGuard aGuard( *m_pData );
    1231                 :            : 
    1232                 :         44 :     size_t nActionPos = m_pData->pUndoArray->nCurUndoAction;
    1233         [ +  + ]:         44 :     if ( nActionPos == 0 )
    1234                 :            :     {
    1235                 :         12 :         return (i_mark == m_pData->mnEmptyMark);
    1236                 :            :     }
    1237                 :            : 
    1238                 :            :     const MarkedUndoAction& rAction =
    1239         [ +  - ]:         32 :             m_pData->pUndoArray->aUndoActions[ nActionPos-1 ];
    1240   [ #  #  +  - ]:         64 :     for (   ::std::vector< UndoStackMark >::const_iterator markPos = rAction.aMarks.begin();
                 [ -  + ]
    1241                 :         32 :             markPos != rAction.aMarks.end();
    1242                 :            :             ++markPos
    1243                 :            :         )
    1244                 :            :     {
    1245 [ #  # ][ #  # ]:          0 :         if ( *markPos == i_mark )
    1246                 :          0 :             return true;
    1247                 :            :     }
    1248                 :            : 
    1249         [ +  - ]:         44 :     return false;
    1250                 :            : }
    1251                 :            : 
    1252                 :            : //------------------------------------------------------------------------
    1253                 :            : 
    1254                 :          0 : void SfxUndoManager::RemoveOldestUndoActions( size_t const i_count )
    1255                 :            : {
    1256         [ #  # ]:          0 :     UndoManagerGuard aGuard( *m_pData );
    1257                 :            : 
    1258                 :          0 :     size_t nActionsToRemove = i_count;
    1259         [ #  # ]:          0 :     while ( nActionsToRemove )
    1260                 :            :     {
    1261         [ #  # ]:          0 :         SfxUndoAction* pActionToRemove = m_pData->pUndoArray->aUndoActions[0].pAction;
    1262                 :            : 
    1263 [ #  # ][ #  # ]:          0 :         if ( IsInListAction() && ( m_pData->pUndoArray->nCurUndoAction == 1 ) )
         [ #  # ][ #  # ]
    1264                 :            :         {
    1265                 :            :             OSL_ENSURE( false, "SfxUndoManager::RemoveOldestUndoActions: cannot remove a not-yet-closed list action!" );
    1266                 :          0 :             return;
    1267                 :            :         }
    1268                 :            : 
    1269         [ #  # ]:          0 :         aGuard.markForDeletion( pActionToRemove );
    1270         [ #  # ]:          0 :         m_pData->pUndoArray->aUndoActions.Remove( 0 );
    1271                 :          0 :         --m_pData->pUndoArray->nCurUndoAction;
    1272                 :          0 :         --nActionsToRemove;
    1273 [ #  # ][ #  # ]:          0 :     }
    1274                 :            : }
    1275                 :            : 
    1276                 :            : //------------------------------------------------------------------------
    1277                 :            : 
    1278                 :        602 : sal_uInt16 SfxListUndoAction::GetId() const
    1279                 :            : {
    1280                 :        602 :     return nId;
    1281                 :            : }
    1282                 :            : 
    1283                 :            : //------------------------------------------------------------------------
    1284                 :            : 
    1285                 :     433546 : rtl::OUString SfxListUndoAction::GetComment() const
    1286                 :            : {
    1287                 :     433546 :     return aComment;
    1288                 :            : }
    1289                 :            : 
    1290                 :            : //------------------------------------------------------------------------
    1291                 :            : 
    1292                 :       6972 : void SfxListUndoAction::SetComment( const UniString& rComment )
    1293                 :            : {
    1294                 :       6972 :     aComment = rComment;
    1295                 :       6972 : }
    1296                 :            : 
    1297                 :            : //------------------------------------------------------------------------
    1298                 :            : 
    1299                 :          8 : XubString SfxListUndoAction::GetRepeatComment(SfxRepeatTarget &) const
    1300                 :            : {
    1301                 :          8 :     return aRepeatComment;
    1302                 :            : }
    1303                 :            : 
    1304                 :            : 
    1305                 :            : //------------------------------------------------------------------------
    1306                 :            : 
    1307                 :     518309 : SfxListUndoAction::SfxListUndoAction
    1308                 :            : (
    1309                 :            :     const XubString &rComment,
    1310                 :            :     const XubString rRepeatComment,
    1311                 :            :     sal_uInt16 Id,
    1312                 :            :     SfxUndoArray *pFather
    1313                 :            : )
    1314 [ +  - ][ +  - ]:     518309 : : nId(Id), aComment(rComment), aRepeatComment(rRepeatComment)
                 [ +  - ]
    1315                 :            : {
    1316                 :     518309 :     pFatherUndoArray = pFather;
    1317                 :     518309 :     nMaxUndoActions = USHRT_MAX;
    1318                 :     518309 : }
    1319                 :            : 
    1320                 :            : //------------------------------------------------------------------------
    1321                 :            : 
    1322                 :         54 : void SfxListUndoAction::Undo()
    1323                 :            : {
    1324         [ +  + ]:        152 :     for(size_t i=nCurUndoAction;i>0;)
    1325                 :         98 :         aUndoActions[--i].pAction->Undo();
    1326                 :         54 :     nCurUndoAction=0;
    1327                 :         54 : }
    1328                 :            : 
    1329                 :            : //------------------------------------------------------------------------
    1330                 :            : 
    1331                 :         32 : void SfxListUndoAction::UndoWithContext( SfxUndoContext& i_context )
    1332                 :            : {
    1333         [ +  + ]:         80 :     for(size_t i=nCurUndoAction;i>0;)
    1334                 :         48 :         aUndoActions[--i].pAction->UndoWithContext( i_context );
    1335                 :         32 :     nCurUndoAction=0;
    1336                 :         32 : }
    1337                 :            : 
    1338                 :            : //------------------------------------------------------------------------
    1339                 :            : 
    1340                 :          0 : void SfxListUndoAction::Redo()
    1341                 :            : {
    1342         [ #  # ]:          0 :     for(size_t i=nCurUndoAction;i<aUndoActions.size();i++)
    1343                 :          0 :         aUndoActions[i].pAction->Redo();
    1344                 :          0 :     nCurUndoAction = aUndoActions.size();
    1345                 :          0 : }
    1346                 :            : 
    1347                 :            : //------------------------------------------------------------------------
    1348                 :            : 
    1349                 :          4 : void SfxListUndoAction::RedoWithContext( SfxUndoContext& i_context )
    1350                 :            : {
    1351         [ +  + ]:          8 :     for(size_t i=nCurUndoAction;i<aUndoActions.size();i++)
    1352                 :          4 :         aUndoActions[i].pAction->RedoWithContext( i_context );
    1353                 :          4 :     nCurUndoAction = aUndoActions.size();
    1354                 :          4 : }
    1355                 :            : 
    1356                 :            : //------------------------------------------------------------------------
    1357                 :            : 
    1358                 :          0 : void SfxListUndoAction::Repeat(SfxRepeatTarget&rTarget)
    1359                 :            : {
    1360         [ #  # ]:          0 :     for(size_t i=0;i<nCurUndoAction;i++)
    1361                 :          0 :         aUndoActions[i].pAction->Repeat(rTarget);
    1362                 :          0 : }
    1363                 :            : 
    1364                 :            : //------------------------------------------------------------------------
    1365                 :            : 
    1366                 :         16 : sal_Bool SfxListUndoAction::CanRepeat(SfxRepeatTarget&r)  const
    1367                 :            : {
    1368         [ +  + ]:         40 :     for(size_t i=0;i<nCurUndoAction;i++)
    1369         [ -  + ]:         24 :         if(!aUndoActions[i].pAction->CanRepeat(r))
    1370                 :          0 :             return sal_False;
    1371                 :         16 :     return sal_True;
    1372                 :            : }
    1373                 :            : 
    1374                 :            : //------------------------------------------------------------------------
    1375                 :            : 
    1376                 :          0 : sal_Bool SfxListUndoAction::Merge( SfxUndoAction *pNextAction )
    1377                 :            : {
    1378 [ #  # ][ #  # ]:          0 :     return !aUndoActions.empty() && aUndoActions[aUndoActions.size()-1].pAction->Merge( pNextAction );
    1379                 :            : }
    1380                 :            : 
    1381                 :            : //------------------------------------------------------------------------
    1382                 :            : 
    1383                 :          0 : SfxLinkUndoAction::SfxLinkUndoAction(::svl::IUndoManager *pManager)
    1384                 :            : /*  [Beschreibung]
    1385                 :            : 
    1386                 :            :     Richtet eine LinkAction ein, die auf einen weiteren UndoManager zeigt.
    1387                 :            :     Holt sich als zugehoerige Action des weiteren UndoManagers dessen
    1388                 :            :     aktuelle Action.
    1389                 :            : */
    1390                 :            : 
    1391                 :            : {
    1392                 :          0 :     pUndoManager = pManager;
    1393         [ #  # ]:          0 :     SfxUndoManager* pUndoManagerImplementation = dynamic_cast< SfxUndoManager* >( pManager );
    1394 [ #  # ][ #  # ]:          0 :     ENSURE_OR_THROW( pUndoManagerImplementation != NULL, "unsupported undo manager implementation!" );
         [ #  # ][ #  # ]
    1395                 :            :         // yes, this cast is dirty. But reaching into the the SfxUndoManager's implementation,
    1396                 :            :         // directly accessing its internal stack, and tampering with an action on that stack
    1397                 :            :         // is dirty, too.
    1398 [ #  # ][ #  # ]:          0 :     if ( pManager->GetMaxUndoActionCount() )
    1399                 :            :     {
    1400         [ #  # ]:          0 :         size_t nPos = pManager->GetUndoActionCount()-1;
    1401         [ #  # ]:          0 :         pAction = pUndoManagerImplementation->m_pData->pActUndoArray->aUndoActions[nPos].pAction;
    1402         [ #  # ]:          0 :         pAction->SetLinked();
    1403                 :            :     }
    1404                 :            :     else
    1405                 :          0 :         pAction = 0;
    1406                 :          0 : }
    1407                 :            : 
    1408                 :            : //------------------------------------------------------------------------
    1409                 :            : 
    1410                 :          0 : void SfxLinkUndoAction::Undo()
    1411                 :            : {
    1412         [ #  # ]:          0 :     if ( pAction )
    1413                 :          0 :         pUndoManager->Undo();
    1414                 :          0 : }
    1415                 :            : 
    1416                 :            : //------------------------------------------------------------------------
    1417                 :            : 
    1418                 :          0 : void SfxLinkUndoAction::Redo()
    1419                 :            : {
    1420         [ #  # ]:          0 :     if ( pAction )
    1421                 :          0 :         pUndoManager->Redo();
    1422                 :          0 : }
    1423                 :            : 
    1424                 :            : //------------------------------------------------------------------------
    1425                 :            : 
    1426                 :            : 
    1427                 :          0 : sal_Bool SfxLinkUndoAction::CanRepeat(SfxRepeatTarget& r) const
    1428                 :            : {
    1429 [ #  # ][ #  # ]:          0 :     return pAction && pAction->CanRepeat(r);
    1430                 :            : }
    1431                 :            : 
    1432                 :            : 
    1433                 :            : //------------------------------------------------------------------------
    1434                 :            : 
    1435                 :            : 
    1436                 :          0 : void SfxLinkUndoAction::Repeat(SfxRepeatTarget&r)
    1437                 :            : {
    1438 [ #  # ][ #  # ]:          0 :     if ( pAction && pAction->CanRepeat( r ) )
                 [ #  # ]
    1439                 :          0 :         pAction->Repeat( r );
    1440                 :          0 : }
    1441                 :            : 
    1442                 :            : 
    1443                 :            : //------------------------------------------------------------------------
    1444                 :            : 
    1445                 :          0 : rtl::OUString SfxLinkUndoAction::GetComment() const
    1446                 :            : {
    1447         [ #  # ]:          0 :     if ( pAction )
    1448                 :          0 :         return pAction->GetComment();
    1449                 :          0 :     return rtl::OUString();
    1450                 :            : }
    1451                 :            : 
    1452                 :            : 
    1453                 :            : //------------------------------------------------------------------------
    1454                 :            : 
    1455                 :          0 : XubString SfxLinkUndoAction::GetRepeatComment(SfxRepeatTarget&r) const
    1456                 :            : {
    1457         [ #  # ]:          0 :     if ( pAction )
    1458                 :          0 :         return pAction->GetRepeatComment(r);
    1459                 :            :     else
    1460                 :          0 :         return XubString();
    1461                 :            : }
    1462                 :            : 
    1463                 :            : //------------------------------------------------------------------------
    1464                 :            : 
    1465                 :          0 : SfxLinkUndoAction::~SfxLinkUndoAction()
    1466                 :            : {
    1467         [ #  # ]:          0 :     if( pAction )
    1468         [ #  # ]:          0 :         pAction->SetLinked( sal_False );
    1469         [ #  # ]:          0 : }
    1470                 :            : 
    1471                 :            : 
    1472                 :            : //------------------------------------------------------------------------
    1473                 :            : 
    1474                 :     545554 : SfxUndoArray::~SfxUndoArray()
    1475                 :            : {
    1476         [ +  + ]:     787704 :     while ( !aUndoActions.empty() )
    1477                 :            :     {
    1478         [ +  - ]:     242150 :         SfxUndoAction *pAction = aUndoActions[ aUndoActions.size() - 1 ].pAction;
    1479         [ +  - ]:     242150 :         aUndoActions.Remove( aUndoActions.size() - 1 );
    1480 [ +  - ][ +  - ]:     242150 :         delete pAction;
    1481                 :            :     }
    1482                 :     545554 : }
    1483                 :            : 
    1484                 :            : 
    1485                 :          0 : sal_uInt16 SfxLinkUndoAction::GetId() const
    1486                 :            : {
    1487         [ #  # ]:          0 :       return pAction ? pAction->GetId() : 0;
    1488 [ +  - ][ +  - ]:       1062 : }
    1489                 :            : 
    1490                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10