Ask Reuben

Cancel and Close Actions

Why is there an int_flag in dialog code? 

What does DEFER INTERRUPT do? 

What is special about the cancel action? 

What happens when user clicks close on a GDC window?

The cancel and close actions have some interesting characteristics in a Genero application context.  To give a better understanding it is necessary to go back to the character based origins of Genero.

Text User Interface (TUI)

If we look at a TUI Informix-4gl application, an INPUT statement would typically be coded

INPUT ...
   ...
   AFTER INPUT
      IF int_flag THEN
          EXIT INPUT
      END IF
      ... validate the record
END INPUT
IF int_flag THEN
   LET int_flag = 0  # an alternate standard was to do this prior to INPUT
   ...
END IF

and if we looked in the initialisation code executed at the beginning of the program we would hopefully find a

DEFER INTERRUPT

and you might find an

OPTIONS ACCEPT KEY key

but it is unlikely you would find an

OPTIONS INTERRUPT KEY key

What does this all this mean?

A dialog had two exit keys.  If you were happy with the dialog, you would press the key specified by OPTIONS ACCEPT KEY.  If none was specified, then it would default to the Escape key.  We might think this choice of key strange but in the keyboards of the day it was bigger and physically separate from other keys.  (Someone with more grey here than me might offer a better explanation).

The Return/Enter key was also used to move to the next field which may have been also tied to the fact this key was also placed in the numeric keyboard and facilitated its use in high-volume keyboard input.    This moving to the next field could also result in the end of the dialog depending on the value of OPTIONS INPUT WRAP.  With OPTIONS INPUT NO WRAP the dialog would exit if the user pressed Return in the last field.

When the dialog was exited for either of the above two reasons, the AFTER INPUT block would be triggered.

If you were not happy with what was entered in the dialog, you could cancel it by pressing the interrupt key for the terminal.   This choice of key was configured outside the application by the TTY settings.  This was typically Control-C.  The DEFER INTERRUPT command told the runtime that if the running process received this key whilst the user was in the middle of a dialog, it meant that the user intended to exit the dialog, don’t interrupt the process, and so the runtime would enter the AFTER INPUT block with the interrupt flag (int_flag) set.

The AFTER INPUT block could therefore be triggered in a negative or positive manner.  In a negative manner when int_flag was set as the user had pressed Control-C to cancel the dialog, or in a positive manner when either the user pressed the accept key or had pressed return/enter on the last field if there was no wrap, and in this case int_flag would not be set.

So typically you would see at the beginning of the AFTER INPUT block a test on int_flag,  to determine if the user was cancelling the dialog or accepting the dialog.  You can see this in the code example above in the first line of the AFTER INPUT.

GUI (Graphical User Interface)

With the introduction of GUI user interfaces, dialogs would typically have an OK button and a Cancel button.  The user would press the OK button, or a keyboard accelerator, typically the Return key if they wanted to signify they were happy with what they had entered and to carry on.  If the user was not happy with the dialog they would press the Cancel button, or a keyboard accelerator, typically the Escape when they wanted to signify they were not happy with what they had entered and to back out.

To minimise the code changes required in transforming from TUI to GUI, the processing for actions introduced with Genero had the behaviour that triggering the accept action had the same result as if the user had pressed the accept key in a TUI application.  Similarly triggering the cancel action had the same result as if the user had pressed the interrupt key in a TUI application.   That is both the accept and cancel action would enter the AFTER INPUT block, to distinguish inside the block you would look at the value of int_flag.

This allowed the code to stay the same as

AFTER INPUT
   IF int_flag THEN
      -- cancel action triggered
      ... cancel logic ...
      EXIT INPUT
   END IF
    -- accept action triggered 
    ... accept logic ...
END INPUT
IF int_flag THEN
   LET int_flag = 0
   ... more cancel logic ...
END IF

It was NOT a requirement to modify your code to the equivalent of

   ON ACTION accept
      ... accept logic ...
      EXIT INPUT

   ON ACTION cancel
      ... cancel logic ...
      EXIT INPUT

If you were starting from scratch you might choose to go down that path.  With Multiple Dialogs, as that is new code, that is the path you may need to consider.

Close Action

With GUI windows, there was something new that needed to be considered.  The top-corner of a Window typically contained an X (on OSX a red circle in top left).  What should happen when the user clicked this or pressed the corresponding accelerator key (Alt-F4)?  There are a number of circumstances detailed here but with existing code that would not have an ON ACTION close, the runtime would proceed as if cancel was triggered.  That is the AFTER INPUT would be entered with the int_flag set.  If you wanted to distinguish between cancel and close then you needed to explicitly add an ON ACTION close to handle it.

MENU statements provided an interesting dilemma.  If you had …

MENU "" ATTRIBUTES(COMMENT="Please choose ...")
   COMMAND "Y" "Yes"
      LET choice = "Y"
      EXIT MENU
   COMMAND "N" "No"
      LET choice = "N"
      EXIT MENU
END MENU

… and the user clicked the close icon (or pressed escape) what was the value of the variable choice?   The behaviour is documented here.  You do need to pay attention as their maybe circumstances where the above code can exit the MENU without the choice variable being populated!  That is normally identified and captured as part of a Genero transformation and incorporated in your library code and/or coding standards.

Action Defaults

The default Action Defaults file has values that help illustrate the accept, cancel, and close actions.  Bot the cancel and close actions have validate=”no” meaning that the current field value is not validated when these actions are triggered.

The default acceleratorName values of Return for accept, Escape for cancel, and Alt-F4 for close  default to the keys you’d expect in a GUI application.  You could change values for accept, cancel in your .4ad to Escape, Control-C but I would not recommend it.  My experience is that when users moved to the GUI environment they adapt to the normal GUI keys very quickly.

Triggering AFTER INPUT

The ACCEPT INPUT command can be used so that other actions trigger the validation, AFTER FIELD, AFTER INPUT blocks that the accept action normally does.

Summary

Hopefully that has given you some history to why the AFTER INPUT code typically looks like it does, and what happens when the accept, cancel, or close actions are triggered.