Using the Keyboard Input Buffer Saves Time, Increases Productivity



W$KEYBUF: Theory and Practice

Appendix I of the ACUCOBOL-85 and ACUCOBOL-GT® manuals describes the library routines that are built into the runtime system. These routines are special functions that are activated via the "CALL" verb. Since they perform functions outside of standard COBOL, these routines have not been introduced as extensions to the language.

With each new version of the compiler, Acucobol has increased the number of library routines that it maintains. With the release of ACUCOBOL-GT Version 3.1, there are now 40 routines in all (see Table 1).

In this article, we describe the use of one particular library routine: W$KEYBUF. This routine manages the keyboard input buffer and allows you to record character sequences that can be reproduced to simulate data input from the user. The character sequences can be stored in temporary variables or files. By storing characters in the keyboard input buffer, you can alleviate repetitive work for end users and, at the same time, increase their productivity. Some Acucorp tools, such as AcuEdit--the new editor written totally in ACUCOBOL-85--employ a CALL to W$KEYBUF to manage macro commands.

The W$KEYBUF routine can be useful in real business situations. For example, accounting programs can often be repetitive for operators, because they commonly require long series of similar data to be entered. Registration or invoicing applications also require operators to enter sequences of similar or identical data. With W$KEYBUF, operators can simply press a single key to enter information, saving them from a repetitive job.

In this article, we examine the call's syntax and functions, and we illustrate a practical application, which we hope will be useful to you. But first, it is important that you understand the keyboard buffer and how it is managed.

The Keyboard Buffer

The keyboard buffer is a memory area containing a representation of the keys the user has pressed. It can be updated with new data when the program is not executing an ACCEPT.

Let's try to compile and execute the source code in Table 2. After clearing the screen, the program waits for three seconds (C$SLEEP) and then executes the ACCEPT. If you press any key in the meantime, its content is returned in the acknowledgment field.

When executing an ACCEPT instruction, the Acucobol runtime checks to see if the keyboard's buffer contains any characters. If so, the runtime transfers the characters from the buffer to the variable specified in the acknowledgment field. Since W$KEYBUF lets you add or eliminate characters in this buffer, you need to know the format of the character sequences in the buffer.

Buffer Format

The memory area of the keyboard buffer contains alphanumeric information. It can be assimilated to a COBOL variable, defined as PIC X( ), where the parentheses contain the keys' codes. These codes can be either alphanumeric characters or function keys. Alphanumeric codes, normally used to write text, are represented in their natural format. Function key codes are represented according to this convention:

     {Function-key}

where Function-key is the code used in the UNIX a_termcap file to represent the key. For example, <F1> and <F2> are represented by the "k1" and "k2" codes between curly braces ({k1}, {k2}).

During reproduction, when W$KEYBUF encounters curly braces, it emulates the typing of the corresponding function key. This allows you to pick out special keys that return control sequences. For example, if you want to input a company's full address, and you want confirmation with the <F1> key, you can type the following. (Note: the <Enter> key is written as {^M}.)

Acucorp, Inc.  {^M} 7950 Silverton Avenue {^M} 
       San Diego {^M} {k1}

