/*
Copyright (C) Magna Carta Software, Inc. 1990. All Rights Reserved
ALTOS3.C -- Altos III terminal emulation routines.
*/
#include <comm.h>
#include <ctype.h>
#if defined(__TURBOC__)
#include <mem.h>
#elif defined(MSC) || defined(__WATCOMC__) || defined(__POWERC)
#include <string.h>
#endif
#include <vt.h>
#include <ansi.h>
#include <biosvid.h>
#include <colors.h>
#include <terminal.h>
#include <altos3.h>
WORD pf[MAX_FUNC_KEYS] = {F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
ALT_F1, ALT_F2, ALT_F3, ALT_F4};
WORD shift_pf[] = {SF1, SF2, SF3, SF4, SF5, SF6, SF7, SF8, SF9, SF10, SF11, SF12,
CTRL_F1, CTRL_F2, CTRL_F3, CTRL_F4};
WORD pad[MAX_PAD_KEYS] = {',', '-', KPERIOD, 0XFF, K0, K1, K2, K3, K4, K5, K6, K7, K8, K9};
WORD arrow[MAX_ARROW_KEYS] = {GREY_UP_ARROW, GREY_DOWN_ARROW, GREY_RIGHT_ARROW, GREY_LEFT_ARROW};
WORD shift_arrow[4] = {SUP_ARROW, SDOWN_ARROW, SRIGHT_ARROW, SLEFT_ARROW};
TERMKEYS tk_altos3 = {
HOME, /* "HOME" key */
0, /* "HELP" key (e.g. ALTOS III) */
KENTER, /* "enter" key */
TAB, /* horizontal tab */
ENTER, /* vertical tab */
PAGE_UP, /* key to page to prev screen */
PAGE_DOWN, /* key to page to next screen */
16, /* number of function keys on terminal */
pf, /* programmable function keys */
shift_pf, /* shifted programmable function keys */
15, /* number of keys on terminal keypad */
pad, /* programmable function keys */
4, /* number of arrow keys on terminal */
arrow, /* PC arrow key codes */
shift_arrow, /* PC shift arrow key codes */
};
/*
ALTOS3_INIT -- Initialize for ALTOS3 terminal emulation. This function
is passed as a pointer to "init_port()".
*/
short altos3_init(TERMINAL *t)
{
t->csi1 = ESC;
t->csi2 = '[';
t->delim1 = ';';
t->mode = 0X8004;
t->d_att = 7;
t->att = 7;
t->tk = &tk_altos3;
((struct comm_port *) t->port)->c_write = altos3_c_write; /* fn. to send byte to port */
((struct comm_port *) t->port)->c_out = altos3_conoutc; /* local echo function */
return (0);
}
/*
ALTOS3_WRITE -- VT100 driver function to send a byte out of the serial port.
This function is pointed at by p->c_write (i.e. it replaces u8250_write(), etc.
It is just a 'binding' to make the VT100 code independent of CCT.
*/
void altos3_c_write(COMM_PORT *p, short ch)
{
altos3_c_putc(p->term, ch);
}
/*
ALTOS3_C_PUTC -- ALTOS III driver function to send a byte out of the serial
port (typically, a keystroke). This function is pointed at by
p->c_write (i.e. it replaces u8250_write(), and works if transmitter
interrupts are enabled.
'ch' is the character to be sent out of the port. It may be a keystroke,
in which case it can consist of a scan code in the high byte and a character
code in the low byte. See KEYS.H and ASCII.H for key definitions.
*/
void altos3_c_putc(TERMINAL *t, short ch)
{
short i, f_ascii = TRUE;
/* if (ch == TAB) printf("TAB pressed"); */
/* TEST FOR "HOME" */
if (ch == t->tk->home) {
(*t->c_putc)(t, ESC);
(*t->c_putc)(t, '[');
ch = 'H';
f_ascii = FALSE;
}
/* TEST FOR "HELP" */
if (ch == t->tk->help) {
(*t->c_putc)(t, SOH);
(*t->c_putc)(t, 'P');
ch = CR;
f_ascii = FALSE;
}
/* TEST FOR "PREVIOUS SCREEN" */
if (ch == t->tk->prevscreen) {
(*t->c_putc)(t, ESC);
(*t->c_putc)(t, '[');
ch = 'T';
f_ascii = FALSE;
}
/* TEST FOR "NEXT SCREEN" */
if (ch == t->tk->nextscreen) {
(*t->c_putc)(t, ESC);
(*t->c_putc)(t, '[');
ch = 'S';
f_ascii = FALSE;
}
/* TEST FOR A FUNCTION KEY */
for (i=0; i< t->tk->numfkeys; i++) {
if (ch == t->tk->pf[i]) { /* F1 - F12, ALT_F1 - ALT_F4 */
(*t->c_putc)(t, SOH);
(*t->c_putc)(t, '@' + i);
ch = CR;
f_ascii = FALSE;
break;
}
if (ch == t->tk->shift_pf[i]) { /* SF1 - SF12, CTRL_F1 - CTRL_F4 */
(*t->c_putc)(t, SOH);
(*t->c_putc)(t, '`' + i);
ch = CR;
f_ascii = FALSE;
break;
}
}
/* TEST FOR KEYPAD KEYS (in Application Mode) */
if (isapp()) {
for (i=0; i< t->tk->numpadkeys; i++) {
if ((ch & 0XFF) == t->tk->pad[i]) {
(*t->c_putc)(t, ESC);
(*t->c_putc)(t, 'O');
ch = 'l' + i;
f_ascii = FALSE;
break;
}
}
/* TEST FOR ENTER KEY (on numeric keypad) */
if (ch == t->tk->enter) {
(*t->c_putc)(t, ESC);
(*t->c_putc)(t, 'O');
ch = 'M';
f_ascii = FALSE;
}
}
/* TEST FOR ARROW KEYS */
for (i=0; i< t->tk->numarrowkeys; i++) {
if (ch == t->tk->arrow[i]) {
(*t->c_putc)(t, ESC);
if (isapp() && iscur()) (*t->c_putc)(t, 'O');
else (*t->c_putc)(t, '[');
ch = 'A' + i;
f_ascii = FALSE;
break;
}
if (ch == t->tk->shift_arrow[i]) {
(*t->c_putc)(t, SOH);
(*t->c_putc)(t, 'q' + i);
ch = CR;
f_ascii = FALSE;
break;
}
}
/* A VALID CHARACTER CODE */
if (f_ascii) switch(ch & 0XFF) {
case CR: /* treat these as LFs */
case VT:
case FF:
if (isaddlf()) {
(*t->c_putc)(t, CR);
ch = LF;
}
break;
default:
break;
}
(*t->c_putc)(t, ch); /* send character */
}
/*
ALTOS3_CONOUTC --- Under ALTOS3 emulation, this function replaces conoutc().
It is just a 'binding' to make the ALTOS3 code independent of CCT.
*/
void altos3_conoutc(COMM_PORT *p, short ch)
{
altos3_parse(p->term, ch);
}
/*
ALTOS3_PARSE -- All characters for output to the screen go through here.
This is the ALTOS3 console emulation driver.
*/
void altos3_parse(TERMINAL *t, short ch)
{
short ret = 0;
/* COMMAND SEQUENCE INTRODUCER RECEIVED */
if (ch == ESC) {
#if DEBUG
(*t->putc)(ch, FG(t->att | 8), BG(t->att));
#endif
t->inescape = 1;
t->s = t->sequence; /* initialize buffer ptr. */
memset(t->sequence, 0X0, MAX_ESC_LEN); /* initialize buffer */
}
/* ALREADY IN AN ESCAPE SEQUENCE */
else if (t->inescape) {
/* HANDLE BUFFER OVERFLOW */
if (t->s - t->sequence >= MAX_ESC_LEN) ret = EOF;
else if (t->inescape == 1) {
#if DEBUG
(*t->putc)(ch, FG(t->att | 8), BG(t->att));
#endif
*t->s++ = (char) ch;
if (ch == '[' || ch == '(') t->inescape++;
else {
ret = ansi_dispatch(t, t->sequence, ch);
if (ret == EOF) ret = vt100_dispatch(t, t->sequence, ch);
ret = EOF;
}
}
else {
if (isalpha(ch)) {
#if DEBUG
(*t->putc)(ch, FG(t->att | 8), BG(t->att));
#endif
ret = ansi_dispatch(t, t->sequence, ch);
if (ret == EOF) vt100_dispatch(t, t->sequence, ch);
if (ret == EOF) ret = altos3_dispatch(t, t->sequence, ch);
ret = EOF;
}
else *t->s++ = (char) ch;
}
}
/* CONTROL CHARACTER RECEIVED */
else if (iscntrl(ch)) ret = vt_dispatch_ctrl(t, ch);
/* NON-CONTROL ASCII CHARACTER */
else (*t->putc)(ch, FG(t->att), BG(t->att));
if (ret == EOF) t->inescape = FALSE;
}
/*
ALTOS3_DISPATCH -- Test for a DEC PRIVATE command received from the serial
port.
Return value:
0 -- OK
EOF -- Command not recognized.
*/
short altos3_dispatch(TERMINAL *t, char *buf, short ch)
{
WORD num[128];
short count, ret = 0;
t->ccol = cur_get_col();
t->crow = cur_get_row();
count = term_parse(buf, num, ';'); /* no. of parameters */
if (buf[0] == '[' || buf[0] == '(') {
if (buf[1] == '?' || buf[1] == '>' || buf[1] == '=') {
if (ch == 'h') ret = altos3_set_mode(t, num, count, buf[1]);
else if (ch == 'l') ret = altos3_reset_mode(t, num, count, buf[1]);
}
}
else ret = EOF;
return (ret);
}
/*
ALTOS3_SET_MODE -- Called on receipt of "CSI Ps;...;Psh" (SM) sequence.
This routine sets ALTOS3 modes.
*/
short altos3_set_mode(TERMINAL *t, WORD *num, WORD len, WORD delim)
{
short i = 0, ret = 0;
while (i < len) {
if (delim == '>') switch(num[i]) {
case 0:
break;
case 1:
break;
case 5:
/* cursor invisible */
break;
default:
ret = EOF;
break;
}
else if (delim == '=') switch(num[i]) {
case 0:
break;
case 1:
/* select printer echo mode */
break;
case 2:
/* select unformatted printer mode */
break;
default:
ret = EOF;
break;
}
else ret = EOF;
i++;
}
return (ret);
}
/*
ALTOS3_RESET_MODE -- Called on receipt of "CSI Ps;...;Psl" (SM) sequence.
This routine resets ALTOS3 modes.
*/
short altos3_reset_mode(TERMINAL *t, WORD *num, WORD len, WORD delim)
{
short i = 0, ret = 0;
while (i < len) {
if (delim == '>') switch(num[i]) {
case 0:
break;
case 1:
break;
case 5:
/* cursor visible */
break;
default:
ret = EOF;
break;
}
else if (delim == '=') switch(num[i]) {
case 0:
break;
case 1:
/* select printer pass through mode */
break;
case 2:
/* select formatted printer mode */
break;
default:
ret = EOF;
break;
}
else ret = EOF;
i++;
}
return (ret);
}