Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

OpenVMS Programming Concepts Manual


Previous Contents Index

9.4.9 Controlling Screen Updates

If your program needs to make a number of changes to a virtual display, you can use SMG$ routines to make all of the changes before updating the display. The SMG$BEGIN_DISPLAY_UPDATE routine causes output operations to a pasted display to be reflected only in the display's buffers. The SMG$END_DISPLAY_UPDATE routine writes the display's buffer to the pasteboard.

The SMG$BEGIN_DISPLAY_UPDATE and SMG$END_DISPLAY_UPDATE routines increment and decrement a counter. When this counter's value is 0, output to the virtual display is sent to the pasteboard immediately. The counter mechanism allows a subroutine to request and turn off batching without disturbing the batching state of the calling program.

A second set of routines, SMG$BEGIN_PASTEBOARD_UPDATE and SMG$END_PASTEBOARD_UPDATE, allow you to buffer output to a pasteboard in a similar manner.

9.4.10 Maintaining Modularity

When using the SMG$ routines, you must take care not to corrupt the mapping between the screen appearance and the internal representation of the screen. Therefore, observe the following guidelines:

9.5 Performing Special Input/Output Actions

Screen management input routines and the SYS$QIO and SYS$QIOW system services allow you to perform I/O operations otherwise unavailable to high-level languages. For example, you can allow a user to interrupt normal program execution by typing a character and by providing a mechanism for reading that character. You can also control such things as echoing, time allowed for input, and whether data is read from the type-ahead buffer.

Some of the operations described in the following sections require the use of the SYS$QIO or SYS$QIOW system services. For more information about the QIO system services, see the OpenVMS System Services Reference Manual and Chapter 11.

Other operations, described in the following sections, can be performed by calling the SMG$ input routines. The SMG$ input routines can be used alone or with the SMG$ output routines. Section 9.4 describes how to use the input routines with the output routines. This section assumes that you are using the input routines alone. To use the SMG$ input routines, do the following:

  1. Call SMG$CREATE_VIRTUAL_KEYBOARD to associate a logical keyboard with a device or file specification (SYS$INPUT by default). SMG$CREATE_VIRTUAL_KEYBOARD returns a keyboard identification number; use that number to identify the device or file to the SMG$ input routines.
  2. Call an SMG$ input routine (SMG$READ_STRING or SMG$READ_COMPOSED_LINE) to read data typed at the device associated with the virtual keyboard.

When using the SMG$ input routines without the SMG$ output routines, do not specify the optional VDID argument of the input routine.

9.5.1 Using Ctrl/C and Ctrl/Y Interrupts

The QIO system services enable you to detect a Ctrl/C or Ctrl/Y interrupt at a user terminal, even if you have not issued a read to the terminal. To do so, you must take the following steps:

  1. Queue an asynchronous system trap (AST)---Issue the SYS$QIO or SYS$QIOW system service with a function code of IO$_SETMODE modified by either IO$M_CTRLCAST (for Ctrl/C interrupts) or IO$M_CTRLYAST (for Ctrl/Y interrupts). For the P1 argument, provide the name of a subroutine to be executed when the interrupt occurs. For the P2 argument, you can optionally identify one longword argument to pass to the AST subroutine.
  2. Write an AST subroutine---Write the subroutine identified in the P1 argument of the QIO system service and link the subroutine into your program. Your subroutine can take one longword dummy argument to be associated with the P2 argument in the QIO system service. You must define common areas to access any other data in your program from the AST routine.

If you press Ctrl/C or Ctrl/Y after your program queues the appropriate AST, the system interrupts your program and transfers control to your AST subroutine (this action is called delivering the AST). After your AST subroutine executes, the system returns control to your program at the point of interruption (unless your AST subroutine causes the program to exit, or unless another AST has been queued). Note the following guidelines for using Ctrl/C and Ctrl/Y ASTs:

Example 9-13 permits the terminal user to interrupt a display to see how many lines have been typed up to that point.

Example 9-13 Using Interrupts to Perform I/O

!Main Program 
   .
   .
   .
