I don't know how many times I've needed to end a CL program because a user, who just called the CL program to run a Query/400 routine, pressed the F3 or F12 key to exit without running the query. My CL had no way of knowing if the user pressed F3 to exit the Query prompt.
Likewise, I have a utility that allows users to run the WRKSPLF CL command after entering some criteria. If the user presses Enter or F12 to return, I want the system to perform one task; if the user presses F3, I want the system to do something else. But how?
You might think it would be impractical do something like this or require access to some mystical DSM API set. As it turns out, the solution was there all along; the Retrieve Job Information API (QUSRJOBI) actually returns two on/off-style flags that indicate whether F3 or F12 was pressed on an IBM-supplied screen.
Using this API to check for F3 or F12 isn't difficult, but it is somewhat stealthy. The location of the information is buried in the middle of some API data structure that contains other information that you just don't need when testing for F3 or F12.
You can either call the API directly or use the handy wrapper command that I've provided here. The wrapper allows you to use the RTVEXITKEY command to check for F3 or F12 by retrieving the values into CL variables. The command definition source for RTVEXITKEY and two command processing programs (you get to choose one) are listed below.
Here's the command definition source for RTVEXITKEY:
/* Command processing program is RTVEXITKEY *CLP */
PARM KWD(RTNF3) TYPE(*CHAR) LEN(1) RTNVAL(*YES) +
PROMPT('CL var for F3 key (1)')
PARM KWD(RTNF12) TYPE(*CHAR) LEN(1) RTNVAL(*YES) +
PROMPT('CL var for F12 key (1)')
To use this command, compile it with the following options:
CRTCMD CMD(RTVEXITKEY) PGM(RTVEXITKEY) +
ALLOW(*IPGM *BPGM *IMOD *BMOD)
You have two choices for the program to call when this command is run. You can use either the CL example listed below or the RPG IV program listed after the CL (but not both!). The advantage of the CL is that it is quick and easy; the advantage of the RPG IV is that that you have more options and better control. For example, with the RPG IV version, you may specify the RTNF3 parameter, the RTNF12 parameter, or both; with the CL version, you must specify both return parameters.
Here's the CL version of the command processing program for RTVEXITKEY:
DCL VAR(&JOB) TYPE(*CHAR) LEN(26) VALUE('*')
DCL VAR(&INTJOBID) TYPE(*CHAR) LEN(16) VALUE(' ')
DCL VAR(&JOBINFO) TYPE(*CHAR) LEN(350)
DCL VAR(&F3LOC) TYPE(*DEC) LEN(5 0) VALUE(103)
DCL VAR(&F12LOC) TYPE(*DEC) LEN(5 0) VALUE(104)
DCL VAR(&F12) TYPE(*CHAR) LEN(1)
DCL VAR(&F3) TYPE(*CHAR) LEN(1)
DCL VAR(&RTNLEN) TYPE(*CHAR) LEN(4) +
VALUE(X'00000000')
CHGVAR VAR(%BIN(&RTNLEN)) VALUE(350)
CALL PGM(QUSRJOBI) PARM(&JOBINFO &RTNLEN +
'JOBI0600' &JOB &INTJOBID)
CHGVAR VAR(&F3) VALUE(%SST(&JOBINFO &F3LOC 1))
CHGVAR VAR(&F12) VALUE(%SST(&JOBINFO &F12LOC 1))
ENDPGM: ENDPGM
Here's the RPG IV version of the command processing program for RTVEXITKEY:
**************************************************************
**
** RTVEXITKEY - Return the status of the F3 & F12 keys
** Use this program as the CPP for the
** RtvExitKey command to retrieve whether or
** not the end-user pressed F3 or F12 to
** leave a system display. For example, if
** RUNQRY was being used, this program can
** return an indication as to whether F3 or
** F12 was used to leave RUNQRY, thus not
** actually running the query itself.
**
**************************************************************
** Prototype for this program.
D RtvExitKey PR
D RtnF3 1A
D RtnF12 1A OPTIONS(*NOPASS)
** Entry PList for this program.
D RtvExitKey PI
D RtnF3 1A
D RtnF12 1A OPTIONS(*NOPASS)
** Standard API Error Data Structure
D QUSEC DS Inz
D dsLen 10I 0 Inz(%size(QUSEC))
D nErrRtnLen 10I 0
D CPFMSGID 7A
D szReserved1 1A
** Prototype for Retrieve Job Info API
D QUSRJOBI PR EXTPGM('QUSRJOBI')
D rtnBuffer 32765A OPTIONS(*VARSIZE)
D nLenRtnbuffer 10I 0 Const
D Format 8A Const
D Job 26A Const
D IntJob 16A Const
D api_error Like(QUSEC)
** Return DS for returned job information
D JobInfo DS
D F3 1A Overlay(JobInfo:103)
D F12 1A Overlay(JobInfo:104)
** Call the Retrieve Job Information API
C CALLP QUSRJOBI(JOBINFO: %size(jobInfo) :
C 'JOBI0600': '*': ' ':QUSEC)
** Did it work?
C if nErrRtnLen = 0
** If we need to return the status of F12, do it.
C if %Parms >= 1
C eval RtnF3 = F3
** If we need to return the status of F3, do it.
C if %Parms >= 2
C eval RtnF12 = F12
C endif
C endif
C endif
** ENDPGM:
C eval *INLR = *ON
C return
The following example illustrates how to use this command:
DCL VAR(&F3) TYPE(*CHAR) LEN(1)
DCL VAR(&F12) TYPE(*CHAR) LEN(1)
SPLF: WRKSPLF
RTVEXITKEY RTNF3(&F3)
IF (&F3 = '1') DO
/* user pressed F3 to exit WrkSplf */
ENDDO
ENDPGM: ENDPGM
Bob Cozzi is a programmer/consultant, writer/author, and software developer. His popular RPG xTools add-on subprocedure library for RPG IV is fast becoming a standard with RPG developers. His book The Modern RPG Language has been the most widely used RPG programming book for more than a decade. He, along with others, speaks at and produces the highly popular RPG World conference for RPG programmers.
LATEST COMMENTS
MC Press Online