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