/* emulate.c  -- key parsing for vt102/vt52/h19/etc  emulation
 *
 * (C) Copyright 1988, 1989 Chris Newman
 * All Rights Reserved
 * Permission is granted ot copy, modify, and use this as long
 * as this notice remains intact.  This is a nifty program.
 * 
 * Doug's contribution: it
 * "What do you mean? The implementation of scroll bars is trivial."
 *
 * $Author: ppessi $ $Revision: 1.3 $ $Date: 1993/03/29 07:49:14 $
 */

#include <stdio.h>
#include "nifty.h"
#include "display.h"

/* import bell routines from beep.c or private display module */
extern void audiobell();

/* import from misc.c */
extern char *itos();

/* import from main routines */
extern int write_to_tty();

/* import from display routines */
extern int dsstyle();
extern void dskeyboard();

#define	MAXTERMBUF  300
#define	MAXESCBUF   20
#define	MAXARG	    7

#define VT100ATTRIBS  "\033[?1;2c"

/* these are program global variables */
int emulation =	EMU_VT102;		/* current terminal emulation */
int vt100_yucky_wrap_mode = 0;		/* vt100 wrap flag */
int ansi_LNM = 0;			/* line feed/new line mode */
int bell_type =	1;			/* 0 = norm, 1 = visual, 2 = audio, 3 = both */
int pass8=1;                            /* 0 = strip 8th bit, 1 = pass 8th bit */
/* these are local to this module */
int savecurset = 0, saveG[2] = {0, 1};	/* area to save params */
int esc_mode;				/* current escape mode */
int private = 0;			/* private terminal modes -- 0, 1 = DEC, 2 = H19 */
int curarg, arg[MAXARG+1];		/* ANSI code arguments */
int curset = 0;				/* current VT100 character set */
int G[2] = {0, 1};			/* settings for 2 VT100 sets */
int sendgarbage	= 3;			/* if 2, terminal reports may be sent at times */

#if 0
static char *termtype = "TERM=vt102";
static char *termcap = "TERMCAP=dy|vt102|vt-102|wm|dec vt102:co#80:li#24:bw:am:xn:\
\n\t:so=\\E[7m:se=\\E[27m:us=\\E[4m:ue=\\E[24m:ms:as=\\E)0^N:ae=\\E(B^O:\
\n\t:md=\\E[1m:mr=\\E[7m:mb=\\E[5m:mt=\\E[3m:mk=\\E[8m:me=\\E[m:bc=^H:\
\n\t:do=\\E[B:up=\\E[A:le=^H:nd=\\E[C:UP=\\E[%dA:DO=\\E[%dB:RI=\\E%dC:LE=\\E[%dD:\
\n\t:cl=\\E[H\\E[2J:ho=\\E[H:cm=\\E[%i%d;%dH:cs=\\E[%i%d;%dr:IC=\\E[%d@:\
\n\t:ce=\\E[K:cd=\\E[J:dc=\\E[P:DC=\\E[%dP:al=\\E[L:dl=\\E[M:rs=\\Ec:\
\n\t:sc=\\E7:rc=\\E8:sf=\\ED:sr=\\EM:vb=\\EQ:AL=\\E[%dL:DL=\\E[%dM:\
\n\t:im=\\E[4h:ei=\\E[4l:mi:km:ta=^I:";
static char *h19termtype = "TERM=h19";
static char *h19termcap = "TERMCAP=kb|h19|heath|zenith|z19|wm|heathkit h19:co#80:li#24:\
\n\t:cr=^M:nl=^J:al=\\EL:am:le=^H:bs:cd=\\EJ:ce=\\EK:cl=\\EE:\
\n\t:cm=\\EY%+ %+ :dc=\\EN:ei=\\EO:im=\\E@:mi:ta=^I:\
\n\t:dl=\\EM:do=\\EB:ho=\\EH:mi:nd=\\EC:as=\\EF:ae=\\EG:ms:pt:sr=\\EI:\
\n\t:se=\\Eq:so=\\Ep:up=\\EA:vs=\\Ex4:ve=\\Ey4:km:";
static char *vt52termtype = "TERM=vt52";
static char *vt52termcap = "TERMCAP=dw|vt52|vt-52|wm|dec vt52:\
\n\t:do=^J:le=^H:bs:cd=\\EJ:ce=\\EK:cl=\\EH\\EJ:cm=\\EY%+ %+ :co#80:li#24:\
\n\t:nd=\\EC:pt:sr=\\EI:up=\\EA:kb=^H:km:";

