xref: /plan9-contrib/sys/src/cmd/vt/vt.c (revision 21abd8f25aed5cdf552ef4ed86cf7cccb8b56d7c)
180ee5cbfSDavid du Colombier /*
280ee5cbfSDavid du Colombier  * Known bugs:
380ee5cbfSDavid du Colombier  *
480ee5cbfSDavid du Colombier  * 1. We don't handle cursor movement characters inside escape sequences.
580ee5cbfSDavid du Colombier  * 	That is, ESC[2C moves two to the right, so ESC[2\bC is supposed to back
680ee5cbfSDavid du Colombier  *	up one and then move two to the right.
780ee5cbfSDavid du Colombier  *
880ee5cbfSDavid du Colombier  * 2. We don't handle tabstops past nelem(tabcol) columns.
980ee5cbfSDavid du Colombier  *
1080ee5cbfSDavid du Colombier  * 3. We don't respect requests to do reverse video for the whole screen.
1180ee5cbfSDavid du Colombier  *
1280ee5cbfSDavid du Colombier  * 4. We ignore the ESC#n codes, so that we don't do double-width nor
1380ee5cbfSDavid du Colombier  * 	double-height lines, nor the ``fill the screen with E's'' confidence check.
149a747e4fSDavid du Colombier  *
159a747e4fSDavid du Colombier  * 5. Cursor key sequences aren't selected by keypad application mode.
169a747e4fSDavid du Colombier  *
179a747e4fSDavid du Colombier  * 6. "VT220" mode (-2) currently just switches the default cursor key
189a747e4fSDavid du Colombier  *	functions (same as -a); it's still just a VT100 emulation.
199a747e4fSDavid du Colombier  *
209a747e4fSDavid du Colombier  * 7. VT52 mode and a few other rarely used features are not implemented.
2180ee5cbfSDavid du Colombier  */
2280ee5cbfSDavid du Colombier 
237dd7cddfSDavid du Colombier #include <u.h>
247dd7cddfSDavid du Colombier #include <libc.h>
257dd7cddfSDavid du Colombier #include <draw.h>
267dd7cddfSDavid du Colombier #include <bio.h>
277dd7cddfSDavid du Colombier #include <ctype.h>
287dd7cddfSDavid du Colombier #include "cons.h"
297dd7cddfSDavid du Colombier 
3080ee5cbfSDavid du Colombier int	wraparound = 1;
3180ee5cbfSDavid du Colombier int	originrelative = 0;
3280ee5cbfSDavid du Colombier 
3380ee5cbfSDavid du Colombier int	tabcol[200];
3480ee5cbfSDavid du Colombier 
357dd7cddfSDavid du Colombier struct funckey vt100fk[NKEYS] = {
367dd7cddfSDavid du Colombier 	{ "up key",		"\033OA", },
377dd7cddfSDavid du Colombier 	{ "down key",		"\033OB", },
387dd7cddfSDavid du Colombier 	{ "left key",		"\033OD", },
397dd7cddfSDavid du Colombier 	{ "right key",		"\033OC", },
407dd7cddfSDavid du Colombier };
417dd7cddfSDavid du Colombier 
4280ee5cbfSDavid du Colombier struct funckey ansifk[NKEYS] = {
4380ee5cbfSDavid du Colombier 	{ "up key",		"\033[A", },
4480ee5cbfSDavid du Colombier 	{ "down key",		"\033[B", },
4580ee5cbfSDavid du Colombier 	{ "left key",		"\033[D", },
4680ee5cbfSDavid du Colombier 	{ "right key",		"\033[C", },
4780ee5cbfSDavid du Colombier 	{ "F1",			"\033OP", },
4880ee5cbfSDavid du Colombier 	{ "F2",			"\033OQ", },
4980ee5cbfSDavid du Colombier 	{ "F3",			"\033OR", },
5080ee5cbfSDavid du Colombier 	{ "F4",			"\033OS", },
5180ee5cbfSDavid du Colombier 	{ "F5",			"\033OT", },
5280ee5cbfSDavid du Colombier 	{ "F6",			"\033OU", },
5380ee5cbfSDavid du Colombier 	{ "F7",			"\033OV", },
5480ee5cbfSDavid du Colombier 	{ "F8",			"\033OW", },
5580ee5cbfSDavid du Colombier 	{ "F9",			"\033OX", },
5680ee5cbfSDavid du Colombier 	{ "F10",		"\033OY", },
5780ee5cbfSDavid du Colombier 	{ "F11",		"\033OZ", },
5880ee5cbfSDavid du Colombier 	{ "F12",		"\033O1", },
5980ee5cbfSDavid du Colombier };
6080ee5cbfSDavid du Colombier 
617dd7cddfSDavid du Colombier struct funckey vt220fk[NKEYS] = {
627dd7cddfSDavid du Colombier 	{ "up key",		"\033[A", },
637dd7cddfSDavid du Colombier 	{ "down key",		"\033[B", },
647dd7cddfSDavid du Colombier 	{ "left key",		"\033[D", },
657dd7cddfSDavid du Colombier 	{ "right key",		"\033[C", },
667dd7cddfSDavid du Colombier };
677dd7cddfSDavid du Colombier 
6832e56137SDavid du Colombier struct funckey xtermfk[NKEYS] = {
6932e56137SDavid du Colombier 	{ "page up",	"\033[5~", },
7032e56137SDavid du Colombier 	{ "page down",	"\033[6~", },
7132e56137SDavid du Colombier 	{ "up key",		"\033[A", },
7232e56137SDavid du Colombier 	{ "down key",		"\033[B", },
7332e56137SDavid du Colombier 	{ "left key",		"\033[D", },
7432e56137SDavid du Colombier 	{ "right key",		"\033[C", },
7532e56137SDavid du Colombier 	{ "F1",			"\033[11~", },
7632e56137SDavid du Colombier 	{ "F2",			"\033[12~", },
7732e56137SDavid du Colombier 	{ "F3",			"\033[13~", },
7832e56137SDavid du Colombier 	{ "F4",			"\033[14~", },
7932e56137SDavid du Colombier 	{ "F5",			"\033[15~", },
8032e56137SDavid du Colombier 	{ "F6",			"\033[17~", },
8132e56137SDavid du Colombier 	{ "F7",			"\033[18~", },
8232e56137SDavid du Colombier 	{ "F8",			"\033[19~", },
8332e56137SDavid du Colombier 	{ "F9",			"\033[20~", },
8432e56137SDavid du Colombier 	{ "F10",		"\033[21~", },
8532e56137SDavid du Colombier 	{ "F11",		"\033[22~", },
8632e56137SDavid du Colombier 	{ "F12",		"\033[23~", },
8732e56137SDavid du Colombier };
8832e56137SDavid du Colombier 
897dd7cddfSDavid du Colombier char gmap[256] = {
907dd7cddfSDavid du Colombier 	['_']	' ',	/* blank */
917dd7cddfSDavid du Colombier 	['\\']	'*',	/* diamond */
927dd7cddfSDavid du Colombier 	['a']	'X',	/* checkerboard */
937dd7cddfSDavid du Colombier 	['b']	'\t',	/* HT */
947dd7cddfSDavid du Colombier 	['c']	'\x0C',	/* FF */
957dd7cddfSDavid du Colombier 	['d']	'\r',	/* CR */
967dd7cddfSDavid du Colombier 	['e']	'\n',	/* LF */
977dd7cddfSDavid du Colombier 	['f']	'o',	/* degree */
987dd7cddfSDavid du Colombier 	['g']	'+',	/* plus/minus */
997dd7cddfSDavid du Colombier 	['h']	'\n',	/* NL, but close enough */
1007dd7cddfSDavid du Colombier 	['i']	'\v',	/* VT */
1017dd7cddfSDavid du Colombier 	['j']	'+',	/* lower right corner */
1027dd7cddfSDavid du Colombier 	['k']	'+',	/* upper right corner */
1037dd7cddfSDavid du Colombier 	['l']	'+',	/* upper left corner */
1047dd7cddfSDavid du Colombier 	['m']	'+',	/* lower left corner */
1057dd7cddfSDavid du Colombier 	['n']	'+',	/* crossing lines */
1067dd7cddfSDavid du Colombier 	['o']	'-',	/* horiz line - scan 1 */
1077dd7cddfSDavid du Colombier 	['p']	'-',	/* horiz line - scan 3 */
1087dd7cddfSDavid du Colombier 	['q']	'-',	/* horiz line - scan 5 */
1097dd7cddfSDavid du Colombier 	['r']	'-',	/* horiz line - scan 7 */
1107dd7cddfSDavid du Colombier 	['s']	'-',	/* horiz line - scan 9 */
1117dd7cddfSDavid du Colombier 	['t']	'+',	/* |-   */
1127dd7cddfSDavid du Colombier 	['u']	'+',	/* -| */
1137dd7cddfSDavid du Colombier 	['v']	'+',	/* upside down T */
1147dd7cddfSDavid du Colombier 	['w']	'+',	/* rightside up T */
1157dd7cddfSDavid du Colombier 	['x']	'|',	/* vertical bar */
1167dd7cddfSDavid du Colombier 	['y']	'<',	/* less/equal */
1177dd7cddfSDavid du Colombier 	['z']	'>',	/* gtr/equal */
1187dd7cddfSDavid du Colombier 	['{']	'p',	/* pi */
1197dd7cddfSDavid du Colombier 	['|']	'!',	/* not equal */
1207dd7cddfSDavid du Colombier 	['}']	'L',	/* pound symbol */
1217dd7cddfSDavid du Colombier 	['~']	'.',	/* centered dot: · */
1227dd7cddfSDavid du Colombier };
1237dd7cddfSDavid du Colombier 
12480ee5cbfSDavid du Colombier static void setattr(int argc, int *argv);
12580ee5cbfSDavid du Colombier 
1267dd7cddfSDavid du Colombier void
fixops(int * operand)12732e56137SDavid du Colombier fixops(int *operand)
12832e56137SDavid du Colombier {
12932e56137SDavid du Colombier 	if(operand[0] < 1)
13032e56137SDavid du Colombier 		operand[0] = 1;
13132e56137SDavid du Colombier }
13232e56137SDavid du Colombier 
13332e56137SDavid du Colombier void
emulate(void)1347dd7cddfSDavid du Colombier emulate(void)
1357dd7cddfSDavid du Colombier {
1367dd7cddfSDavid du Colombier 	char buf[BUFS+1];
13732e56137SDavid du Colombier 	int i;
1387dd7cddfSDavid du Colombier 	int n;
1397dd7cddfSDavid du Colombier 	int c;
14080ee5cbfSDavid du Colombier 	int operand[10];
14180ee5cbfSDavid du Colombier 	int noperand;
1427fb4e6f1SDavid du Colombier 	int savex, savey, saveattr, saveisgraphics;
1437dd7cddfSDavid du Colombier 	int isgraphics;
1447dd7cddfSDavid du Colombier 	int g0set, g1set;
14532e56137SDavid du Colombier 	int dch;
1467dd7cddfSDavid du Colombier 
1477dd7cddfSDavid du Colombier 	isgraphics = 0;
1487dd7cddfSDavid du Colombier 	g0set = 'B';	/* US ASCII */
1497dd7cddfSDavid du Colombier 	g1set = 'B';	/* US ASCII */
1507dd7cddfSDavid du Colombier 	savex = savey = 0;
15180ee5cbfSDavid du Colombier 	yscrmin = 0;
15280ee5cbfSDavid du Colombier 	yscrmax = ymax;
1537fb4e6f1SDavid du Colombier 	saveattr = 0;
15480ee5cbfSDavid du Colombier 	saveisgraphics = 0;
1559a747e4fSDavid du Colombier 	/* set initial tab stops to DEC-standard 8-column spacing */
1569a747e4fSDavid du Colombier 	for(c=0; (c+=8)<nelem(tabcol);)
1579a747e4fSDavid du Colombier 		tabcol[c] = 1;
1587dd7cddfSDavid du Colombier 
1597dd7cddfSDavid du Colombier 	for (;;) {
1607dd7cddfSDavid du Colombier 		if (y > ymax) {
1617dd7cddfSDavid du Colombier 			x = 0;
1627dd7cddfSDavid du Colombier 			newline();
1637dd7cddfSDavid du Colombier 		}
1647dd7cddfSDavid du Colombier 		buf[0] = get_next_char();
1657dd7cddfSDavid du Colombier 		buf[1] = '\0';
1667dd7cddfSDavid du Colombier 		switch(buf[0]) {
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier 		case '\000':
1697dd7cddfSDavid du Colombier 		case '\001':
1707dd7cddfSDavid du Colombier 		case '\002':
1717dd7cddfSDavid du Colombier 		case '\003':
1727dd7cddfSDavid du Colombier 		case '\004':
1737dd7cddfSDavid du Colombier 		case '\005':
1747dd7cddfSDavid du Colombier 		case '\006':
17580ee5cbfSDavid du Colombier 			goto Default;
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier 		case '\007':		/* bell */
1787dd7cddfSDavid du Colombier 			ringbell();
1797dd7cddfSDavid du Colombier 			break;
1807dd7cddfSDavid du Colombier 
1817dd7cddfSDavid du Colombier 		case '\010':		/* backspace */
1827dd7cddfSDavid du Colombier 			if (x > 0)
1837dd7cddfSDavid du Colombier 				--x;
1847dd7cddfSDavid du Colombier 			break;
1857dd7cddfSDavid du Colombier 
1869a747e4fSDavid du Colombier 		case '\011':		/* tab to next tab stop; if none, to right margin */
18780ee5cbfSDavid du Colombier 			for(c=x+1; c<nelem(tabcol) && !tabcol[c]; c++)
18880ee5cbfSDavid du Colombier 				;
18980ee5cbfSDavid du Colombier 			if(c < nelem(tabcol))
19080ee5cbfSDavid du Colombier 				x = c;
19180ee5cbfSDavid du Colombier 			else
1929a747e4fSDavid du Colombier 				x = xmax;
1937dd7cddfSDavid du Colombier 			break;
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier 		case '\012':		/* linefeed */
1967dd7cddfSDavid du Colombier 		case '\013':
1977dd7cddfSDavid du Colombier 		case '\014':
1987dd7cddfSDavid du Colombier 			newline();
1997dd7cddfSDavid du Colombier 			if (ttystate[cs->raw].nlcr)
2007dd7cddfSDavid du Colombier 				x = 0;
2017dd7cddfSDavid du Colombier 			break;
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier 		case '\015':		/* carriage return */
2047dd7cddfSDavid du Colombier 			x = 0;
2057dd7cddfSDavid du Colombier 			if (ttystate[cs->raw].crnl)
2067dd7cddfSDavid du Colombier 				newline();
2077dd7cddfSDavid du Colombier 			break;
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier 		case '\016':	/* SO: invoke G1 char set */
2107dd7cddfSDavid du Colombier 			isgraphics = (isdigit(g1set));
2117dd7cddfSDavid du Colombier 			break;
2127dd7cddfSDavid du Colombier 		case '\017':	/* SI: invoke G0 char set */
2137dd7cddfSDavid du Colombier 			isgraphics = (isdigit(g0set));
2147dd7cddfSDavid du Colombier 			break;
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier 		case '\020':	/* DLE */
2177dd7cddfSDavid du Colombier 		case '\021':	/* DC1 */
2187dd7cddfSDavid du Colombier 		case '\022':	/* XON */
2197dd7cddfSDavid du Colombier 		case '\023':	/* DC3 */
2207dd7cddfSDavid du Colombier 		case '\024':	/* XOFF */
2217dd7cddfSDavid du Colombier 		case '\025':	/* NAK */
2227dd7cddfSDavid du Colombier 		case '\026':	/* SYN */
2237dd7cddfSDavid du Colombier 		case '\027':	/* ETB */
2249a747e4fSDavid du Colombier 		case '\030':	/* CAN: cancel escape sequence, display checkerboard (not implemented) */
2259a747e4fSDavid du Colombier 		case '\031':	/* EM */
2267dd7cddfSDavid du Colombier 		case '\032':	/* SUB: same as CAN */
22780ee5cbfSDavid du Colombier 			goto Default;
22880ee5cbfSDavid du Colombier ;
2297dd7cddfSDavid du Colombier 		/* ESC, \033, is handled below */
2307dd7cddfSDavid du Colombier 		case '\034':	/* FS */
2317dd7cddfSDavid du Colombier 		case '\035':	/* GS */
2327dd7cddfSDavid du Colombier 		case '\036':	/* RS */
2337dd7cddfSDavid du Colombier 		case '\037':	/* US */
2347dd7cddfSDavid du Colombier 			break;
2357dd7cddfSDavid du Colombier 		case '\177':	/* delete: ignored */
2367dd7cddfSDavid du Colombier 			break;
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier 		case '\033':
23932e56137SDavid du Colombier 			switch(dch = get_next_char()){
2407dd7cddfSDavid du Colombier 			/*
2419a747e4fSDavid du Colombier 			 * 1 - graphic processor option on (no-op; not installed)
2429a747e4fSDavid du Colombier 			 */
2439a747e4fSDavid du Colombier 			case '1':
2449a747e4fSDavid du Colombier 				break;
2459a747e4fSDavid du Colombier 
2469a747e4fSDavid du Colombier 			/*
2479a747e4fSDavid du Colombier 			 * 2 - graphic processor option off (no-op; not installed)
2489a747e4fSDavid du Colombier 			 */
2499a747e4fSDavid du Colombier 			case '2':
2509a747e4fSDavid du Colombier 				break;
2519a747e4fSDavid du Colombier 
2529a747e4fSDavid du Colombier 			/*
2537dd7cddfSDavid du Colombier 			 * 7 - save cursor position.
2547dd7cddfSDavid du Colombier 			 */
2557dd7cddfSDavid du Colombier 			case '7':
25632e56137SDavid du Colombier //print("save\n");
2577dd7cddfSDavid du Colombier 				savex = x;
2587dd7cddfSDavid du Colombier 				savey = y;
2597fb4e6f1SDavid du Colombier 				saveattr = attr;
26080ee5cbfSDavid du Colombier 				saveisgraphics = isgraphics;
2617dd7cddfSDavid du Colombier 				break;
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier 			/*
2647dd7cddfSDavid du Colombier 			 * 8 - restore cursor position.
2657dd7cddfSDavid du Colombier 			 */
2667dd7cddfSDavid du Colombier 			case '8':
26732e56137SDavid du Colombier //print("restore\n");
2687dd7cddfSDavid du Colombier 				x = savex;
2697dd7cddfSDavid du Colombier 				y = savey;
2707fb4e6f1SDavid du Colombier 				attr = saveattr;
27180ee5cbfSDavid du Colombier 				isgraphics = saveisgraphics;
2727dd7cddfSDavid du Colombier 				break;
2737dd7cddfSDavid du Colombier 
2747dd7cddfSDavid du Colombier 			/*
27580ee5cbfSDavid du Colombier 			 * c - Reset terminal.
27680ee5cbfSDavid du Colombier 			 */
27780ee5cbfSDavid du Colombier 			case 'c':
27832e56137SDavid du Colombier print("resetterminal\n");
27980ee5cbfSDavid du Colombier 				cursoron = 1;
28080ee5cbfSDavid du Colombier 				ttystate[cs->raw].nlcr = 0;
28180ee5cbfSDavid du Colombier 				break;
28280ee5cbfSDavid du Colombier 
28380ee5cbfSDavid du Colombier 			/*
28480ee5cbfSDavid du Colombier 			 * D - active position down a line, scroll if at bottom margin.
2859a747e4fSDavid du Colombier 			 * (Original VT100 had a bug: tracked new-line/line-feed mode.)
2867dd7cddfSDavid du Colombier 			 */
2877dd7cddfSDavid du Colombier 			case 'D':
28880ee5cbfSDavid du Colombier 				if(++y > yscrmax) {
28980ee5cbfSDavid du Colombier 					y = yscrmax;
29080ee5cbfSDavid du Colombier 					scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax);
29180ee5cbfSDavid du Colombier 				}
2927dd7cddfSDavid du Colombier 				break;
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier 			/*
29580ee5cbfSDavid du Colombier 			 * E - active position to start of next line, scroll if at bottom margin.
29680ee5cbfSDavid du Colombier 			 */
29780ee5cbfSDavid du Colombier 			case 'E':
29880ee5cbfSDavid du Colombier 				x = 0;
29980ee5cbfSDavid du Colombier 				if(++y > yscrmax) {
30080ee5cbfSDavid du Colombier 					y = yscrmax;
30180ee5cbfSDavid du Colombier 					scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax);
30280ee5cbfSDavid du Colombier 				}
30380ee5cbfSDavid du Colombier 				break;
30480ee5cbfSDavid du Colombier 
30580ee5cbfSDavid du Colombier 			/*
30680ee5cbfSDavid du Colombier 			 * H - set tab stop at current column.
3079a747e4fSDavid du Colombier 			 * (This is cursor home in VT52 mode (not implemented).)
30880ee5cbfSDavid du Colombier 			 */
30980ee5cbfSDavid du Colombier 			case 'H':
31080ee5cbfSDavid du Colombier 				if(x < nelem(tabcol))
31180ee5cbfSDavid du Colombier 					tabcol[x] = 1;
31280ee5cbfSDavid du Colombier 				break;
31380ee5cbfSDavid du Colombier 
31480ee5cbfSDavid du Colombier 			/*
31580ee5cbfSDavid du Colombier 			 * M - active position up a line, scroll if at top margin..
3167dd7cddfSDavid du Colombier 			 */
3177dd7cddfSDavid du Colombier 			case 'M':
31880ee5cbfSDavid du Colombier 				if(--y < yscrmin) {
31980ee5cbfSDavid du Colombier 					y = yscrmin;
32080ee5cbfSDavid du Colombier 					scroll(yscrmin, yscrmax, yscrmin+1, yscrmin);
32180ee5cbfSDavid du Colombier 				}
3227dd7cddfSDavid du Colombier 				break;
3237dd7cddfSDavid du Colombier 
3247dd7cddfSDavid du Colombier 			/*
32580ee5cbfSDavid du Colombier 			 * Z - identification.  the terminal
3267dd7cddfSDavid du Colombier 			 * emulator will return the response
3277dd7cddfSDavid du Colombier 			 * code for a generic VT100.
3287dd7cddfSDavid du Colombier 			 */
3297dd7cddfSDavid du Colombier 			case 'Z':
3307dd7cddfSDavid du Colombier 			Ident:
3319a747e4fSDavid du Colombier 				sendnchars2(7, "\033[?1;2c");	/* VT100 with AVO option */
3329a747e4fSDavid du Colombier //				sendnchars2(5, "\033[?6c");	/* VT102 (insert/delete-char, etc.) */
3337dd7cddfSDavid du Colombier 				break;
3347dd7cddfSDavid du Colombier 
3357dd7cddfSDavid du Colombier 			/*
33680ee5cbfSDavid du Colombier 			 * < - enter ANSI mode
3377dd7cddfSDavid du Colombier 			 */
33880ee5cbfSDavid du Colombier 			case '<':
3397dd7cddfSDavid du Colombier 				break;
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 			/*
3429a747e4fSDavid du Colombier 			 * > - set numeric keypad mode on (not implemented)
3437dd7cddfSDavid du Colombier 			 */
3447dd7cddfSDavid du Colombier 			case '>':
3457dd7cddfSDavid du Colombier 				break;
3467dd7cddfSDavid du Colombier 
3477dd7cddfSDavid du Colombier 			/*
3489a747e4fSDavid du Colombier 			 * = - set numeric keypad mode off (not implemented)
3497dd7cddfSDavid du Colombier 			 */
3507dd7cddfSDavid du Colombier 			case '=':
3517dd7cddfSDavid du Colombier 				break;
3527dd7cddfSDavid du Colombier 
3537dd7cddfSDavid du Colombier 			/*
35480ee5cbfSDavid du Colombier 			 * # - Takes a one-digit argument
3557dd7cddfSDavid du Colombier 			 */
3567dd7cddfSDavid du Colombier 			case '#':
35780ee5cbfSDavid du Colombier 				switch(get_next_char()){
35880ee5cbfSDavid du Colombier 				case '3':		/* Top half of double-height line */
35980ee5cbfSDavid du Colombier 				case '4':		/* Bottom half of double-height line */
3609a747e4fSDavid du Colombier 				case '5':		/* Single-width single-height line */
36180ee5cbfSDavid du Colombier 				case '6':		/* Double-width line */
3629a747e4fSDavid du Colombier 				case '7':		/* Screen print */
36380ee5cbfSDavid du Colombier 				case '8':		/* Fill screen with E's */
36480ee5cbfSDavid du Colombier 					break;
36580ee5cbfSDavid du Colombier 				}
3667dd7cddfSDavid du Colombier 				break;
3677dd7cddfSDavid du Colombier 
3687dd7cddfSDavid du Colombier 			/*
3697dd7cddfSDavid du Colombier 			 * ( - switch G0 character set
3707dd7cddfSDavid du Colombier 			 */
3717dd7cddfSDavid du Colombier 			case '(':
3727dd7cddfSDavid du Colombier 				g0set = get_next_char();
3737dd7cddfSDavid du Colombier 				break;
3747dd7cddfSDavid du Colombier 
3757dd7cddfSDavid du Colombier 			/*
3767dd7cddfSDavid du Colombier 			 * - switch G1 character set
3777dd7cddfSDavid du Colombier 			 */
3787dd7cddfSDavid du Colombier 			case ')':
3797dd7cddfSDavid du Colombier 				g1set = get_next_char();
3807dd7cddfSDavid du Colombier 				break;
3817dd7cddfSDavid du Colombier 
3827dd7cddfSDavid du Colombier 			/*
3837dd7cddfSDavid du Colombier 			 * Received left bracket.
3847dd7cddfSDavid du Colombier 			 */
3857dd7cddfSDavid du Colombier 			case '[':
3867dd7cddfSDavid du Colombier 				/*
38780ee5cbfSDavid du Colombier 				 * A semi-colon or ? delimits arguments.
3887dd7cddfSDavid du Colombier 				 */
38980ee5cbfSDavid du Colombier 				memset(operand, 0, sizeof(operand));
39032e56137SDavid du Colombier 				operand[0] = number(buf, &i);
39180ee5cbfSDavid du Colombier 				noperand = 1;
3927dd7cddfSDavid du Colombier 				while(buf[0] == ';' || buf[0] == '?'){
39380ee5cbfSDavid du Colombier 					if(noperand < nelem(operand)){
39480ee5cbfSDavid du Colombier 						noperand++;
39580ee5cbfSDavid du Colombier 						operand[noperand-1] = number(buf, nil);
39680ee5cbfSDavid du Colombier 					} else
39780ee5cbfSDavid du Colombier 						number(buf, nil);
3987dd7cddfSDavid du Colombier 				}
3997dd7cddfSDavid du Colombier 
4007dd7cddfSDavid du Colombier 				/*
4017dd7cddfSDavid du Colombier 				 * do escape2 stuff
4027dd7cddfSDavid du Colombier 				 */
40332e56137SDavid du Colombier 				switch(dch = buf[0]){
4047dd7cddfSDavid du Colombier 					/*
4059a747e4fSDavid du Colombier 					 * c - same as ESC Z: what are you?
4067dd7cddfSDavid du Colombier 					 */
4077dd7cddfSDavid du Colombier 					case 'c':
4087dd7cddfSDavid du Colombier 						goto Ident;
4097dd7cddfSDavid du Colombier 
4107dd7cddfSDavid du Colombier 					/*
41180ee5cbfSDavid du Colombier 					 * g - various tabstop manipulation
4127dd7cddfSDavid du Colombier 					 */
41380ee5cbfSDavid du Colombier 					case 'g':
41480ee5cbfSDavid du Colombier 						switch(operand[0]){
41580ee5cbfSDavid du Colombier 						case 0:	/* clear tab at current column */
41680ee5cbfSDavid du Colombier 							if(x < nelem(tabcol))
41780ee5cbfSDavid du Colombier 								tabcol[x] = 0;
41880ee5cbfSDavid du Colombier 							break;
41980ee5cbfSDavid du Colombier 						case 3:	/* clear all tabs */
42080ee5cbfSDavid du Colombier 							memset(tabcol, 0, sizeof tabcol);
42180ee5cbfSDavid du Colombier 							break;
42280ee5cbfSDavid du Colombier 						}
4237dd7cddfSDavid du Colombier 						break;
4247dd7cddfSDavid du Colombier 
4257dd7cddfSDavid du Colombier 					/*
42680ee5cbfSDavid du Colombier 					 * l - clear various options.
42780ee5cbfSDavid du Colombier 					 */
42880ee5cbfSDavid du Colombier 					case 'l':
42980ee5cbfSDavid du Colombier 						if(noperand == 1){
43080ee5cbfSDavid du Colombier 							switch(operand[0]){
43180ee5cbfSDavid du Colombier 							case 20:	/* set line feed mode */
43232e56137SDavid du Colombier 								ttystate[cs->raw].nlcr = 1;
43380ee5cbfSDavid du Colombier 								break;
4349a747e4fSDavid du Colombier 							case 30:	/* screen invisible (? not supported through VT220) */
43580ee5cbfSDavid du Colombier 								break;
43680ee5cbfSDavid du Colombier 							}
4379a747e4fSDavid du Colombier 						}else while(--noperand > 0){
4389a747e4fSDavid du Colombier 							switch(operand[noperand]){
4399a747e4fSDavid du Colombier 							case 1:	/* set cursor keys to send ANSI functions: ESC [ A..D */
44080ee5cbfSDavid du Colombier 								break;
4419a747e4fSDavid du Colombier 							case 2:	/* set VT52 mode (not implemented) */
44280ee5cbfSDavid du Colombier 								break;
44380ee5cbfSDavid du Colombier 							case 3:	/* set 80 columns */
44480ee5cbfSDavid du Colombier 								setdim(-1, 80);
44580ee5cbfSDavid du Colombier 								break;
44680ee5cbfSDavid du Colombier 							case 4:	/* set jump scrolling */
44780ee5cbfSDavid du Colombier 								break;
44880ee5cbfSDavid du Colombier 							case 5:	/* set normal video on screen */
44980ee5cbfSDavid du Colombier 								break;
45080ee5cbfSDavid du Colombier 							case 6:	/* set origin to absolute */
45180ee5cbfSDavid du Colombier 								originrelative = 0;
4529a747e4fSDavid du Colombier 								x = y = 0;
45380ee5cbfSDavid du Colombier 								break;
45480ee5cbfSDavid du Colombier 							case 7:	/* reset auto-wrap mode */
45580ee5cbfSDavid du Colombier 								wraparound = 0;
45680ee5cbfSDavid du Colombier 								break;
45780ee5cbfSDavid du Colombier 							case 8:	/* reset auto-repeat mode */
45880ee5cbfSDavid du Colombier 								break;
45980ee5cbfSDavid du Colombier 							case 9:	/* reset interlacing mode */
46080ee5cbfSDavid du Colombier 								break;
4619a747e4fSDavid du Colombier 							case 25:	/* text cursor off (VT220) */
4629a747e4fSDavid du Colombier 								cursoron = 0;
4639a747e4fSDavid du Colombier 								break;
46480ee5cbfSDavid du Colombier 							}
46580ee5cbfSDavid du Colombier 						}
46680ee5cbfSDavid du Colombier 						break;
46780ee5cbfSDavid du Colombier 
46880ee5cbfSDavid du Colombier 					/*
46932e56137SDavid du Colombier 					* s - some dec private stuff. actually [ ? num s, but we can't detect it.
47032e56137SDavid du Colombier 					*/
47132e56137SDavid du Colombier 					case 's':
47232e56137SDavid du Colombier 						break;
47332e56137SDavid du Colombier 
47432e56137SDavid du Colombier 					/*
47580ee5cbfSDavid du Colombier 					 * h - set various options.
4767dd7cddfSDavid du Colombier 					 */
4777dd7cddfSDavid du Colombier 					case 'h':
47880ee5cbfSDavid du Colombier 						if(noperand == 1){
47980ee5cbfSDavid du Colombier 							switch(operand[0]){
48032e56137SDavid du Colombier 							default:
48132e56137SDavid du Colombier 								break;
48280ee5cbfSDavid du Colombier 							case 20:	/* set newline mode */
48332e56137SDavid du Colombier 								ttystate[cs->raw].nlcr = 0;
48480ee5cbfSDavid du Colombier 								break;
4859a747e4fSDavid du Colombier 							case 30:	/* screen visible (? not supported through VT220) */
48680ee5cbfSDavid du Colombier 								break;
48780ee5cbfSDavid du Colombier 							}
4889a747e4fSDavid du Colombier 						}else while(--noperand > 0){
4899a747e4fSDavid du Colombier 							switch(operand[noperand]){
49032e56137SDavid du Colombier 							default:
49132e56137SDavid du Colombier 								break;
4929a747e4fSDavid du Colombier 							case 1:	/* set cursor keys to send application function: ESC O A..D */
49380ee5cbfSDavid du Colombier 								break;
49480ee5cbfSDavid du Colombier 							case 2:	/* set ANSI */
49580ee5cbfSDavid du Colombier 								break;
49680ee5cbfSDavid du Colombier 							case 3:	/* set 132 columns */
49780ee5cbfSDavid du Colombier 								setdim(-1, 132);
49880ee5cbfSDavid du Colombier 								break;
49980ee5cbfSDavid du Colombier 							case 4:	/* set smooth scrolling */
50080ee5cbfSDavid du Colombier 								break;
5019a747e4fSDavid du Colombier 							case 5:	/* set screen to reverse video (not implemented) */
50280ee5cbfSDavid du Colombier 								break;
50380ee5cbfSDavid du Colombier 							case 6:	/* set origin to relative */
50480ee5cbfSDavid du Colombier 								originrelative = 1;
5059a747e4fSDavid du Colombier 								x = 0;
5069a747e4fSDavid du Colombier 								y = yscrmin;
50780ee5cbfSDavid du Colombier 								break;
50880ee5cbfSDavid du Colombier 							case 7:	/* set auto-wrap mode */
50980ee5cbfSDavid du Colombier 								wraparound = 1;
51080ee5cbfSDavid du Colombier 								break;
51180ee5cbfSDavid du Colombier 							case 8:	/* set auto-repeat mode */
51280ee5cbfSDavid du Colombier 								break;
51380ee5cbfSDavid du Colombier 							case 9:	/* set interlacing mode */
51480ee5cbfSDavid du Colombier 								break;
5159a747e4fSDavid du Colombier 							case 25:	/* text cursor on (VT220) */
5169a747e4fSDavid du Colombier 								cursoron = 1;
5179a747e4fSDavid du Colombier 								break;
51880ee5cbfSDavid du Colombier 							}
51980ee5cbfSDavid du Colombier 						}
52080ee5cbfSDavid du Colombier 						break;
52180ee5cbfSDavid du Colombier 
52280ee5cbfSDavid du Colombier 					/*
5237fb4e6f1SDavid du Colombier 					 * m - change character attrs.
52480ee5cbfSDavid du Colombier 					 */
52580ee5cbfSDavid du Colombier 					case 'm':
52680ee5cbfSDavid du Colombier 						setattr(noperand, operand);
52780ee5cbfSDavid du Colombier 						break;
52880ee5cbfSDavid du Colombier 
52980ee5cbfSDavid du Colombier 					/*
5309a747e4fSDavid du Colombier 					 * n - request various reports
5319a747e4fSDavid du Colombier 					 */
5329a747e4fSDavid du Colombier 					case 'n':
5339a747e4fSDavid du Colombier 						switch(operand[0]){
5349a747e4fSDavid du Colombier 						case 5:	/* status */
5359a747e4fSDavid du Colombier 							sendnchars2(4, "\033[0n");	/* terminal ok */
5369a747e4fSDavid du Colombier 							break;
5379a747e4fSDavid du Colombier 						case 6:	/* cursor position */
5389a747e4fSDavid du Colombier 							sendnchars2(sprint(buf, "\033[%d;%dR",
5399a747e4fSDavid du Colombier 								originrelative ? y+1 - yscrmin : y+1, x+1), buf);
5409a747e4fSDavid du Colombier 							break;
5419a747e4fSDavid du Colombier 						}
5429a747e4fSDavid du Colombier 						break;
5439a747e4fSDavid du Colombier 
5449a747e4fSDavid du Colombier 					/*
5459a747e4fSDavid du Colombier 					 * q - turn on list of LEDs; turn off others.
54680ee5cbfSDavid du Colombier 					 */
54780ee5cbfSDavid du Colombier 					case 'q':
54880ee5cbfSDavid du Colombier 						break;
54980ee5cbfSDavid du Colombier 
55080ee5cbfSDavid du Colombier 					/*
55180ee5cbfSDavid du Colombier 					 * r - change scrolling region.  operand[0] is
55280ee5cbfSDavid du Colombier 					 * min scrolling region and operand[1] is max
55380ee5cbfSDavid du Colombier 					 * scrolling region.
55480ee5cbfSDavid du Colombier 					 */
55580ee5cbfSDavid du Colombier 					case 'r':
55680ee5cbfSDavid du Colombier 						yscrmin = 0;
55780ee5cbfSDavid du Colombier 						yscrmax = ymax;
55880ee5cbfSDavid du Colombier 						switch(noperand){
55980ee5cbfSDavid du Colombier 						case 2:
56080ee5cbfSDavid du Colombier 							yscrmax = operand[1]-1;
5619a747e4fSDavid du Colombier 							if(yscrmax > ymax)
5629a747e4fSDavid du Colombier 								yscrmax = ymax;
56380ee5cbfSDavid du Colombier 						case 1:
56480ee5cbfSDavid du Colombier 							yscrmin = operand[0]-1;
56580ee5cbfSDavid du Colombier 							if(yscrmin < 0)
56680ee5cbfSDavid du Colombier 								yscrmin = 0;
56780ee5cbfSDavid du Colombier 						}
56880ee5cbfSDavid du Colombier 						x = 0;
56980ee5cbfSDavid du Colombier 						y = yscrmin;
5707dd7cddfSDavid du Colombier 						break;
5717dd7cddfSDavid du Colombier 
5727dd7cddfSDavid du Colombier 					/*
5739a747e4fSDavid du Colombier 					 * x - report terminal parameters
5749a747e4fSDavid du Colombier 					 */
5759a747e4fSDavid du Colombier 					case 'x':
5769a747e4fSDavid du Colombier 						sendnchars2(20, "\033[3;1;1;120;120;1;0x");
5779a747e4fSDavid du Colombier 						break;
5789a747e4fSDavid du Colombier 
5799a747e4fSDavid du Colombier 					/*
5809a747e4fSDavid du Colombier 					 * y - invoke confidence test
5819a747e4fSDavid du Colombier 					 */
5829a747e4fSDavid du Colombier 					case 'y':
5839a747e4fSDavid du Colombier 						break;
5849a747e4fSDavid du Colombier 
5859a747e4fSDavid du Colombier 					/*
5867dd7cddfSDavid du Colombier 					 * A - cursor up.
5877dd7cddfSDavid du Colombier 					 */
58832e56137SDavid du Colombier 					case 'e':
5897dd7cddfSDavid du Colombier 					case 'A':
59032e56137SDavid du Colombier 						fixops(operand);
59180ee5cbfSDavid du Colombier 						y -= operand[0];
59280ee5cbfSDavid du Colombier 						if(y < yscrmin)
59380ee5cbfSDavid du Colombier 							y = yscrmin;
59480ee5cbfSDavid du Colombier 						olines -= operand[0];
5957dd7cddfSDavid du Colombier 						if(olines < 0)
5967dd7cddfSDavid du Colombier 							olines = 0;
5977dd7cddfSDavid du Colombier 						break;
5987dd7cddfSDavid du Colombier 
5997dd7cddfSDavid du Colombier 					/*
6007dd7cddfSDavid du Colombier 					 * B - cursor down
6017dd7cddfSDavid du Colombier 					 */
6027dd7cddfSDavid du Colombier 					case 'B':
60332e56137SDavid du Colombier 						fixops(operand);
60480ee5cbfSDavid du Colombier 						y += operand[0];
60580ee5cbfSDavid du Colombier 						if(y > yscrmax)
60680ee5cbfSDavid du Colombier 							y=yscrmax;
6077dd7cddfSDavid du Colombier 						break;
6087dd7cddfSDavid du Colombier 
6097dd7cddfSDavid du Colombier 					/*
6109a747e4fSDavid du Colombier 					 * C - cursor right
6117dd7cddfSDavid du Colombier 					 */
61232e56137SDavid du Colombier 					case 'a':
6137dd7cddfSDavid du Colombier 					case 'C':
61432e56137SDavid du Colombier 						fixops(operand);
61580ee5cbfSDavid du Colombier 						x += operand[0];
61680ee5cbfSDavid du Colombier 						/*
61780ee5cbfSDavid du Colombier 						 * VT-100-UG says not to go past the
61880ee5cbfSDavid du Colombier 						 * right margin.
61980ee5cbfSDavid du Colombier 						 */
62080ee5cbfSDavid du Colombier 						if(x > xmax)
62180ee5cbfSDavid du Colombier 							x = xmax;
6227dd7cddfSDavid du Colombier 						break;
6237dd7cddfSDavid du Colombier 
6247dd7cddfSDavid du Colombier 					/*
6259a747e4fSDavid du Colombier 					 * D - cursor left
6267dd7cddfSDavid du Colombier 					 */
6277dd7cddfSDavid du Colombier 					case 'D':
62832e56137SDavid du Colombier 						fixops(operand);
62980ee5cbfSDavid du Colombier 						x -= operand[0];
6307dd7cddfSDavid du Colombier 						if(x < 0)
6317dd7cddfSDavid du Colombier 							x = 0;
6327dd7cddfSDavid du Colombier 						break;
6337dd7cddfSDavid du Colombier 
6347dd7cddfSDavid du Colombier 					/*
63532e56137SDavid du Colombier 					 *	G - cursor to column
63632e56137SDavid du Colombier 					 */
63732e56137SDavid du Colombier 					case '\'':
63832e56137SDavid du Colombier 					case 'G':
63932e56137SDavid du Colombier 						fixops(operand);
64032e56137SDavid du Colombier 						x = operand[0] - 1;
64132e56137SDavid du Colombier 						if(x > xmax)
64232e56137SDavid du Colombier 							x = xmax;
64332e56137SDavid du Colombier 						break;
64432e56137SDavid du Colombier 
64532e56137SDavid du Colombier 					/*
64680ee5cbfSDavid du Colombier 					 * H and f - cursor motion.  operand[0] is row and
6479a747e4fSDavid du Colombier 					 * operand[1] is column, origin 1.
6487dd7cddfSDavid du Colombier 					 */
6497dd7cddfSDavid du Colombier 					case 'H':
65080ee5cbfSDavid du Colombier 					case 'f':
65132e56137SDavid du Colombier 						fixops(operand+1);
65280ee5cbfSDavid du Colombier 						x = operand[1] - 1;
65380ee5cbfSDavid du Colombier 						if(x > xmax)
65480ee5cbfSDavid du Colombier 							x = xmax;
65532e56137SDavid du Colombier 
65632e56137SDavid du Colombier 						/* fallthrough */
65732e56137SDavid du Colombier 
65832e56137SDavid du Colombier 					/*
65932e56137SDavid du Colombier 					 * d - cursor to line n (xterm)
66032e56137SDavid du Colombier 					 */
66132e56137SDavid du Colombier 					case 'd':
66232e56137SDavid du Colombier 						fixops(operand);
66380ee5cbfSDavid du Colombier 						y = operand[0] - 1;
66480ee5cbfSDavid du Colombier 						if(originrelative){
66580ee5cbfSDavid du Colombier 							y += yscrmin;
66680ee5cbfSDavid du Colombier 							if(y > yscrmax)
66780ee5cbfSDavid du Colombier 								y = yscrmax;
66832e56137SDavid du Colombier 						}else{
66932e56137SDavid du Colombier 							if(y > ymax)
67032e56137SDavid du Colombier 								y = ymax;
67180ee5cbfSDavid du Colombier 						}
6727dd7cddfSDavid du Colombier 						break;
6737dd7cddfSDavid du Colombier 
6747dd7cddfSDavid du Colombier 					/*
67580ee5cbfSDavid du Colombier 					 * J - clear some or all of the display.
6767dd7cddfSDavid du Colombier 					 */
6777dd7cddfSDavid du Colombier 					case 'J':
67880ee5cbfSDavid du Colombier 						switch (operand[0]) {
6797dd7cddfSDavid du Colombier 							/*
6807dd7cddfSDavid du Colombier 							 * operand 2:  whole screen.
6817dd7cddfSDavid du Colombier 							 */
6827dd7cddfSDavid du Colombier 							case 2:
6837dd7cddfSDavid du Colombier 								clear(Rpt(pt(0, 0), pt(xmax+1, ymax+1)));
6847dd7cddfSDavid du Colombier 								break;
6857dd7cddfSDavid du Colombier 							/*
68680ee5cbfSDavid du Colombier 							 * operand 1: start of screen to active position, inclusive.
68780ee5cbfSDavid du Colombier 							 */
68880ee5cbfSDavid du Colombier 							case 1:
6899a747e4fSDavid du Colombier 								clear(Rpt(pt(0, 0), pt(xmax+1, y)));
69080ee5cbfSDavid du Colombier 								clear(Rpt(pt(0, y), pt(x+1, y+1)));
69180ee5cbfSDavid du Colombier 								break;
69280ee5cbfSDavid du Colombier 							/*
69380ee5cbfSDavid du Colombier 							 * Default:  active position to end of screen, inclusive.
6947dd7cddfSDavid du Colombier 							 */
6957dd7cddfSDavid du Colombier 							default:
69680ee5cbfSDavid du Colombier 								clear(Rpt(pt(x, y), pt(xmax+1, y+1)));
6977dd7cddfSDavid du Colombier 								clear(Rpt(pt(0, y+1), pt(xmax+1, ymax+1)));
6987dd7cddfSDavid du Colombier 								break;
6997dd7cddfSDavid du Colombier 						}
7007dd7cddfSDavid du Colombier 						break;
7017dd7cddfSDavid du Colombier 
7027dd7cddfSDavid du Colombier 					/*
70380ee5cbfSDavid du Colombier 					 * K - clear some or all of the line.
7047dd7cddfSDavid du Colombier 					 */
7057dd7cddfSDavid du Colombier 					case 'K':
70680ee5cbfSDavid du Colombier 						switch (operand[0]) {
70780ee5cbfSDavid du Colombier 							/*
70880ee5cbfSDavid du Colombier 							 * operand 2: whole line.
70980ee5cbfSDavid du Colombier 							 */
71080ee5cbfSDavid du Colombier 							case 2:
7119a747e4fSDavid du Colombier 								clear(Rpt(pt(0, y), pt(xmax+1, y+1)));
7127dd7cddfSDavid du Colombier 								break;
71380ee5cbfSDavid du Colombier 							/*
71480ee5cbfSDavid du Colombier 							 * operand 1: start of line to active position, inclusive.
71580ee5cbfSDavid du Colombier 							 */
71680ee5cbfSDavid du Colombier 							case 1:
71780ee5cbfSDavid du Colombier 								clear(Rpt(pt(0, y), pt(x+1, y+1)));
71880ee5cbfSDavid du Colombier 								break;
71980ee5cbfSDavid du Colombier 							/*
72080ee5cbfSDavid du Colombier 							 * Default: active position to end of line, inclusive.
72180ee5cbfSDavid du Colombier 							 */
72280ee5cbfSDavid du Colombier 							default:
72380ee5cbfSDavid du Colombier 								clear(Rpt(pt(x, y), pt(xmax+1, y+1)));
72480ee5cbfSDavid du Colombier 								break;
72580ee5cbfSDavid du Colombier 						}
72680ee5cbfSDavid du Colombier 						break;
7277dd7cddfSDavid du Colombier 
7287dd7cddfSDavid du Colombier 					/*
72932e56137SDavid du Colombier 					 *	P - delete character(s) from right of cursor (xterm)
73032e56137SDavid du Colombier 					 */
73132e56137SDavid du Colombier 					case 'P':
73232e56137SDavid du Colombier 						fixops(operand);
73332e56137SDavid du Colombier 						i = x + operand[0];
73432e56137SDavid du Colombier 						draw(screen, Rpt(pt(x, y), pt(xmax+1, y+1)), screen, nil, pt(i, y));
73532e56137SDavid du Colombier 						clear(Rpt(pt(xmax-operand[0], y), pt(xmax+1, y+1)));
73632e56137SDavid du Colombier 						break;
73732e56137SDavid du Colombier 
73832e56137SDavid du Colombier 					/*
73932e56137SDavid du Colombier 					 *	@ - insert blank(s) to right of cursor (xterm)
74032e56137SDavid du Colombier 					 */
74132e56137SDavid du Colombier 					case '@':
74232e56137SDavid du Colombier 						fixops(operand);
74332e56137SDavid du Colombier 						i = x + operand[0];
74432e56137SDavid du Colombier 						draw(screen, Rpt(pt(i, y), pt(xmax+1, y+1)), screen, nil, pt(x, y));
74532e56137SDavid du Colombier 						clear(Rpt(pt(x, y), pt(i, y+1)));
74632e56137SDavid du Colombier 						break;
74732e56137SDavid du Colombier 
74832e56137SDavid du Colombier 
74932e56137SDavid du Colombier 					/*
75032e56137SDavid du Colombier 					 *	X - erase character(s) at cursor and to the right (xterm)
75132e56137SDavid du Colombier 					 */
75232e56137SDavid du Colombier 					case 'X':
75332e56137SDavid du Colombier 						fixops(operand);
75432e56137SDavid du Colombier 						i = x + operand[0];
75532e56137SDavid du Colombier 						clear(Rpt(pt(x, y), pt(i, y+1)));
75632e56137SDavid du Colombier 						break;
75732e56137SDavid du Colombier 
75832e56137SDavid du Colombier 					/*
7599a747e4fSDavid du Colombier 					 * L - insert a line at cursor position (VT102 and later)
7607dd7cddfSDavid du Colombier 					 */
7617dd7cddfSDavid du Colombier 					case 'L':
76232e56137SDavid du Colombier 						fixops(operand);
76332e56137SDavid du Colombier 						for(i = 0; i < operand[0]; ++i)
76480ee5cbfSDavid du Colombier 							scroll(y, yscrmax, y+1, y);
7657dd7cddfSDavid du Colombier 						break;
7667dd7cddfSDavid du Colombier 
7677dd7cddfSDavid du Colombier 					/*
7689a747e4fSDavid du Colombier 					 * M - delete a line at cursor position (VT102 and later)
7697dd7cddfSDavid du Colombier 					 */
7707dd7cddfSDavid du Colombier 					case 'M':
77132e56137SDavid du Colombier 						fixops(operand);
77232e56137SDavid du Colombier 						for(i = 0; i < operand[0]; ++i)
77380ee5cbfSDavid du Colombier 							scroll(y+1, yscrmax+1, y, yscrmax);
7747dd7cddfSDavid du Colombier 						break;
7757dd7cddfSDavid du Colombier 
77632e56137SDavid du Colombier 					/*
77732e56137SDavid du Colombier 					 * S,T - scroll up/down (xterm)
77832e56137SDavid du Colombier 					 */
77932e56137SDavid du Colombier 					case 'T':
78032e56137SDavid du Colombier 						fixops(operand);
78132e56137SDavid du Colombier 						for(i = 0; i < operand[0]; ++i)
78232e56137SDavid du Colombier 							scroll(yscrmin, yscrmax, yscrmin+1, yscrmin);
78332e56137SDavid du Colombier 						break;
78432e56137SDavid du Colombier 
78532e56137SDavid du Colombier 					case 'S':
78632e56137SDavid du Colombier 						fixops(operand);
78732e56137SDavid du Colombier 						for(i = 0; i < operand[0]; ++i)
78832e56137SDavid du Colombier 							scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmin);
78932e56137SDavid du Colombier 						break;
79032e56137SDavid du Colombier 
7919a747e4fSDavid du Colombier 					case '=':	/* ? not supported through VT220 */
79280ee5cbfSDavid du Colombier 						number(buf, nil);
79380ee5cbfSDavid du Colombier 						switch(buf[0]) {
79480ee5cbfSDavid du Colombier 						case 'h':
79580ee5cbfSDavid du Colombier 						case 'l':
7967dd7cddfSDavid du Colombier 							break;
79780ee5cbfSDavid du Colombier 						}
7987dd7cddfSDavid du Colombier 						break;
7997dd7cddfSDavid du Colombier 
8007dd7cddfSDavid du Colombier 					/*
8017dd7cddfSDavid du Colombier 					 * Anything else we ignore for now...
8027dd7cddfSDavid du Colombier 					 */
8037dd7cddfSDavid du Colombier 					default:
80432e56137SDavid du Colombier print("unknown escape2 '%c' (0x%x)\n", dch, dch);
8057dd7cddfSDavid du Colombier 						break;
8067dd7cddfSDavid du Colombier 				}
8077dd7cddfSDavid du Colombier 
8087dd7cddfSDavid du Colombier 				break;
8097dd7cddfSDavid du Colombier 
8107dd7cddfSDavid du Colombier 			/*
8119a747e4fSDavid du Colombier 			 * Collapse multiple '\033' to one.
8129a747e4fSDavid du Colombier 			 */
8139a747e4fSDavid du Colombier 			case '\033':
8149a747e4fSDavid du Colombier 				peekc = '\033';
8159a747e4fSDavid du Colombier 				break;
8169a747e4fSDavid du Colombier 
81732e56137SDavid du Colombier 			/* set title */
81832e56137SDavid du Colombier 			case ']':	/* it's actually <esc> ] num ; title <bel> */
81932e56137SDavid du Colombier 				{
82032e56137SDavid du Colombier 					int ch, fd;
82132e56137SDavid du Colombier 					number(buf, nil);
82232e56137SDavid du Colombier 					i = 0;
82332e56137SDavid du Colombier 					while((ch = get_next_char()) != '\a')
82432e56137SDavid du Colombier 						if(i < sizeof buf)
82532e56137SDavid du Colombier 							buf[i++] = ch;
82632e56137SDavid du Colombier 					fd = open("/dev/label", OWRITE);
82732e56137SDavid du Colombier 					write(fd, buf, i);
82832e56137SDavid du Colombier 					close(fd);
82932e56137SDavid du Colombier 				}
83032e56137SDavid du Colombier 				break;
83132e56137SDavid du Colombier 
8329a747e4fSDavid du Colombier 			/*
8337dd7cddfSDavid du Colombier 			 * Ignore other commands.
8347dd7cddfSDavid du Colombier 			 */
8357dd7cddfSDavid du Colombier 			default:
83632e56137SDavid du Colombier print("unknown command '%c' (0x%x)\n", dch, dch);
8377dd7cddfSDavid du Colombier 				break;
8387dd7cddfSDavid du Colombier 
8397dd7cddfSDavid du Colombier 			}
8407dd7cddfSDavid du Colombier 			break;
8417dd7cddfSDavid du Colombier 
8427dd7cddfSDavid du Colombier 		default:		/* ordinary char */
84380ee5cbfSDavid du Colombier Default:
8447dd7cddfSDavid du Colombier 			if(isgraphics && gmap[(uchar) buf[0]])
8457dd7cddfSDavid du Colombier 				buf[0] = gmap[(uchar) buf[0]];
8467dd7cddfSDavid du Colombier 
8477dd7cddfSDavid du Colombier 			/* line wrap */
8487dd7cddfSDavid du Colombier 			if (x > xmax){
84980ee5cbfSDavid du Colombier 				if(wraparound){
8507dd7cddfSDavid du Colombier 					x = 0;
8517dd7cddfSDavid du Colombier 					newline();
85280ee5cbfSDavid du Colombier 				}else{
85380ee5cbfSDavid du Colombier 					continue;
85480ee5cbfSDavid du Colombier 				}
8557dd7cddfSDavid du Colombier 			}
8567dd7cddfSDavid du Colombier 			n = 1;
8577dd7cddfSDavid du Colombier 			c = 0;
8587dd7cddfSDavid du Colombier 			while (!cs->raw && host_avail() && x+n<=xmax && n<BUFS
8597dd7cddfSDavid du Colombier 			    && (c = get_next_char())>=' ' && c<'\177') {
8607dd7cddfSDavid du Colombier 				buf[n++] = c;
8617dd7cddfSDavid du Colombier 				c = 0;
8627dd7cddfSDavid du Colombier 			}
8637dd7cddfSDavid du Colombier 			buf[n] = 0;
8647dd7cddfSDavid du Colombier //			clear(Rpt(pt(x,y), pt(x+n, y+1)));
8657fb4e6f1SDavid du Colombier 			drawstring(pt(x, y), buf, attr);
8667dd7cddfSDavid du Colombier 			x += n;
8677dd7cddfSDavid du Colombier 			peekc = c;
8687dd7cddfSDavid du Colombier 			break;
8697dd7cddfSDavid du Colombier 		}
8707dd7cddfSDavid du Colombier 	}
8717dd7cddfSDavid du Colombier }
87280ee5cbfSDavid du Colombier 
87380ee5cbfSDavid du Colombier static void
setattr(int argc,int * argv)87480ee5cbfSDavid du Colombier setattr(int argc, int *argv)
87580ee5cbfSDavid du Colombier {
87680ee5cbfSDavid du Colombier 	int i;
87780ee5cbfSDavid du Colombier 
87880ee5cbfSDavid du Colombier 	for(i=0; i<argc; i++) {
87980ee5cbfSDavid du Colombier 		switch(argv[i]) {
88080ee5cbfSDavid du Colombier 		case 0:
8817fb4e6f1SDavid du Colombier 			attr = defattr;
8827fb4e6f1SDavid du Colombier 			fgcolor = fgdefault;
8837fb4e6f1SDavid du Colombier 			bgcolor = bgdefault;
88480ee5cbfSDavid du Colombier 			break;
88580ee5cbfSDavid du Colombier 		case 1:
8867fb4e6f1SDavid du Colombier 			attr |= THighIntensity;
88780ee5cbfSDavid du Colombier 			break;
88880ee5cbfSDavid du Colombier 		case 4:
8897fb4e6f1SDavid du Colombier 			attr |= TUnderline;
89080ee5cbfSDavid du Colombier 			break;
89180ee5cbfSDavid du Colombier 		case 5:
8927fb4e6f1SDavid du Colombier 			attr |= TBlink;
89380ee5cbfSDavid du Colombier 			break;
89480ee5cbfSDavid du Colombier 		case 7:
8957fb4e6f1SDavid du Colombier 			attr |= TReverse;
89680ee5cbfSDavid du Colombier 			break;
89780ee5cbfSDavid du Colombier 		case 8:
8987fb4e6f1SDavid du Colombier 			attr |= TInvisible;
89980ee5cbfSDavid du Colombier 			break;
90080ee5cbfSDavid du Colombier 		case 22:
9017fb4e6f1SDavid du Colombier 			attr &= ~THighIntensity;
90280ee5cbfSDavid du Colombier 			break;
90380ee5cbfSDavid du Colombier 		case 24:
9047fb4e6f1SDavid du Colombier 			attr &= ~TUnderline;
90580ee5cbfSDavid du Colombier 			break;
90680ee5cbfSDavid du Colombier 		case 25:
9077fb4e6f1SDavid du Colombier 			attr &= ~TBlink;
90880ee5cbfSDavid du Colombier 			break;
90980ee5cbfSDavid du Colombier 		case 27:
9107fb4e6f1SDavid du Colombier 			attr &= ~TReverse;
91180ee5cbfSDavid du Colombier 			break;
91280ee5cbfSDavid du Colombier 		case 28:
9137fb4e6f1SDavid du Colombier 			attr &= ~TInvisible;
91480ee5cbfSDavid du Colombier 			break;
91532e56137SDavid du Colombier 		case 30:	/* black */
91632e56137SDavid du Colombier 		case 31:	/* red */
91732e56137SDavid du Colombier 		case 32:	/* green */
91832e56137SDavid du Colombier 		case 33:	/* brown */
91932e56137SDavid du Colombier 		case 34:	/* blue */
92032e56137SDavid du Colombier 		case 35:	/* purple */
92132e56137SDavid du Colombier 		case 36:	/* cyan */
92232e56137SDavid du Colombier 		case 37:	/* white */
923*21abd8f2SDavid du Colombier 			fgcolor = (nocolor? fgdefault: colors[argv[i]-30]);
92480ee5cbfSDavid du Colombier 			break;
92532e56137SDavid du Colombier 		case 39:
9267fb4e6f1SDavid du Colombier 			fgcolor = fgdefault;
92732e56137SDavid du Colombier 			break;
92832e56137SDavid du Colombier 		case 40:	/* black */
92932e56137SDavid du Colombier 		case 41:	/* red */
93032e56137SDavid du Colombier 		case 42:	/* green */
93132e56137SDavid du Colombier 		case 43:	/* brown */
93232e56137SDavid du Colombier 		case 44:	/* blue */
93332e56137SDavid du Colombier 		case 45:	/* purple */
93432e56137SDavid du Colombier 		case 46:	/* cyan */
93532e56137SDavid du Colombier 		case 47:	/* white */
936*21abd8f2SDavid du Colombier 			bgcolor = (nocolor? bgdefault: colors[argv[i]-40]);
93780ee5cbfSDavid du Colombier 			break;
93832e56137SDavid du Colombier 		case 49:
9397fb4e6f1SDavid du Colombier 			bgcolor = bgdefault;
94032e56137SDavid du Colombier 			break;
94180ee5cbfSDavid du Colombier 		}
94280ee5cbfSDavid du Colombier 	}
94380ee5cbfSDavid du Colombier }
944