wsemul_vt100.c revision 1.13 1 /* $NetBSD: wsemul_vt100.c,v 1.13 2000/04/28 21:56:16 mycroft 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 #ifdef DIAGNOSTIC
407 if (kernel)
408 panic("ESC in kernel output");
409 #endif
410 if (edp->state == VT100_EMUL_STATE_STRING) {
411 /* might be a string end */
412 edp->state = VT100_EMUL_STATE_STRING_ESC;
413 } else {
414 /* XXX cancel current escape sequence */
415 edp->state = VT100_EMUL_STATE_ESC;
416 }
417 break;
418 #if 0
419 case CSI: /* 8-bit */
420 /* XXX cancel current escape sequence */
421 edp->nargs = 0;
422 memset(edp->args, 0, sizeof (edp->args));
423 edp->modif1 = edp->modif2 = '\0';
424 edp->state = VT100_EMUL_STATE_CSI;
425 break;
426 case DCS: /* 8-bit */
427 /* XXX cancel current escape sequence */
428 edp->nargs = 0;
429 memset(edp->args, 0, sizeof (edp->args));
430 edp->state = VT100_EMUL_STATE_DCS;
431 break;
432 case ST: /* string end 8-bit */
433 /* XXX only in VT100_EMUL_STATE_STRING */
434 wsemul_vt100_handle_dcs(edp);
435 return (VT100_EMUL_STATE_NORMAL);
436 #endif
437 case ASCII_LF:
438 case ASCII_VT:
439 case ASCII_FF:
440 if (ROWS_BELOW > 0) {
441 edp->crow++;
442 CHECK_DW;
443 } else
444 wsemul_vt100_scrollup(edp, 1);
445 break;
446 }
447 }
448
449 static u_int
450 wsemul_vt100_output_esc(edp, c)
451 struct wsemul_vt100_emuldata *edp;
452 u_char c;
453 {
454 u_int newstate = VT100_EMUL_STATE_NORMAL;
455 int i;
456
457 switch (c) {
458 case '[': /* CSI */
459 edp->nargs = 0;
460 memset(edp->args, 0, sizeof (edp->args));
461 edp->modif1 = edp->modif2 = '\0';
462 newstate = VT100_EMUL_STATE_CSI;
463 break;
464 case '7': /* DECSC */
465 edp->savedcursor_row = edp->crow;
466 edp->savedcursor_col = edp->ccol;
467 edp->savedattr = edp->curattr;
468 edp->savedbkgdattr = edp->bkgdattr;
469 edp->savedattrflags = edp->attrflags;
470 edp->savedfgcol = edp->fgcol;
471 edp->savedbgcol = edp->bgcol;
472 for (i = 0; i < 4; i++)
473 edp->savedchartab_G[i] = edp->chartab_G[i];
474 edp->savedchartab0 = edp->chartab0;
475 edp->savedchartab1 = edp->chartab1;
476 break;
477 case '8': /* DECRC */
478 edp->crow = edp->savedcursor_row;
479 edp->ccol = edp->savedcursor_col;
480 edp->curattr = edp->savedattr;
481 edp->bkgdattr = edp->savedbkgdattr;
482 edp->attrflags = edp->savedattrflags;
483 edp->fgcol = edp->savedfgcol;
484 edp->bgcol = edp->savedbgcol;
485 for (i = 0; i < 4; i++)
486 edp->chartab_G[i] = edp->savedchartab_G[i];
487 edp->chartab0 = edp->savedchartab0;
488 edp->chartab1 = edp->savedchartab1;
489 break;
490 case '=': /* DECKPAM application mode */
491 edp->flags |= VTFL_APPLKEYPAD;
492 break;
493 case '>': /* DECKPNM numeric mode */
494 edp->flags &= ~VTFL_APPLKEYPAD;
495 break;
496 case 'E': /* NEL */
497 edp->ccol = 0;
498 /* FALLTHRU */
499 case 'D': /* IND */
500 if (ROWS_BELOW > 0) {
501 edp->crow++;
502 CHECK_DW;
503 break;
504 }
505 wsemul_vt100_scrollup(edp, 1);
506 break;
507 case 'H': /* HTS */
508 KASSERT(edp->tabs != 0);
509 edp->tabs[edp->ccol] = 1;
510 break;
511 case '~': /* LS1R */
512 edp->chartab1 = 1;
513 break;
514 case 'n': /* LS2 */
515 edp->chartab0 = 2;
516 break;
517 case '}': /* LS2R */
518 edp->chartab1 = 2;
519 break;
520 case 'o': /* LS3 */
521 edp->chartab0 = 3;
522 break;
523 case '|': /* LS3R */
524 edp->chartab1 = 3;
525 break;
526 case 'N': /* SS2 */
527 edp->sschartab = 2;
528 break;
529 case 'O': /* SS3 */
530 edp->sschartab = 3;
531 break;
532 case 'M': /* RI */
533 if (ROWS_ABOVE > 0) {
534 edp->crow--;
535 CHECK_DW;
536 break;
537 }
538 wsemul_vt100_scrolldown(edp, 1);
539 break;
540 case 'P': /* DCS */
541 edp->nargs = 0;
542 memset(edp->args, 0, sizeof (edp->args));
543 newstate = VT100_EMUL_STATE_DCS;
544 break;
545 case 'c': /* RIS */
546 wsemul_vt100_reset(edp);
547 wsemul_vt100_ed(edp, 2);
548 edp->ccol = edp->crow = 0;
549 break;
550 case '(': case ')': case '*': case '+': /* SCS */
551 edp->designating = c - '(';
552 newstate = VT100_EMUL_STATE_SCS94;
553 break;
554 case '-': case '.': case '/': /* SCS */
555 edp->designating = c - '-' + 1;
556 newstate = VT100_EMUL_STATE_SCS96;
557 break;
558 case '#':
559 newstate = VT100_EMUL_STATE_ESC_HASH;
560 break;
561 case ' ': /* 7/8 bit */
562 newstate = VT100_EMUL_STATE_ESC_SPC;
563 break;
564 case ']': /* OSC operating system command */
565 case '^': /* PM privacy message */
566 case '_': /* APC application program command */
567 /* ignored */
568 newstate = VT100_EMUL_STATE_STRING;
569 break;
570 case '<': /* exit VT52 mode - ignored */
571 break;
572 default:
573 #ifdef VT100_PRINTUNKNOWN
574 printf("ESC%c unknown\n", c);
575 #endif
576 break;
577 }
578
579 return (newstate);
580 }
581
582 static u_int
583 wsemul_vt100_output_scs94(edp, c)
584 struct wsemul_vt100_emuldata *edp;
585 u_char c;
586 {
587 u_int newstate = VT100_EMUL_STATE_NORMAL;
588
589 switch (c) {
590 case '%': /* probably DEC supplemental graphic */
591 newstate = VT100_EMUL_STATE_SCS94_PERCENT;
592 break;
593 case 'A': /* british / national */
594 edp->chartab_G[edp->designating] = edp->nrctab;
595 break;
596 case 'B': /* ASCII */
597 edp->chartab_G[edp->designating] = 0;
598 break;
599 case '<': /* user preferred supplemental */
600 /* XXX not really "user" preferred */
601 edp->chartab_G[edp->designating] = edp->isolatin1tab;
602 break;
603 case '0': /* DEC special graphic */
604 edp->chartab_G[edp->designating] = edp->decgraphtab;
605 break;
606 case '>': /* DEC tech */
607 edp->chartab_G[edp->designating] = edp->dectechtab;
608 break;
609 default:
610 #ifdef VT100_PRINTUNKNOWN
611 printf("ESC%c%c unknown\n", edp->designating + '(', c);
612 #endif
613 break;
614 }
615 return (newstate);
616 }
617
618 static u_int
619 wsemul_vt100_output_scs94_percent(edp, c)
620 struct wsemul_vt100_emuldata *edp;
621 u_char c;
622 {
623 switch (c) {
624 case '5': /* DEC supplemental graphic */
625 /* XXX there are differences */
626 edp->chartab_G[edp->designating] = edp->isolatin1tab;
627 break;
628 default:
629 #ifdef VT100_PRINTUNKNOWN
630 printf("ESC%c%%%c unknown\n", edp->designating + '(', c);
631 #endif
632 break;
633 }
634 return (VT100_EMUL_STATE_NORMAL);
635 }
636
637 static u_int
638 wsemul_vt100_output_scs96(edp, c)
639 struct wsemul_vt100_emuldata *edp;
640 u_char c;
641 {
642 u_int newstate = VT100_EMUL_STATE_NORMAL;
643 int nrc;
644
645 switch (c) {
646 case '%': /* probably portugese */
647 newstate = VT100_EMUL_STATE_SCS96_PERCENT;
648 break;
649 case 'A': /* ISO-latin-1 supplemental */
650 edp->chartab_G[edp->designating] = edp->isolatin1tab;
651 break;
652 case '4': /* dutch */
653 nrc = 1;
654 goto setnrc;
655 case '5': case 'C': /* finnish */
656 nrc = 2;
657 goto setnrc;
658 case 'R': /* french */
659 nrc = 3;
660 goto setnrc;
661 case 'Q': /* french canadian */
662 nrc = 4;
663 goto setnrc;
664 case 'K': /* german */
665 nrc = 5;
666 goto setnrc;
667 case 'Y': /* italian */
668 nrc = 6;
669 goto setnrc;
670 case 'E': case '6': /* norwegian / danish */
671 nrc = 7;
672 goto setnrc;
673 case 'Z': /* spanish */
674 nrc = 9;
675 goto setnrc;
676 case '7': case 'H': /* swedish */
677 nrc = 10;
678 goto setnrc;
679 case '=': /* swiss */
680 nrc = 11;
681 setnrc:
682 vt100_setnrc(edp, nrc); /* what table ??? */
683 break;
684 default:
685 #ifdef VT100_PRINTUNKNOWN
686 printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c);
687 #endif
688 break;
689 }
690 return (newstate);
691 }
692
693 static u_int
694 wsemul_vt100_output_scs96_percent(edp, c)
695 struct wsemul_vt100_emuldata *edp;
696 u_char c;
697 {
698 switch (c) {
699 case '6': /* portugese */
700 vt100_setnrc(edp, 8);
701 break;
702 default:
703 #ifdef VT100_PRINTUNKNOWN
704 printf("ESC%c%%%c unknown\n", edp->designating + '-', c);
705 #endif
706 break;
707 }
708 return (VT100_EMUL_STATE_NORMAL);
709 }
710
711 static u_int
712 wsemul_vt100_output_esc_spc(edp, c)
713 struct wsemul_vt100_emuldata *edp;
714 u_char c;
715 {
716 switch (c) {
717 case 'F': /* 7-bit controls */
718 case 'G': /* 8-bit controls */
719 #ifdef VT100_PRINTNOTIMPL
720 printf("ESC<SPC>%c ignored\n", c);
721 #endif
722 break;
723 default:
724 #ifdef VT100_PRINTUNKNOWN
725 printf("ESC<SPC>%c unknown\n", c);
726 #endif
727 break;
728 }
729 return (VT100_EMUL_STATE_NORMAL);
730 }
731
732 static u_int
733 wsemul_vt100_output_string(edp, c)
734 struct wsemul_vt100_emuldata *edp;
735 u_char c;
736 {
737 if (edp->dcstype && edp->dcspos < DCS_MAXLEN)
738 edp->dcsarg[edp->dcspos++] = c;
739 return (VT100_EMUL_STATE_STRING);
740 }
741
742 static u_int
743 wsemul_vt100_output_string_esc(edp, c)
744 struct wsemul_vt100_emuldata *edp;
745 u_char c;
746 {
747 if (c == '\\') { /* ST complete */
748 wsemul_vt100_handle_dcs(edp);
749 return (VT100_EMUL_STATE_NORMAL);
750 } else
751 return (VT100_EMUL_STATE_STRING);
752 }
753
754 static u_int
755 wsemul_vt100_output_dcs(edp, c)
756 struct wsemul_vt100_emuldata *edp;
757 u_char c;
758 {
759 u_int newstate = VT100_EMUL_STATE_DCS;
760
761 switch (c) {
762 case '0': case '1': case '2': case '3': case '4':
763 case '5': case '6': case '7': case '8': case '9':
764 /* argument digit */
765 if (edp->nargs > VT100_EMUL_NARGS - 1)
766 break;
767 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
768 (c - '0');
769 break;
770 case ';': /* argument terminator */
771 edp->nargs++;
772 break;
773 default:
774 edp->nargs++;
775 if (edp->nargs > VT100_EMUL_NARGS) {
776 #ifdef VT100_DEBUG
777 printf("vt100: too many arguments\n");
778 #endif
779 edp->nargs = VT100_EMUL_NARGS;
780 }
781 newstate = VT100_EMUL_STATE_STRING;
782 switch (c) {
783 case '$':
784 newstate = VT100_EMUL_STATE_DCS_DOLLAR;
785 break;
786 case '{': /* DECDLD soft charset */
787 case '!': /* DECRQUPSS user preferred supplemental set */
788 /* 'u' must follow - need another state */
789 case '|': /* DECUDK program F6..F20 */
790 #ifdef VT100_PRINTNOTIMPL
791 printf("DCS%c ignored\n", c);
792 #endif
793 break;
794 default:
795 #ifdef VT100_PRINTUNKNOWN
796 printf("DCS%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
797 #endif
798 break;
799 }
800 }
801
802 return (newstate);
803 }
804
805 static u_int
806 wsemul_vt100_output_dcs_dollar(edp, c)
807 struct wsemul_vt100_emuldata *edp;
808 u_char c;
809 {
810 switch (c) {
811 case 'p': /* DECRSTS terminal state restore */
812 case 'q': /* DECRQSS control function request */
813 #ifdef VT100_PRINTNOTIMPL
814 printf("DCS$%c ignored\n", c);
815 #endif
816 break;
817 case 't': /* DECRSPS restore presentation state */
818 switch (ARG(0)) {
819 case 0: /* error */
820 break;
821 case 1: /* cursor information restore */
822 #ifdef VT100_PRINTNOTIMPL
823 printf("DCS1$t ignored\n");
824 #endif
825 break;
826 case 2: /* tab stop restore */
827 edp->dcspos = 0;
828 edp->dcstype = DCSTYPE_TABRESTORE;
829 break;
830 default:
831 #ifdef VT100_PRINTUNKNOWN
832 printf("DCS%d$t unknown\n", ARG(0));
833 #endif
834 break;
835 }
836 break;
837 default:
838 #ifdef VT100_PRINTUNKNOWN
839 printf("DCS$%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
840 #endif
841 break;
842 }
843 return (VT100_EMUL_STATE_STRING);
844 }
845
846 static u_int
847 wsemul_vt100_output_esc_hash(edp, c)
848 struct wsemul_vt100_emuldata *edp;
849 u_char c;
850 {
851 int i;
852
853 switch (c) {
854 case '5': /* DECSWL single width, single height */
855 if (edp->dw) {
856 for (i = 0; i < edp->ncols / 2; i++)
857 (*edp->emulops->copycols)(edp->emulcookie,
858 edp->crow,
859 2 * i, i, 1);
860 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
861 i, edp->ncols - i,
862 edp->bkgdattr);
863 edp->dblwid[edp->crow] = 0;
864 edp->dw = 0;
865 }
866 break;
867 case '6': /* DECDWL double width, single height */
868 case '3': /* DECDHL double width, double height, top half */
869 case '4': /* DECDHL double width, double height, bottom half */
870 if (!edp->dw) {
871 for (i = edp->ncols / 2 - 1; i >= 0; i--)
872 (*edp->emulops->copycols)(edp->emulcookie,
873 edp->crow,
874 i, 2 * i, 1);
875 for (i = 0; i < edp->ncols / 2; i++)
876 (*edp->emulops->erasecols)(edp->emulcookie,
877 edp->crow,
878 2 * i + 1, 1,
879 edp->bkgdattr);
880 edp->dblwid[edp->crow] = 1;
881 edp->dw = 1;
882 if (edp->ccol > (edp->ncols >> 1) - 1)
883 edp->ccol = (edp->ncols >> 1) - 1;
884 }
885 break;
886 case '8': { /* DECALN */
887 int i, j;
888 for (i = 0; i < edp->nrows; i++)
889 for (j = 0; j < edp->ncols; j++)
890 (*edp->emulops->putchar)(edp->emulcookie, i, j,
891 'E', edp->curattr);
892 }
893 edp->ccol = 0;
894 edp->crow = 0;
895 break;
896 default:
897 #ifdef VT100_PRINTUNKNOWN
898 printf("ESC#%c unknown\n", c);
899 #endif
900 break;
901 }
902 return (VT100_EMUL_STATE_NORMAL);
903 }
904
905 static u_int
906 wsemul_vt100_output_csi(edp, c)
907 struct wsemul_vt100_emuldata *edp;
908 u_char c;
909 {
910 u_int newstate = VT100_EMUL_STATE_CSI;
911
912 switch (c) {
913 case '0': case '1': case '2': case '3': case '4':
914 case '5': case '6': case '7': case '8': case '9':
915 /* argument digit */
916 if (edp->nargs > VT100_EMUL_NARGS - 1)
917 break;
918 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
919 (c - '0');
920 break;
921 case ';': /* argument terminator */
922 edp->nargs++;
923 break;
924 case '?': /* DEC specific */
925 case '>': /* DA query */
926 edp->modif1 = c;
927 break;
928 case '!':
929 case '"':
930 case '$':
931 case '&':
932 edp->modif2 = c;
933 break;
934 default: /* end of escape sequence */
935 edp->nargs++;
936 if (edp->nargs > VT100_EMUL_NARGS) {
937 #ifdef VT100_DEBUG
938 printf("vt100: too many arguments\n");
939 #endif
940 edp->nargs = VT100_EMUL_NARGS;
941 }
942 wsemul_vt100_handle_csi(edp, c);
943 newstate = VT100_EMUL_STATE_NORMAL;
944 break;
945 }
946 return (newstate);
947 }
948
949 void
950 wsemul_vt100_output(cookie, data, count, kernel)
951 void *cookie;
952 const u_char *data;
953 u_int count;
954 int kernel;
955 {
956 struct wsemul_vt100_emuldata *edp = cookie;
957
958 #ifdef DIAGNOSTIC
959 if (kernel && !edp->console)
960 panic("wsemul_vt100_output: kernel output, not console");
961 #endif
962
963 if (edp->flags & VTFL_CURSORON)
964 (*edp->emulops->cursor)(edp->emulcookie, 0,
965 edp->crow, edp->ccol << edp->dw);
966 for (; count > 0; data++, count--) {
967 if ((*data & 0x7f) < 0x20) {
968 wsemul_vt100_output_c0c1(edp, *data, kernel);
969 continue;
970 }
971 if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
972 wsemul_vt100_output_normal(edp, *data, kernel);
973 continue;
974 }
975 #ifdef DIAGNOSTIC
976 if (edp->state > sizeof(vt100_output) / sizeof(vt100_output[0]))
977 panic("wsemul_vt100: invalid state %d\n", edp->state);
978 #endif
979 edp->state = vt100_output[edp->state - 1](edp, *data);
980 }
981 if (edp->flags & VTFL_CURSORON)
982 (*edp->emulops->cursor)(edp->emulcookie, 1,
983 edp->crow, edp->ccol << edp->dw);
984 }
985