#endif
/***** look at the code for ts and fs and ds and is -- status line *****
 */

/* terminal capabilites:
 * co# -- number of columns, set on startup
 * li# -- number of lines, set on startup
 * bw -- cursor left is backspace
 * am, xn -- Terminal wraps at 80 columns, only if two graphic characters are sent.
 * mi,ms -- safe to move in insert/standout mode
 * so,se -- standout (inverse video) characters start/end
 * us,ue -- underline characters start/end
 * as,ae -- enter/exit alternate character set
 * md,mr,mb -- make dark (bold), make reverse (inverse), make blink (flash)
 * mt,mk,me -- make iTalic, make blank, make styles end
 * do,le, bc -- cursor down, cursor left, backspace character (same as cursor left).
 * up,nd -- cursor up, cursor right (non-destructive space)
 * UP, DO, RI, LE -- move up/down/right/left n characters
 * cl,ho -- clear screen, home cursor
 * ce,cd -- clear to end of line/display
 * sc,rc -- save/recall cursor position
 * cs -- change scrolling region
 * rs -- reset terminal
 * dc,DC -- delete character(s)
 * IC -- insert character(s)
 * al,AL,dl,DL -- add line(s), delete line(s)
 * im, ei -- insert mode, end insert mode
 * vs, ve -- very visual cursor, normal visual cursor
 * sf, sr -- scroll forward/reverse.  Cursor must be at bottom/top of screen.
 * vb -- visual bell
 * cm -- cursor move
 * ta,cr,nl -- tab/carriage return/new line
 */

/* different terminal modes
 */
void terminalMode(num, private, on)
int num, private, on;
{
    switch (private) {
	case 0:	/* standard ansi modes */
	    switch (num) {
		case 4:
		    dsfunction(on ? INSERT_ON : INSERT_OFF);
		    break;

		case 20:
		    ansi_LNM = on;
		    break;
	    }
	    break;

	case 1: /* vt100 private modes */
	    /* unimplemented modes:
	     * 3 - 80/132 column mode
	     * 4 - soft/jump scroll
	     */
	    switch (num) {
		case 1:
		    dskeyboard(DS_KEYPADAPPMODE, on);
		    break;

		case 2:
		    if (!on)
			emulation = EMU_VT52;
		    break;

		case 5:
		    dsinvert(on ? INVERT_ON : INVERT_OFF);
		    break;
			    
		case 6:
		    dsfunction(on ? ORIGIN_ON : ORIGIN_OFF);
		    break;

		case 7:
		    dsfunction(on ? WRAP_ON : WRAP_OFF);
		    break;

		case 8:
		    dskeyboard(DS_AUTOREPEAT, on);
		    break;
	    }
	    break;

	case 2: /* h19 private modes */
	    /* modes not implemented:
	     * 1 - 25th line status (on -> enabled)
	     * 3 - hold screen mode
	     * 8 - auto linefeed on CR
	     * 9 - auto CR on linefeed
	     */
	    switch (num) {
		case 2:
		    dskeyboard(DS_KEYCLICK, on ? 0 : 1);
		    break;

		case 4:
		    dsfunction(on ? BLOCK_CURSOR : UNDERLINE_CURSOR);
		    break;
		    
		case 5:
		    dsfunction(on ? INVISIBLE_CURSOR : VISIBLE_CURSOR);
		    break;

		case 6:
		    dskeyboard(DS_KEYPADMODE, on ? KEYPAD_H19S : KEYPAD_H19);
		    break;

		case 7:
		    dskeyboard(DS_KEYPADAPPMODE, on);
		    break;
	    }
	    break;
    }
}

/* handle escape sequences
 */
