Document revision date: 19 July 1999 | |
Previous | Contents | Index |
A foreign terminal is any terminal for which the device type is not one of the standard Digital terminals recognized by the OpenVMS operating system, or any terminal on which the ANSI_CRT characteristic is not set.
When you use a Digital (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 Digital 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:
In addition, if the corresponding Boolean capability is set in the terminal definition, the following flags are set:
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.
This chapter discusses some recommended methods for using the Screen Management Facility for developing new programs.
Screen management routines are not AST reentrant. |
There are two ways in which an application can call screen management routines.
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:
By adhering to the following guidelines, you can develop your application in a modular fashion:
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.
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 |
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 VAX 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 VAX 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 VAX 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 |