C******************************************************************************* SUBROUTINE CURSOR_EDIT (TTY_NAME, IOCHAN, ECHO, + POSITION_TABLE, NUM_FIELDS, ORIENTATION, + KEY_PRESSED, FIELD, STATUS) C******************************************************************************* C C PROGRAM TITLE: C C Move Cursor among Different Fields on Screen. C C PROJECT: C GENERAL ELECTRIC COMPANY, LANDSAT-D GROUND SEGMENT C C GROUP: C FACILITY - IGF C SUBSYSTEM - TIPS C PACKAGE ID - TAG C C PROGRAMMED BY: ALEX MEASDAY DATE: 16-JUN-1984 C C CREATION ENVIRONMENT: C COMPUTER SYSTEM: VAX 11/780 C OPERATING SYSTEM: VMS, VERSION 2.2 C C PURPOSE: C C Subroutine CURSOR_EDIT is a utility routine designed for use C in programs that require interactive screen editing. The calling C routine displays the screen of data and calls CURSOR_EDIT, passing C a table of field positions to the subroutine. CURSOR_EDIT uses C the table to position the cursor to various fields on the screen C under the direction of the user (via cursor control keys). C A non-cursor control key causes exit from the CURSOR_EDIT, which C returns the key to the calling routine. Example usage in a calling C routine might be as follows: C C field := first data field C DO WHILE key_pressed <> exit_key C Display screen C CALL CURSOR_EDIT (position_table, key_pressed, field) C IF key_pressed = change_key THEN C change data item located at field C ENDIF C ENDDO C C The movement of the cursor on the screen is governed by the C position table that is passed to CURSOR_EDIT. The table is C dimensioned as POSITION_TABLE(3,NUM_FIELDS). For field i, C POSITION_TABLE[1,i] is the row (1..24) on the screen of the data C field; POSITION_TABLE[2,i] is the column (1..132) on the screen C of the data field; and POSITION_TABLE[3,i] indicates (.TRUE. or C .FALSE.) whether this data field is the last one in its logical C column or row (all fields in a logical column need not have the C same physical screen column). C C The position table can be set up with two orientations, C "by row" and "by column". The "by row" orientation is useful in C situations where there is a variable amount of data; i.e., dumping C and editing a variable number of bytes from a file. The end of row C indications (POSITION_TABLE[3,i]) for 22 data items might be set C up as follows, where 0 (.FALSE.) indicates a data item and -1 C (.TRUE.) indicates a data item at the end of the logical row: C C 0 0 0 0 0 -1 C 0 0 0 0 0 -1 C 0 0 0 0 0 -1 C 0 0 0 -1 C C In "by row" editing, cursors left and right move to the previous C and succeeding entries, respectively, in the position table. C Cursors up and down move to the previous and succeeding logical C rows, respectively, in the position table. C C The "by column" orientation is useful in situations where C there is a fixed amount of data; i.e., editing a certain piece C of data for each of the 100 TM detectors. The end of column C indications (POSITION_TABLE[3,i]) for 23 data items might be C set up as follows, where 0 (.FALSE.) indicates a data item and C -1 (.TRUE.) indicates a data item at the end of the logical C column: C C 0 0 0 0 0 C 0 0 0 0 0 C 0 0 0 -1 0 C 0 0 -1 0 C -1 -1 0 C -1 C C In "by column" editing, cursors left and right move to the C previous and succeeding logical columns, respectively, in the C position table. Cursors up and down move to the previous and C succeeding entries, respectively, in the position table. C C C CALLING SEQUENCE: C [NAME] [ARG-TYP - I,I/O,O] [DESCRIPTION] C C TTY_NAME C*(*) I Terminal name (if it needs to be assigned). C C IOCHAN I*4 I/O I/O channel number; if zero, GET assigns the terminal. C C ECHO L I If true, then echo characters as they are typed. C If false, then don't echo characters as they are typed. C C POSITION_TABLE I*4 I Array of cursor positions (see Purpose above). C C NUM_FIELDS I*4 I Number of entries in the position table. C C ORIENTATION I*4 I Logical interpretation of position table, where C 0 = By column. C 1 = By row. C See Purpose above for "THE MEANING". C C KEY_PRESSED C*(*) O Most recent key pressed that caused exit from CURSOR_EDIT. C C FIELD I*4 O Index in the position table of the data field at which C the cursor was positioned upon exit from CURSOR_EDIT. C C STATUS I*4 O System status. C C C INPUTS/OUTPUTS: C NAME - NAMED COMMON, PARAMETER DESCRIPTION C GLOBAL COMMON, OR FILE NAME NAME C *************************** ********* *********** C C FILES - C C TTY_NAME IOCHAN Terminal to be read. C C C ERROR HANDLING: C C Errors assigning or reading the terminal cause a message to be C written to the user's terminal (SYS$OUTPUT) and an error status C to be returned to the calling program. C C ASSUMPTIONS AND RESTRICTIONS: C C See purpose above. C C******************************************************************************* IMPLICIT NONE C... Subroutine arguments. CHARACTER*(*) KEY_PRESSED, TTY_NAME INTEGER*4 FIELD, IOCHAN, NUM_FIELDS, ORIENTATION, STATUS INTEGER*4 POSITION_TABLE(3,NUM_FIELDS) LOGICAL ECHO C... Parameters and external definitions. INCLUDE 'ALEX$LIB:VTERM.INC' PARAMETER MAX_NUM_COLUMNS = 132 PARAMETER ROW = 1, COLUMN = 2, END_OF_COLUMN = 3, END_OF_ROW = 3 PARAMETER BY_COLUMN = 0, BY_ROW = 1 C... Local variables. CHARACTER*8 BUFFER INTEGER*4 I INTEGER*4 LAST_COLUMN, LOGICAL_COLUMN, NUM_LOGICAL_COLUMNS INTEGER*4 LAST_ROW, LOGICAL_ROW, NUM_LOGICAL_ROWS INTEGER*4 SCREEN_COLUMN, SCREEN_ROW INTEGER*4 START_OF(MAX_NUM_COLUMNS) STATUS = 1 C... Build the start-of-column/row table. START_OF[i] is the C index in the position table of the first data field in logical C column/row i. Also, determine the logical column/row into which C the initial cursor position falls. NUM_LOGICAL_COLUMNS = 1 START_OF(1) = 1 LOGICAL_COLUMN = 1 DO I = 1, NUM_FIELDS - 1 IF (POSITION_TABLE(END_OF_COLUMN,I)) THEN NUM_LOGICAL_COLUMNS = NUM_LOGICAL_COLUMNS + 1 START_OF(NUM_LOGICAL_COLUMNS) = I + 1 IF (FIELD .GT. I) LOGICAL_COLUMN = NUM_LOGICAL_COLUMNS ENDIF ENDDO LOGICAL_ROW = LOGICAL_COLUMN NUM_LOGICAL_ROWS = NUM_LOGICAL_COLUMNS C... Move the cursor around among the data fields until a C non-cursor control key is entered. LAST_ROW = POSITION_TABLE(ROW,FIELD) LAST_COLUMN = POSITION_TABLE(COLUMN,FIELD) KEY_PRESSED = CHAR(0) DO WHILE (((KEY_PRESSED .EQ. CURSOR_UP) .OR. + (KEY_PRESSED .EQ. CURSOR_DOWN) .OR. + (KEY_PRESSED .EQ. CURSOR_LEFT) .OR. + (KEY_PRESSED .EQ. CURSOR_RIGHT) .OR. + (KEY_PRESSED .EQ. CHAR(0))) .AND. STATUS) C... Position the cursor. SCREEN_ROW = POSITION_TABLE(ROW,FIELD) SCREEN_COLUMN = POSITION_TABLE(COLUMN,FIELD) CALL LIB$SET_CURSOR (SCREEN_ROW, SCREEN_COLUMN) C... Input a key from the user. CALL GET (TTY_NAME, IOCHAN, ECHO, KEY_PRESSED, 1, STATUS) IF (.NOT. STATUS) RETURN CALL STR$UPCASE (KEY_PRESSED, KEY_PRESSED) IF (KEY_PRESSED .EQ. ESC) THEN ! Escape sequence? BUFFER = KEY_PRESSED CALL GETFUNC (TTY_NAME, IOCHAN, ECHO, + BUFFER, 0, KEY_PRESSED, STATUS) IF (.NOT. STATUS) RETURN ! ... N O T E : Do not "upper-case" function key pseudo-characters. ... ENDIF C... Move cursor up. IF (KEY_PRESSED .EQ. CURSOR_UP) THEN IF (ORIENTATION .EQ. BY_COLUMN) THEN ! Move to the previous entry in the table. FIELD = MAX (FIELD - 1, 1) LAST_ROW = POSITION_TABLE(ROW,FIELD) IF (POSITION_TABLE(END_OF_COLUMN,FIELD)) THEN LOGICAL_COLUMN = MAX (LOGICAL_COLUMN - 1, 1) ENDIF ELSEIF (ORIENTATION .EQ. BY_ROW) THEN ! Move to the previous logical row. IF (LOGICAL_ROW .GT. 1) THEN LOGICAL_ROW = LOGICAL_ROW - 1 FIELD = START_OF(LOGICAL_ROW) DO WHILE ! Preserve logical columns over shorter rows. + ((POSITION_TABLE(COLUMN,FIELD) .LT. LAST_COLUMN) + .AND. + (.NOT. POSITION_TABLE(END_OF_ROW,FIELD))) FIELD = FIELD + 1 ENDDO ELSE FIELD = 1 LAST_COLUMN = POSITION_TABLE(COLUMN,FIELD) ENDIF ENDIF C... Move cursor down. ELSEIF (KEY_PRESSED .EQ. CURSOR_DOWN) THEN IF (ORIENTATION .EQ. BY_COLUMN) THEN ! Move to the succeeding entry in the table. IF (POSITION_TABLE(END_OF_COLUMN,FIELD)) THEN LOGICAL_COLUMN = MIN (LOGICAL_COLUMN + 1, + NUM_LOGICAL_COLUMNS) ENDIF FIELD = MIN (FIELD + 1, NUM_FIELDS) LAST_ROW = POSITION_TABLE(ROW,FIELD) ELSEIF (ORIENTATION .EQ. BY_ROW) THEN ! Move to the succeeding logical row. IF (LOGICAL_ROW .LT. NUM_LOGICAL_ROWS) THEN LOGICAL_ROW = LOGICAL_ROW + 1 FIELD = START_OF(LOGICAL_ROW) DO WHILE ! Preserve logical columns over shorter rows. + ((POSITION_TABLE(COLUMN,FIELD) .LT. LAST_COLUMN) + .AND. + (.NOT. POSITION_TABLE(END_OF_ROW,FIELD))) FIELD = FIELD + 1 ENDDO ELSE FIELD = NUM_FIELDS LAST_COLUMN = POSITION_TABLE(COLUMN,FIELD) ENDIF ENDIF C... Move cursor left. ELSEIF (KEY_PRESSED .EQ. CURSOR_LEFT) THEN IF (ORIENTATION .EQ. BY_COLUMN) THEN ! Move to the previous logical column. IF (LOGICAL_COLUMN .GT. 1) THEN LOGICAL_COLUMN = LOGICAL_COLUMN - 1 FIELD = START_OF(LOGICAL_COLUMN) DO WHILE ! Preserve logical rows over shorter columns. + ((POSITION_TABLE(ROW,FIELD) .LT. LAST_ROW) + .AND. + (.NOT. POSITION_TABLE(END_OF_COLUMN,FIELD))) FIELD = FIELD + 1 ENDDO ELSE FIELD = 1 LAST_ROW = POSITION_TABLE(ROW,FIELD) ENDIF ELSEIF (ORIENTATION .EQ. BY_ROW) THEN ! Move to the previous entry in the table. FIELD = MAX (FIELD - 1, 1) LAST_COLUMN = POSITION_TABLE(COLUMN,FIELD) IF (POSITION_TABLE(END_OF_ROW,FIELD)) THEN LOGICAL_ROW = MAX (LOGICAL_ROW - 1, 1) ENDIF ENDIF C... Move cursor right. ELSEIF (KEY_PRESSED .EQ. CURSOR_RIGHT) THEN IF (ORIENTATION .EQ. BY_COLUMN) THEN ! Move to the succeeding logical column. IF (LOGICAL_COLUMN .LT. NUM_LOGICAL_COLUMNS) THEN LOGICAL_COLUMN = LOGICAL_COLUMN + 1 FIELD = START_OF(LOGICAL_COLUMN) DO WHILE ! Preserve logical rows over shorter columns. + ((POSITION_TABLE(ROW,FIELD) .LT. LAST_ROW) + .AND. + (.NOT. POSITION_TABLE(END_OF_COLUMN,FIELD))) FIELD = FIELD + 1 ENDDO ELSE FIELD = NUM_FIELDS LAST_ROW = POSITION_TABLE(ROW,FIELD) ENDIF ELSEIF (ORIENTATION .EQ. BY_ROW) THEN ! Move to the succeeding entry in the table. IF (POSITION_TABLE(END_OF_ROW,FIELD)) THEN LOGICAL_ROW = MIN (LOGICAL_ROW + 1, + NUM_LOGICAL_ROWS) ENDIF FIELD = MIN (FIELD + 1, NUM_FIELDS) LAST_COLUMN = POSITION_TABLE(COLUMN,FIELD) ENDIF ENDIF ENDDO ! Until non-cursor control character entered. RETURN END