int decode_escapes(c)
char	c;
{
    int i, x, y;
    
    switch (esc_mode) {
	case 1: /* escape key just pressed */
	    switch (c) {
		case '[': /* ANSI sequence prefix */
		    for (i=0; i<=MAXARG; i++)
			arg[i]=0;
		    esc_mode = 2;
		    private = 0;
		    return (0);

		case '#': /* DEC Private line width modes */
		    esc_mode = 3;
		    return (0);

		case '(': /* SCS: select character set -- for G[0] set */
		    esc_mode = 4;
		    return (0);

		case ')': /* SCS: select character set -- for G[1] set */
		    esc_mode = 5;
		    return (0);

		case 'D': /* IND (index): cursor down with scroll forward */
		    dscursormove(INDEX,0);
		    break;

		case 'E': /* NEL (next line): proper return */
		    dscursormove(NEXT_LINE,1);
		    break;

		case 'H': /* HTS horizontal tabulation set */
		    dsfunction(SET_TAB);
		    break;

		case 'M': /* RI (reverse index): cursor up with scroll reverse */
		    dscursormove(REVERSE_INDEX,0);
		    break;
		    
		case 'Q': /* visual bell VT220 */
		    dsinvert(VISUAL_BELL);
		    break;

		case 'Z': /* DECID identify terminal */
		    (void) write_to_tty(VT100ATTRIBS,7);
		    break;

		case '7': /* DECSC save cursor position (DEC private) */
		    dscursormove(SAVE_CURSOR,0);
		    savecurset = curset;
		    saveG[0] = G[0];
		    saveG[1] = G[1];
		    break;

		case '8': /* DECRC restore cursor position (DEC private) */
		    dscursormove(RESTORE_CURSOR,0);
		    curset = savecurset;
		    G[0]=saveG[0];
		    G[1]=saveG[1];
		    break;

		case 'c': /* RIS reset to initial state */
		    dsfunction(RESET_DISPLAY);
		    break;
	    }
	    break;

	case 2: /* escape [ foo character */
	    switch (c) {
		case ISDIGIT:
		    arg[curarg] *= 10;
		    arg[curarg] += c-'0';
		    return (0);

		case '?':
		    private = 1;
		    return (0);

		case '>':
		    private = 2;
		    return (0);
		    
		case ';': /* get next parameter */
		    if (curarg < MAXARG)
			arg[++curarg]=0;
		    return (0);

		case 'A': /* CUU cursor up */
		    dscursormove(CURSOR_UP, arg[0]);
		    break;

		case 'B': /* CUD cursor down */
		    dscursormove(CURSOR_DOWN, arg[0]);
		    break;

		case 'C': /* CUF cursor right/forward */
		    dscursormove(CURSOR_RIGHT, arg[0]);
		    break;

		case 'D': /* CUB cursor left/backward */
		    dscursormove(CURSOR_LEFT, arg[0]);
		    break;

		case 'H': case 'f': /* move cursor to specific position. CUP, HVP */
		    if (arg[0])  arg[0]--;
		    if (arg[1])  arg[1]--;
		    dscursorto(arg[1], arg[0]);
		    break;

		case 'J': /* ED clear to end of display. (erase in display) */
		    switch (arg[0]) {
			case 0:
			    dsfunction(ERASETO_EOS);
			    break;

			case 1:
			    dsfunction(ERASETO_SOS);
			    break;

			case 2:
			    dsclearscreen();
			    break;
		    }
		    break;
		    
		case 'K': /* EL clear to end of line. (erase in line) */
		    switch (arg[0]) {
			case 0:
			    dsfunction(ERASETO_EOL);
			    break;

			case 1:
			    dsfunction(ERASETO_SOL);
			    break;

			case 2:
			    dsfunction(ERASE_LINE);
			    break;
		    }
		    break;

		case 'L': /* insert line VT102 */
		    dscursormove(INSERT_LINE, arg[0]);
		    break;

		case 'M': /* delete line VT102 */
		    dscursormove(DELETE_LINE, arg[0]);
		    break;

		case 'P': /* delete character VT102 */
		    if (!arg[0])
			arg[0] = 1;
		    dsdelete(arg[0]);
		    break;

		case '@': /* ansi insert character */
		    dscursormove(INSERT_CHAR, arg[0]);
		    break;

		case 'c': /* DA Device Attributes request */
		    if (arg[0] == 0) {
			(void) write_to_tty(VT100ATTRIBS,7);
		    }
		    break;

		case 'g': /* TBC tabulation clear */
		    dsgetcursor(&x, &y);
		    for (i=0; i<=curarg; i++) switch (arg[i]) {
			case 0:
			    dsfunction(CLEAR_TAB);
			    break;

			case 3:
			    dsfunction(CLEAR_ALL_TABS);
		    }
		    break;

		case 'h': /* SM set terminal mode */
		    for (i=0; i<=curarg; i++)
			terminalMode(arg[i], private, 1);
		    break;

		case 'l': /* RM reset terminal mode */
		    for (i=0; i<=curarg; i++)
			terminalMode(arg[i], private, 0);
		    break;
		    
		case 'm': /* SGR styles (select graphic rendition) */
		    for (i=0; i<=curarg; i++)
			vtstyle(arg[i]);
		    break;

		case 'n': /* DSR  Device status report */
		    for (i=0; i<=curarg; i++) switch (arg[i]) {
			case 5:
			    (void) write_to_tty("\033[0n",4);
			    break;

			case 6: {
			    char cursorpos[10];
			    char *cpos;
			    int tempx, tempy;

			    dsgetcursor(&tempx, &tempy);
			    if (tempx == 0 && tempy == 0)
				(void) write_to_tty("\033[R",3);
			    else {
				cursorpos[0] = '\033';
				cursorpos[1] = '[';
				(void) strcpy(cursorpos + 2, itos(tempy + 1));
				cpos = cursorpos + strlen(cursorpos);
				*cpos++ = ';';
				(void) strcpy(cpos, itos(tempx + 1));
				(void) strcat(cpos, "R");
				(void) write_to_tty(cursorpos, strlen(cursorpos));
			    }
			    break;
			    }
		    }
		    break;

		case 'q': /* DECLL set LEDs on keyboard */
		    {
			int leds = 0;

			for (i=0; i<=curarg; i++) {
			    if (!arg[i])
			        leds = 0;
			    else if (arg[i] <= 4)
			        leds |= 1 << (arg[i]-1);
			}
			dskeyboard(DS_LEDS, leds);
		    }
		    break;

		case 'r': /* DECSTBM set top and bottom margins (scrolling range) */
		    dssetscroll(arg[0],arg[1]);
		    break;

		case 'x': /* DECREQTPARM Request Terminal Parameters */
		    switch (arg[0]) {
			case 0:
			    sendgarbage=2;
			    vtreport();
			    break;

			case 1:
			    sendgarbage=3;
			    vtreport();
			    break;
		    }
		    break;
		    
		default:
		    break;
	    }
	    break;

	case 3: /* dec private codes for fonts */
	    switch(c) {
		case '3':
		    (void) dsstyle(DWIDTHTOP);
		    break;

		case '4':
		    (void) dsstyle(DWIDTHBOT);
		    break;

		case '5':
		    (void) dsstyle(DWIDTH0);
		    break;

		case '6':
		    (void) dsstyle(DWIDTH1);
		    break;
		    
		case '8':
		    dstestscreen();
		    break;
	    }
	    break;

	case 4: case 5: /* SCS: select character set: ESC( or ESC) */
	    switch (c) {
		case 'A': case 'B': case '1': /* change to UK/US/other ROM set */
		    G[esc_mode - 4] = 0;
		    if (esc_mode - 4 == curset)
			(void) dsstyle(ALTERNATE0);
		    break;

		case '0': case '2': /* change to graphic set/graphic ROM set */
		    G[esc_mode - 4] = 1;
		    if (esc_mode - 4 == curset)
			(void) dsstyle(ALTERNATE1);
		    break;

		default:
		    esc_mode = 0;
		    return (1);
	    }
	    break;

	case 10: /* VT52 emulation -- ESC just hit */
	    switch (c) {
		case 'A': /* cursor up */
		    dscursormove(CURSOR_UP, 1);
		    break;

		case 'B': /* cursor down */
		    dscursormove(CURSOR_DOWN, 1);
		    break;

		case 'C': /* cursor right */
		    dscursormove(CURSOR_RIGHT, 1);
		    break;

		case 'D': /* cursor left */
		    dscursormove(CURSOR_LEFT, 1);
		    break;

		case 'F': /* alternate characters */
		    (void) dsstyle(ALTERNATE1);
		    break;

		case 'G': /* standard characters */
		    (void) dsstyle(ALTERNATE0);
		    break;

		case 'H': /* home cursor */
		    dscursorto(0,0);
		    break;

		case 'I': /* reverse line feed */
		    dscursormove(REVERSE_INDEX,1);
		    break;

		case 'J': /* erase to end of screen */
		    dsfunction(ERASETO_EOS);
		    break;

		case 'K': /* erase to end of line */
		    dsfunction(ERASETO_EOL);
		    break;

		case 'Y': /* move cursor to specific position */
		    esc_mode = 11;
		    return (0);

		case 'Z': /* Identify terminal sequence */
		    (void) write_to_tty("\033/Z",3); /* VT100 emulating a VT52 */
		    break;

		case '<': /* switch to ANSI mode */
		    emulation = EMU_VT102;
		    break;
	    }
	    break;

	case 11:
	    arg[0] = (c&0x7f) - ' ';
	    esc_mode = 12;
	    return (0);

	case 12:
	    arg[1] = (c&0x7f) - ' ';
	    dscursorto(arg[1], arg[0]);
	    break;

	case 20: /* H19 emulation -- ESC just hit */
	    /* here is a list of unimplemented escapes:
	     * <   enter ansi mode
	     * [   enter hold screen mode (implemented as ansi codes)
	     * \   exit hold screen mode
	     * }   inhibit keyboard output
	     * {   enable keyboard output
	     * ]   Transmit 25th line
	     * #   Transmit page
	     * r   Set baud rate
	     */
	    switch (c) {
		case 'A': /* HCUU: cursor up */
		    dscursormove(CURSOR_UP, 1);
		    break;

		case 'B': /* HCUD: cursor down */
		    dscursormove(CURSOR_DOWN, 1);
		    break;

		case 'C': /* HCUF: cursor right */
		    dscursormove(CURSOR_RIGHT, 1);
		    break;

		case 'D': /* HCUB: cursor left */
		    dscursormove(CURSOR_LEFT, 1);
		    break;

		case 'E': /* HCD: clear screen */
		    dsclearscreen();
		    break;

		case 'F': /* HEGM: alternate characters */
		    (void) dsstyle(ALTERNATE1);
		    break;

		case 'G': /* HXGM: standard characters */
		    (void) dsstyle(ALTERNATE0);
		    break;

		case 'H': /* HCUH: home cursor */
		    dscursorto(0,0);
		    break;

		case 'I': /* HRI: reverse line feed */
		    dscursormove(REVERSE_INDEX,1);
		    break;

		case 'J': /* HEOP: erase to end of screen */
		    dsfunction(ERASETO_EOS);
		    break;

		case 'K': /* HEOL: erase to end of line */
		    dsfunction(ERASETO_EOL);
		    break;

		case 'L': /* HIL: add new blank line */
		    dscursormove(INSERT_LINE,1);
		    break;

		case 'M': /* HDL: delete line */
		    dscursormove(DELETE_LINE,1);
		    break;

		case 'N': /* HDCH: delete character */
		    dsdelete(1);
		    break;

		case 'O': /* HERM: end insert mode */
		    dsfunction(INSERT_OFF);
		    break;

		case 'Y': /* HDCA: move cursor to specific position */
		    esc_mode = 11;
		    return (0);

		case 'Z': /* HID: Identify terminal sequence */
		    (void) write_to_tty("\033/K",3); /* can be vt52 */
		    break;

		case '@': /* HEIM: begin insert mode */
		    dsfunction(INSERT_ON);
		    break;

		case '[': /* ANSI controls for fun */
		    for (i=0; i<=MAXARG; i++)
			arg[i]=0;
		    esc_mode = 2;
		    private = 0;
		    return (0);

		case '=': /* HAKM: enter alternate keypad mode */
		    dskeyboard(DS_KEYPADAPPMODE, 1);
		    break;

		case '>': /* HXAM: exit alternate keypad mode */
		    dskeyboard(DS_KEYPADAPPMODE, 0);

		case 'b': /* HBD: erase to start of screen */
		    dsfunction(ERASETO_SOS);
		    break;

		case 'j': /* HSCP: save cursor position */
		    dscursormove(SAVE_CURSOR,0);
		    break;

		case 'k': /* HRCP: restore cursor position */
		    dscursormove(RESTORE_CURSOR,0);
		    break;

		case 'l': /* HEL: erase the current line */
		    dsfunction(ERASE_LINE);
		    break;

		case 'n': { /* HCPR: report cursor position */
		    char cursorpos[10];
		    int tempx, tempy;

		    dsgetcursor(&tempx, &tempy);
		    cursorpos[0] = '\033';
		    cursorpos[1] = 'Y';
		    cursorpos[2] = tempy + ' ';
		    cursorpos[3] = tempx + ' ';
		    cursorpos[4] = 0;
		    (void) write_to_tty(cursorpos, strlen(cursorpos));
		    break;
		    }

		case 'o': /* HEBL: erase to the beginning of the line */
		    dsfunction(ERASETO_SOL);
		    break;

		case 'p': /* HERV: begin stand out mode */
		    (void) dsstyle(INVERSE1);
		    break;

		case 'q': /* HXRV: end stand out mode */
		    (void) dsstyle(INVERSE0);
		    break;

		case 't': /* HEKS: enter shifted keypad mode */
		    dskeyboard(DS_KEYPADMODE, KEYPAD_H19S);
		    break;

		case 'u': /* HXKS: exit shifted keypad mode */
		    dskeyboard(DS_KEYPADMODE, KEYPAD_H19);
		    break;

		case 'v': /* HEWA: wrap mode on */
		    dsfunction(WRAP_ON);
		    break;

		case 'w': /* HXWA: wrap mode off */
		    dsfunction(WRAP_OFF);
		    break;

		case 'x': /* HSM: set mode */
		    esc_mode = 21;
		    return (0);

		case 'y': /* HRM: reset mode */
		    esc_mode = 22;
		    return (0);

		case 'z': /* HRAM: reset to power-up config */
		    dsfunction(RESET_DISPLAY);
		    break;
	    }
	    break;

	case 21: case 22:
	    terminalMode(c - '0', 2, esc_mode == 21);
	    break;
    }

    return (esc_mode = 0);
}

