In any REXX script, the SYNTAX condition may be raised as a result of either an improperly written REXX script, or because you pass improperly formatted arguments to a function, or even because of some "severe" run-time error such as low memory.

If you do not trap the SYNTAX condition at all, your main script will abruptly abort when SYNTAX is raised. If you have data that may need to be saved to permanent media, it will be lost unless you have a FINALLY section which does the save. So too, if you have any handles to anything that are not maintained by Reginald or some other REXX add-on, these may not be properly closed unless your FINALLY section takes care of this.

Therefore, you should trap SYNTAX if you don't want your script to abort, and you should have a FINALLY section if you have any special cleanup that needs to be done before your script ends.

If you have created a standard Main Window Layout script, then it includes a CATCH instruction to handle SYNTAX condition raised in the main script. If a child script has a SYNTAX error, and doesn't have its own CATCH SYNTAX to handle it, then the main script's CATCH SYNTAX will deal with it as well.

The main script's CATCH SYNTAX simply posts a message box informing the user of an error, and then continues on with the message loop. So, some particular operation may be aborted, but otherwise, the main script will carry on.

The main script also has a FINALLY section to which you can add any special cleanup instructions.

Note: HALT condition is not raised in a GUI script unless you specifically use the RAISE instruction to raise it. If you do that, you should also CATCH HALT, or your script will abort.


Non-syntax errors

With the exception of GuiSay() and GuiInfo(), all GUI functions will return an empty string if successful, or an error message if a problem occurs. So, you can check the return from a GUI function, and if it's not an empty string, then do some error handling.

By default, you are expected to check the return string from any GUI function you call (except for GuiSay and GuiInfo) and do error handling if necessary. You will also need to take care of presenting a message to the user (if you desire that).

For example, consider the following instructions (note: we assume OPTIONS "C_CALL"):

/* Do user interaction. */
err = GuiGetMsg()

/* Check if GuiGetMsg succeeded. */
IF err == "" THEN DO

   /* Yes, GuiGetMsg succeeded. Here, you would
    * determine who woke you up, and why.
    */

END

ELSE
  GuiSay(err)
