COBOL TIPS #21
by
Shawn M. Gordon
President S.M.Gordon & Associates

Ok, so this month I am really going to talk about using function keys in your own programs. For some people this might seem pretty basic, but I imagine if we all think back to when we first figured out how to program and use function keys, we’ll realize that it wasn’t that straight forward.

Now what I am going to be talking about here is function keys operating in a character mode environment, so I am not talking View here, which is a different environment.

The first thing to be aware of is that each function key can be loaded with data by the use of a fairly simple escape sequence, as seen here;

01 SET-FKEY.
03 PIC X VALUE %33.
03 PIC X(02) VALUE ‘&f’.
03 FKEY-TYPE PIC 9 VALUE 2.
03 PIC X VALUE ‘a’.
03 FKEY-NUM PIC 9.
03 PIC X(04) VALUE ‘k16d’.
03 FKEY-LEN PIC 99 VALUE 02.
03 PIC X VALUE ‘L’.
03 FKEY-LABEL PIC X(16).
03 FKEY-DATA PIC X(02).
03 PIC X VALUE %15.

If you put some data in FKEY-NUM, FKEY-LABEL, and FKEY-DATA and DISPLAY this record structure, you will have a function key that you loaded on your own.

Now if you go and look at a terminal that has the default function keys up, you will see that the default values, or the value that the function key will display when it is depressed, are escape lower case ‘p’ for function key one, thru escape lower case ‘w’ for function key eight. I have found that in a program it is just as easy to use the default values as it is to use a custom string, if all I am doing is looking for actions to take, like ‘Exit Program’.

So from the previous record structure definition we need to know a few things. The field FKEY-TYPE indicates whether the data in the function key will be transmitted, I always transmit the data, so I use a value of 2 here. FKEY-NUM is which function key to load, this is a value from 1 to 8. The FKEY-LEN is the length of the data in the function key. Since I always use the default function key values, I use a length of two. FKEY-LABEL is the data that will show in the function key label, the first eight bytes will display on the top line of the function key, and the second eight bytes will display on the bottom line. FKEY-DATA is the actual data that will be transmitted when you press this function key. There is another advantage to using the default values of the function keys, they are escape sequences and they don’t display on the screen.

Now there are a couple of other escape sequences that are handy to know when using function keys, and they are;

01 KEY-ON.
03 PIC X VALUE %33.
03 PIC X(03) VALUE “&jB”.
*
01 KEY-OFF.
03 PIC X VALUE %33.
03 PIC X(03) VALUE “&j@”.

The KEY-ON sequence will display the USER programmed function keys, as opposed to MODES, or DEVICES, or something like that. The KEY-OFF sequence will suppress the display of the function keys entirely. You will almost always want to use KEY-ON so you can make sure that the function keys are displayed.

The next thing I do is define all the default values for the function keys as variables;

01 KEY1.
05 PIC X VALUE %33.
05 PIC X VALUE ‘p’.
*
01 KEY2.
05 PIC X VALUE %33.
05 PIC X VALUE ‘q’.
*
01 KEY3.
05 PIC X VALUE %33.
05 PIC X VALUE ‘r’.
*
01 KEY4.
05 PIC X VALUE %33.
05 PIC X VALUE ‘s’.
*
01 KEY5.
05 PIC X VALUE %33.
05 PIC X VALUE ‘t’.
*
01 KEY6.
05 PIC X VALUE %33.
05 PIC X VALUE ‘u’.
*
01 KEY7.
05 PIC X VALUE %33.
05 PIC X VALUE ‘v’.
*
01 KEY8.
05 PIC X VALUE %33.
05 PIC X VALUE ‘w’.

Now lastly I define a couple of variables for loading up a big buffer with the function key values;

01 KEY-POINT PIC S9(9) COMP VALUE 0.
01 KEY-BUFF PIC X(300) VALUE SPACES.

The purpose for this is to reduce system overhead. It is much faster to load all eight function keys into one buffer and display it once rather than doing it eight times. If you have one hundred people on your system changing screens
and reloading function keys, you can have a huge impact from this one thing.

So the next step now is to actually load the function key’s with data that is meaningful to your application, and then test for user input. Here are a series of COBOL macros that I came up with that make loading function keys a little
easier, at least for me. I won’t go back over the use of macros here, since we covered it in depth in previous columns;

$DEFINE %PREPFKEY=
MOVE SPACES TO KEY-BUFF
MOVE 1 TO KEY-POINT#
*
$DEFINE %LOADFKEY=
MOVE !1 TO FKEY-LABEL
MOVE !2 TO FKEY-DATA
MOVE !3 TO FKEY-NUM
STRING SET-FKEY DELIMITED BY SIZE INTO KEY-BUFF
WITH POINTER KEY-POINT#
*
$DEFINE %SHOWFKEY=
STRING KEY-ON DELIMITED BY SIZE INTO KEY-BUFF
WITH POINTER KEY-POINT
SUBTRACT 1 FROM KEY-POINT
MULTIPLY KEY-POINT BY -1 GIVING KEY-POINT
CALL INTRINSIC “PRINT” USING KEY-BUFF, KEY-POINT, %320#
*
%PREPFKEY.
%LOADFKEY(“List by Number “#,KEY1#,1#).
%LOADFKEY(“List By Name “#,KEY2#,2#).
%LOADFKEY(” List No Hstry”#,KEY3#,3#).
%LOADFKEY(” List History “#,KEY4#,4#).
%LOADFKEY(” “#,KEY5#,5#).
%LOADFKEY(” “#,KEY6#,6#).
%LOADFKEY(” Back Up “#,KEY7#,7#).
%LOADFKEY(” EXIT “#,KEY8#,8#).
%SHOWFKEY.

ACCEPT INPUT-BUFF.
IF INPUT-BUFF = KEY8
STOP RUN.
IF INPUT-BUFF = KEY1
PERFORM B1000-NUM-LIST THRU B1000-EXIT.
IF INPUT-BUFF = KEY2
PERFORM B2000-NAME-LIST THRU B2000-EXIT.

etc…

Let me explain the macros a little bit here. First we use the macro to clear the function key buffer, and set the buffer pointer to 1, so we are pointing at the first byte of the buffer before the first LOADFKEY statement. The LOADFKEY macro simply takes your parameters, loads them into our function key structure, and then appends it into the function key buffer. Lastly we use the SHOWFKEY macro to append the KEY-ON escape sequence, adjust the buffer pointer so it points to the last actual used byte in our function key buffer. Set the buffer pointer value to a negative value, and then call the PRINT intrinsic with a no carriage return parameter %320. The PRINT intrinsic has less overhad than the
DISPLAY statement, but you could just say DISPLAY KEY-BUFF NO ADVANCING and get the same result.

I hope that clears up some of the gaps that I left in the function key arena. I have found the methods described here to be very straightforward, and productive for me in my various projects. If you have any ideas, or better methods I would love to hear about them.