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