Document revision date: 30 March 2001

## OpenVMS RTL Screen Management (SMG$) Manual

Previous | Contents | Index

## 5.7 Input Support for Foreign Terminals

A foreign terminal is any terminal for which the device type is not one of the standard Compaq terminals recognized by the OpenVMS operating system, or any terminal on which the ANSI_CRT characteristic is not set.

When you use a Compaq (or ANSI) terminal, typing a special key such as a function key or a keypad key sends an escape sequence (as defined by the ANSI standard) to the OpenVMS terminal driver. The OpenVMS terminal driver understands this ANSI standard and interprets the escape sequence according to this standard. Thus, the OpenVMS terminal driver knows how long the escape sequence is and what characters are allowed in which positions in that sequence.

The OpenVMS terminal driver does not echo any of the printing characters from the sequence because those characters are interpreted with special meaning as part of the escape sequence. Normal keys are echoed unless the TRM$M_TM_NOECHO modifier is specified.

The OpenVMS terminal driver returns to the Screen Management Facility the sequence, the length of the sequence, and the number of characters entered before the function key was pressed. The Screen Management Facility determines which key was pressed by comparing the sequence and its length against the list of key definitions for that particular terminal in TERMTABLE.EXE. This code is returned to the user in the format SMG$K_TRM_xxx, where xxx is used to specify the particular key.

When you press a special key such as a function key or a keypad key on a foreign terminal, a non-ANSI sequence is sent to the OpenVMS terminal driver. If this sequence starts with a control character, the OpenVMS terminal driver interprets this character as a terminator. (By default all control characters are terminators unless you use a terminator mask to specify otherwise.) The terminal driver then stops reading characters and returns to the Screen Management Facility the character, a length of 1, and the number of characters entered before the function key was pressed.

The Screen Management Facility looks at the returned character. If it is a control character, the Screen Management Facility looks in the type-ahead buffer for the next characters of the sequence. If there are characters in the type-ahead buffer, the Screen Management Facility reads one character from the type-ahead buffer, appends it to the control sequence it has already, and checks this new sequence against the list of key definitions for this terminal in TERMTABLE.EXE to determine which key was pressed. If the sequence is not matched, the next character is read from the type-ahead buffer. This continues until a match is found or the type-ahead buffer is empty. Since the terminal driver does not know about this sequence, any printable characters in the sequence are echoed by the terminal driver unless the noecho modifier was specified by the user. Because the Screen Management Facility does not know what characters make up this sequence, it disables line editing in order to allow the actual characters that make up the sequence to be returned to the Screen Management Facility.

Terminals whose special keys send a sequence that does not start with a control character are not supported by the Screen Management Facility for input. Changing the terminator mask to exclude the control character that starts the function key sequence is not supported. In addition, the performance of a foreign terminal doing input will not match that of a Compaq terminal doing the same input since SMG$ must parse the sequence in place of the OpenVMS terminal driver.

## 5.8 Support for SET and SHOW TERMINAL Commands

The DCL command SET TERMINAL is the mechanism for setting your terminal to conform to a TERMTABLE definition. SET TERMINAL causes the following three fields to be retrieved from the TERMTABLE database and set for your terminal:

- Terminal type---A signed integer assigned by the system and associated with a particular device type
- Width---The number of columns on the physical screen
- Page size---The number of rows on the screen

In addition, if the corresponding Boolean capability is set in the terminal definition, the following flags are set:

- ADVANCED_VIDEO
- ANSI_COLOR
- ANSI_CRT
- BLOCK_MODE
- DEC_CRT
- EDIT
- EIGHT_BIT
- FORM
- FULLDUP
- LOWERCASE
- REGIS
- SCOPE
- SIXEL_GRAPHICS
- SOFT_CHARACTERS
- TAB

If any of these fields is missing from your definition, the previous setting for that characteristic is retained; SET TERMINAL does not try to set that characteristic for your terminal. You should include all of the above capabilities in your definitions to avoid unpredictable settings.

SET TERMINAL operates as it always has for known terminals such as the VT300 series, VT200 series, VT100, and VT52. When SET TERMINAL encounters an unknown device name, it searches TERMTABLE for a definition with that name. Notice that your definitions must have names other than the names that SET TERMINAL currently recognizes. The terminals currently recognized are listed as follows:

