The germ for this post came from a comment made by Glenn Gundermann on last week's Display screens of results without having to press Enter:
How would you do it for the times you don't want to lock the keyboard? You might want to have a screen being displayed to allow the user to do actions but if they don't, perform an action after a timeout.
After a bit of playing I have a solution that will have a screen time out if someone does not press a key in a certain amount of time. This is just simple example to demonstrate the method I found. In the example the user will be presented with a screen they can either press Enter, F3 to exit, or do nothing. If they do nothing after two seconds the program will proceed and display a second screen.
This is the display file:
01 A DSPSIZ(24 80 *DS3) 02 A CA03 03 A INDARA 04 A R SCREEN1 05 A INVITE 06 A 3 3'This is the first screen' 07 A R SCREEN2 08 A 3 3'We are finished'
I am sure most of you are familiar with the keywords in the display file. Exceptions might be for the INDARA and the INVITE.
I discussed using the INDARA in No More Number Indicators, therefore, if are unfamiliar with INDARA I recommend you check the post out.
The INVITE keyword is described in the IBM documentation as:
To send an invite to a specific device, your program sends an output operation to the device with the INVITE keyword in effect.
The keyword can be used at the file or record format level. I want to use it at the record format for SCREEN1, as I do not want to use it with SCREEN2.
I compiled this display file with the following command. Notice that the 'Maximum record wait time' parameter, WAITRCD, is given. I have given two seconds. If you were using this in a "live" environment you would want to use a larger value.
CRTDSPF FILE(MYLIB/TESTDSPF) SRCFILE(MYLIB/DEVSRC) RSTDSP(*YES) DFRWRT(*NO) WAITRCD(2)
And now for the RPG, all free of course:
01 dcl-f TESTDSPF workstn indds(IndDs) maxdev(*file) ; 02 dcl-ds IndDs qualified ; 03 Exit ind pos(3) ; 04 end-ds ; 05 dcl-s wkCount packed(3) ; 06 for wkCount = 1 to 10 ; 07 write SCREEN1 ; 08 read(e) TESTDSPF ; 09 if (%status = 01331) ; 10 leave ; 11 elseif (IndDs.Exit) ; 12 *inlr = *on ; 13 return ; 14 endif ; 15 endfor ; 16 exfmt SCREEN2 ; 17 *inlr = *on ;
If you have to use RPG fixed format definitions you can see the code here.
The first thing to notice is the MAXDEV(*FILE) keyword on line 1. Officially this is to give the number of devices defined for the work station file. In reality it just has to be there.
Lines 2 to 4 are my indicator area data structure.
Line 5 is a work variable I will use in a FOR group, which start on line 6, if you are not familiar with the FOR group check out FOR replaces DO in RPGLE. This FOR group will be executed ten times if I press the Enter key.
To do this I cannot use EXFMT to display my display file record format SCREEN1. I have to use a WRITE to the record format, line 7, followed by a READ of the display file, line 8. I need to have an error extender on the READ.
I use the %STATUS built in function to check the program/file status, line 9. If it is "01331" then the time given in the CRTDSPF's WAITRCD parameter has been exceeded. I leave the FOR group on line 10.
If F3 has been pressed I quit the program, lines 11 – 13.
I can use EXFMT for SCREEN2 as there is no invite in that record format.
If you remember all the steps in both the display file and RPG, it is easy to create a similar timeout functionality in your own code.
More information about these keywords can be found on the IBM website...
This article was written for IBM i 7.2, and it should work with earlier releases too.
Fixed format definitions
01 FTESTDSPF CF E WORKSTN indds(IndDs) 02 F maxdev(*file) 03 D IndDs DS qualified 04 D Exit 3 3N 05 D wkCount S 3P 0 /free