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