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