LA12 | VT05 | VT131
LA34 | VT52 | VT132
LA36 | VT55 | VT200-SERIES
LA38 | VT100 | VT300-SERIES
LA100 | VT101 | VT400-SERIES
LA120 | VT102 | VT500-SERIES
LQP02 | VT125 | FT1 through FT8
Unknown |  |

If SET TERMINAL finds the device name in its own internal tables, it does not search the TERMTABLE database.

Since the SET TERMINAL command recognizes only the first 15 characters of a device name, you may want to limit your terminal names to 15 characters.

The SET TERMINAL/DEVICE=name command causes the TERMTABLE database to be searched for the named terminal, if that terminal is unknown to the OpenVMS operating system. SET TERMINAL/DEVICE=name then sets various terminal characteristics, as shown in the following table, based on the presence of these capabilities in the TERMTABLE database:

Capability Field | Terminal Characteristic
--- | ---
LOWERCASE | LOWERCASE
PHYSICAL_TABS | TABS
SCOPE | SCOPE
EIGHT_BIT | EIGHTBIT
PHYSICAL_FF | FORM
FULLDUP | FULLDUP
SIXEL_GRAPHICS | SIXEL
SOFT_CHARACTERS | SOFT
ANSI_CRT | ANSI_CRT
ANSI_COLOR | ANSI_COLOR
REGIS | REGIS
BLOCK_MODE | BLOCK
ADVANCED_VIDEO | AVO
EDIT_MODE | EDIT
DEC_CRT | DEC_CRT

The SET TERMINAL/DEVICE_TYPE=format must be used with TERMTABLE terminals. SET TERMINAL/name is an old format that works for a small set of device names and is maintained only for compatibility with previous versions of the OpenVMS operating system.

## Chapter 6
Using Screen Management Routines to Develop New Programs

This chapter discusses some recommended methods for using the Screen Management Facility for developing new programs.

Important Screen management routines are not AST reentrant.

## 6.1 Calling Screen Management Routines

There are two ways in which an application can call screen management routines.

- Directly
  Applications that call the Screen Management Facility directly already use pasteboards and virtual displays.
- Indirectly
  This kind of application does not use the Screen Management Facility directly, but may use it in the course of invoking other routines.
  Because many callable routines may use the Screen Management Facility to produce their output, it is difficult to determine whether your application is in this category.

In either case, the calling routine is likely at some point to call a subsystem so that the subsystem can write data to the screen.

At some later point, the terminal user will want to remove the subsystem-specific display. However, if the subsystem created and used a virtual display to display the data, the display identifier is not available to the calling program and therefore the calling program cannot remove it. Furthermore, unless the calling program is a direct user of the Screen Management Facility, the screen's pasteboard identifier is also not available to it.

The solution is to require that all callable routines that use the Screen Management Facility, directly or indirectly, have an (optional) input argument for the pasteboard-id and an (optional) output argument for the virtual display-id. Passing the pasteboard and display identifiers lets you avoid accumulating subsystem-specific data on the screen that cannot be removed by the calling program.

These guidelines are developed as follows:

- If the pasteboard-id argument is provided by the calling program, then:
  - The called program should not create a pasteboard of its own.
  - The called program must deliver all of its output to the pasteboard supplied by the calling program; that is, the called program may paste its displays only to the pasteboard specified by pasteboard-id.
  - The called program can delete any virtual displays it created by calling SMG$DELETE_VIRTUAL_DISPLAY, but it must not delete the pasteboard.
    Note that the called program should not simply call the SMG$UNPASTE_VIRTUAL_DISPLAY routine with the expectation that this virtual display can be reused in a later invocation. Since the called program and the calling program are sharing a pasteboard, the calling program may use the SMG$POP_VIRTUAL_DISPLAY routine to delete all displays created by the called program.
  - The called program must pass the pasteboard-id on to any routines it in turn calls. Thus all output is directed to the specified pasteboard.