INTEGER STATUS 
! Accumulated data records 
CHARACTER*132 STORAGE (255) 
INTEGER*4     STORAGE_SIZE (255), 
2             STORAGE_COUNT 
! QIOW and QIO structures 
INTEGER*2 INPUT_CHAN 
INTEGER*4 CODE 
STRUCTURE /IOSTAT_BLOCK/ 
  INTEGER*2 IOSTAT 
  BYTE      TRANSMIT, 
2           RECEIVE, 
2           CRFILL, 
2           LFFILL, 
2           PARITY, 
2           ZERO 
END STRUCTURE 
RECORD /IOSTAT_BLOCK/ IOSB 
! Flag to notify program of CTRL/C interrupt 
LOGICAL*4 CTRLC_CALLED 
! AST subroutine to handle CTRL/C interrupt 
EXTERNAL CTRLC_AST 
! Subroutines 
INTEGER SYS$ASSIGN, 
2       SYS$QIOW 
! Symbols used for I/O operations 
INCLUDE '($IODEF)' 
! Put values into array 
CALL LOAD_STORAGE (STORAGE, 
2                  STORAGE_SIZE, 
2                  STORAGE_COUNT) 
! Assign channel and set up QIOW structures 
STATUS = SYS$ASSIGN ('SYS$INPUT', 
2                    INPUT_CHAN,,) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
CODE = IO$_SETMODE .OR. IO$M_CTRLCAST 
! Queue an AST to handle CTRL/C interrupt 
STATUS = SYS$QIOW (, 
2                  %VAL (INPUT_CHAN), 
2                  %VAL (CODE), 
2                  IOSB, 
2                  ,, 
2                  CTRLC_AST,    ! Name of AST routine 
2                  CTRLC_CALLED, ! Argument for AST routine 
2                  ,,,) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
IF (.NOT. IOSB.IOSTAT) 
2  CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT)) 
! Display STORAGE array, one element per line 
DO I = 1, STORAGE_COUNT 
  TYPE *, STORAGE (I) (1:STORAGE_SIZE (I)) 
 
  ! Additional actions if user types CTRL/C 
  IF (CTRLC_CALLED) THEN 
    CTRLC_CALLED = .FALSE. 
    ! Show user number of lines displayed so far 
    TYPE *, 'Number of lines: ', I 
    ! Requeue AST 
    STATUS = SYS$QIOW (, 
2                      %VAL (INPUT_CHAN), 
2                      %VAL (CODE), 
2                      IOSB, 
2                      ,, 
2                      CTRLC_AST, 
2                      CTRLC_CALLED, 
2                      ,,,) 
    IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
    IF (.NOT. IOSB.IOSTAT) 
2      CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT)) 
  END IF 
END DO 
 
END 

AST Routine

! AST routine 
! Notifies program that user typed CTRL/C 
SUBROUTINE CTRLC_AST (CTRLC_CALLED) 
LOGICAL*4 CTRLC_CALLED 
CTRLC_CALLED = .TRUE. 
 
END 

9.5.2 Detecting Unsolicited Input

You can detect input from the terminal even if you have not called SMG$READ_COMPOSED_LINE or SMG$READ_STRING by using SMG$ENABLE_UNSOLICITED_INPUT. This routine uses the AST mechanism to transfer control to a subprogram of your choice each time the user types at the terminal; the AST subprogram is responsible for reading any input. When the subprogram completes, control returns to the point in your mainline code where it was interrupted.

The SMG$ENABLE_UNSOLICITED_INPUT routine is not an SMG$ input routine. Before invoking SMG$ENABLE_UNSOLICITED_INPUT, you must invoke SMG$CREATE_PASTEBOARD to associate a pasteboard with the terminal and SMG$CREATE_VIRTUAL_KEYBOARD to associate a virtual keyboard with the same terminal.

SMG$ENABLE_UNSOLICITED_INPUT accepts the following arguments:

When SMG$ENABLE_UNSOLICITED_INPUT invokes the AST subprogram, it passes two arguments to the subprogram: the pasteboard identification number and the argument that you specified. Typically, you write the AST subprogram to read the unsolicited input with SMG$READ_STRING. Since SMG$READ_STRING requires that you specify the virtual keyboard at which the input was typed, specify the virtual keyboard identification number as the second argument to pass to the AST subprogram.