Let's assume that you have not opened any GUI windows before calling GuiGetMsg. Reginald considers that to be an error. So what happens when you call GuiGetMsg? GuiGetMsg returns an error message of No open windows. You'll note above that we check whether GuiGetMsg has returned an empty string, and if not, then we display that error message to the user (using GuiSay's message box). Therefore, we properly check for errors above.


Error numbers versus strings

Every error message that a GUI function can return has a unique number associated with it. For example, the error number 114 is associated with the error message No open windows. If you prefer, each GUI function can return the error number instead of the error message (ie, 114 versus No open windows). To enable this option, you set a variable named GuiErr to the value 'NUM' (before calling any GUI functions) as so:

/* Return error numbers instead of messages. */
GuiErr = 'NUM'
You need set GuiErr only once. Its setting will remain in effect until you either set it to some other value, or DROP it to restore the default error message returns.
/* Restore the default -- error messages. */
DROP GuiErr
Here is each error number, and its respective message. Note that where you see part of a message enclosed within < and >, this will be replaced by some other, more detailed text in the error message.

Number Message
100Cancel
101Out of memory for this operation
102Object already has a window
103An existing object must call this function
104Bad filename
105GUI block not found
106WINDOW definition not found in GUI block
107WINDOW x, y, width, and height must be whole numbers, or -1 for defaults
108Control x, y, width, and height must be whole numbers
109No open windows
110Object doesn't have an open window
111FONT height and width must be whole numbers
112Window defaults can't be set while a window is still open
113Not a window
114Not a defined type of control
115Error creating MENU heading <headingNum>
116Error creating MENU item <headingNum> : <itemNum>
117Error creating MENU item <headingNum> : <itemNum> : <subItemNum>
118Unknown message string
119Can't find the STRING definition named <name>
120STRING definition is missing its DEND
121Error adding the string: <string>
195Message will vary. It concerns GuiCreateWindow failing to add the menu to the window
196Message will vary. It concerns GuiSetCtlPlacement failing to move or resize the window
197Message will vary. It concerns GuiWindowDefaults failing to register your chosen window defaults
198Message will vary. It concerns bad styles specified for some control in your WINDOW definition when calling GuiCreateWindow, or passed to GuiAddControl
199Message will vary. It concerns GuiCreateWindow failing to create the window
200Message will vary. It concerns GuiMakeShortcut failing


Adding a heading to the message/number

If desired, you can tell Reginald to preface the message or number with a heading. This heading will tell you which GUI function caused the failure. For example, if GuiGetMsg is called with no windows being open, then the error message will be DLL function "GUIGETMSG" reports "No open windows". This is more informative when you present the error message to the user.

To enable headings, you must set a variable named GuiHeading once:

/* Add a heading to error messages/numbers. */
GuiHeading = 1
To restore the default of no headings, then DROP GuiHeading.


SYNTAX

Alternately, you can choose to have Reginald raise the SYNTAX condition when an error occurs with a GUI function.

If you have not set up your own SYNTAX handler in your script, then your script will immediately abort with a message box automatically displayed by Reginald. The message box will include the error message, the source line upon which the error occurred, the name of the script that caused the error, and a help button to bring up online help for that error.

On the other hand, if you've used CATCH SYNTAX to set up your own SYNTAX handler, then Reginald will automatically jump to that handler. You'll never even return from that call to GuiGetMsg. Rather, you'll jump out of GuiGetMsg and jump directly to your CATCH SYNTAX instructions. You can use CONDITION('D') to retrieve the error message (ie, here it would be No open windows or DLL function "GUIGETMSG" reports "No open windows", depending upon whether you have enabled headings), CONDITION('E') to fetch the error number associated with that message (ie, here it would be 110), and CONDITION('M') to display a message box to the user containing the error message.

To enable the SYNTAX reporting feature, set GuiErr to the value 'SYNTAX' before calling any GUI functions. Here, we enable the 'SYNTAX' option, and we CATCH SYNTAX. You'll note that we no longer have to check the return from GuiGetMsg. Why? Because if an error occurs, we will jump directly to the CATCH SYNTAX. So, it's irrelevant what GuiGetMsg returns.

/* Enable SYNTAX option and headings. */
GuiErr = 'SYNTAX'
GuiHeading = 1

/* A useful option. */
OPTIONS "C_CALL"

/* Do our event loop. */
EventLoop:
DO FOREVER

   /* Do user interaction. */
   GuiGetMsg()

   /* GuiGetMsg succeeded if we didn't jump to CATCH SYNTAX.
    * So here, you would determine who woke you up, and why.
    */

   CATCH SYNTAX
      /* Display an error message. */
      CONDITION('M')

      /* We'll drop out of the DO FOREVER loop now. If
       * you wish to instead attempt to recover, you
       * would SIGNAL to the EventLoop label.
       */

   /* NOTE: If you have any special cleanup code, then put
    * a FINALLY instruction here, followed by your
    * cleanup instructions.
    */

END

Note: Unless you create an Empty Window Layout script with REXX Programmer Center's resource editor, then the script automatically sets the GuiErr and GuiHeading variables such that SYNTAX condition is raised for GUI errors, and a heading is prepended to the error message.


ERROR

Another alternative you have is for Reginald to raise the ERROR condition when an error occurs with a GUI function.

If you have not set up your own CATCH ERROR handler, then the GUI function will simply return the error message as it does by default. Your script will not abort. Of course, you should check the return string for an error message in this case.

On the other hand, if you've used CATCH ERROR to set up your own ERROR handler, then Reginald will automatically jump to your CATCH ERROR instructions, just like in our SYNTAX example above.

To enable the ERROR reporting feature, set GuiErr to the value 'ERROR' before calling any GUI functions.

/* Raise ERROR whenever a GUI function has an error. */
GuiErr = 'ERROR'

FAILURE

Another alternative you have is for Reginald to raise the FAILURE condition when an error occurs with a GUI function.

If you have not set up your own CATCH FAILURE handler, then the GUI function will simply return the error message as it does by default. Your script will not abort. Of course, you should check the return string for an error message in this case.

On the other hand, if you've used CATCH FAILURE to set up your own FAILURE handler, then Reginald will automatically jump to your CATCH FAILURE instructions, just like in our SYNTAX example above.

To enable the FAILURE reporting feature, set GuiErr to the value 'FAILURE' before calling any GUI functions.

/* Raise FAILURE whenever a GUI function has an error. */
GuiErr = 'FAILURE'

USER

Another alternative you have is for Reginald to raise one of the USER conditions when an error occurs with a GUI function.

If you have not set up your own CATCH USER handler, then the GUI function will simply return the error message as it does by default. Your script will not abort. Of course, you should check the return string for an error message in this case.

On the other hand, if you've used CATCH USER to set up your own USER handler, then Reginald will automatically jump to your CATCH USER instructions, just like in our SYNTAX example above.

To enable the USER reporting feature, set GuiErr to the number of the desired USER condition before calling any GUI functions. Here, we have modified our event loop to use USER 10 condition:

/* Enable USER 10 option and headings. */
GuiErr = 10
GuiHeading = 1

/* A useful option. */
OPTIONS "C_CALL"

/* Do our event loop. */
EventLoop:
DO FOREVER

   /* Do user interaction. */
   GuiGetMsg()

   /* GuiGetMsg succeeded if we didn't jump to CATCH USER 10.
    * So here, you would determine who woke you up, and why.
    */

   CATCH USER 10
      /* Display an error message. */
      CONDITION('M')

      /* We'll drop out of the DO FOREVER loop now. If
       * you wish to instead attempt to recover, you
       * would SIGNAL to the EventLoop label.
       */

   /* NOTE: If you have any special cleanup code, then put
    * a FINALLY instruction here, followed by your
    * cleanup instructions.
    */

END