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