/* output characters to display
 * the buffer text must have at least one extra byte after text+count
 */
#define	FLUSHBUF    if (front < text) { *text = 0; dsputs(front); } front = text + 1;
void
termout(text, count)
char *text;
int count;
{
    static char buffer[MAXTERMBUF];
    char    c;
    char    *textend = text + count;
    char    *bp = buffer, *bpend = buffer + MAXTERMBUF - 1;
    char    *front;

    dscursoroff();
    for (front = text; text < textend; text++) {
	if ((c = *text ) >= ' ' || (c < 0)) {
	    if(!pass8) *text &= 127;
	    if (c == DEL) {
		vt100_yucky_wrap_mode = 0;
		FLUSHBUF;
		continue;
	    } else if (esc_mode) {
		vt100_yucky_wrap_mode = 0;
		if (!decode_escapes(c))
		    front++;
	    } 
	    continue;
	} else {
	    vt100_yucky_wrap_mode = 0;
	    FLUSHBUF;
	    switch (c) {
		case CTRL('G'):
		    if (bell_type & 1)
			dsinvert(VISUAL_BELL);
		    if (bell_type & 2)
			audiobell();
		    if (bell_type & 4)
		        DisplayBeep(0);
		    break;
		
		case CTRL('H'): /* cursor left */
		    dscursormove(CURSOR_LEFT, 1);
		    break;

		case '\t':	/* tab */
		    dscursormove(TAB_STOP,0);
		    break;

		case CTRL('L'): /* clear screen on h19 */
		    if (emulation == EMU_H19) {
			dsclearscreen();
			break;
		    }		/* fall through */
		case CTRL('J'):
		    if (ansi_LNM && c == CTRL('J')) {
			dscursormove(NEXT_LINE, 1);
			break;
		    }		/* fall through */
		case CTRL('K'): /* cursor down w/ scroll */
		    if (!dscheckdown()) {
			register char   *scan;
			register int    retcnt = 1;

			for (scan = text+1; scan < textend && *scan != ESC; scan++)
			    if (*scan == CTRL('J') || *scan == CTRL('K'))
				retcnt++;
			dscursormove(DOWN1_AND_SCROLL, retcnt);
		    }
		    break;

		case CTRL('M'): /* CR / newline */
		    dscursormove(BEGIN_LINE, 0);
		    break;

		case CTRL('N'): /* SI -- shift in alternate */
		    curset=1;
		    if (G[curset] || emulation == EMU_VT52)
			(void) dsstyle(ALTERNATE1);
		    else
			(void) dsstyle(ALTERNATE0);
		    break;

		case CTRL('O'): /* SO -- shift out alternate */
		    curset=0;
		    if (G[curset] && emulation == EMU_VT102)
			(void) dsstyle(ALTERNATE1);
		    else
			(void) dsstyle(ALTERNATE0);
		    break;

		case CTRL('X'): case CTRL('Z'): /* cancel escape sequence */
		    esc_mode = 0;
		    break;

		case ESC:	/* escape key */
		    switch (emulation) {
			case EMU_VT102:
			    esc_mode = 1;
			    break;

			case EMU_VT52:
			    esc_mode = 10;
			    break;

			case EMU_H19:
			    esc_mode = 20;
			    break;
		    }
		    curarg = 0;
		    break;
	    }
	}
    }
    FLUSHBUF;
    dscursoron();
}

