Updated: 11 December 1998 |
OpenVMS Programming Concepts Manual
Previous | Contents | Index |
The SMG$PUT_LINE and SMG$PUT_LINE_MULTI routines write lines to virtual displays one line after another. If the display area is full, it is scrolled. You do not have to keep track of which line you are on. All routines permit you to scroll forward (up); SMG$PUT_LINE and SMG$PUT_LINE_MULTI permit you to scroll backward (down) as well. SMG$PUT_LINE permits spacing other than single spacing.
Example 9-7 writes lines from a buffer to a display area. The output is scrolled forward if the buffer contains more lines than the display area.
Example 9-7 Scrolling Forward Through a Display |
---|
INTEGER*4 BUFF_COUNT, 2 BUFF_SIZE (4096) CHARACTER*512 BUFF (4096) . . . DO I = 1, BUFF_COUNT STATUS = SMG$PUT_LINE (VDID, 2 BUFF (I) (1:BUFF_SIZE (I))) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) END DO |
Example 9-8 scrolls the output backward.
Example 9-8 Scrolling Backward Through a Display |
---|
DO I = BUFF_COUNT, 1, -1 STATUS = SMG$PUT_LINE (VDID, 2 BUFF (I) (1:BUFF_SIZE (I)), 2 SMG$M_DOWN) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) END DO |
To maintain precise control over cursor movement and scrolling, you can write with SMG$PUT_CHARS and scroll explicitly with SMG$SCROLL_DISPLAY_AREA. SMG$PUT_CHARS leaves the cursor after the last character written and does not force scrolling; SMG$SCROLL_DISPLAY_AREA scrolls the current contents of the display forward, backward, or sideways without writing to the display. To restrict the scrolling region to a portion of the display area, use the SMG$SET_DISPLAY_SCROLL_REGION routine.
Inserting and Overwriting Text
To insert text rather than overwrite the current contents of the screen, use the SMG$INSERT_LINE routine. Existing lines are shifted up or down to open space for the new text. If the text is longer than a single line, you can specify whether or not you want the excess characters to be truncated or wrapped.
In addition, you can use SMG$PUT_LINE_WIDE to write a line of text to the screen using double-width characters. You must allot two spaces for each double-width character on the line. You cannot mix single- and double-width characters on a line.
Specifying Special Video Attributes
All line routines provide rendition-set and
rendition-complement arguments, which allow you to
specify special video attributes for the text being written.
SMG$PUT_LINE_MULTI allows you to specify more than one video attribute
for the text. The explanation of the SMG$CHANGE_RENDITION routine in
Section 9.4.4.5 discusses how to use the rendition-set
and rendition-complement arguments.
9.4.6.4 Drawing Lines
The routine SMG$DRAW_LINE draws solid lines on the screen. Appropriate corner and crossing marks are drawn when lines join or intersect. The routine SMG$DRAW_CHARACTER draws a single character. You can also use the routine SMG$DRAW_RECTANGLE to draw a solid rectangle. Suppose that you want to draw an object such as that shown in Figure 9-5 in the statistics display area (an area of 10 rows by 55 columns).
Figure 9-5 Statistics Display
Example 9-9 shows how you can create a statistics display using SMG$DRAW_LINE and SMG$DRAW_RECTANGLE.
Example 9-9 Creating a Statistics Display |
---|
STATUS = SMG$CREATE_VIRTUAL_DISPLAY (10, 2 55, 2 STATS_VDID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Draw rectangle with upper left corner at row 1 column 1 ! and lower right corner at row 10 column 55 STATUS =SMG$DRAW_RECTANGLE (STATS_VDID, 2 1, 1, 2 10, 55) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Draw vertical lines at columns 11, 21, and 31 DO I = 11, 31, 10 STATUS = SMG$DRAW_LINE (STATS_VDID, 2 1, I, 2 10, I) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) END DO ! Draw horizontal line at row 3 STATUS = SMG$DRAW_LINE (STATS_VDID, 2 3, 1, 2 3, 55) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$PASTE_VIRTUAL_DISPLAY (STATS_VDID, 2 PBID, 2 3, 2 2) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) |
The following routines erase specified characters, leaving the rest of the screen intact:
The following routines perform delete operations. In a delete operation, characters following the deleted characters are shifted into the empty space.
The following example erases the remaining characters on the line whose line number is specified by LINE_NO, starting at the column specified by COLUMN_NO:
STATUS = SMG$ERASE_LINE (STATS_VDID, 2 LINE_NO, 2 COLUMN_NO) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) |
You can use SMG$ routines to set up menus to read user input. The type of menus you can create include the following:
Menus are associated with a virtual display, and only one menu can be used for each virtual display.
The menu routines include the following:
When you are using menus, no other output should be sent to the menu area; otherwise, unpredictable results may occur.
The default SMG$SELECT_FROM_MENU allows specific operations, such as
use of the arrow keys to move up and down the menu selections, keys to
make a menu selection, ability to select more than one item at a time,
ability to reselect an item already selected, and the key sequence to
invoke online help. By using the flags argument to
modify this operation, you have the option of disallowing reselection
of a menu item and of allowing any key pressed to select an item.
9.4.8 Reading Data
You can read text from a virtual display (SMG$READ_FROM_DISPLAY) or from a virtual keyboard (SMG$READ_STRING, SMG$READ_COMPOSED_LINE, or SMG$READ_KEYSTROKE). The three routines for virtual keyboard input are known as the SMG$ input routines. SMG$READ_FROM_DISPLAY is not a true input routine because it reads text from the virtual display rather than from a user.
The SMG$ input routines can be used alone or with the SMG$ output routines. This section assumes that you are using the input routines with the output routines. Section 9.5 describes how to use the input routines without the output routines.
When you use the SMG$ input routines with the SMG$ output routines,
always specify the optional vdid argument of the input
routine, which specifies the virtual display in which the input is to
occur. The specified virtual display must be pasted to the device
associated with the virtual keyboard that is specified as the first
argument of the input routine. The display must be pasted in column 1,
cannot be occluded, and cannot have any other display to its right;
input begins at the current cursor position, but the cursor must be in
column 1.
9.4.8.1 Reading from a Display
You can read the contents of the display using the routine SMG$READ_FROM_DISPLAY. By default, the read operation reads all of the characters from the current cursor position to the end of that line. The row argument of SMG$READ_FROM_DISPLAY allows you to choose the starting point of the read operation, that is, the contents of the specified row to the rightmost column in that row.
If the terminator-string argument is specified, SMG$READ_FROM_DISPLAY searches backward from the current cursor position and reads the line beginning at the first terminator encountered (or at the beginning of the line). A terminator is a character string. You must calculate the length of the character string read operation yourself.
The following example reads the current contents of the first line in the STATS_VDID display:
CHARACTER*4 STRING INTEGER*4 SIZE . . . STATUS = SMG$HOME_CURSOR (STATS_VDID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = SMG$READ_FROM_DISPLAY (STATS_VDID, 2 STRING) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) SIZE = 55 DO WHILE ((STRING (SIZE:SIZE) .EQ. ' ') .AND. 2 (SIZE .GT. 1)) SIZE = SIZE - 1 END DO |
The SMG$CREATE_VIRTUAL_KEYBOARD routine establishes a device for input operations; the default device is the user's terminal. The routine SMG$READ_STRING reads characters typed on the screen until the user types a terminator or until the maximum size (which defaults to 512 characters) is exceeded. (The terminator is usually a carriage return; see the routine description in the OpenVMS RTL Screen Management (SMG$) Manual for a complete list of terminators.) The current cursor location for the display determines where the read operation begins.
The operating system's terminal driver processes carriage returns differently than the SMG$ routines. Therefore, in order to scroll input accurately, you must keep track of your vertical position in the display area. Explicitly set the cursor position and scroll the display. If a read operation takes place on a row other than the last row of the display, advance the cursor to the beginning of the next row before the next operation. If a read operation takes place on the last row of the display, scroll the display with SMG$SCROLL_DISPLAY_AREA and then set the cursor to the beginning of the row. Modify the read operation with TRM$M_TM_NOTRMECHO to ensure that no extraneous scrolling occurs.
Example 9-10 reads input until Ctrl/Z is pressed.
Example 9-10 Reading Data from a Virtual Keyboard |
---|
. . . ! Read first record STATUS = SMG$HOME_CURSOR (VDID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$READ_STRING (KBID, 2 TEXT, 2 'Prompt: ', 2 4, 2 TRM$M_TM_TRMNOECHO,,, 2 TEXT_SIZE,, 2 VDID) ! Read remaining records until CTRL/Z DO WHILE (STATUS .NE. SMG$_EOF) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Process record . . . ! Set up screen for next read ! Display area contains four rows STATUS = SMG$RETURN_CURSOR_POS (VDID, ROW, COL) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) IF (ROW .EQ. 4) THEN STATUS = SMG$SCROLL_DISPLAY_AREA (VDID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$SET_CURSOR_ABS (VDID, 4, 1) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ELSE STATUS = SMG$SET_CURSOR_ABS (VDID,, 1) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$SET_CURSOR_REL (VDID, 1) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) END IF ! Read next record STATUS = SMG$READ_STRING (KBID, 2 TEXT, 2 'Prompt: ', 2 4, 2 TRM$M_TM_TRMNOECHO,,, 2 TEXT_SIZE,, 2 VDID) END DO |
Because you are controlling the scrolling, SMG$PUT_LINE and SMG$PUT_LINE_MULTI might not scroll as expected. When scrolling a mix of input and output, you can prevent problems by using SMG$PUT_CHARS. |
To read from the keypad in keypad mode (that is, pressing a keypad character to perform some special action rather than entering data), modify the read operation with TRM$M_TM_ESCAPE and TRM$M_TM_NOECHO. Examine the terminator to determine which key was pressed.
Example 9-11 moves the cursor on the screen in response to the user's pressing the keys surrounding the keypad 5 key. The keypad 8 key moves the cursor north (up); the keypad 9 key moves the cursor northeast; the keypad 6 key moves the cursor east (right); and so on. The SMG$SET_CURSOR_REL routine is called, instead of being invoked as a function, because you do not want to abort the program on an error. (The error attempts to move the cursor out of the display area and, if this error occurs, you do not want the cursor to move.) The read operation is also modified with TRM$M_TM_PURGE to prevent the user from getting ahead of the cursor.
See Section 9.4.8.1 for the guidelines for reading from the display.
Example 9-11 Reading Data from the Keypad |
---|
. . . INTEGER STATUS, 2 PBID, 2 ROWS, 2 COLUMNS, 2 VDID, ! Virtual display ID 2 KID, ! Keyboard ID 2 SMG$CREATE_PASTEBOARD, 2 SMG$CREATE_VIRTUAL_DISPLAY, 2 SMG$CREATE_VIRTUAL_KEYBOARD, 2 SMG$PASTE_VIRTUAL_DISPLAY, 2 SMG$HOME_CURSOR, 2 SMG$SET_CURSOR_REL, 2 SMG$READ_STRING, 2 SMG$ERASE_PASTEBOARD, 2 SMG$PUT_CHARS, 2 SMG$READ_FROM_DISPLAY CHARACTER*31 INPUT_STRING, 2 MENU_STRING INTEGER*2 TERMINATOR INTEGER*4 MODIFIERS INCLUDE '($SMGDEF)' INCLUDE '($TRMDEF)' ! Set up screen and keyboard STATUS = SMG$CREATE_PASTEBOARD (PBID, 2 'SYS$OUTPUT', 2 ROWS, 2 COLUMNS) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$CREATE_VIRTUAL_DISPLAY (ROWS, 2 COLUMNS, 2 VDID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$PUT_CHARS (VDID, 2 '__ MENU CHOICE ONE', 2 10,30) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$PUT_CHARS (VDID, 2 '__ MENU CHOICE TWO', 2 15,30) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (KID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$PASTE_VIRTUAL_DISPLAY (VDID, 2 PBID, 2 1, 2 1) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Put cursor in NW corner STATUS = SMG$HOME_CURSOR (VDID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Read character from keyboard MODIFIERS = TRM$M_TM_ESCAPE .OR. 2 TRM$M_TM_NOECHO .OR. 2 TRM$M_TM_PURGE STATUS = SMG$READ_STRING (KID, 2 INPUT_STRING, 2 , 2 6, 2 MODIFIERS, 2 , 2 , 2 , 2 TERMINATOR) DO WHILE ((STATUS) .AND. 2 (TERMINATOR .NE. SMG$K_TRM_CR)) ! Check status of last read IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! North IF (TERMINATOR .EQ. SMG$K_TRM_KP8) THEN CALL SMG$SET_CURSOR_REL (VDID, -1, 0) ! Northeast ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP9) THEN CALL SMG$SET_CURSOR_REL (VDID, -1, 1) ! Northwest ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP7) THEN CALL SMG$SET_CURSOR_REL (VDID, -1, -1) ! South ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP2) THEN CALL SMG$SET_CURSOR_REL (VDID, 1, 0) ! Southeast ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP3) THEN CALL SMG$SET_CURSOR_REL (VDID, 1, 1) ! Southwest ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP1) THEN CALL SMG$SET_CURSOR_REL (VDID, 1, -1) ! East ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP6) THEN CALL SMG$SET_CURSOR_REL (VDID, 0, 1) ! West ELSE IF (TERMINATOR .EQ. SMG$K_TRM_KP4) THEN CALL SMG$SET_CURSOR_REL (VDID, 0, -1) END IF ! Read another character STATUS = SMG$READ_STRING (KID, 2 INPUT_STRING, 2 , 2 6, 2 MODIFIERS, 2 , 2 , 2 , 2 TERMINATOR) END DO ! Read menu entry and process ! STATUS = SMG$READ_FROM_DISPLAY (VDID, 2 MENU_STRING) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) . . . ! Clear screen STATUS = SMG$ERASE_PASTEBOARD (PBID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) END |
The SMG$CREATE_KEY_TABLE routine creates a table that equates keys to character strings. When you read input using the routine SMG$READ_COMPOSED_LINE and the user presses a defined key, the corresponding character string in the table is substituted for the key. The SMG$ADD_KEY_DEF routine can be used to load the table. Composed input also permits the following:
Example 9-12 defines keypad keys 1 through 9 and permits the user to change state temporarily by pressing the PF1 key. Pressing the keypad 1 key is equivalent to typing 1000 and pressing the Return key. Pressing PF1 key and then the keypad 1 key is equivalent to typing 10000 and pressing the Return key.
Example 9-12 Redefining Keys |
---|
INTEGER*4 TABLEID . . . ! Create table for key definitions STATUS = SMG$CREATE_KEY_TABLE (TABLEID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Load table ! If user presses PF1, the state changes to BYTEN ! The BYTEN state is in effect only for the very next key STATUS = SMG$ADD_KEY_DEF (TABLEID, 2 'PF1', 2 ,,,'BYTEN') IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Pressing KP1 through Kp9 in the null state is like typing ! 1000 through 9000 and pressing return STATUS = SMG$ADD_KEY_DEF (TABLEID, 2 'KP1', 2 , 2 SMG$M_KEY_TERMINATE, 2 '1000') IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$ADD_KEY_DEF (TABLEID, 2 'KP2', 2 , 2 SMG$M_KEY_TERMINATE, 2 '2000') IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) . . . STATUS = SMG$ADD_KEY_DEF (TABLEID, 2 'KP9', 2 , 2 SMG$M_KEY_TERMINATE, 2 '9000') IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Pressing KP1 through KP9 in the BYTEN state is like ! typing 10000 through 90000 and pressing return STATUS = SMG$ADD_KEY_DEF (TABLEID, 2 'KP1', 2 'BYTEN', 2 SMG$M_KEY_TERMINATE, 2 '10000') IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SMG$ADD_KEY_DEF (TABLEID, 2 'KP2', 2 'BYTEN', 2 SMG$M_KEY_TERMINATE, 2 '20000') IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) . . . STATUS = SMG$ADD_KEY_DEF (TABLEID, 2 'KP9', 2 'BYTEN', 2 SMG$M_KEY_TERMINATE, 2 '90000') IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! End loading key definition table . . . ! Read input which substitutes key definitions where appropriate STATUS = SMG$READ_COMPOSED_LINE (KBID, 2 TABLEID, 2 STRING, 2 SIZE, 2 VDID) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) . . . |
Use the SMG$DELETE_KEY_DEF routine to delete a key definition; use the SMG$GET_KEY_DEF routine to examine a key definition. You can also load key definition tables with the SMG$DEFINE_KEY and SMG$LOAD_KEY_DEFS routines; use the DCL command DEFINE/KEY to specify input to these routines.
To use keypad keys 0 through 9, the keypad must be in application mode. For details, see SMG$SET_KEYPAD_MODE in the OpenVMS RTL Screen Management (SMG$) Manual.
Previous | Next | Contents | Index |
Copyright © Compaq Computer Corporation 1998. All rights reserved. Legal |
5841PRO_025.HTML
|