/* VMSVT.C * * Advanced VMS terminal driver * * Knows about any terminal defined in SMGTERMS.TXT and TERMTABLE.TXT * located in SYS$SYSTEM. * * Author: Curtis Smith * modified by Petri Kutvonen */ #include /* Standard I/O package */ #include "estruct.h" /* Emacs' structures */ #include "edef.h" /* Emacs' definitions */ #if VMSVT #include /* Descriptor definitions */ /* These would normally come from iodef.h and ttdef.h */ #define IO$_SENSEMODE 0x27 /* Sense mode of terminal */ #define TT$_UNKNOWN 0x00 /* Unknown terminal */ #define TT$_VT100 96 /** Forward references **/ int vmsopen(), ttclose(), vmskopen(), vmskclose(), ttgetc(), ttputc(); int ttflush(), vmsmove(), vmseeol(), vmseeop(), vmsbeep(), vmsrev(); int vmscres(); extern int eolexist, revexist; extern char sres[]; #if COLOR int vmsfcol(), vmsbcol(); #endif /** SMG stuff **/ static char *begin_reverse, *end_reverse, *erase_to_end_line; static char *erase_whole_display; static int termtype; #define SMG$K_BEGIN_REVERSE 0x1bf #define SMG$K_END_REVERSE 0x1d6 #define SMG$K_SET_CURSOR_ABS 0x23a #define SMG$K_ERASE_WHOLE_DISPLAY 0x1da #define SMG$K_ERASE_TO_END_LINE 0x1d9 #if SCROLLCODE #define SMG$K_SCROLL_FORWARD 561 /* from sys$library:smgtrmptr.h */ #define SMG$K_SCROLL_REVERSE 562 #define SMG$K_SET_SCROLL_REGION 572 static char *scroll_forward, *scroll_reverse; #endif /* Dispatch table. All hard fields just point into the terminal I/O code. */ struct terminal term = { #if PKCODE MAXROW, #else 24 - 1, /* Max number of rows allowable */ #endif /* Filled in */ -1, /* Current number of rows used */ MAXCOL, /* Max number of columns */ /* Filled in */ 0, /* Current number of columns */ 64, /* Min margin for extended lines */ 8, /* Size of scroll region */ 100, /* # times thru update to pause */ vmsopen, /* Open terminal at the start */ ttclose, /* Close terminal at end */ vmskopen, /* Open keyboard */ vmskclose, /* Close keyboard */ ttgetc, /* Get character from keyboard */ ttputc, /* Put character to display */ ttflush, /* Flush output buffers */ vmsmove, /* Move cursor, origin 0 */ vmseeol, /* Erase to end of line */ vmseeop, /* Erase to end of page */ vmsbeep, /* Beep */ vmsrev, /* Set reverse video state */ vmscres /* Change screen resolution */ #if COLOR , vmsfcol, /* Set forground color */ vmsbcol /* Set background color */ #endif #if SCROLLCODE , NULL #endif }; /*** * ttputs - Send a string to ttputc * * Nothing returned ***/ ttputs(string) char *string; /* String to write */ { if (string) while (*string != '\0') ttputc(*string++); } /*** * vmsmove - Move the cursor (0 origin) * * Nothing returned ***/ vmsmove(row, col) int row; /* Row position */ int col; /* Column position */ { char buffer[32]; int ret_length; static int request_code = SMG$K_SET_CURSOR_ABS; static int max_buffer_length = sizeof(buffer); static int arg_list[3] = { 2 }; char *cp; int i; /* Set the arguments into the arg_list array * SMG assumes the row/column positions are 1 based (boo!) */ arg_list[1] = row + 1; arg_list[2] = col + 1; if ((smg$get_term_data( /* Get terminal data */ &termtype, /* Terminal table address */ &request_code, /* Request code */ &max_buffer_length, /* Maximum buffer length */ &ret_length, /* Return length */ buffer, /* Capability data buffer */ arg_list) /* Argument list array */ /* We'll know soon enough if this doesn't work */ &1) == 0) { ttputs("OOPS"); return; } /* Send out resulting sequence */ i = ret_length; cp = buffer; while (i-- > 0) ttputc(*cp++); } #if SCROLLCODE vmsscroll_reg(from, to, howmany) { int i; if (to == from) return; if (to < from) { vmsscrollregion(to, from + howmany - 1); vmsmove(from + howmany - 1, 0); for (i = from - to; i > 0; i--) ttputs(scroll_forward); } else { /* from < to */ vmsscrollregion(from, to + howmany - 1); vmsmove(from, 0); for (i = to - from; i > 0; i--) ttputs(scroll_reverse); } vmsscrollregion(-1, -1); } vmsscrollregion(top, bot) int top; /* Top position */ int bot; /* Bottom position */ { char buffer[32]; int ret_length; static int request_code = SMG$K_SET_SCROLL_REGION; static int max_buffer_length = sizeof(buffer); static int arg_list[3] = { 2 }; char *cp; int i; /* Set the arguments into the arg_list array * SMG assumes the row/column positions are 1 based (boo!) */ arg_list[1] = top + 1; arg_list[2] = bot + 1; if ((smg$get_term_data( /* Get terminal data */ &termtype, /* Terminal table address */ &request_code, /* Request code */ &max_buffer_length, /* Maximum buffer length */ &ret_length, /* Return length */ buffer, /* Capability data buffer */ arg_list) /* Argument list array */ /* We'll know soon enough if this doesn't work */ &1) == 0) { ttputs("OOPS"); return; } ttputc(0); /* Send out resulting sequence */ i = ret_length; cp = buffer; while (i-- > 0) ttputc(*cp++); } #endif /*** * vmsrev - Set the reverse video status * * Nothing returned ***/ vmsrev(status) int status; /* TRUE if setting reverse */ { if (status) ttputs(begin_reverse); else ttputs(end_reverse); } /*** * vmscres - Change screen resolution (which it doesn't) * * Nothing returned ***/ vmscres() { /* But it could. For vt100/vt200s, one could switch from 80 and 132 columns modes */ } #if COLOR /*** * vmsfcol - Set the forground color (not implimented) * * Nothing returned ***/ vmsfcol() { } /*** * vmsbcol - Set the background color (not implimented) * * Nothing returned ***/ vmsbcol() { } #endif /*** * vmseeol - Erase to end of line * * Nothing returned ***/ vmseeol() { ttputs(erase_to_end_line); } /*** * vmseeop - Erase to end of page (clear screen) * * Nothing returned ***/ vmseeop() { ttputs(erase_whole_display); } /*** * vmsbeep - Ring the bell * * Nothing returned ***/ vmsbeep() { ttputc('\007'); } /*** * vmsgetstr - Get an SMG string capability by name * * Returns: Escape sequence * NULL No escape sequence available ***/ char *vmsgetstr(request_code) int request_code; /* Request code */ { char *result; static char seq_storage[1024]; static char *buffer = seq_storage; static int arg_list[2] = { 1, 1 }; int max_buffer_length, ret_length; /* Precompute buffer length */ max_buffer_length = (seq_storage + sizeof(seq_storage)) - buffer; /* Get terminal commands sequence from master table */ if ((smg$get_term_data( /* Get terminal data */ &termtype, /* Terminal table address */ &request_code, /* Request code */ &max_buffer_length, /* Maximum buffer length */ &ret_length, /* Return length */ buffer, /* Capability data buffer */ arg_list) /* Argument list array */ /* If this doesn't work, try again with no arguments */ &1) == 0 && (smg$get_term_data( /* Get terminal data */ &termtype, /* Terminal table address */ &request_code, /* Request code */ &max_buffer_length, /* Maximum buffer length */ &ret_length, /* Return length */ buffer) /* Capability data buffer */ /* Return NULL pointer if capability is not available */ &1) == 0) return NULL; /* Check for empty result */ if (ret_length == 0) return NULL; /* Save current position so we can return it to caller */ result = buffer; /* NIL terminate the sequence for return */ buffer[ret_length] = 0; /* Advance buffer */ buffer += ret_length + 1; /* Return capability to user */ return result; } /** I/O information block definitions **/ struct iosb { /* I/O status block */ short i_cond; /* Condition value */ short i_xfer; /* Transfer count */ long i_info; /* Device information */ }; struct termchar { /* Terminal characteristics */ char t_class; /* Terminal class */ char t_type; /* Terminal type */ short t_width; /* Terminal width in characters */ long t_mandl; /* Terminal's mode and length */ long t_extend; /* Extended terminal characteristics */ }; static struct termchar tc; /* Terminal characteristics */ /*** * vmsgtty - Get terminal type from system control block * * Nothing returned ***/ vmsgtty() { short fd; int status; struct iosb iostatus; $DESCRIPTOR(devnam, "SYS$INPUT"); /* Assign input to a channel */ status = sys$assign(&devnam, &fd, 0, 0); if ((status & 1) == 0) exit(status); /* Get terminal characteristics */ status = sys$qiow( /* Queue and wait */ 0, /* Wait on event flag zero */ fd, /* Channel to input terminal */ IO$_SENSEMODE, /* Get current characteristic */ &iostatus, /* Status after operation */ 0, 0, /* No AST service */ &tc, /* Terminal characteristics buf */ sizeof(tc), /* Size of the buffer */ 0, 0, 0, 0); /* P3-P6 unused */ /* De-assign the input device */ if ((sys$dassgn(fd) & 1) == 0) exit(status); /* Jump out if bad status */ if ((status & 1) == 0) exit(status); if ((iostatus.i_cond & 1) == 0) exit(iostatus.i_cond); } /*** * vmsopen - Get terminal type and open terminal * * Nothing returned ***/ vmsopen() { /* Get terminal type */ vmsgtty(); if (tc.t_type == TT$_UNKNOWN) { printf("Terminal type is unknown!\n"); printf ("Try set your terminal type with SET TERMINAL/INQUIRE\n"); printf("Or get help on SET TERMINAL/DEVICE_TYPE\n"); exit(3); } /* Access the system terminal definition table for the */ /* information of the terminal type returned by IO$_SENSEMODE */ if ((smg$init_term_table_by_type(&tc.t_type, &termtype) & 1) == 0) return -1; /* Set sizes */ term.t_nrow = ((unsigned int) tc.t_mandl >> 24) - 1; term.t_ncol = tc.t_width; /* Get some capabilities */ begin_reverse = vmsgetstr(SMG$K_BEGIN_REVERSE); end_reverse = vmsgetstr(SMG$K_END_REVERSE); revexist = begin_reverse != NULL && end_reverse != NULL; erase_to_end_line = vmsgetstr(SMG$K_ERASE_TO_END_LINE); eolexist = erase_to_end_line != NULL; erase_whole_display = vmsgetstr(SMG$K_ERASE_WHOLE_DISPLAY); #if SCROLLCODE scroll_forward = vmsgetstr(SMG$K_SCROLL_FORWARD); scroll_reverse = vmsgetstr(SMG$K_SCROLL_REVERSE); if (tc.t_type < TT$_VT100 || scroll_reverse == NULL || scroll_forward == NULL) term.t_scroll = NULL; else term.t_scroll = vmsscroll_reg; #endif /* Set resolution */ strcpy(sres, "NORMAL"); /* Open terminal I/O drivers */ ttopen(); } /*** * vmskopen - Open keyboard (not used) * * Nothing returned ***/ vmskopen() { } /*** * vmskclose - Close keyboard (not used) * * Nothing returned ***/ vmskclose() { } #endif