/*
Copyright (C) Magna Carta Software, Inc. 1988-1991. All Rights Reserved
C COMMUNICATIONS TOOLKIT
ANSI.C -- X3.64 terminal emulation routines.
*/
#define CCT_DEVELOPMENT
#if (defined(CCTW) || defined(_WINDOWS))
#include <windows.h>
#endif
#include <string.h>
#include <compat.h>
#include <ctype.h>
#include <stdlib.h>
#include <ansi.h>
#include <colors.h>
#include <biosvid.h>
/*
ANSI_CPR -- Send a cursor position report from an ANSI terminal.
*/
void ansi_cpr_(TERMINAL *t)
{
char *pa, asc[4];
term_write(t, t->csi);
term_write(t, '[');
itoa((*t->cur_get_row)(t)+1, asc, 10);
pa = asc;
while (*pa) term_write(t, *pa++);
term_write(t, t->delim1);
itoa((*t->cur_get_col)(t)+1, asc, 10);
pa = asc;
while (*pa) term_write(t, *pa++);
term_write(t, 'R');
}
/*
ANSI_CURSOR -- Handle terminal movement commands.
*/
void ansi_cursor_(TERMINAL *t, short cmd)
{
switch(cmd) {
case CUB: /* cursor back */
if (t->ccol > t->clmargin) {
t->ccol = (t->num[0]==0) ? t->ccol-1 : max(t->ccol-t->num[0], t->clmargin);
}
break;
case CUD:
if (t->crow < t->cbmargin) {
t->crow = (t->num[0] == 0) ? t->crow+1 : min(t->crow+t->num[0], t->cbmargin);
}
break;
case CUF:
if (t->ccol < t->crmargin) {
t->ccol = (t->num[0] == 0) ? t->ccol+1 : min(t->ccol+t->num[0], t->crmargin);
}
break;
case CUP:
case HVP:
t->crow = (t->num[0] == 0) ? t->ctmargin : t->ctmargin + t->num[0] - 1;
t->ccol = (t->num[1] == 0) ? t->clmargin : t->clmargin + t->num[1] - 1;
if (t->num[0] == 22 && t->num[1] == 0)
t->num[0] = 22;
break;
case CUU:
if (t->crow > t->ctmargin) {
t->crow = (t->num[0] == 0) ? t->crow-1 : max(t->crow-t->num[0], t->ctmargin);
}
break;
case IND: /* index */
if (t->crow == t->bmargin) (*t->scroll)(t, t->lmargin, t->tmargin, t->rmargin, t->bmargin, t->d_att, 1);
else t->crow++;
break;
case NEL: /* next line */
if (t->crow == t->bmargin) (*t->scroll)(t, t->lmargin, t->tmargin, t->rmargin, t->bmargin, t->d_att, 1);
else t->crow++;
t->ccol = 0;
break;
case TRI: /* reverse index */
if (t->crow == t->tmargin) (*t->scroll)(t, t->lmargin, t->tmargin, t->rmargin, t->bmargin, t->d_att, -1);
else t->crow--;
break;
default:
#if XDEBUG
printf("Unrecognized term_cursor() command %d", cmd);
#endif
break;
}
(*t->cur_pos_)(t, t->ccol, t->crow);
}
/*
ANSI_ERASE -- Generic function to handle several erase commands.
ANSI X3.64 escape code is "ESC [ Ps K"
*/
void ansi_erase_(TERMINAL *t, short cmd)
{
switch (cmd) {
case ECH:
(*t->ech)(t, SP, t->att, 1);
break;
case EED0: /* erase from active pos. to end of display */
case EED1:
(*t->eed)(t, SP, t->d_att);
break;
case EBD: /* erase from start of display to active posn. */
(*t->ebd)(t, SP, t->d_att);
break;
case ED: /* erase all of display */
(*t->scroll)(t, 0, 0, t->d_cols, t->d_rows, t->d_att, 0);
if (t->type == ANSI_SYS) {
t->crow = 0;
t->ccol = 0;
(*t->cur_pos_)(t, 0, 0);
}
break;
case EEL0: /* erase from active pos. to end of line */
case EEL1:
if (t->type == ANSI_SYS) (*t->eel)(t, SP, t->att);
else (*t->eel)(t, SP, t->d_att);
break;
case EBL: /* erase from start of line to active posn. */
(*t->ebl)(t, SP, t->d_att);
break;
case EL: /* erase all of line */
(*t->eil)(t, SP, t->d_att);
break;
default:
#if XDEBUG
printf("Unrecognized term_erase() command %d", cmd);
#endif
break;
}
}
/*
ANSI_HTS -- ANSI X3.64 tabulation set (HTS) ESC H.
*/
void ansi_hts_(TERMINAL *t)
{
t->tabstop[t->ccol] = (char) 1;
}
/*
ANSI_INSERT -- Generic function to handle several insert commands.
ANSI X3.64 escape codes:
IL Insert Line "ESC [ Ps L"
*/
void ansi_insert_(TERMINAL *t, short cmd)
{
switch (cmd) {
case IL:
(*t->scroll)(t, t->lmargin, t->crow, t->rmargin, t->bmargin, t->d_att, -1);
break;
default:
#if XDEBUG
printf("Unrecognized ansi_insert() command %d", cmd);
#endif
break;
}
}
/*
ANSI_MEDIA_COPY -- ANSI X3.64 media copy commands.
ANSI X3.64 commands CSIxxPn i
*/
void ansi_media_copy_(TERMINAL *t)
{
WORD i=0;
while (i < t->parmcount || i == 0) {
switch (t->num[0]) {
case 0: /* copy entire screen to primary aux. device */
break;
case 1: /* copy from primary auxilliary device */
break;
case 2: /* copy entire screen to secondary aux. device */
break;
case 3: /* copy from secondary auxilliary device */
break;
case 4: /* turn off copying RX data to primary aux. */
t->ansimode &= ~PRN_CTRL;
break;
case 5: /* turn on copying RX data to primary aux. */
t->ansimode |= PRN_CTRL;
break;
case 6: /* turn off copying RX data to secondary aux. */
break;
case 7: /* turn off copying RX data to secondary aux. */
break;
default:
#if XDEBUG
printf("HOST: Unrecognized ANSI printer controller sequence");
#endif
break;
}
i++;
}
}
/*
ANSI_PARSE_CMD -- Search forward through the the set of strings that may be
received from the host for the one in the command buffer.
Ignore parameter specifications ('%').
If the string is not found, return EOF, else return
*/
short ansi_parse_cmd_(TERMINAL *t, const char *n)
{
short i, j, k;
TERM_RESPONSE *h = t->tr;
BYTE ch;
if (*n != '\0') {
for (i=0; i < MAX_TERM_CMDS; i++) {
if (h[i].sh2t[0] == '\0') continue;
for (j=0, k=0; j < MAX_PARM_LEN && k < MAX_PARM_LEN; j++, k++) {
#if XDEBUG
if (i == SGR && n[k-1] == 'm')
i = i;
#endif
ch = h[i].sh2t[j];
if (ch == '\0')
return (i);
while (n[k] == (char) t->delim1 || n[k] == (char) t->csi) k++;
if (ch == '%' || ch == (BYTE) t->delim1) {
while (h[i].sh2t[j] == '%' || h[i].sh2t[j] == (char) t->delim1) j++;
while (isdigit(n[k]) || n[k] == (char) t->delim1) k++;
}
if (h[i].sh2t[j] == n[k]) continue;
else break;
}
}
}
return (EOF);
}
/*
ANSI_RESET -- Reset an ANSI X3.64 terminal to its initial state.
*/
void ansi_reset_(TERMINAL *t)
{
t = t; /* silence compiler warning */
return;
}
/*
ANSI_RESET_MODE -- Called on receipt of "CSI Ps;...;Psl" (SM) sequence.
This routine handles ANSI X3.64 modes.
*/
void ansi_reset_mode_(TERMINAL *t)
{
WORD i=0;
while (i < t->parmcount || i == 0) {
switch (t->num[i]) {
case LNM: /* set CR = CRLF mode ON */
t->ansimode &= ~ANSI_LNM;
break;
default:
break;
}
i++;
}
}
/*
ANSI_SET_MODE -- Called on receipt of "CSI Ps;...;Psh" (SM) sequence.
This routine handles ANSI X3.64 modes.
*/
void ansi_set_mode_(TERMINAL *t)
{
WORD i=0;
while (i < t->parmcount) {
switch (t->num[i]) {
case 0:
break;
case LNM: /* set CR = CRLF mode ON */
t->ansimode |= ANSI_LNM;
break;
default:
break;
}
i++;
}
}
/*
ANSI_SGR -- Set screen attributes on ANSI X3.64 compatible terminals.
Return value:
0 -- OK;
EOF -- unrecognized attribute request;
*/
void ansi_sgr_(TERMINAL *t)
{
short fc, bc, blink, underscore; /* ATTRIBUTES */
short ch, ret = 0;
short bright, reverse;
WORD i=0;
reverse = FALSE;
fc = FG(t->att);
bc = BG(t->att);
blink = (t->att & 0X80) ? TRUE : FALSE;
underscore = (fc == 1) ? TRUE: FALSE;
bright = fc & 0X8;
while (i < t->parmcount || i == 0) {
#if 0
printf("Num[%d]=%d", i, t->num[i]);
#endif
switch(t->num[i]) {
case 0:
fc = FG(t->d_att); bc = BG(t->d_att);
bright = reverse = underscore = blink = FALSE;
break;
case 1:
bright = TRUE;
break;
case 4:
underscore = TRUE;
break;
case 5:
blink = TRUE;
break;
case 7: /* reverse video on */
fc = FG(t->d_att); bc = BG(t->d_att);
bright = underscore = blink = FALSE;
reverse = TRUE;
break;
case 8: /* cancelled on */
fc = bc;
break;
case 22: /* bright off */
bright = FALSE;
break;
case 24: /* underline off */
underscore = FALSE;
break;
case 25: /* blink off */
blink = FALSE;
break;
case 27: /* display positive image (?) */
reverse = FALSE;
ch = fc;
fc = bc;
bc = ch;
break;
case 30: /* black foreground */
fc = BLACK;
break;
case 31: /* red foreground */
fc = RED;
break;
case 32: /* green foreground */
fc = GREEN;
break;
case 33: /* yellow foreground */
fc = YELLOW;
break;
case 34: /* blue foreground */
fc = BLUE;
break;
case 35: /* magenta foreground */
fc = MAGENTA;
break;
case 36: /* cyan foreground */
fc = CYAN;
break;
case 37: /* white foreground */
fc = LIGHTGREY;
break;
case 40: /* black background */
bc = BLACK;
break;
case 41: /* red background */
bc = RED;
break;
case 42: /* green background */
bc = GREEN;
break;
case 43: /* yellow background */
bc = YELLOW;
break;
case 44: /* blue background */
bc = BLUE;
break;
case 45: /* magenta background */
bc = MAGENTA;
break;
case 46: /* cyan background */
bc = CYAN;
break;
case 47: /* white background */
bc = LIGHTGREY;
break;
default:
ret = EOF;
break;
}
i++; /* increment to next attribute */
if (ret == EOF) break;
}
if (reverse) {
ch = fc;
fc = bc;
bc = ch;
}
if (bright) fc |= 0X08;
else if (fc != YELLOW) fc &= 0X7;
if (blink) bc |= 0X08;
else bc &= 0X7;
if (underscore) fc |= 0X1;
t->att = 0; /* necessary to fix a TC v2.0 bug */
t->att = (bc << 4) + fc; /* update terminal structure */
#if XDEBUG
printf("fc=%d, bc=%d", fc, bc);
printf("att=%#x", t->att);
#endif
}
/*
ANSI_TBC -- ANSI X3.64 tabulation clear (TBC) ESC [Psg.
If Ps = 0 clear tabs at cursor column.
If Ps = 3 clear all tabs.
*/
void ansi_tbc_(TERMINAL *t)
{
/* CLEAR ALL TABS */
if (t->num[0] == 3) memset(t->tabstop, 0, (size_t) t->d_cols);
else t->tabstop[t->ccol] = 0;
}