mirror of
https://github.com/rfivet/uemacs.git
synced 2024-12-24 18:16:35 -05:00
489 lines
11 KiB
C
489 lines
11 KiB
C
/* 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 <stdio.h> /* Standard I/O package */
|
|
#include "estruct.h" /* Emacs' structures */
|
|
|
|
#if VMSVT
|
|
|
|
#include <descrip.h> /* 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
|