wsemul_vt100.c revision 1.3 1 /* $NetBSD: wsemul_vt100.c,v 1.3 1998/06/26 21:20:34 drochner Exp $ */
2
3 /*
4 * Copyright (c) 1998
5 * Matthias Drochner. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project
18 * by Matthias Drochner.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/time.h>
38 #include <sys/malloc.h>
39 #include <sys/fcntl.h>
40
41 #include <dev/wscons/wsconsio.h>
42 #include <dev/wscons/wsdisplayvar.h>
43 #include <dev/wscons/wsemulvar.h>
44 #include <dev/wscons/wsemul_vt100var.h>
45 #include <dev/wscons/ascii.h>
46
47 #include "opt_wskernattr.h"
48
49 void *wsemul_vt100_cnattach __P((const struct wsscreen_descr *, void *,
50 int, int, long));
51 void *wsemul_vt100_attach __P((int console, const struct wsscreen_descr *,
52 void *, int, int, void *, long));
53 void wsemul_vt100_output __P((void *cookie, const u_char *data, u_int count,
54 int));
55 void wsemul_vt100_detach __P((void *cookie, u_int *crowp, u_int *ccolp));
56
57 const struct wsemul_ops wsemul_vt100_ops = {
58 "vt100",
59 wsemul_vt100_cnattach,
60 wsemul_vt100_attach,
61 wsemul_vt100_output,
62 wsemul_vt100_translate,
63 wsemul_vt100_detach,
64 };
65
66 struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata;
67
68 static void wsemul_vt100_init __P((struct wsemul_vt100_emuldata *,
69 const struct wsscreen_descr *,
70 void *, int, int, long));
71
72 static u_int wsemul_vt100_output_normal __P((struct wsemul_vt100_emuldata *,
73 u_char, int));
74 typedef u_int vt100_handler __P((struct wsemul_vt100_emuldata *, u_char));
75 static vt100_handler
76 wsemul_vt100_output_esc,
77 wsemul_vt100_output_csi,
78 wsemul_vt100_output_scs94,
79 wsemul_vt100_output_scs94_percent,
80 wsemul_vt100_output_scs96,
81 wsemul_vt100_output_scs96_percent,
82 wsemul_vt100_output_esc_hash,
83 wsemul_vt100_output_esc_spc,
84 wsemul_vt100_output_string,
85 wsemul_vt100_output_string_esc,
86 wsemul_vt100_output_dcs,
87 wsemul_vt100_output_dcs_dollar;
88
89 #define VT100_EMUL_STATE_NORMAL 0 /* normal processing */
90 #define VT100_EMUL_STATE_ESC 1 /* got ESC */
91 #define VT100_EMUL_STATE_CSI 2 /* got CSI (ESC[) */
92 #define VT100_EMUL_STATE_SCS94 3 /* got ESC{()*+} */
93 #define VT100_EMUL_STATE_SCS94_PERCENT 4 /* got ESC{()*+}% */
94 #define VT100_EMUL_STATE_SCS96 5 /* got ESC{-./} */
95 #define VT100_EMUL_STATE_SCS96_PERCENT 6 /* got ESC{-./}% */
96 #define VT100_EMUL_STATE_ESC_HASH 7 /* got ESC# */
97 #define VT100_EMUL_STATE_ESC_SPC 8 /* got ESC<SPC> */
98 #define VT100_EMUL_STATE_STRING 9 /* waiting for ST (ESC\) */
99 #define VT100_EMUL_STATE_STRING_ESC 10 /* waiting for ST, got ESC */
100 #define VT100_EMUL_STATE_DCS 11 /* got DCS (ESC P) */
101 #define VT100_EMUL_STATE_DCS_DOLLAR 12 /* got DCS<p>$ */
102
103 vt100_handler *vt100_output[] = {
104 wsemul_vt100_output_esc,
105 wsemul_vt100_output_csi,
106 wsemul_vt100_output_scs94,
107 wsemul_vt100_output_scs94_percent,
108 wsemul_vt100_output_scs96,
109 wsemul_vt100_output_scs96_percent,
110 wsemul_vt100_output_esc_hash,
111 wsemul_vt100_output_esc_spc,
112 wsemul_vt100_output_string,
113 wsemul_vt100_output_string_esc,
114 wsemul_vt100_output_dcs,
115 wsemul_vt100_output_dcs_dollar,
116 };
117
118 static void
119 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr)
120 struct wsemul_vt100_emuldata *edp;
121 const struct wsscreen_descr *type;
122 void *cookie;
123 int ccol, crow;
124 long defattr;
125 {
126 edp->emulops = type->textops;
127 edp->emulcookie = cookie;
128 edp->scrcapabilities = type->capabilities;
129 edp->nrows = type->nrows;
130 edp->ncols = type->ncols;
131 edp->crow = crow;
132 edp->ccol = ccol;
133 edp->defattr = defattr;
134 }
135
136 void *
137 wsemul_vt100_cnattach(type, cookie, ccol, crow, defattr)
138 const struct wsscreen_descr *type;
139 void *cookie;
140 int ccol, crow;
141 long defattr;
142 {
143 struct wsemul_vt100_emuldata *edp;
144 int res;
145
146 edp = &wsemul_vt100_console_emuldata;
147 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
148 #ifdef DIAGNOSTIC
149 edp->console = 1;
150 #endif
151 edp->cbcookie = NULL;
152
153 #if defined(WS_KERNEL_FG) || defined(WS_KERNEL_BG) || \
154 defined(WS_KERNEL_COLATTR) || defined(WS_KERNEL_MONOATTR)
155 #ifndef WS_KERNEL_FG
156 #define WS_KERNEL_FG WSCOL_WHITE
157 #endif
158 #ifndef WS_KERNEL_BG
159 #define WS_KERNEL_BG WSCOL_BLACK
160 #endif
161 #ifndef WS_KERNEL_COLATTR
162 #define WS_KERNEL_COLATTR 0
163 #endif
164 #ifndef WS_KERNEL_MONOATTR
165 #define WS_KERNEL_MONOATTR 0
166 #endif
167 if (type->capabilities & WSSCREEN_WSCOLORS)
168 res = (*edp->emulops->alloc_attr)(cookie,
169 WS_KERNEL_FG, WS_KERNEL_BG,
170 WS_KERNEL_COLATTR | WSATTR_WSCOLORS,
171 &edp->kernattr);
172 else
173 res = (*edp->emulops->alloc_attr)(cookie, 0, 0,
174 WS_KERNEL_MONOATTR,
175 &edp->kernattr);
176 if (res)
177 #endif
178 edp->kernattr = defattr;
179
180 edp->tabs = 0;
181 edp->dblwid = 0;
182 edp->dw = 0;
183 edp->dcsarg = 0;
184 edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = 0;
185 edp->nrctab = 0;
186 wsemul_vt100_reset(edp);
187 return (edp);
188 }
189
190 void *
191 wsemul_vt100_attach(console, type, cookie, ccol, crow, cbcookie, defattr)
192 int console;
193 const struct wsscreen_descr *type;
194 void *cookie;
195 int ccol, crow;
196 void *cbcookie;
197 long defattr;
198 {
199 struct wsemul_vt100_emuldata *edp;
200
201 if (console) {
202 edp = &wsemul_vt100_console_emuldata;
203 #ifdef DIAGNOSTIC
204 KASSERT(edp->console == 1);
205 #endif
206 } else {
207 edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK);
208 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
209 #ifdef DIAGNOSTIC
210 edp->console = 0;
211 #endif
212 }
213 edp->cbcookie = cbcookie;
214
215 edp->tabs = malloc(type->ncols, M_DEVBUF, M_NOWAIT);
216 edp->dblwid = malloc(type->nrows, M_DEVBUF, M_NOWAIT);
217 bzero(edp->dblwid, type->nrows);
218 edp->dw = 0;
219 edp->dcsarg = malloc(DCS_MAXLEN, M_DEVBUF, M_NOWAIT);
220 edp->isolatin1tab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
221 edp->decgraphtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
222 edp->dectechtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
223 edp->nrctab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
224 vt100_initchartables(edp);
225 wsemul_vt100_reset(edp);
226 return (edp);
227 }
228
229 void
230 wsemul_vt100_detach(cookie, crowp, ccolp)
231 void *cookie;
232 u_int *crowp, *ccolp;
233 {
234 struct wsemul_vt100_emuldata *edp = cookie;
235
236 *crowp = edp->crow;
237 *ccolp = edp->ccol;
238 #define f(ptr) if (ptr) {free(ptr, M_DEVBUF); ptr = 0;}
239 f(edp->tabs)
240 f(edp->dblwid)
241 f(edp->dcsarg)
242 f(edp->isolatin1tab)
243 f(edp->decgraphtab)
244 f(edp->dectechtab)
245 f(edp->nrctab)
246 #undef f
247 if (edp != &wsemul_vt100_console_emuldata)
248 free(edp, M_DEVBUF);
249 }
250
251 void
252 wsemul_vt100_reset(edp)
253 struct wsemul_vt100_emuldata *edp;
254 {
255 int i;
256
257 edp->state = VT100_EMUL_STATE_NORMAL;
258 edp->flags = VTFL_DECAWM | VTFL_CURSORON;
259 edp->curattr = edp->defattr;
260 edp->attrflags = 0;
261 edp->fgcol = WSCOL_WHITE;
262 edp->bgcol = WSCOL_BLACK;
263 edp->scrreg_startrow = 0;
264 edp->scrreg_nrows = edp->nrows;
265 if (edp->tabs) {
266 bzero(edp->tabs, edp->ncols);
267 for (i = 1; i < edp->ncols; i += 8 - (i & 7))
268 edp->tabs[i] = 1;
269 }
270 edp->dcspos = 0;
271 edp->dcstype = 0;
272 edp->chartab_G[0] = 0;
273 edp->chartab_G[1] = edp->nrctab; /* ??? */
274 edp->chartab_G[2] = edp->isolatin1tab;
275 edp->chartab_G[3] = edp->isolatin1tab;
276 edp->chartab0 = 0;
277 edp->chartab1 = 2;
278 edp->sschartab = 0;
279 }
280
281 /*
282 * now all the state machine bits
283 */
284
285 static u_int
286 wsemul_vt100_output_normal(edp, c, kernel)
287 struct wsemul_vt100_emuldata *edp;
288 u_char c;
289 int kernel;
290 {
291 u_int newstate = VT100_EMUL_STATE_NORMAL;
292 u_int n, dc;
293 u_int *ct;
294
295 switch (c) {
296 case ASCII_NUL:
297 /* ignore */
298 break;
299 case ASCII_BEL:
300 wsdisplay_emulbell(edp->cbcookie);
301 break;
302 case ASCII_BS:
303 if (edp->ccol > 0) {
304 edp->ccol--;
305 edp->flags &= ~VTFL_LASTCHAR;
306 }
307 break;
308 case ASCII_CR:
309 edp->ccol = 0;
310 edp->flags &= ~VTFL_LASTCHAR;
311 break;
312 case ASCII_HT:
313 if (edp->tabs) {
314 if (!COLS_LEFT)
315 break;
316 for (n = edp->ccol + 1; n < NCOLS - 1; n++)
317 if (edp->tabs[n])
318 break;
319 } else {
320 n = edp->ccol + min(8 - (edp->ccol & 7), COLS_LEFT);
321 }
322 ERASECOLS(edp->ccol, n - edp->ccol,
323 kernel ? edp->kernattr : edp->curattr);
324 edp->ccol = n;
325 break;
326 case ASCII_SO: /* LS1 */
327 edp->chartab0 = 1;
328 break;
329 case ASCII_SI: /* LS0 */
330 edp->chartab0 = 0;
331 break;
332 case ASCII_ESC:
333 #ifdef DIAGNOSTIC
334 if (kernel)
335 panic("ESC in kernel output");
336 #endif
337 newstate = VT100_EMUL_STATE_ESC;
338 break;
339 #if 0
340 case CSI: /* 8-bit */
341 edp->nargs = 0;
342 bzero(edp->args, sizeof (edp->args));
343 edp->modif1 = edp->modif2 = '\0';
344 newstate = VT100_EMUL_STATE_CSI;
345 break;
346 case DCS: /* 8-bit */
347 edp->nargs = 0;
348 bzero(edp->args, sizeof (edp->args));
349 newstate = VT100_EMUL_STATE_DCS;
350 break;
351 #endif
352 default: /* normal character */
353 if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
354 (VTFL_LASTCHAR | VTFL_DECAWM)) {
355 if (ROWS_BELOW > 0) {
356 edp->crow++;
357 CHECK_DW;
358 } else
359 wsemul_vt100_scrollup(edp, 1);
360 edp->ccol = 0;
361 edp->flags &= ~VTFL_LASTCHAR;
362 }
363
364 if (c & 0x80) {
365 c &= 0x7f;
366 ct = edp->chartab_G[edp->chartab1];
367 } else {
368 if (edp->sschartab) {
369 ct = edp->chartab_G[edp->sschartab];
370 edp->sschartab = 0;
371 } else
372 ct = edp->chartab_G[edp->chartab0];
373 }
374 dc = (ct ? ct[c] : c);
375
376 if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT)
377 COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT);
378
379 (*edp->emulops->putchar)(edp->emulcookie, edp->crow,
380 edp->ccol << edp->dw, dc,
381 kernel ? edp->kernattr : edp->curattr);
382
383 if (COLS_LEFT)
384 edp->ccol++;
385 else
386 edp->flags |= VTFL_LASTCHAR;
387 break;
388 case ASCII_LF:
389 case ASCII_VT:
390 case ASCII_FF:
391 if (ROWS_BELOW > 0) {
392 edp->crow++;
393 CHECK_DW;
394 } else
395 wsemul_vt100_scrollup(edp, 1);
396 break;
397 }
398
399 return (newstate);
400 }
401
402 static u_int
403 wsemul_vt100_output_esc(edp, c)
404 struct wsemul_vt100_emuldata *edp;
405 u_char c;
406 {
407 u_int newstate = VT100_EMUL_STATE_NORMAL;
408 int i;
409
410 switch (c) {
411 case '[': /* CSI */
412 edp->nargs = 0;
413 bzero(edp->args, sizeof (edp->args));
414 edp->modif1 = edp->modif2 = '\0';
415 newstate = VT100_EMUL_STATE_CSI;
416 break;
417 case '7': /* DECSC */
418 edp->savedcursor_row = edp->crow;
419 edp->savedcursor_col = edp->ccol;
420 edp->savedattr = edp->curattr;
421 edp->savedattrflags = edp->attrflags;
422 edp->savedfgcol = edp->fgcol;
423 edp->savedbgcol = edp->bgcol;
424 for (i = 0; i < 4; i++)
425 edp->savedchartab_G[i] = edp->chartab_G[i];
426 edp->savedchartab0 = edp->chartab0;
427 edp->savedchartab1 = edp->chartab1;
428 break;
429 case '8': /* DECRC */
430 edp->crow = edp->savedcursor_row;
431 edp->ccol = edp->savedcursor_col;
432 edp->curattr = edp->savedattr;
433 edp->attrflags = edp->savedattrflags;
434 edp->fgcol = edp->savedfgcol;
435 edp->bgcol = edp->savedbgcol;
436 for (i = 0; i < 4; i++)
437 edp->chartab_G[i] = edp->savedchartab_G[i];
438 edp->chartab0 = edp->savedchartab0;
439 edp->chartab1 = edp->savedchartab1;
440 break;
441 case '=': /* DECKPAM application mode */
442 edp->flags |= VTFL_APPLKEYPAD;
443 break;
444 case '>': /* DECKPNM numeric mode */
445 edp->flags &= ~VTFL_APPLKEYPAD;
446 break;
447 case 'E': /* NEL */
448 edp->ccol = 0;
449 /* FALLTHRU */
450 case 'D': /* IND */
451 if (ROWS_BELOW > 0) {
452 edp->crow++;
453 CHECK_DW;
454 break;
455 }
456 wsemul_vt100_scrollup(edp, 1);
457 break;
458 case 'H': /* HTS */
459 KASSERT(edp->tabs != 0);
460 edp->tabs[edp->ccol] = 1;
461 break;
462 case '~': /* LS1R */
463 edp->chartab1 = 1;
464 break;
465 case 'n': /* LS2 */
466 edp->chartab0 = 2;
467 break;
468 case '}': /* LS2R */
469 edp->chartab1 = 2;
470 break;
471 case 'o': /* LS3 */
472 edp->chartab0 = 3;
473 break;
474 case '|': /* LS3R */
475 edp->chartab1 = 3;
476 break;
477 case 'N': /* SS2 */
478 edp->sschartab = 2;
479 break;
480 case 'O': /* SS3 */
481 edp->sschartab = 3;
482 break;
483 case 'M': /* RI */
484 if (ROWS_ABOVE > 0) {
485 edp->crow--;
486 CHECK_DW;
487 break;
488 }
489 wsemul_vt100_scrolldown(edp, 1);
490 break;
491 case 'P': /* DCS */
492 edp->nargs = 0;
493 bzero(edp->args, sizeof (edp->args));
494 newstate = VT100_EMUL_STATE_DCS;
495 break;
496 case 'c': /* RIS */
497 wsemul_vt100_reset(edp);
498 wsemul_vt100_ed(edp, 2);
499 edp->ccol = edp->crow = 0;
500 break;
501 case '(': case ')': case '*': case '+': /* SCS */
502 edp->designating = c - '(';
503 newstate = VT100_EMUL_STATE_SCS94;
504 break;
505 case '-': case '.': case '/': /* SCS */
506 edp->designating = c - '-' + 1;
507 newstate = VT100_EMUL_STATE_SCS96;
508 break;
509 case '#':
510 newstate = VT100_EMUL_STATE_ESC_HASH;
511 break;
512 case ' ': /* 7/8 bit */
513 newstate = VT100_EMUL_STATE_ESC_SPC;
514 break;
515 case ']': /* OSC operating system command */
516 case '^': /* PM privacy message */
517 case '_': /* APC application program command */
518 /* ignored */
519 newstate = VT100_EMUL_STATE_STRING;
520 break;
521 case '<': /* exit VT52 mode - ignored */
522 break;
523 default:
524 #ifdef VT100_PRINTUNKNOWN
525 printf("ESC%c unknown\n", c);
526 #endif
527 break;
528 }
529
530 return (newstate);
531 }
532
533 static u_int
534 wsemul_vt100_output_scs94(edp, c)
535 struct wsemul_vt100_emuldata *edp;
536 u_char c;
537 {
538 u_int newstate = VT100_EMUL_STATE_NORMAL;
539
540 switch (c) {
541 case '%': /* probably DEC supplemental graphic */
542 newstate = VT100_EMUL_STATE_SCS94_PERCENT;
543 break;
544 case 'A': /* british / national */
545 edp->chartab_G[edp->designating] = edp->nrctab;
546 break;
547 case 'B': /* ASCII */
548 edp->chartab_G[edp->designating] = 0;
549 break;
550 case '<': /* user preferred supplemental */
551 /* XXX not really "user" preferred */
552 edp->chartab_G[edp->designating] = edp->isolatin1tab;
553 break;
554 case '0': /* DEC special graphic */
555 edp->chartab_G[edp->designating] = edp->decgraphtab;
556 break;
557 case '>': /* DEC tech */
558 edp->chartab_G[edp->designating] = edp->dectechtab;
559 break;
560 default:
561 #ifdef VT100_PRINTUNKNOWN
562 printf("ESC%c%c unknown\n", edp->designating + '(', c);
563 #endif
564 break;
565 }
566 return (newstate);
567 }
568
569 static u_int
570 wsemul_vt100_output_scs94_percent(edp, c)
571 struct wsemul_vt100_emuldata *edp;
572 u_char c;
573 {
574 switch (c) {
575 case '5': /* DEC supplemental graphic */
576 /* XXX there are differences */
577 edp->chartab_G[edp->designating] = edp->isolatin1tab;
578 break;
579 default:
580 #ifdef VT100_PRINTUNKNOWN
581 printf("ESC%c%%%c unknown\n", edp->designating + '(', c);
582 #endif
583 break;
584 }
585 return (VT100_EMUL_STATE_NORMAL);
586 }
587
588 static u_int
589 wsemul_vt100_output_scs96(edp, c)
590 struct wsemul_vt100_emuldata *edp;
591 u_char c;
592 {
593 u_int newstate = VT100_EMUL_STATE_NORMAL;
594 int nrc;
595
596 switch (c) {
597 case '%': /* probably portugese */
598 newstate = VT100_EMUL_STATE_SCS96_PERCENT;
599 break;
600 case 'A': /* ISO-latin-1 supplemental */
601 edp->chartab_G[edp->designating] = edp->isolatin1tab;
602 break;
603 case '4': /* dutch */
604 nrc = 1;
605 goto setnrc;
606 case '5': case 'C': /* finnish */
607 nrc = 2;
608 goto setnrc;
609 case 'R': /* french */
610 nrc = 3;
611 goto setnrc;
612 case 'Q': /* french canadian */
613 nrc = 4;
614 goto setnrc;
615 case 'K': /* german */
616 nrc = 5;
617 goto setnrc;
618 case 'Y': /* italian */
619 nrc = 6;
620 goto setnrc;
621 case 'E': case '6': /* norwegian / danish */
622 nrc = 7;
623 goto setnrc;
624 case 'Z': /* spanish */
625 nrc = 9;
626 goto setnrc;
627 case '7': case 'H': /* swedish */
628 nrc = 10;
629 goto setnrc;
630 case '=': /* swiss */
631 nrc = 11;
632 setnrc:
633 vt100_setnrc(edp, nrc); /* what table ??? */
634 break;
635 default:
636 #ifdef VT100_PRINTUNKNOWN
637 printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c);
638 #endif
639 break;
640 }
641 return (newstate);
642 }
643
644 static u_int
645 wsemul_vt100_output_scs96_percent(edp, c)
646 struct wsemul_vt100_emuldata *edp;
647 u_char c;
648 {
649 switch (c) {
650 case '6': /* portugese */
651 vt100_setnrc(edp, 8);
652 break;
653 default:
654 #ifdef VT100_PRINTUNKNOWN
655 printf("ESC%c%%%c unknown\n", edp->designating + '-', c);
656 #endif
657 break;
658 }
659 return (VT100_EMUL_STATE_NORMAL);
660 }
661
662 static u_int
663 wsemul_vt100_output_esc_spc(edp, c)
664 struct wsemul_vt100_emuldata *edp;
665 u_char c;
666 {
667 switch (c) {
668 case 'F': /* 7-bit controls */
669 case 'G': /* 8-bit controls */
670 #ifdef VT100_PRINTNOTIMPL
671 printf("ESC<SPC>%c ignored\n", c);
672 #endif
673 break;
674 default:
675 #ifdef VT100_PRINTUNKNOWN
676 printf("ESC<SPC>%c unknown\n", c);
677 #endif
678 break;
679 }
680 return (VT100_EMUL_STATE_NORMAL);
681 }
682
683 static u_int
684 wsemul_vt100_output_string(edp, c)
685 struct wsemul_vt100_emuldata *edp;
686 u_char c;
687 {
688 switch (c) {
689 case ASCII_ESC: /* might be a string end */
690 return (VT100_EMUL_STATE_STRING_ESC);
691 #if 0
692 case ST: /* string end 8-bit */
693 wsemul_vt100_handle_dcs(edp);
694 return (VT100_EMUL_STATE_NORMAL);
695 #endif
696 default:
697 if (edp->dcstype && edp->dcspos < DCS_MAXLEN)
698 edp->dcsarg[edp->dcspos++] = c;
699 }
700 return (VT100_EMUL_STATE_STRING);
701 }
702
703 static u_int
704 wsemul_vt100_output_string_esc(edp, c)
705 struct wsemul_vt100_emuldata *edp;
706 u_char c;
707 {
708 if (c == '\\') { /* ST complete */
709 wsemul_vt100_handle_dcs(edp);
710 return (VT100_EMUL_STATE_NORMAL);
711 } else
712 return (VT100_EMUL_STATE_STRING);
713 }
714
715 static u_int
716 wsemul_vt100_output_dcs(edp, c)
717 struct wsemul_vt100_emuldata *edp;
718 u_char c;
719 {
720 u_int newstate = VT100_EMUL_STATE_DCS;
721
722 switch (c) {
723 case '0': case '1': case '2': case '3': case '4':
724 case '5': case '6': case '7': case '8': case '9':
725 /* argument digit */
726 if (edp->nargs > VT100_EMUL_NARGS - 1)
727 break;
728 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
729 (c - '0');
730 break;
731 case ';': /* argument terminator */
732 edp->nargs++;
733 break;
734 default:
735 edp->nargs++;
736 if (edp->nargs > VT100_EMUL_NARGS) {
737 #ifdef VT100_DEBUG
738 printf("vt100: too many arguments\n");
739 #endif
740 edp->nargs = VT100_EMUL_NARGS;
741 }
742 newstate = VT100_EMUL_STATE_STRING;
743 switch (c) {
744 case '$':
745 newstate = VT100_EMUL_STATE_DCS_DOLLAR;
746 break;
747 case '{': /* DECDLD soft charset */
748 case '!': /* DECRQUPSS user preferred supplemental set */
749 /* 'u' must follow - need another state */
750 case '|': /* DECUDK program F6..F20 */
751 #ifdef VT100_PRINTNOTIMPL
752 printf("DCS%c ignored\n", c);
753 #endif
754 break;
755 default:
756 #ifdef VT100_PRINTUNKNOWN
757 printf("DCS%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
758 #endif
759 break;
760 }
761 }
762
763 return (newstate);
764 }
765
766 static u_int
767 wsemul_vt100_output_dcs_dollar(edp, c)
768 struct wsemul_vt100_emuldata *edp;
769 u_char c;
770 {
771 switch (c) {
772 case 'p': /* DECRSTS terminal state restore */
773 case 'q': /* DECRQSS control function request */
774 #ifdef VT100_PRINTNOTIMPL
775 printf("DCS$%c ignored\n", c);
776 #endif
777 break;
778 case 't': /* DECRSPS restore presentation state */
779 switch (ARG(0)) {
780 case 0: /* error */
781 break;
782 case 1: /* cursor information restore */
783 #ifdef VT100_PRINTNOTIMPL
784 printf("DCS1$t ignored\n");
785 #endif
786 break;
787 case 2: /* tab stop restore */
788 edp->dcspos = 0;
789 edp->dcstype = DCSTYPE_TABRESTORE;
790 break;
791 default:
792 #ifdef VT100_PRINTUNKNOWN
793 printf("DCS%d$t unknown\n", ARG(0));
794 #endif
795 break;
796 }
797 break;
798 default:
799 #ifdef VT100_PRINTUNKNOWN
800 printf("DCS$%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
801 #endif
802 break;
803 }
804 return (VT100_EMUL_STATE_STRING);
805 }
806
807 static u_int
808 wsemul_vt100_output_esc_hash(edp, c)
809 struct wsemul_vt100_emuldata *edp;
810 u_char c;
811 {
812 int i;
813
814 switch (c) {
815 case '5': /* DECSWL single width, single height */
816 if (edp->dw) {
817 for (i = 0; i < edp->ncols / 2; i++)
818 (*edp->emulops->copycols)(edp->emulcookie,
819 edp->crow,
820 2 * i, i, 1);
821 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
822 i, edp->ncols - i,
823 edp->defattr);
824 edp->dblwid[edp->crow] = 0;
825 edp->dw = 0;
826 }
827 break;
828 case '6': /* DECDWL double width, single height */
829 case '3': /* DECDHL double width, double height, top half */
830 case '4': /* DECDHL double width, double height, bottom half */
831 if (!edp->dw) {
832 for (i = edp->ncols / 2 - 1; i >= 0; i--)
833 (*edp->emulops->copycols)(edp->emulcookie,
834 edp->crow,
835 i, 2 * i, 1);
836 for (i = 0; i < edp->ncols / 2; i++)
837 (*edp->emulops->erasecols)(edp->emulcookie,
838 edp->crow,
839 2 * i + 1, 1,
840 edp->defattr);
841 edp->dblwid[edp->crow] = 1;
842 edp->dw = 1;
843 if (edp->ccol > (edp->ncols >> 1) - 1)
844 edp->ccol = (edp->ncols >> 1) - 1;
845 }
846 break;
847 case '8': { /* DECALN */
848 int i, j;
849 for (i = 0; i < edp->nrows; i++)
850 for (j = 0; j < edp->ncols; j++)
851 (*edp->emulops->putchar)(edp->emulcookie, i, j,
852 'E', edp->curattr);
853 }
854 edp->ccol = 0;
855 edp->crow = 0;
856 break;
857 default:
858 #ifdef VT100_PRINTUNKNOWN
859 printf("ESC#%c unknown\n", c);
860 #endif
861 break;
862 }
863 return (VT100_EMUL_STATE_NORMAL);
864 }
865
866 static u_int
867 wsemul_vt100_output_csi(edp, c)
868 struct wsemul_vt100_emuldata *edp;
869 u_char c;
870 {
871 u_int newstate = VT100_EMUL_STATE_CSI;
872
873 switch (c) {
874 case '0': case '1': case '2': case '3': case '4':
875 case '5': case '6': case '7': case '8': case '9':
876 /* argument digit */
877 if (edp->nargs > VT100_EMUL_NARGS - 1)
878 break;
879 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
880 (c - '0');
881 break;
882 case ';': /* argument terminator */
883 edp->nargs++;
884 break;
885 case '?': /* DEC specific */
886 case '>': /* DA query */
887 edp->modif1 = c;
888 break;
889 case '!':
890 case '"':
891 case '$':
892 case '&':
893 edp->modif2 = c;
894 break;
895 default: /* end of escape sequence */
896 edp->nargs++;
897 if (edp->nargs > VT100_EMUL_NARGS) {
898 #ifdef VT100_DEBUG
899 printf("vt100: too many arguments\n");
900 #endif
901 edp->nargs = VT100_EMUL_NARGS;
902 }
903 wsemul_vt100_handle_csi(edp, c);
904 newstate = VT100_EMUL_STATE_NORMAL;
905 break;
906 }
907 return (newstate);
908 }
909
910 void
911 wsemul_vt100_output(cookie, data, count, kernel)
912 void *cookie;
913 const u_char *data;
914 u_int count;
915 int kernel;
916 {
917 struct wsemul_vt100_emuldata *edp = cookie;
918
919 #ifdef DIAGNOSTIC
920 if (kernel && !edp->console)
921 panic("wsemul_vt100_output: kernel output, not console");
922 #endif
923
924 /* XXX */
925 (*edp->emulops->cursor)(edp->emulcookie, 0,
926 edp->crow, edp->ccol << edp->dw);
927 for (; count > 0; data++, count--) {
928 if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
929 edp->state = wsemul_vt100_output_normal(edp, *data,
930 kernel);
931 continue;
932 }
933 #ifdef DIAGNOSTIC
934 if (edp->state > sizeof(vt100_output) / sizeof(vt100_output[0]))
935 panic("wsemul_vt100: invalid state %d\n", edp->state);
936 #endif
937 edp->state = vt100_output[edp->state - 1](edp, *data);
938 }
939 /* XXX */
940 (*edp->emulops->cursor)(edp->emulcookie, edp->flags & VTFL_CURSORON,
941 edp->crow, edp->ccol << edp->dw);
942 }
943