Skip to content

Instantly share code, notes, and snippets.

@mikepotjer
Last active January 3, 2019 19:29
Show Gist options
  • Save mikepotjer/43a1f244cc90531095d93cb2367cf4c8 to your computer and use it in GitHub Desktop.
Save mikepotjer/43a1f244cc90531095d93cb2367cf4c8 to your computer and use it in GitHub Desktop.
Visual FoxPro ESCAPE handler
LPARAMETERS tcOnEscapeCommand AS String
#IF .F.
*-------------------------------------------------------
*---------------- FILE CREATION INFO -------------------
Program....: OXESCAPEHANDLER
Author.....: Michael J. Potjer
Based on ideas in Calvin Hsia's May 15, 2008 blog article
"How to interrupt your code":
http://blogs.msdn.com/calvin_hsia/archive/2008/05/15/8510677.aspx
Date.......: May 21, 2008
*-------------------------------------------------------
*------------------ USAGE SECTION ----------------------
DESCRIPTION:
A function, procedure, and class to encapsulate the process of setting up an
ESCAPE handler, and create an object to restore the relevant settings when
you no longer need the handler.
PARAMETERS:
tcOnEscapeCommand (O) - The command to use as the handler for ON ESCAPE, such as
"DO MyEscapeHandler" or "_SCREEN.oEscapeHandler.OnEscape()".
If omitted or empty, the escape handler procedure
OSI_OnEscapeHandler, defined in this PRG, will be used.
EXAMPLE:
TRY
*-- Load the ESCAPE handler.
loOnEscape = OXEscapeHandler()
*-- Run some process (such as a bunch of queries) which the
*-- user is allowed to abort.
CATCH TO loException WHEN loException.ErrorNo = 2071 ;
AND loException.UserValue == "ESCAPE"
*-- The user aborted the process by pressing ESCAPE. Make
*-- sure you cleanup and abort this process.
CATCH TO loException
*-- Some other error occurred which needs to be handled.
FINALLY
*-- Restore the ESCAPE settings.
loOnEscape = .NULL.
ENDTRY
RETURNS: Object
Returns a push/pop object which stores the original settings related to an
ESCAPE handler, and which will restore those settings when released.
*--------------- MAINTENANCE SECTION -------------------
INPUTS (extracted from environment):
_VFP.AutoYield
SET("Escape")
ON("Escape")
OUTPUTS (changes to environment):
_VFP.AutoYield = .T.
SET ESCAPE ON
ON ESCAPE <Some Procedure>
However, these settings are all returned to their original values when the
object returned from this function is released.
PRE-CONDITION INVARIANTS: None
POST-CONDITION INVARIANTS:
The object returned from this function must be released to restore the ESCAPE settings.
COLLABORATING METHODS:
None, apart from what's contained in this PRG.
#ENDIF
LOCAL loOnEscape, ;
lcOnEscapeCommand
*-- Check if an ON ESCAPE command was specified. If not, we'll use
*-- the procedure included in this program file.
lcOnEscapeCommand = IIF( VARTYPE( m.tcOnEscapeCommand ) = "C" ;
AND NOT EMPTY( m.tcOnEscapeCommand ), ;
ALLTRIM( m.tcOnEscapeCommand ), "DO OSI_OnEscapeHandler" )
*-- Create the push/pop object which will save the current ESCAPE
*-- settings, and turn on the specified ON ESCAPE handler.
loOnEscape = CREATEOBJECT( "cusPushPopOnEscape", m.lcOnEscapeCommand )
RETURN m.loOnEscape
*********************************************************************
*-- The default ON ESCAPE procedure which will be used if you don't
*-- specify a custom procedure.
*********************************************************************
PROCEDURE OSI_OnEscapeHandler
*-- Within a TRY..CATCH, this will generate error 2071 - "User Thrown
*-- Error". If you don't have a TRY..CATCH structure setup to catch
*-- this error, you will get error 2059 - "Unhandled Structured
*-- Exception", and your app will probably shut down.
THROW "ESCAPE"
RETURN
*********************************************************************
*-- An object used to save and restore the settings needed to enable
*-- ESCAPE handling.
*********************************************************************
DEFINE CLASS cusPushPopOnEscape AS Custom
*-- These properties store the settings of SET ESCAPE and ON ESCAPE
*-- at the time this object is instantiated.
icSetEscape = SPACE(0)
icOnEscape = SPACE(0)
*-- This property stores the setting of _VFP.AutoYield at the time
*-- this object is instantiated.
ilAutoYield = .NULL.
*********************************************************************
PROCEDURE Init
LPARAMETERS tcOnEscapeCommand AS String
*-- It's up to the developer to make sure a command expression is
*-- passed to this method.
ASSERT VARTYPE( m.tcOnEscapeCommand ) = "C" ;
AND NOT EMPTY( m.tcOnEscapeCommand ) ;
MESSAGE ALLTRIM( PROGRAM() ) + " failed!" + CHR(13) ;
+ "Invalid ON ESCAPE command specified" + CHR(13) ;
+ "Select <Debug> to check out the problem."
*-- Save the current settings of _VFP.AutoYield, SET ESCAPE, and
*-- ON ESCAPE, so that they can be restored after this object is
*-- released.
This.ilAutoYield = _VFP.AutoYield
This.icSetEscape = SET("Escape")
This.icOnEscape = ON("Escape")
*-- Make sure the AutoYield setting is true, otherwise the setting of
*-- SET ESCAPE is ignored, and treated as SET ESCAPE OFF.
_VFP.AutoYield = .T.
*-- Make sure SET ESCAPE is ON, and set the ON ESCAPE handler to the
*-- specified expression.
SET ESCAPE ON
ON ESCAPE &tcOnEscapeCommand.
ENDPROC
*********************************************************************
*********************************************************************
PROCEDURE Destroy
LOCAL lcSetting
*-- Restore the original ON ESCAPE handler.
lcSetting = This.icOnEscape
ON ESCAPE &lcSetting.
*-- Restore the original SET ESCAPE setting.
lcSetting = This.icSetEscape
SET ESCAPE &lcSetting.
*-- Restore the original AutoYield setting.
_VFP.AutoYield = This.ilAutoYield
ENDPROC
*********************************************************************
ENDDEFINE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment