]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vt/vt.c
vt: dont pollute the outer environment (thanks mischief!)
[plan9front.git] / sys / src / cmd / vt / vt.c
1 /*
2  * Known bugs:
3  *
4  * 1. We don't handle cursor movement characters inside escape sequences.
5  *      That is, ESC[2C moves two to the right, so ESC[2\bC is supposed to back
6  *      up one and then move two to the right.
7  *
8  * 2. We don't handle tabstops past nelem(tabcol) columns.
9  *
10  * 3. We don't respect requests to do reverse video for the whole screen.
11  *
12  * 4. We ignore the ESC#n codes, so that we don't do double-width nor 
13  *      double-height lines, nor the ``fill the screen with E's'' confidence check.
14  *
15  * 5. Cursor key sequences aren't selected by keypad application mode.
16  *
17  * 6. "VT220" mode (-2) currently just switches the default cursor key
18  *      functions (same as -a); it's still just a VT100 emulation.
19  *
20  * 7. VT52 mode and a few other rarely used features are not implemented.
21  */
22
23 #include <u.h>
24 #include <libc.h>
25 #include <draw.h>
26 #include <bio.h>
27 #include <ctype.h>
28 #include "cons.h"
29
30 int     wraparound = 1;
31 int     originrelative = 0;
32
33 int     tabcol[200];
34
35 struct funckey vt100fk[NKEYS] = {
36         { "up key",             "\033OA", },
37         { "down key",           "\033OB", },
38         { "left key",           "\033OD", },
39         { "right key",          "\033OC", },
40 };
41
42 struct funckey ansifk[NKEYS] = {
43         { "up key",             "\033[A", },
44         { "down key",           "\033[B", },
45         { "left key",           "\033[D", },
46         { "right key",          "\033[C", },
47         { "F1",                 "\033OP", },
48         { "F2",                 "\033OQ", },
49         { "F3",                 "\033OR", },
50         { "F4",                 "\033OS", },
51         { "F5",                 "\033OT", },
52         { "F6",                 "\033OU", },
53         { "F7",                 "\033OV", },
54         { "F8",                 "\033OW", },
55         { "F9",                 "\033OX", },
56         { "F10",                "\033OY", },
57         { "F11",                "\033OZ", },
58         { "F12",                "\033O1", },
59 };
60
61 struct funckey vt220fk[NKEYS] = {
62         { "up key",             "\033[A", },
63         { "down key",           "\033[B", },
64         { "left key",           "\033[D", },
65         { "right key",          "\033[C", },
66 };
67
68 struct funckey xtermfk[NKEYS] = {
69         { "page up",    "\033[5~", },
70         { "page down",  "\033[6~", },
71         { "up key",             "\033[A", },
72         { "down key",           "\033[B", },
73         { "left key",           "\033[D", },
74         { "right key",          "\033[C", },
75         { "F1",                 "\033[11~", },
76         { "F2",                 "\033[12~", },
77         { "F3",                 "\033[13~", },
78         { "F4",                 "\033[14~", },
79         { "F5",                 "\033[15~", },
80         { "F6",                 "\033[17~", },
81         { "F7",                 "\033[18~", },
82         { "F8",                 "\033[19~", },
83         { "F9",                 "\033[20~", },
84         { "F10",                "\033[21~", },
85         { "F11",                "\033[22~", },
86         { "F12",                "\033[23~", },
87 };
88
89 char gmap[256] = {
90         ['_']   ' ',    /* blank */
91         ['\\']  '*',    /* diamond */
92         ['a']   'X',    /* checkerboard */
93         ['b']   '\t',   /* HT */
94         ['c']   '\x0C', /* FF */
95         ['d']   '\r',   /* CR */
96         ['e']   '\n',   /* LF */
97         ['f']   'o',    /* degree */
98         ['g']   '+',    /* plus/minus */
99         ['h']   '\n',   /* NL, but close enough */
100         ['i']   '\v',   /* VT */
101         ['j']   '+',    /* lower right corner */
102         ['k']   '+',    /* upper right corner */
103         ['l']   '+',    /* upper left corner */
104         ['m']   '+',    /* lower left corner */
105         ['n']   '+',    /* crossing lines */
106         ['o']   '-',    /* horiz line - scan 1 */
107         ['p']   '-',    /* horiz line - scan 3 */
108         ['q']   '-',    /* horiz line - scan 5 */
109         ['r']   '-',    /* horiz line - scan 7 */
110         ['s']   '-',    /* horiz line - scan 9 */
111         ['t']   '+',    /* |-   */
112         ['u']   '+',    /* -| */
113         ['v']   '+',    /* upside down T */
114         ['w']   '+',    /* rightside up T */
115         ['x']   '|',    /* vertical bar */
116         ['y']   '<',    /* less/equal */
117         ['z']   '>',    /* gtr/equal */
118         ['{']   'p',    /* pi */
119         ['|']   '!',    /* not equal */
120         ['}']   'L',    /* pound symbol */
121         ['~']   '.',    /* centered dot: ยท */
122 };
123
124 static void setattr(int argc, int *argv);
125
126 void
127 fixops(int *operand)
128 {
129         if(operand[0] < 1)
130                 operand[0] = 1;
131 }
132
133 void
134 emulate(void)
135 {
136         char buf[BUFS+1];
137         int i;
138         int n;
139         int c;
140         int operand[10];
141         int noperand;
142         int savex, savey, saveattr, saveisgraphics;
143         int isgraphics;
144         int g0set, g1set;
145         int dch;
146
147         isgraphics = 0;
148         g0set = 'B';    /* US ASCII */
149         g1set = 'B';    /* US ASCII */
150         savex = savey = 0;
151         yscrmin = 0;
152         yscrmax = ymax;
153         saveattr = 0;
154         saveisgraphics = 0;
155         /* set initial tab stops to DEC-standard 8-column spacing */
156         for(c=0; (c+=8)<nelem(tabcol);)
157                 tabcol[c] = 1;
158
159         for (;;) {
160                 if (y > ymax) {
161                         x = 0;
162                         newline();
163                 }
164                 buf[0] = get_next_char();
165                 buf[1] = '\0';
166                 switch(buf[0]) {
167
168                 case '\000':
169                 case '\001':
170                 case '\002':
171                 case '\003':
172                 case '\004':
173                 case '\005':
174                 case '\006':
175                         goto Default;
176
177                 case '\007':            /* bell */
178                         ringbell();
179                         break;
180
181                 case '\010':            /* backspace */
182                         if (x > 0)
183                                 --x;
184                         break;
185
186                 case '\011':            /* tab to next tab stop; if none, to right margin */
187                         for(c=x+1; c<nelem(tabcol) && !tabcol[c]; c++)
188                                 ;
189                         if(c < nelem(tabcol))
190                                 x = c;
191                         else
192                                 x = xmax;
193                         break;
194
195                 case '\012':            /* linefeed */
196                 case '\013':
197                 case '\014':
198                         newline();
199                         if (ttystate[cs->raw].nlcr)
200                                 x = 0;
201                         break;
202
203                 case '\015':            /* carriage return */
204                         x = 0;
205                         if (ttystate[cs->raw].crnl)
206                                 newline();
207                         break;
208
209                 case '\016':    /* SO: invoke G1 char set */
210                         isgraphics = (isdigit(g1set));
211                         break;
212                 case '\017':    /* SI: invoke G0 char set */
213                         isgraphics = (isdigit(g0set));
214                         break;
215
216                 case '\020':    /* DLE */
217                 case '\021':    /* DC1 */
218                 case '\022':    /* XON */
219                 case '\023':    /* DC3 */
220                 case '\024':    /* XOFF */
221                 case '\025':    /* NAK */
222                 case '\026':    /* SYN */
223                 case '\027':    /* ETB */
224                 case '\030':    /* CAN: cancel escape sequence, display checkerboard (not implemented) */
225                 case '\031':    /* EM */
226                 case '\032':    /* SUB: same as CAN */
227                         goto Default;
228 ;
229                 /* ESC, \033, is handled below */
230                 case '\034':    /* FS */
231                 case '\035':    /* GS */
232                 case '\036':    /* RS */
233                 case '\037':    /* US */
234                         break;
235                 case '\177':    /* delete: ignored */
236                         break;
237
238                 case '\033':
239                         switch(dch = get_next_char()){
240                         /*
241                          * 1 - graphic processor option on (no-op; not installed)
242                          */
243                         case '1':
244                                 break;
245
246                         /*
247                          * 2 - graphic processor option off (no-op; not installed)
248                          */
249                         case '2':
250                                 break;
251
252                         /*
253                          * 7 - save cursor position.
254                          */
255                         case '7':
256 //print("save\n");
257                                 savex = x;
258                                 savey = y;
259                                 saveattr = attr;
260                                 saveisgraphics = isgraphics;
261                                 break;
262
263                         /*
264                          * 8 - restore cursor position.
265                          */
266                         case '8':
267 //print("restore\n");
268                                 x = savex;
269                                 y = savey;
270                                 attr = saveattr;
271                                 isgraphics = saveisgraphics;
272                                 break;
273
274                         /*
275                          * c - Reset terminal.
276                          */
277                         case 'c':
278 print("resetterminal\n");
279                                 cursoron = 1;
280                                 ttystate[cs->raw].nlcr = 0;
281                                 break;
282
283                         /*
284                          * D - active position down a line, scroll if at bottom margin.
285                          * (Original VT100 had a bug: tracked new-line/line-feed mode.)
286                          */
287                         case 'D':
288                                 if(++y > yscrmax) {
289                                         y = yscrmax;
290                                         scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax);
291                                 }
292                                 break;
293
294                         /*
295                          * E - active position to start of next line, scroll if at bottom margin.
296                          */
297                         case 'E':
298                                 x = 0;
299                                 if(++y > yscrmax) {
300                                         y = yscrmax;
301                                         scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax);
302                                 }
303                                 break;
304
305                         /*
306                          * H - set tab stop at current column.
307                          * (This is cursor home in VT52 mode (not implemented).)
308                          */
309                         case 'H':
310                                 if(x < nelem(tabcol))
311                                         tabcol[x] = 1;
312                                 break;
313
314                         /*
315                          * M - active position up a line, scroll if at top margin..
316                          */
317                         case 'M':
318                                 if(--y < yscrmin) {
319                                         y = yscrmin;
320                                         scroll(yscrmin, yscrmax, yscrmin+1, yscrmin);
321                                 }
322                                 break;
323
324                         /*
325                          * Z - identification.  the terminal
326                          * emulator will return the response
327                          * code for a generic VT100.
328                          */
329                         case 'Z':
330                         Ident:
331                                 sendnchars2(7, "\033[?1;2c");   /* VT100 with AVO option */
332 //                              sendnchars2(5, "\033[?6c");     /* VT102 (insert/delete-char, etc.) */
333                                 break;
334
335                         /*
336                          * < - enter ANSI mode
337                          */
338                         case '<':
339                                 break;
340
341                         /*
342                          * > - set numeric keypad mode on (not implemented)
343                          */
344                         case '>':
345                                 break;
346
347                         /*
348                          * = - set numeric keypad mode off (not implemented)
349                          */
350                         case '=':
351                                 break;
352
353                         /*
354                          * # - Takes a one-digit argument
355                          */
356                         case '#':
357                                 switch(get_next_char()){
358                                 case '3':               /* Top half of double-height line */
359                                 case '4':               /* Bottom half of double-height line */
360                                 case '5':               /* Single-width single-height line */
361                                 case '6':               /* Double-width line */
362                                 case '7':               /* Screen print */
363                                 case '8':               /* Fill screen with E's */
364                                         break;
365                                 }
366                                 break;
367
368                         /*
369                          * ( - switch G0 character set
370                          */
371                         case '(':
372                                 g0set = get_next_char();
373                                 break;
374
375                         /*
376                          * - switch G1 character set
377                          */
378                         case ')':
379                                 g1set = get_next_char();
380                                 break;
381
382                         /*
383                          * Received left bracket.
384                          */
385                         case '[':
386                                 /*
387                                  * A semi-colon or ? delimits arguments.
388                                  */
389                                 memset(operand, 0, sizeof(operand));
390                                 operand[0] = number(buf, &i);
391                                 noperand = 1;
392                                 while(buf[0] == ';' || buf[0] == '?'){
393                                         if(noperand < nelem(operand)){
394                                                 noperand++;
395                                                 operand[noperand-1] = number(buf, nil);
396                                         } else
397                                                 number(buf, nil);
398                                 }
399
400                                 /*
401                                  * do escape2 stuff
402                                  */
403                                 switch(dch = buf[0]){
404                                         /*
405                                          * c - same as ESC Z: what are you?
406                                          */
407                                         case 'c':
408                                                 goto Ident;
409
410                                         /*
411                                          * g - various tabstop manipulation
412                                          */
413                                         case 'g':
414                                                 switch(operand[0]){
415                                                 case 0: /* clear tab at current column */
416                                                         if(x < nelem(tabcol))
417                                                                 tabcol[x] = 0;
418                                                         break;
419                                                 case 3: /* clear all tabs */
420                                                         memset(tabcol, 0, sizeof tabcol);
421                                                         break;
422                                                 }
423                                                 break;
424
425                                         /*
426                                          * l - clear various options.
427                                          */
428                                         case 'l':
429                                                 if(noperand == 1){
430                                                         switch(operand[0]){     
431                                                         case 20:        /* set line feed mode */
432                                                                 ttystate[cs->raw].nlcr = 1;
433                                                                 break;
434                                                         case 30:        /* screen invisible (? not supported through VT220) */
435                                                                 break;
436                                                         }
437                                                 }else while(--noperand > 0){
438                                                         switch(operand[noperand]){
439                                                         case 1: /* set cursor keys to send ANSI functions: ESC [ A..D */
440                                                                 break;
441                                                         case 2: /* set VT52 mode (not implemented) */
442                                                                 break;
443                                                         case 3: /* set 80 columns */
444                                                                 setdim(-1, 80);
445                                                                 break;
446                                                         case 4: /* set jump scrolling */
447                                                                 break;
448                                                         case 5: /* set normal video on screen */
449                                                                 break;
450                                                         case 6: /* set origin to absolute */
451                                                                 originrelative = 0;
452                                                                 x = y = 0;
453                                                                 break;
454                                                         case 7: /* reset auto-wrap mode */
455                                                                 wraparound = 0;
456                                                                 break;
457                                                         case 8: /* reset auto-repeat mode */
458                                                                 break;
459                                                         case 9: /* reset interlacing mode */
460                                                                 break;
461                                                         case 25:        /* text cursor off (VT220) */
462                                                                 cursoron = 0;
463                                                                 break;
464                                                         }
465                                                 }
466                                                 break;
467
468                                         /*
469                                         * s - some dec private stuff. actually [ ? num s, but we can't detect it.
470                                         */
471                                         case 's':
472                                                 break;
473
474                                         /*
475                                          * h - set various options.
476                                          */
477                                         case 'h':
478                                                 if(noperand == 1){
479                                                         switch(operand[0]){
480                                                         default:
481                                                                 break;
482                                                         case 20:        /* set newline mode */
483                                                                 ttystate[cs->raw].nlcr = 0;
484                                                                 break;
485                                                         case 30:        /* screen visible (? not supported through VT220) */
486                                                                 break;
487                                                         }
488                                                 }else while(--noperand > 0){
489                                                         switch(operand[noperand]){
490                                                         default:
491                                                                 break;
492                                                         case 1: /* set cursor keys to send application function: ESC O A..D */
493                                                                 break;
494                                                         case 2: /* set ANSI */
495                                                                 break;
496                                                         case 3: /* set 132 columns */
497                                                                 setdim(-1, 132);
498                                                                 break;
499                                                         case 4: /* set smooth scrolling */
500                                                                 break;
501                                                         case 5: /* set screen to reverse video (not implemented) */
502                                                                 break;
503                                                         case 6: /* set origin to relative */
504                                                                 originrelative = 1;
505                                                                 x = 0;
506                                                                 y = yscrmin;
507                                                                 break;
508                                                         case 7: /* set auto-wrap mode */
509                                                                 wraparound = 1;
510                                                                 break;
511                                                         case 8: /* set auto-repeat mode */
512                                                                 break;
513                                                         case 9: /* set interlacing mode */
514                                                                 break;
515                                                         case 25:        /* text cursor on (VT220) */
516                                                                 cursoron = 1;
517                                                                 break;
518                                                         }
519                                                 }
520                                                 break;
521
522                                         /*
523                                          * m - change character attrs.
524                                          */
525                                         case 'm':
526                                                 setattr(noperand, operand);
527                                                 break;
528
529                                         /*
530                                          * n - request various reports
531                                          */
532                                         case 'n':
533                                                 switch(operand[0]){
534                                                 case 5: /* status */
535                                                         sendnchars2(4, "\033[0n");      /* terminal ok */
536                                                         break;
537                                                 case 6: /* cursor position */
538                                                         sendnchars2(sprint(buf, "\033[%d;%dR",
539                                                                 originrelative ? y+1 - yscrmin : y+1, x+1), buf);
540                                                         break;
541                                                 }
542                                                 break;
543
544                                         /*
545                                          * q - turn on list of LEDs; turn off others.
546                                          */
547                                         case 'q':
548                                                 break;
549
550                                         /*
551                                          * r - change scrolling region.  operand[0] is
552                                          * min scrolling region and operand[1] is max
553                                          * scrolling region.
554                                          */
555                                         case 'r':
556                                                 yscrmin = 0;
557                                                 yscrmax = ymax;
558                                                 switch(noperand){
559                                                 case 2:
560                                                         yscrmax = operand[1]-1;
561                                                         if(yscrmax > ymax)
562                                                                 yscrmax = ymax;
563                                                 case 1:
564                                                         yscrmin = operand[0]-1;
565                                                         if(yscrmin < 0)
566                                                                 yscrmin = 0;
567                                                 }
568                                                 x = 0;
569                                                 y = yscrmin;
570                                                 break;
571
572                                         /*
573                                          * x - report terminal parameters
574                                          */
575                                         case 'x':
576                                                 sendnchars2(20, "\033[3;1;1;120;120;1;0x");
577                                                 break;
578
579                                         /*
580                                          * y - invoke confidence test
581                                          */
582                                         case 'y':
583                                                 break;
584
585                                         /*
586                                          * z - line spacing
587                                          */
588                                         case 'z':
589                                                 break;
590
591                                         /*
592                                          * A - cursor up.
593                                          */
594                                         case 'e':
595                                         case 'A':
596                                                 fixops(operand);
597                                                 y -= operand[0];
598                                                 if(y < yscrmin)
599                                                         y = yscrmin;
600                                                 olines -= operand[0];
601                                                 if(olines < 0)
602                                                         olines = 0;
603                                                 break;
604
605                                         /*
606                                          * B - cursor down
607                                          */
608                                         case 'B':
609                                                 fixops(operand);
610                                                 y += operand[0];
611                                                 if(y > yscrmax)
612                                                         y=yscrmax;
613                                                 break;
614                                         
615                                         /*
616                                          * C - cursor right
617                                          */
618                                         case 'a':
619                                         case 'C':
620                                                 fixops(operand);
621                                                 x += operand[0];
622                                                 /*
623                                                  * VT-100-UG says not to go past the
624                                                  * right margin.
625                                                  */
626                                                 if(x > xmax)
627                                                         x = xmax;
628                                                 break;
629
630                                         /*
631                                          * D - cursor left
632                                          */
633                                         case 'D':
634                                                 fixops(operand);
635                                                 x -= operand[0];
636                                                 if(x < 0)
637                                                         x = 0;
638                                                 break;
639
640                                         /*
641                                          *      G - cursor to column
642                                          */
643                                         case '\'':
644                                         case 'G':
645                                                 fixops(operand);
646                                                 x = operand[0] - 1;
647                                                 if(x > xmax)
648                                                         x = xmax;
649                                                 break;
650
651                                         /*
652                                          * H and f - cursor motion.  operand[0] is row and
653                                          * operand[1] is column, origin 1.
654                                          */
655                                         case 'H':
656                                         case 'f':
657                                                 fixops(operand+1);
658                                                 x = operand[1] - 1;
659                                                 if(x > xmax)
660                                                         x = xmax;
661
662                                                 /* fallthrough */
663
664                                         /*
665                                          * d - cursor to line n (xterm)
666                                          */
667                                         case 'd':
668                                                 fixops(operand);
669                                                 y = operand[0] - 1;
670                                                 if(originrelative){
671                                                         y += yscrmin;
672                                                         if(y > yscrmax)
673                                                                 y = yscrmax;
674                                                 }else{
675                                                         if(y > ymax)
676                                                                 y = ymax;
677                                                 }
678                                                 break;
679
680                                         /*
681                                          * J - clear some or all of the display.
682                                          */
683                                         case 'J':
684                                                 switch (operand[0]) {
685                                                         /*
686                                                          * operand 2:  whole screen.
687                                                          */
688                                                         case 2:
689                                                                 clear(Rpt(pt(0, 0), pt(xmax+1, ymax+1)));
690                                                                 break;
691                                                         /*
692                                                          * operand 1: start of screen to active position, inclusive.
693                                                          */
694                                                         case 1:
695                                                                 clear(Rpt(pt(0, 0), pt(xmax+1, y)));
696                                                                 clear(Rpt(pt(0, y), pt(x+1, y+1)));
697                                                                 break;
698                                                         /*
699                                                          * Default:  active position to end of screen, inclusive.
700                                                          */
701                                                         default:
702                                                                 clear(Rpt(pt(x, y), pt(xmax+1, y+1)));
703                                                                 clear(Rpt(pt(0, y+1), pt(xmax+1, ymax+1)));
704                                                                 break;
705                                                 }
706                                                 break;
707
708                                         /*
709                                          * K - clear some or all of the line.
710                                          */
711                                         case 'K':
712                                                 switch (operand[0]) {
713                                                         /*
714                                                          * operand 2: whole line.
715                                                          */
716                                                         case 2:
717                                                                 clear(Rpt(pt(0, y), pt(xmax+1, y+1)));
718                                                                 break;
719                                                         /*
720                                                          * operand 1: start of line to active position, inclusive.
721                                                          */
722                                                         case 1:
723                                                                 clear(Rpt(pt(0, y), pt(x+1, y+1)));
724                                                                 break;
725                                                         /*
726                                                          * Default: active position to end of line, inclusive.
727                                                          */
728                                                         default:
729                                                                 clear(Rpt(pt(x, y), pt(xmax+1, y+1)));
730                                                                 break;
731                                                 }
732                                                 break;
733
734                                         /*
735                                          *      P - delete character(s) from right of cursor (xterm)
736                                          */
737                                         case 'P':
738                                                 fixops(operand);
739                                                 i = x + operand[0];
740                                                 draw(screen, Rpt(pt(x, y), pt(xmax+1, y+1)), screen, nil, pt(i, y));
741                                                 clear(Rpt(pt(xmax-operand[0], y), pt(xmax+1, y+1)));
742                                                 break;
743
744                                         /*
745                                          *      @ - insert blank(s) to right of cursor (xterm)
746                                          */
747                                         case '@':
748                                                 fixops(operand);
749                                                 i = x + operand[0];
750                                                 draw(screen, Rpt(pt(i, y), pt(xmax+1, y+1)), screen, nil, pt(x, y));
751                                                 clear(Rpt(pt(x, y), pt(i, y+1)));
752                                                 break;
753
754
755                                         /*
756                                          *      X - erase character(s) at cursor and to the right (xterm)
757                                          */
758                                         case 'X':
759                                                 fixops(operand);
760                                                 i = x + operand[0];
761                                                 clear(Rpt(pt(x, y), pt(i, y+1)));
762                                                 break;
763
764                                         /*
765                                          * L - insert a line at cursor position (VT102 and later)
766                                          */
767                                         case 'L':
768                                                 fixops(operand);
769                                                 for(i = 0; i < operand[0]; ++i)
770                                                         scroll(y, yscrmax, y+1, y);
771                                                 break;
772
773                                         /*
774                                          * M - delete a line at cursor position (VT102 and later)
775                                          */
776                                         case 'M':
777                                                 fixops(operand);
778                                                 for(i = 0; i < operand[0]; ++i)
779                                                         scroll(y+1, yscrmax+1, y, yscrmax);
780                                                 break;
781
782                                         /*
783                                          * S,T - scroll up/down (xterm)
784                                          */
785                                         case 'T':
786                                                 fixops(operand);
787                                                 for(i = 0; i < operand[0]; ++i)
788                                                         scroll(yscrmin, yscrmax, yscrmin+1, yscrmin);
789                                                 break;
790
791                                         case 'S':
792                                                 fixops(operand);
793                                                 for(i = 0; i < operand[0]; ++i)
794                                                         scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmin);
795                                                 break;
796
797                                         case '=':       /* ? not supported through VT220 */
798                                                 number(buf, nil);
799                                                 switch(buf[0]) {
800                                                 case 'h':
801                                                 case 'l':
802                                                         break;
803                                                 }
804                                                 break;
805
806                                         /*
807                                          * Anything else we ignore for now...
808                                          */
809                                         default:
810 print("unknown escape2 '%c' (0x%x)\n", dch, dch);
811                                                 break;
812                                 }
813
814                                 break;
815
816                         /*
817                          * Collapse multiple '\033' to one.
818                          */
819                         case '\033':
820                                 peekc = '\033';
821                                 break;
822
823                         /* set title */
824                         case ']':       /* it's actually <esc> ] num ; title <bel> */
825                                 {
826                                         int ch, fd;
827                                         number(buf, nil);
828                                         i = 0;
829                                         while((ch = get_next_char()) != '\a')
830                                                 if(i < sizeof buf)
831                                                         buf[i++] = ch;
832                                         fd = open("/dev/label", OWRITE);
833                                         write(fd, buf, i);
834                                         close(fd);
835                                 }
836                                 break;
837
838                         /*
839                          * Ignore other commands.
840                          */
841                         default:
842 print("unknown command '%c' (0x%x)\n", dch, dch);
843                                 break;
844
845                         }
846                         break;
847
848                 default:                /* ordinary char */
849 Default:
850                         if(isgraphics && gmap[(uchar) buf[0]])
851                                 buf[0] = gmap[(uchar) buf[0]];
852
853                         /* line wrap */
854                         if (x > xmax){
855                                 if(wraparound){
856                                         x = 0;
857                                         newline();
858                                 }else{
859                                         continue;
860                                 }
861                         }
862                         n = 1;
863                         c = 0;
864                         while (!cs->raw && host_avail() && x+n<=xmax && n<BUFS
865                             && (c = get_next_char())>=' ' && c<'\177') {
866                                 buf[n++] = c;
867                                 c = 0;
868                         }
869                         buf[n] = 0;
870 //                      clear(Rpt(pt(x,y), pt(x+n, y+1)));
871                         drawstring(pt(x, y), buf, attr);
872                         x += n;
873                         peekc = c;
874                         break;
875                 }
876         }
877 }
878
879 static void
880 setattr(int argc, int *argv)
881 {
882         int i;
883
884         for(i=0; i<argc; i++) {
885                 switch(argv[i]) {
886                 case 0:
887                         attr = defattr;
888                         fgcolor = fgdefault;
889                         bgcolor = bgdefault;
890                         break;
891                 case 1:
892                         attr |= THighIntensity;
893                         break;          
894                 case 4:
895                         attr |= TUnderline;
896                         break;          
897                 case 5:
898                         attr |= TBlink;
899                         break;
900                 case 7:
901                         attr |= TReverse;
902                         break;
903                 case 8:
904                         attr |= TInvisible;
905                         break;
906                 case 22:
907                         attr &= ~THighIntensity;
908                         break;          
909                 case 24:
910                         attr &= ~TUnderline;
911                         break;          
912                 case 25:
913                         attr &= ~TBlink;
914                         break;
915                 case 27:
916                         attr &= ~TReverse;
917                         break;
918                 case 28:
919                         attr &= ~TInvisible;
920                         break;
921                 case 30:        /* black */
922                 case 31:        /* red */
923                 case 32:        /* green */
924                 case 33:        /* brown */
925                 case 34:        /* blue */
926                 case 35:        /* purple */
927                 case 36:        /* cyan */
928                 case 37:        /* white */
929                         fgcolor = (nocolor? fgdefault: colors[argv[i]-30]);
930                         break;
931                 case 39:
932                         fgcolor = fgdefault;
933                         break;
934                 case 40:        /* black */
935                 case 41:        /* red */
936                 case 42:        /* green */
937                 case 43:        /* brown */
938                 case 44:        /* blue */
939                 case 45:        /* purple */
940                 case 46:        /* cyan */
941                 case 47:        /* white */
942                         bgcolor = (nocolor? bgdefault: colors[argv[i]-40]);
943                         break;
944                 case 49:
945                         bgcolor = bgdefault;
946                         break;
947                 }
948         }
949 }