- If the pasteboard-id argument is not provided by the calling program, then:
  - The called program must create a pasteboard on its own. The called program may allocate any physical device for the pasteboard, unless specifically directed to a particular device by some other mechanism.
    The called program must check the status of the SMG$CREATE_PASTEBOARD call to see whether it created a unique pasteboard identifier or whether it received the pasteboard identifier of an already existing pasteboard. If the pasteboard already exists, the called program must not delete the pasteboard.
  - If the called routine creates a pasteboard and in turn calls subroutines that may use pasteboards, it should pass the pasteboard-id to the subroutines.
  - The called program can clean up by using the SMG$UNPASTE_VIRTUAL_DISPLAY routine, and the displays can be saved for reuse on a subsequent invocation if such a call seems likely. However, the SMG$UNPASTE_VIRTUAL_DISPLAY routine should be used only if the called program creates its own pasteboard, because in this case the calling program cannot delete the virtual displays created by the called program.
- If the virtual display-id argument is provided by the calling program, then the calling program must clean up any virtual displays created by the called program. The called program must return to the calling program the identifier of the first virtual display pasted. The calling program can then remove this and all later-pasted virtual displays by calling the SMG$POP_VIRTUAL_DISPLAY routine.
- If the virtual display-id argument is not provided by the calling program, the called program must remove all the virtual displays it pastes to the pasteboard.

By adhering to the following guidelines, you can develop your application in a modular fashion:

- Calling programs control the pasteboard on which information is pasted. Pasteboard identifiers flow downward in a hierarchy, with each routine using the pasteboard-id provided by the caller and passing it along to subroutines.
- If a calling program supplies a virtual display-id argument to be filled in by the called program, then the calling program assumes responsibility for cleaning up any displays created by the called program. The called program passes back the display-id of the first virtual display pasted so that the calling program can remove this and all later-pasted displays by calling the SMG$POP_VIRTUAL_DISPLAY routine.
- Virtual displays are created (and pasted) in the routine where they are needed. If the calling program does not supply a display-id argument, then displays are unpasted and/or deleted in the routine that created them.

## 6.2 Calling Routines That Do Not Use the Screen Management Facility