You can also emulate the calls to "W$MENU," the library routine managing the pop-up menus, with {M#}, where # corresponds to the menu choice desired. To represent the curly brace character itself, type "{{".

W$KEYBUF Syntax

The W$KEYBUF routine is activated via the CALL verb, according to the following syntax:

     CALL "W$KEYBUF" USING OP-CODE, parameters.

where OP-CODE indicates the kind of operation to execute, and the parameters depend on the selected op-code.

OP-CODE "1"

Op-code "1" allows you to add characters to the keyboard input buffer, simulating data input. All the characters inserted in the buffer are then attributed to the variables in subsequent ACCEPT commands. For example:

     CALL "W$KEYBUF" USING "1", "TEST {^M}".

attributes the content of "TEST" to the subsequent ACCEPT variable and stops the ACCEPT execution. (Remember that {^M} means <Enter>.) The character sequence to add to the keyboard input buffer can be specified either as a constant, such as in the above example, or an alphanumeric variable. The above example would have worked in the same way if the call had been done like this:

     CALL "W$KEYBUF" USING "1", BUFF.

where BUFF is an alphanumeric variable (PIC X), which has been assigned the "TEST {^M}" value. Moreover, you can include a third optional parameter that specifies the number of characters you really want to add to the buffer. For example, the call:

     CALL "W$KEYBUF" USING "1", "TEST {^M}", "3".

adds "TES" to the keyboard buffer--that is, the first three characters of the "TEST" string. Please note that characters added this way are placed before any character typed by the user. Now try to execute the program shown in Table 3. While the program executes the "C$SLEEP", type the "A" key three times. The result of the "X" variable, when passed to the ACCEPT, is "TESTAAA" and not "AAATEST", as you might have expected. This behavior keeps the user from interfering with the pre-programmed input sequence.

OP-CODE "2"

Op-code "2" is the same as op-code "1", except that the characters are added at the beginning of the input buffer--before any others that already exist--instead of at the end. If you execute the program shown in Table 4, you can see that the "X" variable content assumes the "VATES" value, since the second string of "VA" characters has been inserted in the buffer using operation code "2".

OP-CODE "3"

Op-code "3" is used to clear the keyboard buffer, and it doesn't need any parameters. Note that op-code "3" empties the buffer used by W$KEYBUF, not the one used by the operating system. (In other words, the regular keyboard characters are unaffected by this operation.) Try to execute the program shown in Table 5. While the program executes C$SLEEP, type any character sequence. The "W$KEYBUF USING 3" call excludes the effects of the former call; so this time, no content is assigned to the "X" variable.

OP-CODE "4"

As mentioned earlier, one of W$KEYBUF's functions is to record work sessions. To activate recording, use operation code "4". Immediately following this call, every keystroke is memorized in a variable specified as a second (mandatory) call parameter. The recording remains in effect until deactivated with op-code "5". An optional third parameter, numerical, can set a limit to the number of characters that can be recorded. If this parameter is missing, the limit is defined by the width of the alphanumeric variable.

This code turns off the recording mechanism put in action with op-code "4". When you make this call, the RETURN-CODE implicit variable contains the number of characters typed in, and therefore, the number contained in the memory variable or file set that contains them (see op-code "7").

OP-CODE "6"

This code lets you know if the recording mode is active or not. The result is put in the implicit variable RETURN-CODE. If the value is "1", the recording mechanism is turned on. If it's "0", the mechanism is turned off.

OP-CODE "7"

Sometimes it is not sufficient to record keystrokes in one variable--for instance, if the recording is exceedingly long, or if the maximum length is not known. In these situations, operation code "7" can be used. Op-code "7" lets you specify a sequential file as a recording buffer. The sequential filename must be specified as the second call parameter. If the file can be created and the pathname is valid, the RETURN-CODE implicit variable is set to value "0" (zero). If the file cannot be created, then it is set to "1". If the specified file already exists, it is deleted. This way, the recording duration can be virtually unlimited.

OP-CODE "8"

Operation code "8" is identical to op-code "7", except that the file is appended to if it already exists.

OP-CODE "9"

Op-code "9" is used to play back a session previously recorded in a file. The pathname of the file to be played back is passed as the second parameter. RETURN-CODE is set to "0" if the file is opened successfully; otherwise it is set to "1".

Alternatively, you can initiate playback from the command line by passing the "k" parameter to the runtime, followed by the file pathname. The command syntax is as follows:

runcblprogram-name -k file-recording
New OP-CODES with Release 2.4.2

Prior to Version 2.4.2 of ACUCOBOL-85, the options run by the W$KEYBUF routine occurred without any speed control, so simulated keystrokes were not very realistic. The screen became full at the maximum speed allowed by the hardware, without letting the user understand what was happening. Moreover, the user could not interrupt the reproduction, temporarily or definitively. Version 2.4.2 answers such concerns; the new op-codes that it introduced are described below.

OP-CODE "10"

This new op-code lets you define a delay between the reproduction of one character and the next. The delay, in hundredths of a second, is passed as the second parameter. For example, to set a delay of a quarter of a second, execute the following call:

     CALL "W$KEYBUF" USING 10, 25.

This then becomes your default delay. By inserting additional commands in the reproduced memory buffer, you can then introduce pauses of different durations. Following is a list of possible options:

  • {p#} the reproduction pauses for # hundredths of a second (lower case p, followed by pound sign)
  • {P#} the reproduction pauses for # seconds (capital P, followed by pound sign)
  • {P} the reproduction pauses for one second (capital P)

For example, the following character string inserted in a file or play-back variable will cause a delay of 1-1/2 seconds after reproducing the "Acucobol" string and before ending the ACCEPT input with the <Enter> key:

     "Acucobol {p150}{^M}"
OP-CODE "11"

As mentioned before, some calls specify keys that can be interpreted only by reproductions with pauses. Op-code "11" allows you to define a key that stops buffer playback for an indefinite period of time. Playback resumes when the user presses any other key. For example, if you want thekey to stop playback, you should make the call:

     CALL "W$KEYBUF" USING 11, 27.

where "27" is the ASCII code of the <Esc> key. Please note that this function can be linked only with keys that return a simple ASCII code and not with complex functions keys.

OP-CODE "12"

Op-code "12" is defined in the same way as op-code "11". It allows you to define a key that stops buffer playback, and returns the program to interactive mode.

OP-CODE "13"

Op-code "13" works the same as op-code "12", except that the specified key turns off the procedure running the runtime, in addition to interrupting the recording reproduction. Please note the following:

  • Upon encountering an op-code "13", the runtime displays a "Killed by user" message. If you don't want to read this message, then standard output should be assigned with the "-e" option on the line of command that initiated the runtime.
  • This mode should not be used when the program is executed with the "-s" option (safe mode). In this case, the key pressed to interrupt the program accomplishes two things: it ends execution and then re-starts the ACCEPT command that turned it on. This causes a de-synchronization between the playback buffer and the requests of the reproduced program, with unforseeable results. Therefore, it is not safe to use this mode in presence of the "-s" option.
Deleting Extra Characters from the Buffer

When you record key sequences in a variable or sequential file, the function key chosen to deactivate the recording mechanism is also recorded in the destination buffer. This happens unless you record a program from the beginning to the end, or interrupt the recording after a certain time. Since the deactivation keystroke is of no interest to you, you may want to eliminate it from the buffer. To do this, we suggest two simple methods.

Let's suppose that, in both cases, function key <F1> is used to deactivate the recording. Since is represented as "{K1}" in UNIX a_termcap, you need to eliminate the last four characters of the variable or file.

If your buffer is stored in a variable, you should set the recording end by calling the W$KEYBUF function with op-code "5". Since RETURN-CODE contains the number of inserted characters, it is very simple to eliminate the last four by executing the command:

     move spaces to record_buf (return-code - 3 : )

If you use a file to store the recording, the problem becomes a bit more complex. The memorized file is in binary sequential format and the re-writing operation cannot be used for this kind of file. You should read the entire file, write it to another one, and eliminate the last four characters there. This, of course, can be quite long and complex. It would be much easier to open the sequential file as a relative file with a record length of one byte. This way, it is easy to move to the end of the file and delete the last four characters with READ PREVIOUS. (See Table 6.)

Another way to handle the problem is to synchronize the keyboard buffer reproduced with W$KEYBUF and the program. You need to make the keys' sequences coincide with the ACCEPT instructions, since the W$KEYBUF cannot produce any control. It is not safe to execute a reproduction starting from an ACCEPT different from the one at which you started the recording, because this can produce unforseeable results.

Example

A practical example showing W$KEYBUF calls and parameters may be very useful. We created a tool that allows you to use self-running demos. With this tool you can interactively record sessions of your programs, interrupt them, display information on the screen, or visualize message boxes, etc.

This program is available to you on the Acucobol BBS. Please, download it and try it! Together with the program, you will find some useful instructions and the Version 2.4.2 MS-DOS runtime, since this Acucobol release takes advantage of new calls, illustrated in a section of this article.

Please note that this program has just been completed: so, your comments, suggestions, or notes on possible problems are welcome. Feel free to contact an Acucobol representative at 800-COBOL85 or 619-689-4500, or send e-mail to info@acucorp.com.

Table 1: Acucobol Library Routines

Call Name Function
C$CALLERR It gives back the reason why a CALL didn't work
C$CHAIN It ends the program execution and calls any other program available on the computer.
C$CHDIR It changes the actual work directory.
C$COPY It copies a file.
C$FILEINFO It gives back system information about a file.
C$FILESYS It gives back information about the file system.
C$JUSTIFY It justifies a string of characters on the right, on the left, or in the center.
C$KEYMAP It saves and restores the keyboard configuration.
C$LOCALPRINT It addresses the printing output on a local printer.
C$MEMCPY It copies bytes between two memory locations.
C$NARG It gives back the parameters passed to the actual program.
C$OPENSAVEBOX It creates an OPEN or SAVE AS dialog box.
C$PARAMSIZE It returns the number of bytes passed by the caller for a particular parameter.
C$RECOVER It recovers a file from the transaction log file.
C$RERR It gives back an extended error code.
C$RERRNAME It returns the name of the last file used for I/O.
C$RUN It gives back the actual length of a parameter passed to a program.
C$SLEEP It executes a program pause without seizing the CPU.
C$TOUPPER/C$TOLOWER It changes a character string into upper/lower characters.
LIB$GET_SYMBOL Specific routine for VMS.
LIB$SET_SYMBOL Specific routine for VMS.
M$ALLOC It allocates an area of dynamic memory.
M$FREE It releases a block of memory previously allocated.
M$GET It reads data from a memory block.
M$PUT It memorizes data in a memory block.
RENAME It recalls a file.
SYSTEM It executes calls to the operating system.
W$BITMAP It visualizes images in bitmap format.
W$FONT It provides support for font selection.
W$FORGET It restarts the Acucobol terminal manager.
W$GETC It gives back the pressed key code.
$WINHELP It calls Windows help.
W$KEYBUF See this article.
W$MENU It manages a pop-up menu.
W$MOUSE It manages the mouse.
W$PALETTE It defines the color palette used.
W$TEXTSIZE It measures the height and width of a string of text.
WIN$PRINTER It configures the Windows print spooler.
WIN$VERSION It returns information for Windows and Windows NT.
Table 2
identification division.
program-id.      wkbuf1.
******************************
environment division.
configuration section.
data division.
******************************
working-storage section.
******************************
01  x            
pic x(20).
******************************
procedure division.
******************************
ini.
    display window erase.
    call "c$sleep" using "3".
    accept x at 1010 prompt.
    stop run.
Table 3
identification division.
program-id.      wkbuf2.
******************************
*
environment division.
configuration section.
data division.
******************************
working-storage section.
******************************
01  x            
pic x(20).
******************************
procedure division.
******************************
ini.
    display window erase.
    call "c$sleep"  using "3".
    call "w$keybuf" using "1" "PRO".
    call "w$keybuf" using "1" "VA".
    accept x at 1010 prompt.
    stop run.
Table 4
identification division.
program-id.      wkbuf3.
******************************
*
environment division.
configuration section.
data division.
******************************
working-storage section.
******************************
01  x            
pic x(20).
******************************
procedure division.
******************************
ini.
    display window erase.
    call "c$sleep"  using "3".
    call "w$keybuf" using "1" "PRO".
    call "w$keybuf" using "2" "VA".
    accept x at 1010 prompt.
    stop run.
Table 5
identification division.
program-id.      wkbuf4.
******************************
*
environment division.configuration section.data division.
******************************
working-storage section.
******************************
01  x            
pic x(20).
******************************
procedure division.
******************************
ini.
    display window erase.
    call "c$sleep"  using "3".
    call "w$keybuf" using "1" "PROVA".
    call "w$keybuf" using "3".
    accept x at 1010 prompt.
    stop run.
Table 6
identification division.
program-id.      wkbuf5.
Installation.   Acucorp, Inc.
******************************
environment division.
configuration section.
special-names.
        decimal-point is comma.
input-output section.
file-control.
    select temp_work_file
        assign to random file_name
        organization relative
        access dynamic
        relative key work_key.
******************************
data division.
file section.
fd  temp_work_file.
01  work_record pic x.
******************************
working-storage section.
******************************
01 work_key  pic 9(5).
01 file_name pic x(80).
******************************
procedure division using file_name.
******************************
swapmrc.
    open i-o temp_work_file.
    move 99999 to work_key.
    start temp_work_file  key is not > work_key.
    perform 4 times
       read temp_work_file previous record
       delete temp_work_file record
    end-perform
    close temp_work_file.
    stop run.
Your Session will expire in 90 minutes
Notification will be shown in:
600 seconds