Ask Reuben
int_flag
What is int_flag?
Why is my program acting as if the user pressed Cancel when they did not?
There have been programs coming through the support desk that show lack of understanding of the int_flag variable.
int_flag is a predefined variable set to TRUE when an interruption event is detected or when a cancel action is fired in a singular dialog. The only thing that sets the int_flag back to FALSE is if the developer explicitly codes it.
You should have a programming standard on the use of int_flag within your organisation.
There are two key pieces of documentation on int_flag
- one on the int_flag.
- a second on the wider topic of User Interruption Handling
I have touched on the int_flag in two earlier Ask-Reuben articles
The key things you should make sure your programming standards cover are …
- Make sure DEFER INTERRUPT is set at program start. If you have an initialisation function that every program calls at start, this line will typically be included here.
- When the interrupt flag is set to TRUE (1), make sure the code sets it back to FALSE (0)
- Be consistent in your use of DIALOG, ACCEPT DIALOG, CANCEL DIALOG
As a little exercise, note with the following what value is displayed if you press OK or if you press Cancel
INPUT BY NAME rec.* AFTER INPUT DISPLAY "After Input",int_flag END INPUT DISPLAY "End", int_flag
Click OK you see …
After Input 0 End 0
Click Cancel you see …
After Input 1 End 1
Now also note when DIALOG is introduced into the mix, it is CANCEL DIALOG sets the int_flag to 1
DIALOG INPUT BY NAME rec.* AFTER INPUT DISPLAY "After input",int_flag END INPUT ON ACTION accept DISPLAY "Accept",int_flag ACCEPT DIALOG ON ACTION cancel DISPLAY "Cancel",int_flag CANCEL DIALOG END DIALOG DISPLAY "End", int_flag
Clicking OK you see. …
Accept 0 After Input 0 End 0
Clicking Cancel you see it is the CANCEL DIALOG that sets int_flag to 1, not the ON ACTION cancel …
Cancel 0 After input 1 End 1
In both cases, note the value of int_flag after the dialog has been exited after clicking Cancel. The value of int_flag is still set to 1. This is noticeable if you have two consecutive dialogs …
INPUT BY NAME rec.* AFTER INPUT DISPLAY "After Input 1",int_flag END INPUT DISPLAY "Inbetween", int_flag INPUT BY NAME rec.* AFTER INPUT DISPLAY "After Input 2",int_flag END INPUT DISPLAY "End", int_flag
… note what happens when you click Cancel then OK
After Input 1 1 Inbetween 1 After Input 2 1 End 1
… int_flag is still set to 1 in the AFTER INPUT of the second dialog. So even though the user clicked OK, the runtime will proceed as if Cancel was clicked. The correct thing to do is to add a LET int_flag = 0
between the two input statements.
INPUT BY NAME rec.* AFTER INPUT DISPLAY "After Input 1",int_flag END INPUT DISPLAY "Inbetween", int_flag LET int_flag = 0 -- Make sure int_flag is reset INPUT BY NAME rec.* AFTER INPUT DISPLAY "After Input 2",int_flag END INPUT DISPLAY "End", int_flag
From a coding standards perspective, you need to ensure that you have a LET int_flag =
0 to set the value of the int_flag back to 0. It is not set to 0 by the dialog starting, nor is it set to 0 when the user clicks OK. The coding standard I was brought up with was to set int_flag back to 0 after every dialog statement. I have seen other standards to set it to 0 explicitly before each dialog statement but that does not handle the case of the int_flag being set to 1 by a nested dialog. I was also brought up to put the LET int_flag = 0 line in a function and it was this function that was called at the end of each dialog statement. (Note: I have put dialog in italics as it means each INPUT, INPUT ARRAY, CONSTRUCT, PROMPT, DISPLAY ARRAY, DIALOG (with CANCEL DIALOG) statement, not each DIALOG statement).
The mistake we typically see is forgetting to set int_flag back to 0, and that is due to the lack of a clear enforced coding standard.
I believe you can avoid the use of int_flag if you wrap each dialog statement in DIALOG and use an explicit ON ACTION accept, ON ACTION cancel without using CANCEL DIALOG). If you are prepared to make that change through your code base, that might be a technique to explore, and just save int_flag for interrupting database operations and loops.