/* send a DECREPTPARM report
 */
void
vtreport()
{
    char report[20];
    
    (void) strcpy(report, "\033[0;1;1;88;88;1;0x");
    report[2] = '0' + sendgarbage;
    (void) write_to_tty(report, strlen(report));
}

/* arguments for the style commands: SGR -- ESC [ param ; .. ; m
 */
void
vtstyle(c)
int c;
{
    switch (c) {
	case 1:
	    (void) dsstyle(BOLD1);
	    break;
	case 21:
	    (void) dsstyle(BOLD0);
	    break;
	case 3:
	    (void) dsstyle(ITALIC1);
	    break;
	case 23:
	    (void) dsstyle(ITALIC0);
	    break;
	case 4:
	    (void) dsstyle(UNDERLINE1);
	    break;
	case 24:
	    (void) dsstyle(UNDERLINE0);
	    break;
	case 5:
	    (void) dsstyle(BLINK1);
	    break;
	case 25:
	    (void) dsstyle(BLINK0);
	    break;
	case 7:
	    (void) dsstyle(INVERSE1);
	    break;
	case 27:
	    (void) dsstyle(INVERSE0);
	    break;
	case 8:
	    (void) dsstyle(BLANK1);
	    break;
	case 28:
	    (void) dsstyle(BLANK0);
	    break;
	case 0:
	    (void) dsstyle(STYLESOFF);
	    if (G[curset])
		(void) dsstyle(ALTERNATE1);
	    else
		(void) dsstyle(ALTERNATE0);
	    break;
	case 10:
	    (void) dsstyle(ALTERNATE1);
	    break;
	case 11:
	    (void) dsstyle(ALTERNATE0);
	    break;
    }
}

#if 0
/* set up termcap and termtype
 */
char *gettermcap()
{
    switch (emulation) {
	case EMU_H19:
	    return (h19termcap);
	case EMU_VT52:
	    return (vt52termcap);
	default:
	    return (termcap);
    }
}
char *gettermtype()
{
    switch (emulation) {
	case EMU_H19:
	    return (h19termtype);
	case EMU_VT52:
	    return (vt52termtype);
	default:
	    return (termtype);
    }
}
#endif
