Problem: 1340236

Title: (Commands) Command failure reported as program error

Received: Apr 11 1996 12:02PM


MacApp is reporting command failures as program errors instead of the actual error that occurred (which could be innocuous, such as user cancelled). In addition to the bogus error message, there is a potential data corruption problem, and a memory leak.

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 ***

Fix:

Fixed.

Verified, there is a test of undoable in "CATCH_ALL" of TCommandHandler::PerformCommand().