Tips and Techniques: Checking for F3/F12 from an IBM Command

RPG
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

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:

RTVEXITKEY: CMD        PROMPT('Retrieve F3/F12 Status')
   /* 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:

RTVEXITKEY:  PGM        PARM(&F3 &F12)

             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:

     H DFTACTGRP(*NO) ACTGRP(*CALLER)
      **************************************************************
      **
      **  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:

 TESTFKEY:   PGM
             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.

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$0.00 Raised:
$