Example 9-14 permits the terminal user to interrupt the display of a series of arrays, and either to go on to the next array (by typing input beginning with an uppercase N) or to exit from the program (by typing input beginning with anything else).

Example 9-14 Receiving Unsolicited Input from a Virtual Keyboard

! Main Program 
! The main program calls DISPLAY_ARRAY once for each array. 
! DISPLAY_ARRAY displays the array in a DO loop. 
! If the user enters input from the terminal, the loop is 
! interrupted and the AST routine takes over. 
! If the user types anything beginning with an N, the AST 
! sets DO_NEXT and resumes execution -- DISPLAY_ARRAY drops 
! out of the loop processing the array (because DO_NEXT is 
! set -- and the main program calls DISPLAY_ARRAY for the 
! next array. 
! If the user types anything not beginning with an N, 
! the program exits. 
   .
   .
   .
INTEGER*4 STATUS, 
2         VKID,  ! Virtual keyboard ID 
2         PBID   ! Pasteboard ID 
! Storage arrays 
INTEGER*4 ARRAY1 (256), 
2         ARRAY2 (256), 
2         ARRAY3 (256) 
! System routines 
INTEGER*4 SMG$CREATE_PASTEBOARD, 
2         SMG$CREATE_VIRTUAL_KEYBOARD, 
2         SMG$ENABLE_UNSOLICITED_INPUT 
! AST routine 
EXTERNAL  AST_ROUTINE 
! Create a pasteboard 
STATUS = SMG$CREATE_PASTEBOARD (PBID,        ! Pasteboard ID 
2                               'SYS$INPUT') 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
! Create a keyboard for the same device 
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID,  ! Keyboard ID 
2                                     'SYS$INPUT') 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
! Enable unsolicited input 
STATUS = SMG$ENABLE_UNSOLICITED_INPUT (PBID, ! Pasteboard ID 
2                                      AST_ROUTINE, 
2                                      VKID) ! Pass keyboard 
                                             ! ID to AST 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
   .
   .
   .
! Call display subroutine once for each array 
CALL DISPLAY_ARRAY (ARRAY1) 
CALL DISPLAY_ARRAY (ARRAY2) 
CALL DISPLAY_ARRAY (ARRAY3) 
 
END 

Array Display Routine

! Subroutine to display one array 
SUBROUTINE DISPLAY_ARRAY (ARRAY) 
! Dummy argument 
INTEGER*4 ARRAY (256) 
! Status 
INTEGER*4 STATUS 
! Flag for doing next array 
LOGICAL*4 DO_NEXT 
COMMON /DO_NEXT/ DO_NEXT 
! If AST has been delivered, reset 
IF (DO_NEXT) DO_NEXT = .FALSE. 
! Initialize control variable 
I = 1 
! Display entire array unless interrupted by user 
! If interrupted by user (DO_NEXT is set), drop out of loop 
DO WHILE ((I .LE. 256) .AND. (.NOT. DO_NEXT)) 
  TYPE *, ARRAY (I) 
  I = I + 1 
END DO 
 
END 

AST Routine

! Subroutine to read unsolicited input 
SUBROUTINE AST_ROUTINE (PBID, 
2                       VKID) 
! dummy arguments 
INTEGER*4 PBID,                  ! Pasteboard ID 
2         VKID                   ! Keyboard ID 
! Status 
INTEGER*4 STATUS 
! Flag for doing next array 
LOGICAL*4 DO_NEXT 
COMMON /DO_NEXT/ DO_NEXT 
! Input string 
CHARACTER*4 INPUT 
! Routines 
INTEGER*4 SMG$READ_STRING 
! Read input 
STATUS = SMG$READ_STRING (VKID,  ! Keyboard ID 
2                         INPUT) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
! If user types anything beginning with N, set DO_NEXT 
! otherwise, exit from program 
IF (INPUT (1:1) .EQ. 'N') THEN 
  DO_NEXT = .TRUE. 
ELSE 
  CALL EXIT 
END IF 
 
END 

