Problem: 1340236
Title: (Commands) Command failure reported as program error
Received: Apr 11 1996 12:02PM
TDispatcher only puts a command in the action history if the command can be undone. But TCommandHandler was always trying to abort the current action. If the action history is empty you get a program error from FailNonObject in AbortAction. If it is not empty, the abort may cause the last undoable action to be lost, which could cause data corruption in user documents. Finally, because the abort attempt fails, the command is not freed.
Here are two fixes to work around the problem. The first fix, to UCommandHandler, is serious. The second fix, to UUndo, is a redundant fix that only stops the bogus error message.
File #1:ÊChucko:Projects:SchizoR10:MacApp:Libraries:Framework:Sources:UCommandHandler.cp File #2: Hack:MA:SchizoR10:MacApp:Libraries:Framework:Sources:UCommandHandler.cp Extra lines in 1st before 8 in 2nd (FileÊ"Chucko:Projects:SchizoR10:MacApp:Libraries:Framework:Sources:UCommandHandler.cp"; Line 8:9; File "Hack:MA:SchizoR10:MacApp:Libraries:Framework:Sources:UCommandHandler.cp"; Line Æ8) 6 /* 7 Change History: -------------------------------------------------------------------------------- 8 4/11/96 TWB Use Abort only for commands that can be undone, because 9 otherwise they aren't in the action history. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 3/27/96 srf Account that GetClassName can return a char* now. 11 03/26/96 srf coerce CStrxxx to const char* to get copies of the strings as c style strings Nonmatching lines (FileÊ"Chucko:Projects:SchizoR10:MacApp:Libraries:Framework:Sources:UCommandHandler.cp"; Line 275:282; File "Hack:MA:SchizoR10:MacApp:Libraries:Framework:Sources:UCommandHandler.cp"; Line 273) 273 // Abort the current transaction in the undo handler. 274 // This will free the command. -------------------------------------------------------------------------------- 275 if (volatileCommand->CanBeUndone()) 276 TUndoHandler::fgUndoHandler->Abort(); 277 else 278 { 279 volatileCommand->Abort(); 280 if (volatileCommand->ShouldFreeOnCompletion()) 281 volatileCommand = (TCommand*) FreeIfObject(volatileCommand); 282 } 273 TUndoHandler::fgUndoHandler->Abort(); ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 283 284 FailNewMessage(fi.error, fi.message, BuildMessage((short)aCommandNumber, messageCommandError)); *** EOF on both files at the same time *** File #1: Chucko:Projects:SchizoR10:MacApp:Libraries:Framework:Sources:UUndo.cp File #2: Hack:MA:SchizoR10:MacApp:Libraries:Framework:Sources:UUndo.cp Extra lines in 1st before 8 in 2nd (File "Chucko:Projects:SchizoR10:MacApp:Libraries:Framework:Sources:UUndo.cp"; Line 8; File "Hack:MA:SchizoR10:MacApp:Libraries:Framework:Sources:UUndo.cp"; Line Æ8) 6 /* 7 Change History: -------------------------------------------------------------------------------- 8 4/11/96 TWB Fix Abort so it won't fail if there is nothing to abort. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 03/26/96 mdr Added CUndoStackHook. 10 03/14/96 srf Use CString::Empty. Nonmatching lines (File "Chucko:Projects:SchizoR10:MacApp:Libraries:Framework:Sources:UUndo.cp"; Line 618:637; File "Hack:MA:SchizoR10:MacApp:Libraries:Framework:Sources:UUndo.cp"; Line 617:633) 616 void TUndoHandler::Abort() 617 { -------------------------------------------------------------------------------- 618 if (AnythingToUndo()) 619 { 620 long transaction = fInTransaction; 621 // start with fInTransaction so we can abort a partial transaction 622 623 do 624 { 625 EActionType actionType = AbortAction(); 626 if (actionType == kEndAction) 627 ++transaction; 628 else if (actionType == kBeginAction) 629 { 630 --transaction; 631 #if qDebug 632 Assertion(transaction >= 0, "Bad undo stack"); 633 #endif 634 } 635 } 636 while (transaction != 0); 637 } 617 long transaction = fInTransaction; 618 // start with fInTransaction so we can abort a partial transaction 619 620 do 621 { 622 EActionType actionType = AbortAction(); 623 if (actionType == kEndAction) 624 ++transaction; 625 else if (actionType == kBeginAction) 626 { 627 --transaction; 628 #if qDebug 629 Assertion(transaction >= 0, "Bad undo stack"); 630 #endif 631 } 632 } 633 while (transaction != 0); ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 638 } 639 *** EOF on both files at the same time ***
Fixed.
Verified, there is a test of undoable in "CATCH_ALL" of TCommandHandler::PerformCommand().