A different situation exists if you call a subroutine (or subsystem) that writes to the screen without using the Screen Management Facility. When the Screen Management Facility is bypassed (that is, when text is placed on the screen outside screen management's control), problems result when an attempt is made to perform a screen update.

For this reason, the Screen Management Facility provides two routines for turning over the screen (or a part of it) temporarily to a program that does not use screen management, and for restoring the screen to its previous state after control is returned from the non-SMG$ routine. These routines are SMG$SAVE_PHYSICAL_SCREEN and SMG$RESTORE_PHYSICAL_SCREEN.

Before you call a routine that performs non-SMG$ I/O to the screen, you should call the SMG$SAVE_PHYSICAL_SCREEN routine, specifying what part of the screen is to be turned over to the non-SMG$ routine. SMG$SAVE_PHYSICAL_SCREEN erases the specified area, sets the terminal's physical scrolling region to this area, and sets the physical cursor to row 1, column 1 of the area. If the non-SMG$ code does only sequential input and output (that is, if it does no direct cursor addressing) its output will be confined to the specified area of the screen.

When control is returned from the non-SMG$ routine, you simply call SMG$RESTORE_PHYSICAL_SCREEN, which restores the screen image as it was before the call to SMG$SAVE_PHYSICAL_SCREEN.

## Chapter 7
Examples of Calling SMG$ Routines

This chapter contains examples demonstrating how to call the routine SMG$READ_KEYSTROKE from the major programming languages. Note that not all of the languages represented in these examples are available on OpenVMS Alpha systems. The following languages are supported on Alpha systems:

Ada | BASIC | BLISS | C
C++ | COBOL | Fortran | MACRO-32 1
MACRO-64 | Pascal | PL/I |

1Note that MACRO-32 must be compiled with the AMACRO compiler.

Other SMG$ routines such as SMG$CREATE_VIRTUAL_DISPLAY, SMG$CREATE_PASTEBOARD, SMG$CREATE_VIRTUAL_KEYBOARD, SMG$PASTE_VIRTUAL_DISPLAY, and SMG$PUT_LINE are also used throughout these examples.

Example 7-1 demonstrates the use of SMG$READ_KEYSTROKE from a Compaq Ada program. This program also uses SMG$CREATE_VIRTUAL_DISPLAY, SMG$CREATE_PASTEBOARD, SMG$CREATE_VIRTUAL_KEYBOARD, SMG$PASTE_VIRTUAL_DISPLAY, and SMG$PUT_LINE.

Example 7-1 Using SMG$ Routines in Compaq Ada

    with SYSTEM, CONDITION_HANDLING; use SYSTEM;
    package SMG is  -- declarations of SMG$ routines used

        procedure CREATE_VIRTUAL_DISPLAY (
            STATUS: out CONDITION_HANDLING.COND_VALUE_TYPE;
            ROWS, COLUMNS: INTEGER;
            DISPLAY_ID: out INTEGER;
            DISPLAY_ATTRIBUTES, VIDEO_ATTRIBUTES, CHAR_SET: UNSIGNED_LONGWORD
                := UNSIGNED_LONGWORD'NULL_PARAMETER);
        pragma INTERFACE (SMG, CREATE_VIRTUAL_DISPLAY);
        pragma IMPORT_VALUED_PROCEDURE
            (CREATE_VIRTUAL_DISPLAY, "SMG$CREATE_VIRTUAL_DISPLAY");

        procedure CREATE_PASTEBOARD (
            STATUS: out CONDITION_HANDLING.COND_VALUE_TYPE;
            PASTEBOARD_ID: out INTEGER;
            OUTPUT_DEVICE: STRING := STRING'NULL_PARAMETER;
            ROWS, COLUMNS: INTEGER := INTEGER'NULL_PARAMETER;
            PRESERVE_SCREEN_FLAG: BOOLEAN := BOOLEAN'NULL_PARAMETER);
        pragma INTERFACE (SMG, CREATE_PASTEBOARD);
        pragma IMPORT_VALUED_PROCEDURE
            (CREATE_PASTEBOARD, "SMG$CREATE_PASTEBOARD");

        procedure CREATE_VIRTUAL_KEYBOARD (
            STATUS: out CONDITION_HANDLING.COND_VALUE_TYPE;
            KEYBOARD_ID: out INTEGER;
            FILESPEC, DEFAULT_FILESPEC, RESULTANT_FILESPEC: STRING
                := STRING'NULL_PARAMETER);
        pragma INTERFACE (SMG, CREATE_VIRTUAL_KEYBOARD);
        pragma IMPORT_VALUED_PROCEDURE
            (CREATE_VIRTUAL_KEYBOARD, "SMG$CREATE_VIRTUAL_KEYBOARD");
        procedure PASTE_VIRTUAL_DISPLAY (
            STATUS: out CONDITION_HANDLING.COND_VALUE_TYPE;
            DISPLAY_ID, PASTEBOARD_ID: INTEGER;
            ROW, COLUMN: INTEGER);
        pragma INTERFACE (SMG, PASTE_VIRTUAL_DISPLAY);
        pragma IMPORT_VALUED_PROCEDURE
            (PASTE_VIRTUAL_DISPLAY, "SMG$PASTE_VIRTUAL_DISPLAY");

        procedure READ_KEYSTROKE (
            STATUS: out CONDITION_HANDLING.COND_VALUE_TYPE;
            KEYBOARD_ID: INTEGER;
            TERMINATOR_CODE: out UNSIGNED_WORD;
            PROMPT: STRING := STRING'NULL_PARAMETER;
            TIMEOUT, DISPLAY_ID: INTEGER := INTEGER'NULL_PARAMETER);
        pragma INTERFACE (SMG, READ_KEYSTROKE);
        pragma IMPORT_VALUED_PROCEDURE
            (READ_KEYSTROKE, "SMG$READ_KEYSTROKE");

        procedure PUT_LINE (
            STATUS: out CONDITION_HANDLING.COND_VALUE_TYPE;
            DISPLAY_ID: INTEGER;
            TEXT: STRING;
            LINE_ADVANCE: INTEGER := INTEGER'NULL_PARAMETER;
            RENDITION_SET, RENDITION_COMPLEMENT: UNSIGNED_LONGWORD
                := UNSIGNED_LONGWORD'NULL_PARAMETER;
            WRAP_FLAG: BOOLEAN := BOOLEAN'NULL_PARAMETER;
            CHAR_SET: UNSIGNED_LONGWORD := UNSIGNED_LONGWORD'NULL_PARAMETER);
        pragma INTERFACE (SMG, PUT_LINE);
        pragma IMPORT_VALUED_PROCEDURE
            (PUT_LINE, "SMG$PUT_LINE");
    end SMG;

    -- This routine demonstrates the use of the SMG$ routines, in particular
    -- SMG$READ_KEYSTROKE.

    with SMG, STARLET, CONDITION_HANDLING, SYSTEM;
    procedure SMG_DEMO is
        STATUS: CONDITION_HANDLING.COND_VALUE_TYPE;
        PASTEBOARD_1, DISPLAY_1, KEYBOARD_1: INTEGER;
        TERMINATOR: SYSTEM.UNSIGNED_WORD;
    begin
        -- Create virtual display, pasteboard and virtual keyboard.

        SMG.CREATE_VIRTUAL_DISPLAY (STATUS, ROWS => 7, COLUMNS => 60,
            DISPLAY_ID => DISPLAY_1,
            DISPLAY_ATTRIBUTES => STARLET.SMG_M_BORDER);
        SMG.CREATE_PASTEBOARD (STATUS, PASTEBOARD_ID => PASTEBOARD_1);
        SMG.CREATE_VIRTUAL_KEYBOARD (STATUS, KEYBOARD_ID => KEYBOARD_1);

        -- Paste the virtual display at row 3, column 9.

        SMG.PASTE_VIRTUAL_DISPLAY (STATUS, DISPLAY_ID => DISPLAY_1,
            PASTEBOARD_ID => PASTEBOARD_1, ROW => 3, COLUMN => 9);

        -- Write the instructions to the virtual display.
        SMG.PUT_LINE (STATUS, DISPLAY_ID => DISPLAY_1,
            TEXT => "Enter the character K after the >> prompt.");
        SMG.PUT_LINE (STATUS, DISPLAY_ID => DISPLAY_1,
            TEXT => "This character will not be echoed as you type it.");
        SMG.PUT_LINE (STATUS, DISPLAY_ID => DISPLAY_1,
            TEXT => "The terminal character equivalent of K is displayed.");
        SMG.PUT_LINE (STATUS, DISPLAY_ID => DISPLAY_1,
            TEXT => " ");

        -- Read the keystroke from the virtual keyboard.

        SMG.READ_KEYSTROKE (STATUS, KEYBOARD_ID => KEYBOARD_1,
            DISPLAY_ID => DISPLAY_1,
            TERMINATOR_CODE => TERMINATOR, PROMPT => ">>");

        -- Display the decimal value of the terminator code.

        SMG.PUT_LINE (STATUS, DISPLAY_ID => DISPLAY_1,
            TEXT => " ");
        SMG.PUT_LINE (STATUS, DISPLAY_ID => DISPLAY_1,
            TEXT => "TERMINAL CHARACTER IS " &
                SYSTEM.UNSIGNED_WORD'IMAGE(TERMINATOR));

    end SMG_DEMO;

Example 7-2 uses SMG$READ_KEYSTROKE to read a keystroke from the terminal. This BASIC program also uses SMG$CREATE_VIRTUAL_KEYBOARD and SMG$DELETE_VIRTUAL_KEYBOARD.

Example 7-2 Using SMG$ Routines in Compaq BASIC

    1       OPTION TYPE=EXPLICIT

            !+
            ! This routine demonstrates the use of SMG$READ_KEYSTROKE to read
            ! a keystroke from the terminal.
            !
            ! Build this program using the following commands.
            !
            !$ BASIC READ_KEY
            !$ CREATE SMGDEF.MAR
            !       .TITLE  SMGDEF - Define SMG$ constants
            !       .Ident  /1-000/
            !
            !       $SMGDEF GLOBAL
            !
            !       .END
            !$ MACRO SMGDEF
            !$ LINK READ_KEY,SMGDEF
            !
            !-

            DECLARE LONG KB_ID, RET_STATUS, TERM_CODE, I, TIMER
            EXTERNAL SUB LIB$SIGNAL( LONG BY VALUE )
            EXTERNAL SUB LIB$STOP( LONG BY VALUE )
            EXTERNAL LONG CONSTANT SS$_TIMEOUT
            EXTERNAL LONG CONSTANT SMG$K_TRM_PF1
            EXTERNAL LONG CONSTANT SMG$K_TRM_PERIOD
            EXTERNAL LONG CONSTANT SMG$K_TRM_UP
            EXTERNAL LONG CONSTANT SMG$K_TRM_RIGHT
            EXTERNAL LONG CONSTANT SMG$K_TRM_F6
            EXTERNAL LONG CONSTANT SMG$K_TRM_F20
            EXTERNAL LONG CONSTANT SMG$K_TRM_FIND
            EXTERNAL LONG CONSTANT SMG$K_TRM_NEXT_SCREEN
            EXTERNAL LONG CONSTANT SMG$K_TRM_TIMEOUT
            EXTERNAL LONG FUNCTION SMG$CREATE_VIRTUAL_KEYBOARD( LONG, STRING )
            EXTERNAL LONG FUNCTION SMG$DELETE_VIRTUAL_KEYBOARD( LONG )
            EXTERNAL LONG FUNCTION SMG$READ_KEYSTROKE( LONG, LONG, STRING, &
                LONG, LONG )

            !+
            ! Prompt the user for the timer value.  A value of 0 will cause
            ! the type-ahead buffer to be read.
            !-

            INPUT "Enter timer value (0 to read type-ahead buffer):  ";TIMER

            !+
            ! Establish a SMG connection to SYS$INPUT.  Signal any unexpected
            ! errors.
            !-

            RET_STATUS = SMG$CREATE_VIRTUAL_KEYBOARD( KB_ID, "SYS$INPUT:" )
            IF (RET_STATUS AND 1%) = 0% THEN
                CALL LIB$SIGNAL( RET_STATUS )
            END IF

            !+
            !   Read a keystroke, tell the user what we found.
            !-

            RET_STATUS = SMG$READ_KEYSTROKE( KB_ID, TERM_CODE, , TIMER, )
            IF (RET_STATUS <> SS$_TIMEOUT) AND ((RET_STATUS AND 1%) = 0%) THEN
                CALL LIB$SIGNAL( RET_STATUS )
            END IF

            PRINT "term_code = ";TERM_CODE

            SELECT TERM_CODE

                CASE 0 TO 31
                    PRINT "You typed a control character"

                CASE 32 TO 127
                    PRINT "You typed: ";CHR$(TERM_CODE)

                CASE SMG$K_TRM_PF1 TO SMG$K_TRM_PERIOD
                    PRINT "You typed one of the keypad keys"

                CASE SMG$K_TRM_UP TO SMG$K_TRM_RIGHT
                    PRINT "You typed one of the cursor positioning keys"

                CASE SMG$K_TRM_F6 TO SMG$K_TRM_F20
                    PRINT "You typed one of the function keys"

                CASE SMG$K_TRM_FIND TO SMG$K_TRM_NEXT_SCREEN
                    PRINT "You typed one of the editing keys"

                CASE SMG$K_TRM_TIMEOUT
                    PRINT "You did not type a key fast enough"

                CASE ELSE
                    PRINT "I'm not sure what key you typed"

            END SELECT

            !+
            ! Close the connection to SYS$INPUT, and signal any errors.
            !-

            RET_STATUS = SMG$DELETE_VIRTUAL_KEYBOARD( KB_ID )
            IF (RET_STATUS AND 1%) = 0% THEN
                CALL LIB$SIGNAL( RET_STATUS )
            END IF

            END

The BLISS program in Example 7-3 demonstrates the use of SMG$READ_KEYSTROKE from a lower-level language.

Example 7-3 Using SMG$ Routines in VAX BLISS-32

    MODULE READ_SINGLE_CHAR (       MAIN = PERFORM_READ,
                                    %TITLE 'Read a Keystroke from SYS$INPUT'
                                    IDENT = '1-001'  ) =
    BEGIN

    !+
    ! Facility:     Example programs
    !
    ! Abstract:     This example program uses the routine SMG$READ_KEYSTROKE
    !               to get a single character input from the current SYS$INPUT
    !               device and then indicates the nature of the input to the user.
    !
    ! Environment:  User mode, AST reentrant
    !
    ! Author:       John Doe        Creation Date:  8-Apr-1985
    !
    ! Modified by:
    ! 1-001 - Original.  JD 8-Apr-1985
    !-

    !+
    ! General mode addressing must be used for external references.
    !-

    %SBTTL 'Declarations'
    SWITCHES ADDRESSING_MODE (EXTERNAL=GENERAL, NONEXTERNAL=WORD_RELATIVE);

    !+
    ! Obtain SMG$, SS$, etc. definitions.
    !-

    LIBRARY 'SYS$LIBRARY:STARLET';

    !+
    ! Use the TUTIO package for the purposes of this small example.
    !-

    REQUIRE 'SYS$LIBRARY:TUTIO';

    !+
    ! Declare screen management routines used by this program, as well as
    ! any other external routines.
    !-

    EXTERNAL ROUTINE
        SMG$CREATE_VIRTUAL_KEYBOARD,
        SMG$DELETE_VIRTUAL_KEYBOARD,
        SMG$READ_KEYSTROKE,
        LIB$SIGNAL : NOVALUE;
    !+
    ! Define a convenient way to check the return status from a routine.
    !-

    MACRO CHECK (X) =
    IF NOT X
    THEN
        LIB$SIGNAL (X)
    %;

    %SBTTL 'Routine PERFORM_READ'
    ROUTINE PERFORM_READ: NOVALUE =

    !+
    ! Functional Description:
    !
    !       This routine uses screen management I/O to get a single character
    !       input from the current SYS$INPUT device, and then processes it by
    !       what its character or termination code is.
    !
    ! Calling Sequence:
    !
    !       Not Callable
    !
    ! Formal Arguments:
    !
    !       Not Applicable
    !
    ! Implicit Inputs:
    !
    !       None
    !
    ! Implicit Outputs:
    !
    !       None
    !
    ! Side Effects:
    !
    !       Any error returned by screen management routines except for
    !       SS$_TIMEOUT will be signaled.
    !-

    BEGIN

        LITERAL
            ZERO = 0;

        LOCAL
            KBID : INITIAL(0),
            TERM_CODE : INITIAL(0),
            TIMER_VALUE : INITIAL(0),
            SMG_STATUS;

        !+
        ! Obtain a read timeout value.
        !-

        TIMER_VALUE = 10;

        !+
        ! Establish a screen managed connection to SYS$INPUT.
        !-

        SMG_STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (KBID, %ASCID'SYS$INPUT');
        CHECK (.SMG_STATUS);

        !+
        ! Read a keystroke and tell the user what was found.
        !-

        SMG_STATUS = SMG$READ_KEYSTROKE (KBID, TERM_CODE, ZERO, TIMER_VALUE);
        IF (.SMG_STATUS NEQ SS$_TIMEOUT)
        THEN
           CHECK (.SMG_STATUS);

        SELECTONE .TERM_CODE OF
        SET
            [0 TO 31]:
            TTY_PUT_QUO ('You typed a control character.');

            [32 TO 127]:
            TTY_PUT_QUO ('You typed a printable character.');

            [SMG$K_TRM_PF1 TO SMG$K_TRM_PERIOD]:
            TTY_PUT_QUO ('You typed one of the keypad keys.');

            [SMG$K_TRM_UP TO SMG$K_TRM_RIGHT]:
            TTY_PUT_QUO ('You typed one of the cursor positioning keys.');

            [SMG$K_TRM_F6 TO SMG$K_TRM_F20]:
            TTY_PUT_QUO ('You typed one of the function keys.');

            [SMG$K_TRM_FIND TO SMG$K_TRM_NEXT_SCREEN]:
            TTY_PUT_QUO ('You typed one of the editing keys.');

            [SMG$K_TRM_TIMEOUT]:
            TTY_PUT_QUO ('You did not type a key fast enough.');

            [OTHERWISE]:
            TTY_PUT_QUO ('I am not sure what you typed.');

        TES;
        TTY_PUT_CRLF ();
        !+
        ! Terminate the screen managed connection to SYS$INPUT.
        !-

        SMG_STATUS = SMG$DELETE_VIRTUAL_KEYBOARD (KBID);
        CHECK (.SMG_STATUS);

    END;

    END
    ELUDOM

Previous | Next | Contents | Index

| privacy and legal statement |
5935PRO_007.HTML