9.5.3 Using the Type-Ahead Buffer

Normally, if the user types at the terminal before your application is able to read from that device, the input is saved in a special data structure maintained by the system called the type-ahead buffer. When your application is ready to read from the terminal, the input is transferred from the type-ahead buffer to your input buffer. The type-ahead buffer is preset at a size of 78 bytes. If the HOSTSYNC characteristic is on (the usual condition), input to the type-ahead buffer is stopped (the keyboard locks) when the buffer is within 8 bytes of being full. If the HOSTSYNC characteristic is off, the bell rings when the type-ahead buffer is within 8 bytes of being full; if you overflow the buffer, the excess data is lost. The TTY_ALTALARM system parameter determines the point at which either input is stopped or the bell rings.

You can clear the type-ahead buffer by reading from the terminal with SMG$READ_STRING and by specifying TRM$M_TM_PURGE in the modifiers argument. Clearing the type-ahead buffer has the effect of reading only what the user types on the terminal after the read operation is invoked. Any characters in the type-ahead buffer are lost. The following example illustrates how to purge the type-ahead buffer:


INTEGER*4     SMG$CREATE_VIRTUAL_KEYBOARD, 
2             SMG$READ_STRING, 
2             STATUS, 
2             VKID,      ! Virtual keyboard ID 
2             INPUT_SIZE 
CHARACTER*512 INPUT 
INCLUDE       '($TRMDEF)' 
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID, 
2                                     'SYS$INPUT') ! I/O device 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
STATUS = SMG$READ_STRING (VKID,     ! Keyboard ID 
2                         INPUT,    ! Data read 
2                         'Prompt> ', 
2                         512, 
2                         TRM$M_TM_PURGE, 
2                         ,, 
2                         INPUT_SIZE) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 

You can also clear the type-ahead buffer with a QIO read operation modified by IO$M_PURGE (defined in $IODEF). You can turn off the type-ahead buffer for further read operations with a QIO set mode operation that specifies TT$M_NOTYPEAHD as a basic terminal characteristic.

You can examine the type-ahead buffer by issuing a QIO sense mode operation modified by IO$M_TYPEAHDCNT. The number of characters in the type-ahead buffer and the value of the first character are returned to the P1 argument.

The size of the type-ahead buffer is determined by the TTY_TYPAHDSZ system parameter. You can specify an alternative type-ahead buffer by turning on the ALTYPEAHD terminal characteristic; the size of the alternative type-ahead buffer is determined by the TTY_ALTYPAHD system parameter.

9.5.4 Using Echo

Normally, the system writes back to the terminal any printable characters that the user types at that terminal. The system also writes highlighted words in response to certain control characters; for example, the system writes EXIT if the user enters Ctrl/Z. If the user types ahead of your read, the characters are not echoed until you read them from the type-ahead buffer.

You can turn off echoing when you invoke a read operation by reading from the terminal with SMG$READ_STRING and by specifying TRM$M_TM_NOECHO in the modifiers argument. You can turn off echoing for control characters only by modifying the read operation with TRM$M_TM_TRMNOECHO. The following example turns off all echoing for the read operation:


INTEGER*4     SMG$CREATE_VIRTUAL_KEYBOARD, 
2             SMG$READ_STRING, 
2             STATUS, 
2             VKID,       ! Virtual keyboard ID 
2             INPUT_SIZE 
CHARACTER*512 INPUT 
INCLUDE       '($TRMDEF)' 
STATUS = SMG$CREATE_VIRTUAL_KEYBOARD (VKID,        ! Keyboard ID 
2                                     'SYS$INPUT') ! I/O device 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 
STATUS = SMG$READ_STRING (VKID,        ! Keyboard ID 
2                         INPUT,       ! Data read 
2                         'Prompt> ', 
2                         512, 
2                         TRM$M_TM_NOECHO, 
2                         ,, 
2                         INPUT_SIZE) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) 

You can also turn off echoing with a QIO read operation modified by IO$M_NOECHO (defined in $IODEF). You can turn off echoing for further read operations with a QIO set mode operation that specifies TT$M_NOECHO as a basic terminal characteristic.


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
5841PRO_026.HTML