ophist.cpp

Go to the documentation of this file.
00001 // $Id: ophist.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // Implemetation of the following classes
00100 /*
00101     OperationHistory : The operation history used to store undoable operations
00102     OpUndo           : The undo operation                                    
00103     OpRedo           : The redo operation
00104     
00105 */  
00106 
00107 /*
00108 */ 
00109 #include "camtypes.h"  
00110 //#include "ops.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 
00112 DECLARE_SOURCE("$Revision: 1282 $");
00113              
00114 #include "ophist.h"  
00115 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 //#include "mario.h"
00118 #include "helpids.h"
00119 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 //#include "resource.h"
00121 //#include "barsdlgs.h"
00122 #include <limits.h>
00123 //#include "bubbleid.h"
00124 
00125 CC_IMPLEMENT_MEMDUMP(OperationHistory, CCObject)
00126 #if !defined(EXCLUDE_FROM_RALPH)
00127 CC_IMPLEMENT_DYNCREATE(OpRedo, Operation)  
00128 CC_IMPLEMENT_DYNCREATE(OpUndo, Operation)  
00129 #endif
00130 
00131 // Declare smart memory handling in Debug builds
00132 #define new CAM_DEBUG_NEW
00133      
00134 /********************************************************************************************
00135 
00136 >   OperationHistory::OperationHistory()
00137 
00138     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00139     Created:    6/7/93
00140     Inputs:     -
00141     Outputs:    -
00142     Returns:    -
00143     Purpose:    Constructs an OperationHistory object with a maximum size of UINT32_MAX
00144                 bytes.  
00145     Errors:     -
00146     SeeAlso:    -
00147 
00148 ********************************************************************************************/
00149 
00150 OperationHistory::OperationHistory()
00151 {        
00152     NowPtr = NULL;              // History initially has no operations
00153     CurrentSize = 0;          
00154     //MaxSize = 512000;         // 500K
00155     MaxSize = 2048000;          // 2000K (2MB)      CGS (18/5/2000)
00156                                 // I have changed this because it is too small for some
00157                                 // of the operations that we can now perform
00158     Reduced = FALSE;
00159 }                                     
00160 
00161 /********************************************************************************************
00162 
00163 >   OperationHistory::~OperationHistory()
00164 
00165     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00166     Created:    2/8/93
00167     Inputs:     -
00168     Outputs:    -
00169     Returns:    -
00170     Purpose:    OperationHistory destructor
00171     Errors:     -
00172     SeeAlso:    -
00173 
00174 ********************************************************************************************/
00175 
00176 OperationHistory::~OperationHistory()
00177 {
00178     //if (Action::LastDiscardableAction != NULL)  
00179     //  delete (Action::LastDiscardableAction); 
00180 
00181     // Delete all operations in the OpHistoryList    
00182     // This is done using by calling the normal methods, to ensure deletion order
00183     // is correct
00184     DeleteUndoableOps();
00185     DeleteRedoableOps();    
00186 }
00187 
00188 /********************************************************************************************
00189 
00190 >   OperationHistory::OperationHistory(UINT32 MaximumSize)
00191 
00192     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00193     Created:    6/7/93
00194     Inputs:     MaximumSize: The maximum size of the operation history being constructed
00195     Outputs:    -
00196     Returns:    -
00197     Purpose:    Constructs an operationHistory object with a maximum size of MaximumSize
00198                 bytes. 
00199     Errors:     -
00200     SeeAlso:    -
00201 
00202 ********************************************************************************************/
00203 
00204 OperationHistory::OperationHistory(UINT32 MaximumSize)
00205 {                            
00206     NowPtr = NULL;           // History initially has no operations
00207     CurrentSize = 0; 
00208     MaxSize = MaximumSize; 
00209     Reduced = FALSE;
00210 }    
00211 
00212 /********************************************************************************************
00213 
00214 >   void OperationHistory::SetNewMaxSize(UINT32 NewMaxSize)
00215 
00216     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00217     Created:    6/7/93
00218     Inputs:     NewMaxSize: The new maximum size of the operation history
00219                             in bytes. 
00220     Outputs:    -
00221     Returns:    FALSE only if we are reducing the maximum size, and deleting all undo ops would
00222                 not reduce the current size of the operation history to NewMaxSize bytes or less.
00223                 
00224                 TRUE otherwise
00225                 
00226     Purpose:    For setting a new maximum size for the operation history. 
00227                 
00228                 
00229     Errors:     -
00230     SeeAlso:    OperationHistory::ReduceSize
00231 
00232 ********************************************************************************************/
00233 
00234 BOOL OperationHistory::SetNewMaxSize(UINT32 NewMaxSize)
00235 {   
00236     
00237     if (NewMaxSize < CurrentSize)    
00238     {  
00239         // We must try to reduce the current size of the OperationHistory to NewMaxSize 
00240         // bytes or less.
00241         if (!ReduceSize(NewMaxSize, FALSE))
00242         {
00243             return FALSE; 
00244         } 
00245     }
00246     MaxSize = NewMaxSize; 
00247     return (TRUE); 
00248 } 
00249 
00250 
00251 /********************************************************************************************
00252 
00253 >   UINT32 OperationHistory::GetSize()
00254 
00255     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00256     Created:    6/7/93
00257     Inputs:     -
00258     Outputs:    -
00259     Returns:    The current size of the operation history in bytes. 
00260     Purpose:    For finding the current size of the operation history
00261     Errors:     -
00262     SeeAlso:    -
00263 
00264 ********************************************************************************************/
00265 
00266 UINT32 OperationHistory::GetSize()
00267 {   
00268     return (CurrentSize);  
00269 } 
00270 
00271 /********************************************************************************************
00272 
00273 >   UINT32 OperationHistory::GetMaxSize()
00274 
00275     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00276     Created:    6/7/93
00277     Inputs:     -
00278     Outputs:    -
00279     Returns:    The maximum size of the operation history
00280     Purpose:    To find the maximum size of the operation history
00281     Errors:     -
00282     SeeAlso:    -
00283 
00284 ********************************************************************************************/
00285 
00286 UINT32 OperationHistory::GetMaxSize()
00287 {    
00288     return (MaxSize);  
00289 }  
00290 
00291 
00292 /********************************************************************************************
00293 
00294 >   void OperationHistory::IncSize(UINT32 SizeDecrement)
00295 
00296     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00297     Created:    22/7/93
00298     Inputs:     SizeIncrement: Amount by which the current size of the operation history 
00299                                is to be increased. 
00300     Outputs:    -
00301     Returns:    -
00302     Purpose:    To increase the current size of the operation history. 
00303     Errors:     -      
00304     Scope:      private
00305     SeeAlso:    -
00306 
00307 ********************************************************************************************/
00308 
00309                               
00310 void OperationHistory::IncSize(UINT32 SizeIncrement)
00311 {
00312     CurrentSize += SizeIncrement; 
00313 }  
00314 
00315 /********************************************************************************************
00316 
00317 >   void OperationHistory::DecSize(UINT32 SizeDecrement)
00318 
00319     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00320     Created:    22/7/93
00321     Inputs:     SizeDecrement: Amount by which the current size of the operation history 
00322                                is to be decreased. 
00323     Outputs:    -
00324     Returns:    -
00325     Purpose:    To decrease the current size of the operation history. 
00326     Errors:     -   
00327     Scope:      private
00328     SeeAlso:    -
00329 
00330 ********************************************************************************************/
00331 
00332 
00333 void OperationHistory::DecSize(UINT32 SizeDecrement)
00334 { 
00335     CurrentSize -= SizeDecrement; 
00336 } 
00337 
00338 
00339 
00340 /********************************************************************************************
00341 
00342 >   UINT32 OperationHistory::GetNumUndoSteps()
00343 
00344     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00345     Created:    09/11/94
00346     Inputs:     -
00347     Outputs:    -
00348     Returns:    The number of undo steps in this history.
00349     Purpose:    To return the number of undo steps stored in this history. 
00350     Errors:     -   
00351     Scope:      public
00352     SeeAlso:    OperationHistory::GetNumRedoSteps
00353 
00354 ********************************************************************************************/
00355 UINT32 OperationHistory::GetNumUndoSteps()
00356 { 
00357     if (NowPtr == 0)
00358         return 0;
00359 
00360     ListItem* pOp = OpHistoryList.GetHead();   
00361     
00362     UINT32 count = 1;
00363 
00364     while ((pOp != NowPtr) && (pOp != NULL))
00365     {      
00366         count ++;
00367         pOp = OpHistoryList.GetNext(pOp);       
00368     }   
00369     return count;
00370 } 
00371 
00372 
00373 
00374 /********************************************************************************************
00375 
00376 >   UINT32 OperationHistory::GetNumRedoSteps()
00377 
00378     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00379     Created:    09/11/94
00380     Inputs:     -
00381     Outputs:    -
00382     Returns:    The number of redo steps in this history.
00383     Purpose:    To return the number of redo steps stored in this history. 
00384     Errors:     -   
00385     Scope:      public
00386     SeeAlso:    OperationHistory::GetNumUndoSteps
00387 
00388 ********************************************************************************************/
00389 UINT32 OperationHistory::GetNumRedoSteps()
00390 { 
00391     ListItem* pOp = NULL;
00392 
00393     if (NowPtr == NULL)
00394     {
00395         // If Now is NULL then there are no undo operations
00396         pOp = OpHistoryList.GetHead();
00397     }
00398     else
00399     {
00400         // Get the pointer to the operation following the NowPtr (which points at last undo op)
00401         pOp = OpHistoryList.GetNext(NowPtr);
00402     }
00403         
00404     UINT32 count = 0;
00405 
00406     while (pOp != NULL)
00407     {      
00408         count ++;
00409         pOp = OpHistoryList.GetNext(pOp);       
00410     }   
00411     return count;
00412 } 
00413 
00414 
00415 
00416 /********************************************************************************************
00417 
00418 >   BOOL OperationHistory::IsReduced()
00419 
00420     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00421     Created:    09/11/94
00422     Inputs:     -
00423     Outputs:    -
00424     Returns:    True if operations have been discared to free memory, otherwise FALSE
00425     Purpose:    To discover if operations have been discared, reducing the number of
00426                 undo/redo actions.
00427     Errors:     -   
00428     Scope:      public
00429     SeeAlso:    
00430 
00431 ********************************************************************************************/
00432 BOOL OperationHistory::IsReduced()
00433 { 
00434     return Reduced;
00435 } 
00436 
00437 
00438 
00439 /********************************************************************************************
00440 
00441 >   BOOL OperationHistory::ReduceSize(UINT32 MaxSize, BOOL ExcludeLastUndo, 
00442                                       BOOL DeleteWhatYouCan = FALSE)
00443 
00444     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00445     Created:    23/7/93
00446     Inputs:     MaxSize: The maximum size that the operation history should 
00447                          be reduced to.                       
00448                          
00449                 ExcludeLastUndo: If this flag is TRUE then the routine will 
00450                                  never delete the last undo operation in trying
00451                                  to reduce the size of the operation history.
00452                                  
00453                 DeleteWhatYouCan: If we cannot reduce the size of the operation history as low 
00454                                   as MaxSize bytes, and this flag is TRUE, then as many ops as 
00455                                   possible are deleted. 
00456     Outputs:    -
00457     Returns:    FALSE if the size of the operation history cannot be reduced to MaxSize bytes 
00458                 or less, Otherwise returns TRUE.        
00459     
00460     Purpose:    Tries to Reduce the current size of the operation history so that it is at most 
00461                 MaxSize bytes long. The size is reduced by deleting undo operations 
00462                 (Oldest first), redo operations are never deleted!. If the Operation history
00463                 would be larger than MaxSize bytes after deleting all undo operations, then 
00464                 no operations are deleted and the function returns FALSE.  
00465     
00466     Errors:     -
00467     SeeAlso:    -
00468 
00469 ********************************************************************************************/
00470 
00471 BOOL OperationHistory::ReduceSize(UINT32 MaxHistorySize, BOOL ExcludeLastUndo, BOOL DeleteWhatYouCan /*= FALSE*/)
00472 {                      
00473     // If the Current size of the operation history is less than or equal to MaxHistorySize then 
00474     // there is no need to do anything. 
00475     if ((CurrentSize <= MaxHistorySize))
00476         return (TRUE);          
00477     
00478     // If The NowPtr is NULL then there are no undo operations to be deleted so return FALSE
00479     if (NowPtr == NULL)
00480         return (FALSE); 
00481         
00482     // Calculate how many bytes we need to reduce the size of the Operation history by 
00483     UINT32 Reduction = (CurrentSize - MaxHistorySize);                                
00484     
00485     //-------------------------------------------------------------------------------
00486     // Check if the operation history can be reduced to MaxHistorySize bytes or less
00487                  
00488     // The OpSize total is the count of the number of bytes we can reduce the Operation 
00489     // history by. 
00490     UINT32 OpSizeTotal = 0;                           
00491                    
00492     // We know that the NowPtr is not NULL so the oldest undo operation will be found at 
00493     // the head of the OpHistoryList. 
00494     ListItem* pOp = OpHistoryList.GetHead();   
00495     
00496     // We are allowed to delete all operations from the head of the list 
00497     // upto and excluding StopOp. StopOp is the last undo operation if the 
00498     // ExcludeLastUndo flag is TRUE, else it is the first redo operation.                       
00499     ListItem* StopOp = (ExcludeLastUndo) ? NowPtr: OpHistoryList.GetNext(NowPtr); 
00500     
00501     
00502     // Loop until we either hit StopOp or we have found enough operations to delete 
00503     while ((pOp != StopOp) && (OpSizeTotal < Reduction))
00504     {                   
00505         // In a sane world this should always be true
00506         ENSURE( pOp != NULL, 
00507                 "OperationHistory::ReduceSize: Pointer OperationHistory is NULL"); 
00508         
00509         // Increase the OpSizeTotal by the number of bytes of the current operation 
00510         OpSizeTotal += ((Operation*)pOp)->GetSize();                               
00511         
00512         // Get the next operation
00513         pOp = OpHistoryList.GetNext(pOp);    
00514     };    
00515     
00516     //-------------------------------------------------------------------------------
00517     // Now if we can,  reduce the operation history size 
00518     
00519     if ((OpSizeTotal >= Reduction) || (DeleteWhatYouCan && (OpSizeTotal != 0))) // The size can be reduced 
00520     {                 
00521         // Start at the head of the OpHistoryList
00522         ListItem* pDeleteOp = OpHistoryList.GetHead();   
00523         
00524         #ifdef _DEBUG      
00525         UINT32 TotalChk = 0; 
00526         #endif
00527         
00528         while (pDeleteOp != pOp)
00529         {      
00530             DecSize(((Operation*)pDeleteOp)->GetSize());  // Reduce history size     
00531             
00532             #ifdef _DEBUG      
00533             TotalChk += ((Operation*)pDeleteOp)->GetSize(); 
00534             #endif
00535             ListItem* pNextDeleteOp = OpHistoryList.GetNext(pDeleteOp);       
00536             
00537             // If the operation which is about to be deleted is the operation pointed to by the NowPtr
00538             // then it is the last undo operation, so set NowPtr to NULL. 
00539             if (NowPtr == pDeleteOp) 
00540                 NowPtr = NULL; 
00541             delete(OpHistoryList.RemoveItem(pDeleteOp));         // Delete the operation   
00542             pDeleteOp = pNextDeleteOp; 
00543         }          
00544 
00545         // Defensive programming 
00546 
00547         #ifdef _DEBUG                       // Required because of TotalChk variable
00548         ENSURE( OpSizeTotal == TotalChk, 
00549                 "OperationHistory::ReduceSize: OpSizeTotal != TotalChk");  
00550         #endif             
00551                      
00552 
00553         Reduced = TRUE;
00554         
00555         return (TRUE); 
00556     }                                                     
00557     else
00558         return (FALSE); // Cannot reduce size of history to MaxHistorySize bytes or less
00559 } 
00560 
00561 
00562 /********************************************************************************************
00563 
00564 >   BOOL OperationHistory::UndoPrev()
00565                                        
00566     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00567     Created:    5/7/93
00568     Inputs:     -
00569     Outputs:    -
00570     Returns:    TRUE if an operation was successfully undone, FALSE otherwise. 
00571     Purpose:    To UNDO the previous operation 
00572     Errors:     -
00573     SeeAlso:    -
00574 
00575 ********************************************************************************************/
00576               
00577 BOOL OperationHistory::UndoPrev()
00578 {                       
00579     //TRACE( _T("Called Undo\n"));   
00580     if (NowPtr != NULL) // Check if there is an operation to UNDO                 
00581     {
00582         // Tell the world that the op is about to be undone
00583         BROADCAST_TO_ALL(OpMsg(((Operation*)NowPtr),OpMsg::BEFORE_UNDO)); 
00584         Operation* pOp = (Operation*)NowPtr;
00585 
00586         if (pOp->Undo()) // Undo the operation
00587         {
00588             ERROR3IF(NowPtr == NULL, "The operation which has just been undone has been deleted"); 
00589             if (NowPtr != NULL)
00590             {
00591                 // We used to find the prev op before the undo, this was wrong because it may have been deleted.
00592                 NowPtr = OpHistoryList.GetPrev(NowPtr);
00593             }
00594             Operation* NextOp;
00595             if (NowPtr != NULL)
00596             {
00597                 NextOp = ((Operation*)OpHistoryList.GetNext(NowPtr));     
00598             }
00599             else
00600             {
00601                 NextOp = ((Operation*)OpHistoryList.GetHead());
00602             }
00603             BROADCAST_TO_ALL(OpMsg(NextOp,OpMsg::AFTER_UNDO)); 
00604             return (TRUE);  
00605         } 
00606     }
00607     return (FALSE); // There are no operations to UNDO, or the Operation failed to undo 
00608 }
00609 
00610 
00611 /********************************************************************************************
00612                        
00613 >   BOOL OperationHistory::RedoNext() 
00614     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00615     Created:    5/7/93
00616     Inputs:     -
00617     Outputs:    -
00618     Returns:    TRUE if an operation was successfully redone, FALSE otherwise. 
00619     Purpose:    To REDO the next operation
00620     Errors:     -
00621     SeeAlso:    -
00622 
00623 ********************************************************************************************/
00624  
00625 BOOL OperationHistory::RedoNext() 
00626 {             
00627     ListItem* next;                   
00628     
00629     if (NowPtr == NULL)  
00630     // If the NowPtr is NULL then if there are any redo operations then the first will be 
00631     // found at the head of the OpHistoryList            
00632         next = OpHistoryList.GetHead(); 
00633     else           
00634         // The first redo operation will be found after the NowPtr
00635         next = OpHistoryList.GetNext(NowPtr);
00636     if ( next != NULL) 
00637     {
00638         Operation* pOp = (Operation*)next;
00639         BROADCAST_TO_ALL(OpMsg(pOp,OpMsg::BEFORE_REDO)); 
00640         // There is an operation to redo 
00641         if (pOp->Redo()) // REDO the operation    
00642         {
00643             NowPtr = next;
00644             BROADCAST_TO_ALL(OpMsg(((Operation*)NowPtr), OpMsg::AFTER_REDO)); 
00645             return (TRUE);   
00646         }
00647     }                  
00648     return (FALSE); // There are no operations to REDO
00649 }                   
00650 
00651 /********************************************************************************************
00652 
00653 >   BOOL OperationHistory::CanUndo() 
00654     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00655     Created:    9/7/93
00656     Inputs:     -
00657     Outputs:    -
00658     Returns:    TRUE if there are any operations to UNDO, FALSE otherwise.
00659     Purpose:    To find out whether undo is possible.
00660     Errors:     -
00661     SeeAlso:    -
00662 
00663 ********************************************************************************************/
00664  
00665 BOOL OperationHistory::CanUndo() 
00666 {
00667     return ( NowPtr != NULL );
00668 }
00669 
00670 /********************************************************************************************
00671 
00672 >   BOOL OperationHistory::CanRedo() 
00673     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00674     Created:    9/7/93
00675     Inputs:     -
00676     Outputs:    -
00677     Returns:    TRUE if there are any operations to REDO, FALSE otherwise.
00678     Purpose:    To find out whether a redo is possible.
00679     Errors:     -
00680     SeeAlso:    -
00681 
00682 ********************************************************************************************/
00683  
00684 BOOL OperationHistory::CanRedo() 
00685 {                    
00686     if (NowPtr == NULL)    
00687         // If the NowPtr is NULL then the first redo operation will be found at the head of the 
00688         // OpHistory list
00689         return (OpHistoryList.GetHead() != NULL); 
00690     else             
00691         // The first redo operation will be found at the node after NowPtr
00692         return ((OpHistoryList.GetNext(NowPtr)) != NULL);
00693 }               
00694 
00695 
00696 /********************************************************************************************
00697 
00698 >   void OperationHistory::GetUndoOpName(String_256* OpName)
00699 
00700     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
00701     Created:    4/10/93
00702     Outputs:    OpName String - name of the operation to be undone next
00703     Purpose:    To get the name of the currently undoable operation
00704 
00705 ********************************************************************************************/
00706 
00707 void OperationHistory::GetUndoOpName(String_256* OpName)
00708 {
00709     ((Operation*) NowPtr)->GetOpName(OpName);
00710 }
00711 
00712 /********************************************************************************************
00713 
00714 >   void OperationHistory::GetRedoOpName(String_256* OpName)
00715 
00716     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
00717     Created:    4/10/93
00718     Outputs:    OpName String - name of the operation to be undone next
00719     Purpose:    To get the name of the currently undoable operation
00720 
00721 ********************************************************************************************/
00722  
00723 void OperationHistory::GetRedoOpName(String_256* OpName) 
00724 {                          
00725     if (NowPtr == NULL)    
00726         // If the NowPtr is NULL then the first redo operation will be found at the head of the 
00727         // OpHistory list
00728         ((Operation*) OpHistoryList.GetHead())->GetOpName(OpName);
00729     else             
00730         // The first redo operation will be found at the node after NowPtr
00731         ((Operation*) OpHistoryList.GetNext(NowPtr))->GetOpName(OpName);
00732 }                   
00733 
00734 #ifdef _DEBUG
00735 
00736 /********************************************************************************************
00737 
00738 >   void OperationHistory::DebugSizeCheck()
00739 
00740     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00741     Created:    22/7/93
00742     Inputs:     -
00743     Outputs:    -
00744     Returns:    -
00745     Purpose:    For validating that the sum of the sizes of actions in the operation history
00746                 equals the current size of the operation history. 
00747     Errors:     -
00748     SeeAlso:    -
00749 
00750 ********************************************************************************************/
00751 
00752  
00753 void OperationHistory::DebugSizeCheck()
00754 {
00755     UINT32 TotalOfActionSizes = 0; 
00756     ListItem* pOp = OpHistoryList.GetHead();  // Get first operation
00757     
00758     while (pOp != NULL)                        // For each operation
00759     {       
00760         // Add current operation size to the action total 
00761         TotalOfActionSizes += ((Operation*)pOp)->GetSize();  
00762         pOp = OpHistoryList.GetNext(pOp); 
00763     }                        
00764     //if (IsUserName("Simon"))
00765     //{        
00766         //TRACE( _T("Current Size = %lu, Action Total = %lu\n"), CurrentSize, TotalOfActionSizes); 
00767     //}                   
00768     // Cause a blobby if the total of all action sizes does not equal the current 
00769     // size of the operation history. 
00770     ENSURE(TotalOfActionSizes == CurrentSize, "The size of the operation history is invalid");   
00771 }                
00772 
00773 #endif  
00774    
00775 /********************************************************************************************
00776 
00777 >   void OperationHistory::DeleteUndoableOps()
00778 
00779     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00780     Created:    23/7/93
00781     Inputs:     -
00782     Outputs:    -
00783     Returns:    -
00784     Purpose:    If any undoable operations exist then the method deletes them all.
00785     Errors:     -
00786     SeeAlso:    -
00787 
00788 ********************************************************************************************/
00789    
00790 void OperationHistory::DeleteUndoableOps()
00791 {
00792 #if FALSE
00793 // Removed by Jason
00794 // This was deleting backwards to the desired direction!
00795 // Direction of deletion has been reversed in the #else section below
00796 
00797 /*
00798     if  (NowPtr != NULL)  // Undoable operations exist
00799     {    
00800         ListItem* CurrentOp = NowPtr; // First undoable operation 
00801         // Loop until all undoables have been deleted
00802         do
00803         {                       
00804             ListItem* PrevOp = OpHistoryList.GetPrev(CurrentOp); 
00805             // The size of the operation history is reduced by the size of the  
00806             // operation just about to be deleted.   
00807             DecSize(((Operation*)CurrentOp)->GetSize());  
00808             // Actually delete the current operation 
00809             delete((Operation*)(OpHistoryList.RemoveItem(CurrentOp)));       
00810             // Get next op
00811             CurrentOp = PrevOp; 
00812         }  while (CurrentOp != NULL); 
00813         NowPtr = NULL;                  // No undoable operations
00814     }   
00815 */
00816 #else
00817     if  (NowPtr != NULL)  // Undoable operations exist
00818     {    
00819         ListItem* CurrentOp = OpHistoryList.GetHead(); // First undoable operation 
00820         // Loop until all undoables have been deleted
00821 
00822         if (CurrentOp == NULL)      // No Undo records?! (Shouldn't happen if NowPtr != NULL)
00823             return;
00824 
00825         do
00826         {                       
00827             ListItem* NextOp = OpHistoryList.GetNext(CurrentOp);
00828             // The size of the operation history is reduced by the size of the  
00829             // operation just about to be deleted.   
00830             DecSize(((Operation*)CurrentOp)->GetSize());  
00831             // Actually delete the current operation 
00832             
00833             delete((Operation*)(OpHistoryList.RemoveItem(CurrentOp)));
00834             if (CurrentOp == NowPtr)    // Delete NowPtr item as well
00835                 CurrentOp = NULL;       // it is gone, so we MUST stop now
00836             else
00837                 CurrentOp = NextOp;     // Continue with the next Op
00838 
00839         }  while (CurrentOp != NULL);
00840         NowPtr = NULL;                  // No undoable operations
00841     }
00842 #endif
00843 } 
00844    
00845 /********************************************************************************************
00846 
00847 >   void OperationHistory::DeleteRedoableOps()
00848 
00849     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00850     Created:    23/7/93
00851     Inputs:     -
00852     Outputs:    -
00853     Returns:    -
00854     Purpose:    If any redoable operations exist then the method deletes them all.
00855     Errors:     -
00856     SeeAlso:    -
00857 
00858 ********************************************************************************************/
00859     
00860 void OperationHistory::DeleteRedoableOps()
00861 {   
00862 #if FALSE
00863 // Removed by Jason
00864 // This was deleting backwards to the desired direction!
00865 // Direction of deletion has been reversed in the #else section below
00866 
00867 /*
00868     ListItem* CurrentOp;    
00869                 
00870     // Find the first redoable operation        
00871     if (NowPtr == NULL)                        
00872     // If the NowPtr is NULL then the first redoable operation will be found at the 
00873     // head of the OpHistoryList
00874         CurrentOp = OpHistoryList.GetHead(); // Head of list is first redoable
00875     else                        
00876     // The first redoable operation will be found at the node after NowPtr
00877         CurrentOp = OpHistoryList.GetNext(NowPtr); 
00878       
00879     // Loop while there are redo operations to delete  
00880     while(CurrentOp != NULL)
00881     {              
00882         ListItem* NextOp = OpHistoryList.GetNext(CurrentOp); 
00883         // The size of the operation history is reduced by the size of the  
00884         // deleted operation.   
00885         DecSize(((Operation*)CurrentOp)->GetSize());   
00886         // Actually delete the operation 
00887         delete( (Operation*)((OpHistoryList.RemoveItem(CurrentOp))) );   
00888         // Get the next op      
00889         CurrentOp = NextOp; 
00890     }
00891 */
00892 #else
00893     ListItem* CurrentOp;
00894     ListItem* LastOp;
00895                 
00896     // Find the first redoable operation        
00897     if (NowPtr == NULL)                        
00898     // If the NowPtr is NULL then the first redoable operation will be found at the 
00899     // head of the OpHistoryList
00900         LastOp = OpHistoryList.GetHead(); // Head of list is first redoable
00901     else                        
00902     // The first redoable operation will be found at the node after NowPtr
00903         LastOp = OpHistoryList.GetNext(NowPtr); 
00904 
00905     if (LastOp == NULL)     // No redo list at all
00906         return;
00907 
00908     CurrentOp = OpHistoryList.GetTail();
00909     
00910     // Loop while there are redo operations to delete  
00911     while(CurrentOp != LastOp)
00912     {              
00913         ListItem* PrevOp = OpHistoryList.GetPrev(CurrentOp); 
00914         // The size of the operation history is reduced by the size of the  
00915         // deleted operation.   
00916         DecSize(((Operation*)CurrentOp)->GetSize());
00917         // Actually delete the operation
00918         delete( (Operation*)((OpHistoryList.RemoveItem(CurrentOp))) );
00919         // Get the next op
00920         CurrentOp = PrevOp;
00921     }
00922 
00923     // And also delete the last redoable op
00924     DecSize(((Operation*)LastOp)->GetSize());
00925     delete( (Operation*)((OpHistoryList.RemoveItem(LastOp))) );
00926 #endif
00927 }
00928 
00929 /********************************************************************************************
00930 
00931 >   void OperationHistory::Add(ListItem* Op)
00932 
00933     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00934     Created:    5/7/93
00935     Inputs:     Op: New operation to be added to the history
00936     Outputs:    -
00937     Returns:    -
00938     Purpose:    To add operation Op to the operation history. At present this function
00939                 also deletes all 'REDO' operations.
00940                 
00941                 Note that when an operation is added to the operation history we do not 
00942                 increase its size. The size will have already been increased when actions
00943                 were initialised. 
00944                 
00945     Errors:     -       
00946     Scope:      private
00947     SeeAlso:    -
00948 
00949 ********************************************************************************************/
00950 /* 
00951 Technical Notes: 
00952 
00953 Currently when a new operation is added to the operation history, all redoable operations
00954 are deleted. This may change if we implement a more advanced UNDO system. 
00955 */     
00956     
00957 void OperationHistory::Add(ListItem* Op)
00958 { 
00959     if (NowPtr == NULL)
00960     {             
00961         // There are currently no undo operations so add the new Op to the head of the 
00962         // OpHistory list. 
00963         NowPtr = Op; 
00964         OpHistoryList.AddHead(Op);  
00965     }
00966     else                
00967     {                      
00968         // Insert the new operation after the current undoable operation 
00969         OpHistoryList.InsertAfter(NowPtr, Op);                           
00970         // The new operation becomes the current undoable operation 
00971         NowPtr = Op; 
00972     }   
00973     // Delete all REDOable operations for now (This may change if we start getting clever) 
00974     DeleteRedoableOps();
00975     //if (IsUserName("Simon"))
00976     //{
00977     //  TRACE( _T("Size of operation history = %lu"), CurrentSize); 
00978     //}     
00979    
00980 }
00981 
00982 // -------------------------------------------------------------------------------------
00983 // The following functions are useful for operation merging
00984 
00985 /********************************************************************************************
00986 
00987 >   Operation* OperationHistory::FindLastOp() 
00988 
00989     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00990     Created:    4/11/94
00991     Inputs:     -
00992     Outputs:    -
00993     Returns:    -
00994     Purpose:    This function returns a pointer to the last operation which was performed 
00995                 (but not undone). i.e. The NowPtr. It is provided to allow the merging of 
00996                 operations. NULL is returned if no such operation exists
00997 
00998     Errors:     -
00999     SeeAlso:    OperationHistory::FindPrevToLastOp
01000 
01001 ********************************************************************************************/
01002 
01003 Operation* OperationHistory::FindLastOp()
01004 {
01005     return (Operation*)NowPtr;
01006 }
01007 
01008 
01009 /********************************************************************************************
01010 
01011 >   Operation* OperationHistory::FindPrevToLastOp() 
01012 
01013     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01014     Created:    4/11/94
01015     Inputs:     -
01016     Outputs:    -
01017     Returns:    -
01018     Purpose:    This function returns a pointer to the operation which was performed 
01019                 (and not undone) prior to the last operation. This is the op which will 
01020                 usually need to be changed/extended when we are merging operations.  NULL
01021                 is returned if no such operation exists.
01022 
01023     Errors:     -
01024     SeeAlso:    OperationHistory::FindLastOp
01025 
01026 ********************************************************************************************/
01027 
01028 
01029 Operation* OperationHistory::FindPrevToLastOp() 
01030 {
01031     if (NowPtr != NULL)
01032     {
01033         return ((Operation*)(OpHistoryList.GetPrev(NowPtr)));
01034     }
01035     else
01036     {
01037         return NULL; 
01038     }
01039 }
01040 
01041 /********************************************************************************************
01042 
01043 >   void OperationHistory::DeleteLastOp(BOOL ReduceOpHistSize = TRUE)
01044 
01045     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01046     Created:    4/11/94
01047     Inputs:     ReduceOpHistSize: When TRUE the size of the OperationHistory is reduced by 
01048                 the size of the operation being deleted.
01049     Outputs:    -
01050     Returns:    -
01051     Purpose:    This function deletes the last operation which was performed. It is useful
01052                 to do this after we have merged this last operation with the previous operation.
01053                 The size of the Operation history is reduced by the size of this operation if
01054                 the ReduceOpHistSize flag is TRUE. 
01055 
01056     Errors:     -
01057     SeeAlso:    OperationHistory::FindLastOp
01058                 OperationHistory::FindPrevToLastOp
01059 
01060 ********************************************************************************************/
01061 
01062 void OperationHistory::DeleteLastOp(BOOL ReduceOpHistSize)
01063 {  
01064     Operation* pOpToDelete = FindLastOp(); 
01065 
01066     // The NowPtr needs to be set to the previous operation - if one exists
01067     // if not then NULL is an OK state for the NowPtr
01068     NowPtr = OpHistoryList.GetPrev(NowPtr); 
01069 
01070     if (ReduceOpHistSize)
01071     {
01072         DecSize(pOpToDelete->GetSize());  // Reduce history size 
01073     }    
01074             
01075     OpHistoryList.RemoveItem((ListItem*)pOpToDelete);   // Remove the operation from the
01076                                                         // history list but don't delete it yet
01077     pOpToDelete->DeleteOnEnd();                         // Mark it for deletion when it's safe
01078                                                         // to do so.
01079 } 
01080 
01081 
01082 /********************************************************************************************
01083 
01084 >   void OperationHistory::DeletePrevToLastOp(BOOL ReduceOpHistSize)
01085 
01086     Author:     Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com>
01087     Created:    4/08/97
01088     Inputs:     ReduceOpHistSize: When TRUE the size of the OperationHistory is reduced by 
01089                 the size of the operation being deleted.
01090     Outputs:    -
01091     Returns:    -
01092     Purpose:    This function deletes the previous to last operation which was performed. It is 
01093                 useful to do this after we have merged the last operation with the previous 
01094                 operation. The size of the Operation history is reduced by the size of this 
01095                 operation if the ReduceOpHistSize flag is TRUE. 
01096 
01097     Errors:     -
01098     SeeAlso:    OperationHistory::FindLastOp
01099                 OperationHistory::FindPrevToLastOp
01100 
01101 ********************************************************************************************/
01102 
01103 void OperationHistory::DeletePrevToLastOp(BOOL ReduceOpHistSize)
01104 {  
01105     // find the previous operation
01106     Operation *pPrev = (Operation *)OpHistoryList.GetPrev(NowPtr); // get the PrevToLastOp
01107 
01108     if (pPrev != NULL)
01109     {
01110         if (ReduceOpHistSize)
01111         {
01112             DecSize(pPrev->GetSize());  // Reduce history size 
01113         }    
01114 
01115         // remove it from the list          
01116         OpHistoryList.RemoveItem((ListItem*)pPrev);   // Remove the operation from the
01117                                                       // history list
01118 
01119         // delete it
01120         delete pPrev;
01121     }
01122 }
01123 
01124 
01125 /********************************************************************************************
01126 
01127 >   void OperationHistory::DumpAll()
01128 
01129     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01130     Created:    15/8/95
01131     Inputs:     -
01132     Outputs:    Dumps debugging information to the debugger display
01133     Returns:    -
01134     Purpose:    This function displays debugging information on all the operations in the
01135                 history list
01136     Errors:     -
01137     SeeAlso:    OperationHistory::DumpLast
01138                 Operation::Dump
01139 
01140 ********************************************************************************************/
01141 void OperationHistory::DumpAll()
01142 {
01143 #if DEBUG_TREE
01144     // loop through all the ops in the history, calling their dump functions
01145     ListItem* CurrentOp = OpHistoryList.GetHead();
01146 
01147     TRACEALL( _T("******* Complete Operation history dump *******\n") );
01148 
01149     if (CurrentOp == NULL)
01150         TRACEALL( _T("No operations in history\n") );
01151     else
01152     {
01153         do
01154         {
01155             ((Operation*)CurrentOp)->Dump();
01156 
01157             CurrentOp = OpHistoryList.GetNext(CurrentOp);
01158         } while (CurrentOp != NULL);
01159     }
01160 
01161     TRACEALL( _T("******* End of history dump *******\n\n") );
01162 
01163 #endif
01164 }
01165 
01166 
01167 
01168 /********************************************************************************************
01169 
01170 >   void OperationHistory::DumpAll()
01171 
01172     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01173     Created:    15/8/95
01174     Inputs:     -
01175     Outputs:    Dumps debugging information to the debugger display
01176     Returns:    -
01177     Purpose:    This function displays debugging information on the last operation in the
01178                 operation history.  This is the "current" one.
01179     Errors:     -
01180     SeeAlso:    OperationHistory::DumpAll
01181                 Operation::Dump
01182 
01183 ********************************************************************************************/
01184 void OperationHistory::DumpLast()
01185 {
01186 #if DEBUG_TREE
01187     Operation* CurrentOp = FindLastOp();
01188 
01189     TRACEALL( _T("\n******* Dump of last operation *******\n") );
01190 
01191     if (CurrentOp == NULL)
01192         TRACE( _T("No operations in history\n") );
01193     else
01194         CurrentOp->Dump();
01195 
01196     TRACEALL( _T("\n******* End of last operation dump *******\n\n") );
01197 
01198 #endif
01199 }
01200 
01201 
01202 #if !defined(EXCLUDE_FROM_RALPH)
01203 
01204 // -------------------------------------------------------------------------------------
01205 
01206 
01207 //********************************************************************************************
01208 //                                  UNDO OPERATION
01209   
01210 /********************************************************************************************
01211    
01212 >   OpUndo::OpUndo()
01213 
01214     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01215     Created:    9/7/93
01216     Inputs:     -
01217     Outputs:    -
01218     Returns:    -
01219     Purpose:    Constructs an OpUndo object.
01220     Errors:     -
01221     SeeAlso:    -
01222 
01223 ********************************************************************************************/
01224 
01225 OpUndo::OpUndo(): Operation()
01226 {
01227 }
01228 
01229 /********************************************************************************************
01230 
01231 >   void OpUndo::Do(OpDescriptor*)
01232 
01233     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com> Shamatani
01234     Created:    11/8/93
01235     Inputs:     Pointer to an OpDescriptor (not used)
01236     Outputs:    -
01237     Returns:    -
01238     Purpose:    Actually "DO" the undo operation.
01239     Errors:     -
01240     SeeAlso:    -
01241 
01242 ********************************************************************************************/
01243 
01244 void OpUndo::Do(OpDescriptor*)
01245 {
01246     // Remember our document, because in debug builds we need to access it after End()
01247     // has been called, and End() deletes the operation.
01248     Document *pDoc = pOurDoc;
01249 
01250 //  #ifdef _DEBUG      
01251 //  // Ensure that the size of the operation history is valid before the undo
01252 //  pDoc->GetOpHistory().DebugSizeCheck();   
01253 //  #endif
01254 
01255     pDoc->GetOpHistory().UndoPrev(); // Undo the previous operation
01256     End();     
01257     
01258     // if there are no more actions to undo and the operation history has not been reduced
01259     // then mark the document as un-modified.
01260     if ( (!(pDoc->GetOpHistory().CanUndo())) && (!(pDoc->GetOpHistory().IsReduced())) )
01261     {
01262         pDoc->SetModified(FALSE); 
01263     }
01264 
01265     #ifdef _DEBUG      
01266     // Ensure that the size of the operation history is valid after the undo
01267     pDoc->GetOpHistory().DebugSizeCheck();   
01268     #endif
01269 }
01270 
01271 /********************************************************************************************
01272 
01273 >   OpState OpUndo::GetState(String_256* UIDescription, OpDescriptor*)
01274 
01275     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
01276     Created:    11/8/93
01277     Inputs:     OpDescriptor - To help update the state
01278     Outputs:    String - if MenuItem is enabled Then return the name of the operation to 
01279                             be undone Else return the reason why it is disabled
01280     Returns:    -
01281     Purpose:    Find the state of the OpUndo operation.
01282     Errors:     -
01283     SeeAlso:    -
01284 
01285 ********************************************************************************************/
01286 
01287 OpState OpUndo::GetState(String_256* UIDescription, OpDescriptor*)
01288 {
01289     OpState OpSt;
01290 
01291     // Undo always works on the selected document...
01292     Document *pDocument = Document::GetSelected();
01293 
01294     if (pDocument)
01295     {
01296         OperationHistory *pOpHist = &(pDocument->GetOpHistory());
01297         
01298         // Is there an Operation History?
01299         if (pOpHist)
01300         {
01301             // The Undo operation can only be invoked if there are any operations to undo.             
01302             if (pOpHist->CanUndo())
01303             {
01304                 // Temporary String used for Operation Name
01305                 String_256 OpName;
01306             
01307                 // Get the name of operation to be undone
01308                 pOpHist->GetUndoOpName(&OpName);
01309         
01310                 //Concatenate The Menu Description with the operation name
01311                 String Space = _T(" ");
01312                 *UIDescription += Space;
01313                 *UIDescription += OpName;
01314                 
01315                 return OpSt;
01316             }
01317         }
01318     }
01319 
01320     //ELSE set to state to disabled
01321 
01322     OpSt.Greyed = TRUE;
01323         
01324     // Load reason why operation is disabled
01325     String_256 DisableReason(_R(IDS_UNDO_DISABLED));
01326         
01327     *UIDescription = DisableReason;
01328     
01329     return(OpSt);
01330 }
01331 
01332 
01333 /********************************************************************************************
01334 
01335 >   BOOL OpUndo::Init()
01336 
01337     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01338     Created:    9/7/93
01339     Inputs:     -
01340     Outputs:    -
01341     Returns:    -
01342     Purpose:    Create an OpDescriptor for the Undo operation
01343     Errors:     -
01344     SeeAlso:    -
01345 
01346 ********************************************************************************************/
01347 
01348 BOOL OpUndo::Init()
01349 {
01350     return(
01351             Operation::RegisterOpDescriptor(
01352                                     0, 
01353                                     _R(IDS_EDIT_UNDO),
01354                                     CC_RUNTIME_CLASS(OpUndo), 
01355                                     OPTOKEN_UNDO,
01356                                     OpUndo::GetState,
01357                                     HID_EDIT_UNDO,
01358                                     _R(IDBBL_UNDOOP),
01359                                     _R(IDD_BARCONTROLSTORE),
01360                                     _R(IDC_BTN_EDITUNDO),
01361                                     SYSTEMBAR_EDIT
01362                                 )
01363         ); 
01364 
01365 }
01366 
01367 
01368 //********************************************************************************************
01369 //                                  REDO OPERATION
01370 
01371 
01372 
01373 
01374 /********************************************************************************************
01375 
01376 >   OpRedo::OpRedo(): Operation()
01377 
01378 
01379     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01380     Created:    9/7/93
01381     Inputs:     -
01382     Outputs:    -
01383     Returns:    -
01384     Purpose:    Constructs an OpRedo object.
01385     Errors:     -
01386     SeeAlso:    -
01387 
01388 ********************************************************************************************/
01389 
01390 OpRedo::OpRedo(): Operation()
01391 {
01392 }
01393 
01394 /********************************************************************************************
01395 
01396 >   void OpRedo::Do(OpDescriptor*)
01397 
01398     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01399     Created:    9/7/93
01400     Inputs:     An Operation Descriptor
01401     Outputs:    -
01402     Returns:    -
01403     Purpose:    Actually "DO" a redo operation.
01404     Errors:     -
01405     SeeAlso:    -
01406 
01407 ********************************************************************************************/
01408 
01409 void OpRedo::Do(OpDescriptor*)
01410 {
01411 //  ENSURE(FALSE,"Someone's trying to Redo!");
01412 
01413     // Remember our document, because in debug builds we need to access it after End()
01414     // has been called, and End() deletes the operation.
01415     Document *pDoc = pOurDoc;
01416     pDoc->GetOpHistory().RedoNext();
01417     End();          
01418     
01419     #ifdef _DEBUG      
01420     // Ensure that the size of the operation history is valid 
01421     pDoc->GetOpHistory().DebugSizeCheck();   
01422     #endif
01423 }
01424 
01425 
01426 
01427 /********************************************************************************************
01428 
01429 >   OpState OpRedo::GetState(String_256* UIDescription, OpDescriptor*)
01430 
01431     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
01432     Created:    11/8/93
01433     Inputs:     OpDescriptor - To help update the state
01434     Outputs:    String - if MenuItem is enabled Then return the name of the operation to 
01435                             be undone Else return the reason why it is disabled
01436     Returns:    -
01437     Purpose:    Find the state of the OpRedo operation.
01438     Errors:     -
01439     SeeAlso:    -
01440 
01441 ********************************************************************************************/
01442 
01443 OpState OpRedo::GetState(String_256* UIDescription, OpDescriptor*)
01444 {
01445     OpState OpSt;     
01446 
01447     // Undo always works on the selected document...
01448     Document *pDocument = Document::GetSelected();
01449 
01450     if (pDocument)
01451     {
01452         OperationHistory *pOpHist = &(pDocument->GetOpHistory());
01453         
01454         // Is there an Operation History?
01455         if (pOpHist)
01456         {
01457             // The Redo operation can only be invoked if there are any operations to redo.             
01458             if (pOpHist->CanRedo())
01459             {
01460                 // Temporary String used for Operation Name
01461                 String_256 OpName;
01462             
01463                 // Get the name of operation to be undone
01464                 pOpHist->GetRedoOpName(&OpName);
01465         
01466                 //Concatenate The Menu Description with the operation name
01467                 String Space = _T(" ");
01468                 *UIDescription += Space;
01469                 *UIDescription += OpName;
01470                 
01471                 return OpSt;
01472             }
01473         }
01474     }
01475 
01476     //ELSE set to state to disabled
01477 
01478     OpSt.Greyed = TRUE;
01479         
01480     // Load reason why operation is disabled
01481     String_256 DisableReason(_R(IDS_REDO_DISABLED));
01482         
01483     *UIDescription = DisableReason;
01484     
01485     return(OpSt);   
01486 }                                    
01487 
01488 
01489 
01490 /********************************************************************************************
01491 
01492 >   BOOL OpRedo::Init()
01493 
01494     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
01495     Created:    11/8/93
01496     Inputs:     -
01497     Outputs:    -
01498     Returns:    -
01499     Purpose:    Create an OpDescriptor for the Redo operation
01500     Errors:     ERROR is called if there was insufficient memory to create the operation 
01501     SeeAlso:    -
01502 
01503 ********************************************************************************************/
01504 
01505 BOOL OpRedo::Init()
01506 {
01507     return(Operation::RegisterOpDescriptor( 
01508                                             0, 
01509                                             _R(IDS_EDIT_REDO),
01510                                             CC_RUNTIME_CLASS(OpRedo), 
01511                                             OPTOKEN_REDO,
01512                                             OpRedo::GetState,
01513                                             HID_EDIT_REDO,
01514                                             _R(IDBBL_REDOOP),
01515                                             _R(IDD_BARCONTROLSTORE),
01516                                             _R(IDC_BTN_EDITREDO),
01517                                             SYSTEMBAR_EDIT
01518                                             )
01519           ); 
01520 
01521 }
01522 
01523 
01524 
01525 
01526 #endif

Generated on Sat Nov 10 03:46:15 2007 for Camelot by  doxygen 1.4.4