Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / wscons / wsemul_vt100.c
bloba349a9dbe6134c355fa43d1d9eda2bdb42003057
1 /* $NetBSD: wsemul_vt100.c,v 1.30 2006/11/16 01:33:31 christos Exp $ */
3 /*
4 * Copyright (c) 1998
5 * Matthias Drochner. All rights reserved.
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.
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.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: wsemul_vt100.c,v 1.30 2006/11/16 01:33:31 christos Exp $");
32 #include "opt_wsmsgattrs.h"
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/time.h>
37 #include <sys/malloc.h>
38 #include <sys/fcntl.h>
40 #include <dev/wscons/wsconsio.h>
41 #include <dev/wscons/wsdisplayvar.h>
42 #include <dev/wscons/wsemulvar.h>
43 #include <dev/wscons/wsemul_vt100var.h>
44 #include <dev/wscons/ascii.h>
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 #ifdef WSDISPLAY_CUSTOM_OUTPUT
54 static void wsemul_vt100_getmsgattrs(void *, struct wsdisplay_msgattrs *);
55 static void wsemul_vt100_setmsgattrs(void *, const struct wsscreen_descr *,
56 const struct wsdisplay_msgattrs *);
57 #endif /* WSDISPLAY_CUSTOM_OUTPUT */
59 const struct wsemul_ops wsemul_vt100_ops = {
60 "vt100",
61 wsemul_vt100_cnattach,
62 wsemul_vt100_attach,
63 wsemul_vt100_output,
64 wsemul_vt100_translate,
65 wsemul_vt100_detach,
66 wsemul_vt100_resetop,
67 #ifdef WSDISPLAY_CUSTOM_OUTPUT
68 wsemul_vt100_getmsgattrs,
69 wsemul_vt100_setmsgattrs,
70 #else
71 NULL,
72 NULL,
73 #endif
76 struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata;
78 static void wsemul_vt100_init(struct wsemul_vt100_emuldata *,
79 const struct wsscreen_descr *,
80 void *, int, int, long);
82 static void wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
83 u_char, int);
84 static void wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *,
85 u_char, int);
86 static void wsemul_vt100_nextline(struct wsemul_vt100_emuldata *);
87 typedef u_int vt100_handler(struct wsemul_vt100_emuldata *, u_char);
89 static vt100_handler
90 wsemul_vt100_output_esc,
91 wsemul_vt100_output_csi,
92 wsemul_vt100_output_scs94,
93 wsemul_vt100_output_scs94_percent,
94 wsemul_vt100_output_scs96,
95 wsemul_vt100_output_scs96_percent,
96 wsemul_vt100_output_esc_hash,
97 wsemul_vt100_output_esc_spc,
98 wsemul_vt100_output_string,
99 wsemul_vt100_output_string_esc,
100 wsemul_vt100_output_dcs,
101 wsemul_vt100_output_dcs_dollar;
103 #define VT100_EMUL_STATE_NORMAL 0 /* normal processing */
104 #define VT100_EMUL_STATE_ESC 1 /* got ESC */
105 #define VT100_EMUL_STATE_CSI 2 /* got CSI (ESC[) */
106 #define VT100_EMUL_STATE_SCS94 3 /* got ESC{()*+} */
107 #define VT100_EMUL_STATE_SCS94_PERCENT 4 /* got ESC{()*+}% */
108 #define VT100_EMUL_STATE_SCS96 5 /* got ESC{-./} */
109 #define VT100_EMUL_STATE_SCS96_PERCENT 6 /* got ESC{-./}% */
110 #define VT100_EMUL_STATE_ESC_HASH 7 /* got ESC# */
111 #define VT100_EMUL_STATE_ESC_SPC 8 /* got ESC<SPC> */
112 #define VT100_EMUL_STATE_STRING 9 /* waiting for ST (ESC\) */
113 #define VT100_EMUL_STATE_STRING_ESC 10 /* waiting for ST, got ESC */
114 #define VT100_EMUL_STATE_DCS 11 /* got DCS (ESC P) */
115 #define VT100_EMUL_STATE_DCS_DOLLAR 12 /* got DCS<p>$ */
117 vt100_handler *vt100_output[] = {
118 wsemul_vt100_output_esc,
119 wsemul_vt100_output_csi,
120 wsemul_vt100_output_scs94,
121 wsemul_vt100_output_scs94_percent,
122 wsemul_vt100_output_scs96,
123 wsemul_vt100_output_scs96_percent,
124 wsemul_vt100_output_esc_hash,
125 wsemul_vt100_output_esc_spc,
126 wsemul_vt100_output_string,
127 wsemul_vt100_output_string_esc,
128 wsemul_vt100_output_dcs,
129 wsemul_vt100_output_dcs_dollar,
132 static void
133 wsemul_vt100_init(struct wsemul_vt100_emuldata *edp,
134 const struct wsscreen_descr *type, void *cookie, int ccol, int crow,
135 long defattr)
137 int error;
139 edp->emulops = type->textops;
140 edp->emulcookie = cookie;
141 edp->scrcapabilities = type->capabilities;
142 edp->nrows = type->nrows;
143 edp->ncols = type->ncols;
144 edp->crow = crow;
145 edp->ccol = ccol;
147 /* The underlying driver has already allocated a default and simple
148 * attribute for us, which is stored in defattr. We try to set the
149 * values specified by the kernel options below, but in case of
150 * failure we fallback to the value given by the driver. */
152 if (type->capabilities & WSSCREEN_WSCOLORS) {
153 edp->msgattrs.default_attrs = WS_DEFAULT_COLATTR |
154 WSATTR_WSCOLORS;
155 edp->msgattrs.default_bg = WS_DEFAULT_BG;
156 edp->msgattrs.default_fg = WS_DEFAULT_FG;
158 edp->msgattrs.kernel_attrs = WS_KERNEL_COLATTR |
159 WSATTR_WSCOLORS;
160 edp->msgattrs.kernel_bg = WS_KERNEL_BG;
161 edp->msgattrs.kernel_fg = WS_KERNEL_FG;
162 } else {
163 edp->msgattrs.default_attrs = WS_DEFAULT_MONOATTR;
164 edp->msgattrs.default_bg = edp->msgattrs.default_fg = 0;
166 edp->msgattrs.kernel_attrs = WS_KERNEL_MONOATTR;
167 edp->msgattrs.kernel_bg = edp->msgattrs.kernel_fg = 0;
170 error = (*edp->emulops->allocattr)(cookie,
171 edp->msgattrs.default_fg,
172 edp->msgattrs.default_bg,
173 edp->msgattrs.default_attrs,
174 &edp->defattr);
175 if (error) {
176 edp->defattr = defattr;
177 /* XXX This assumes the driver has allocated white on black
178 * XXX as the default attribute, which is not always true.
179 * XXX Maybe we need an emulop that, given an attribute,
180 * XXX (defattr) returns its flags and colors? */
181 edp->msgattrs.default_attrs = 0;
182 edp->msgattrs.default_bg = WSCOL_BLACK;
183 edp->msgattrs.default_fg = WSCOL_WHITE;
184 } else {
185 if (edp->emulops->replaceattr != NULL)
186 (*edp->emulops->replaceattr)(cookie, defattr,
187 edp->defattr);
190 #if defined(WS_KERNEL_CUSTOMIZED)
191 /* Set up kernel colors, in case they were customized by the user;
192 * otherwise default to the colors specified for the console.
193 * In case of failure, we use console colors too; we can assume
194 * they are good as they have been previously allocated and
195 * verified. */
196 error = (*edp->emulops->allocattr)(cookie,
197 edp->msgattrs.kernel_fg,
198 edp->msgattrs.kernel_bg,
199 edp->msgattrs.kernel_attrs,
200 &edp->kernattr);
201 if (error)
202 #endif
203 edp->kernattr = edp->defattr;
206 void *
207 wsemul_vt100_cnattach(const struct wsscreen_descr *type, void *cookie,
208 int ccol, int crow, long defattr)
210 struct wsemul_vt100_emuldata *edp;
212 edp = &wsemul_vt100_console_emuldata;
213 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
214 #ifdef DIAGNOSTIC
215 edp->console = 1;
216 #endif
217 edp->cbcookie = NULL;
219 edp->tabs = 0;
220 edp->dblwid = 0;
221 edp->dw = 0;
222 edp->dcsarg = 0;
223 edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = 0;
224 edp->nrctab = 0;
225 wsemul_vt100_reset(edp);
226 return (edp);
229 void *
230 wsemul_vt100_attach(int console, const struct wsscreen_descr *type,
231 void *cookie, int ccol, int crow, void *cbcookie, long defattr)
233 struct wsemul_vt100_emuldata *edp;
235 if (console) {
236 edp = &wsemul_vt100_console_emuldata;
237 #ifdef DIAGNOSTIC
238 KASSERT(edp->console == 1);
239 #endif
240 } else {
241 edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK);
242 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
243 #ifdef DIAGNOSTIC
244 edp->console = 0;
245 #endif
247 edp->cbcookie = cbcookie;
249 edp->tabs = malloc(edp->ncols, M_DEVBUF, M_NOWAIT);
250 edp->dblwid = malloc(edp->nrows, M_DEVBUF, M_NOWAIT|M_ZERO);
251 edp->dw = 0;
252 edp->dcsarg = malloc(DCS_MAXLEN, M_DEVBUF, M_NOWAIT);
253 edp->isolatin1tab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
254 edp->decgraphtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
255 edp->dectechtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
256 edp->nrctab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
257 vt100_initchartables(edp);
258 wsemul_vt100_reset(edp);
259 return (edp);
262 void
263 wsemul_vt100_detach(void *cookie, u_int *crowp, u_int *ccolp)
265 struct wsemul_vt100_emuldata *edp = cookie;
267 *crowp = edp->crow;
268 *ccolp = edp->ccol;
269 #define f(ptr) if (ptr) {free(ptr, M_DEVBUF); ptr = 0;}
270 f(edp->tabs)
271 f(edp->dblwid)
272 f(edp->dcsarg)
273 f(edp->isolatin1tab)
274 f(edp->decgraphtab)
275 f(edp->dectechtab)
276 f(edp->nrctab)
277 #undef f
278 if (edp != &wsemul_vt100_console_emuldata)
279 free(edp, M_DEVBUF);
282 void
283 wsemul_vt100_resetop(void *cookie, enum wsemul_resetops op)
285 struct wsemul_vt100_emuldata *edp = cookie;
287 switch (op) {
288 case WSEMUL_RESET:
289 wsemul_vt100_reset(edp);
290 break;
291 case WSEMUL_SYNCFONT:
292 vt100_initchartables(edp);
293 break;
294 case WSEMUL_CLEARSCREEN:
295 wsemul_vt100_ed(edp, 2);
296 edp->ccol = edp->crow = 0;
297 (*edp->emulops->cursor)(edp->emulcookie,
298 edp->flags & VTFL_CURSORON, 0, 0);
299 break;
300 default:
301 break;
305 void
306 wsemul_vt100_reset(struct wsemul_vt100_emuldata *edp)
308 int i;
310 edp->state = VT100_EMUL_STATE_NORMAL;
311 edp->flags = VTFL_DECAWM | VTFL_CURSORON;
312 edp->bkgdattr = edp->curattr = edp->defattr;
313 edp->attrflags = edp->msgattrs.default_attrs;
314 edp->fgcol = edp->msgattrs.default_fg;
315 edp->bgcol = edp->msgattrs.default_bg;
316 edp->scrreg_startrow = 0;
317 edp->scrreg_nrows = edp->nrows;
318 if (edp->tabs) {
319 memset(edp->tabs, 0, edp->ncols);
320 for (i = 8; i < edp->ncols; i += 8)
321 edp->tabs[i] = 1;
323 edp->dcspos = 0;
324 edp->dcstype = 0;
325 edp->chartab_G[0] = 0;
326 edp->chartab_G[1] = edp->nrctab; /* ??? */
327 edp->chartab_G[2] = edp->isolatin1tab;
328 edp->chartab_G[3] = edp->isolatin1tab;
329 edp->chartab0 = 0;
330 edp->chartab1 = 2;
331 edp->sschartab = 0;
335 * now all the state machine bits
339 * Move the cursor to the next line if possible. If the cursor is at
340 * the bottom of the scroll area, then scroll it up. If the cursor is
341 * at the bottom of the screen then don't move it down.
343 static void
344 wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
346 if (ROWS_BELOW == 0) {
347 /* Bottom of the scroll region. */
348 wsemul_vt100_scrollup(edp, 1);
349 } else {
350 if ((edp->crow+1) < edp->nrows)
351 /* Cursor not at the bottom of the screen. */
352 edp->crow++;
353 CHECK_DW;
357 static void
358 wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp, u_char c,
359 int kernel)
361 u_int *ct, dc;
363 if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
364 (VTFL_LASTCHAR | VTFL_DECAWM)) {
365 wsemul_vt100_nextline(edp);
366 edp->ccol = 0;
367 edp->flags &= ~VTFL_LASTCHAR;
370 if (c & 0x80) {
371 c &= 0x7f;
372 ct = edp->chartab_G[edp->chartab1];
373 } else {
374 if (edp->sschartab) {
375 ct = edp->chartab_G[edp->sschartab];
376 edp->sschartab = 0;
377 } else
378 ct = edp->chartab_G[edp->chartab0];
380 dc = (ct ? ct[c] : c);
382 if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT)
383 COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT);
385 (*edp->emulops->putchar)(edp->emulcookie, edp->crow,
386 edp->ccol << edp->dw, dc,
387 kernel ? edp->kernattr : edp->curattr);
389 if (COLS_LEFT)
390 edp->ccol++;
391 else
392 edp->flags |= VTFL_LASTCHAR;
395 static void
396 wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp, u_char c,
397 int kernel)
399 u_int n;
401 switch (c) {
402 case ASCII_NUL:
403 default:
404 /* ignore */
405 break;
406 case ASCII_BEL:
407 wsdisplay_emulbell(edp->cbcookie);
408 break;
409 case ASCII_BS:
410 if (edp->ccol > 0) {
411 edp->ccol--;
412 edp->flags &= ~VTFL_LASTCHAR;
414 break;
415 case ASCII_CR:
416 edp->ccol = 0;
417 edp->flags &= ~VTFL_LASTCHAR;
418 break;
419 case ASCII_HT:
420 if (edp->tabs) {
421 if (!COLS_LEFT)
422 break;
423 for (n = edp->ccol + 1; n < NCOLS - 1; n++)
424 if (edp->tabs[n])
425 break;
426 } else {
427 n = edp->ccol + min(8 - (edp->ccol & 7), COLS_LEFT);
429 edp->ccol = n;
430 break;
431 case ASCII_SO: /* LS1 */
432 edp->chartab0 = 1;
433 break;
434 case ASCII_SI: /* LS0 */
435 edp->chartab0 = 0;
436 break;
437 case ASCII_ESC:
438 if (kernel) {
439 printf("wsemul_vt100_output_c0c1: ESC in kernel output ignored\n");
440 break; /* ignore the ESC */
443 if (edp->state == VT100_EMUL_STATE_STRING) {
444 /* might be a string end */
445 edp->state = VT100_EMUL_STATE_STRING_ESC;
446 } else {
447 /* XXX cancel current escape sequence */
448 edp->state = VT100_EMUL_STATE_ESC;
450 break;
451 #if 0
452 case CSI: /* 8-bit */
453 /* XXX cancel current escape sequence */
454 edp->nargs = 0;
455 memset(edp->args, 0, sizeof (edp->args));
456 edp->modif1 = edp->modif2 = '\0';
457 edp->state = VT100_EMUL_STATE_CSI;
458 break;
459 case DCS: /* 8-bit */
460 /* XXX cancel current escape sequence */
461 edp->nargs = 0;
462 memset(edp->args, 0, sizeof (edp->args));
463 edp->state = VT100_EMUL_STATE_DCS;
464 break;
465 case ST: /* string end 8-bit */
466 /* XXX only in VT100_EMUL_STATE_STRING */
467 wsemul_vt100_handle_dcs(edp);
468 return (VT100_EMUL_STATE_NORMAL);
469 #endif
470 case ASCII_LF:
471 case ASCII_VT:
472 case ASCII_FF:
473 wsemul_vt100_nextline(edp);
474 break;
478 static u_int
479 wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, u_char c)
481 u_int newstate = VT100_EMUL_STATE_NORMAL;
482 int i;
484 switch (c) {
485 case '[': /* CSI */
486 edp->nargs = 0;
487 memset(edp->args, 0, sizeof (edp->args));
488 edp->modif1 = edp->modif2 = '\0';
489 newstate = VT100_EMUL_STATE_CSI;
490 break;
491 case '7': /* DECSC */
492 edp->flags |= VTFL_SAVEDCURS;
493 edp->savedcursor_row = edp->crow;
494 edp->savedcursor_col = edp->ccol;
495 edp->savedattr = edp->curattr;
496 edp->savedbkgdattr = edp->bkgdattr;
497 edp->savedattrflags = edp->attrflags;
498 edp->savedfgcol = edp->fgcol;
499 edp->savedbgcol = edp->bgcol;
500 for (i = 0; i < 4; i++)
501 edp->savedchartab_G[i] = edp->chartab_G[i];
502 edp->savedchartab0 = edp->chartab0;
503 edp->savedchartab1 = edp->chartab1;
504 break;
505 case '8': /* DECRC */
506 if ((edp->flags & VTFL_SAVEDCURS) == 0)
507 break;
508 edp->crow = edp->savedcursor_row;
509 edp->ccol = edp->savedcursor_col;
510 edp->curattr = edp->savedattr;
511 edp->bkgdattr = edp->savedbkgdattr;
512 edp->attrflags = edp->savedattrflags;
513 edp->fgcol = edp->savedfgcol;
514 edp->bgcol = edp->savedbgcol;
515 for (i = 0; i < 4; i++)
516 edp->chartab_G[i] = edp->savedchartab_G[i];
517 edp->chartab0 = edp->savedchartab0;
518 edp->chartab1 = edp->savedchartab1;
519 break;
520 case '=': /* DECKPAM application mode */
521 edp->flags |= VTFL_APPLKEYPAD;
522 break;
523 case '>': /* DECKPNM numeric mode */
524 edp->flags &= ~VTFL_APPLKEYPAD;
525 break;
526 case 'E': /* NEL */
527 edp->ccol = 0;
528 /* FALLTHRU */
529 case 'D': /* IND */
530 wsemul_vt100_nextline(edp);
531 break;
532 case 'H': /* HTS */
533 KASSERT(edp->tabs != 0);
534 edp->tabs[edp->ccol] = 1;
535 break;
536 case '~': /* LS1R */
537 edp->chartab1 = 1;
538 break;
539 case 'n': /* LS2 */
540 edp->chartab0 = 2;
541 break;
542 case '}': /* LS2R */
543 edp->chartab1 = 2;
544 break;
545 case 'o': /* LS3 */
546 edp->chartab0 = 3;
547 break;
548 case '|': /* LS3R */
549 edp->chartab1 = 3;
550 break;
551 case 'N': /* SS2 */
552 edp->sschartab = 2;
553 break;
554 case 'O': /* SS3 */
555 edp->sschartab = 3;
556 break;
557 case 'M': /* RI */
558 if (ROWS_ABOVE > 0) {
559 edp->crow--;
560 CHECK_DW;
561 break;
563 wsemul_vt100_scrolldown(edp, 1);
564 break;
565 case 'P': /* DCS */
566 edp->nargs = 0;
567 memset(edp->args, 0, sizeof (edp->args));
568 newstate = VT100_EMUL_STATE_DCS;
569 break;
570 case 'c': /* RIS */
571 wsemul_vt100_reset(edp);
572 wsemul_vt100_ed(edp, 2);
573 edp->ccol = edp->crow = 0;
574 break;
575 case '(': case ')': case '*': case '+': /* SCS */
576 edp->designating = c - '(';
577 newstate = VT100_EMUL_STATE_SCS94;
578 break;
579 case '-': case '.': case '/': /* SCS */
580 edp->designating = c - '-' + 1;
581 newstate = VT100_EMUL_STATE_SCS96;
582 break;
583 case '#':
584 newstate = VT100_EMUL_STATE_ESC_HASH;
585 break;
586 case ' ': /* 7/8 bit */
587 newstate = VT100_EMUL_STATE_ESC_SPC;
588 break;
589 case ']': /* OSC operating system command */
590 case '^': /* PM privacy message */
591 case '_': /* APC application program command */
592 /* ignored */
593 newstate = VT100_EMUL_STATE_STRING;
594 break;
595 case '<': /* exit VT52 mode - ignored */
596 break;
597 default:
598 #ifdef VT100_PRINTUNKNOWN
599 printf("ESC%c unknown\n", c);
600 #endif
601 break;
604 return (newstate);
607 static u_int
608 wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp, u_char c)
610 u_int newstate = VT100_EMUL_STATE_NORMAL;
612 switch (c) {
613 case '%': /* probably DEC supplemental graphic */
614 newstate = VT100_EMUL_STATE_SCS94_PERCENT;
615 break;
616 case 'A': /* british / national */
617 edp->chartab_G[edp->designating] = edp->nrctab;
618 break;
619 case 'B': /* ASCII */
620 edp->chartab_G[edp->designating] = 0;
621 break;
622 case '<': /* user preferred supplemental */
623 /* XXX not really "user" preferred */
624 edp->chartab_G[edp->designating] = edp->isolatin1tab;
625 break;
626 case '0': /* DEC special graphic */
627 edp->chartab_G[edp->designating] = edp->decgraphtab;
628 break;
629 case '>': /* DEC tech */
630 edp->chartab_G[edp->designating] = edp->dectechtab;
631 break;
632 default:
633 #ifdef VT100_PRINTUNKNOWN
634 printf("ESC%c%c unknown\n", edp->designating + '(', c);
635 #endif
636 break;
638 return (newstate);
641 static u_int
642 wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp, u_char c)
644 switch (c) {
645 case '5': /* DEC supplemental graphic */
646 /* XXX there are differences */
647 edp->chartab_G[edp->designating] = edp->isolatin1tab;
648 break;
649 default:
650 #ifdef VT100_PRINTUNKNOWN
651 printf("ESC%c%%%c unknown\n", edp->designating + '(', c);
652 #endif
653 break;
655 return (VT100_EMUL_STATE_NORMAL);
658 static u_int
659 wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata *edp, u_char c)
661 u_int newstate = VT100_EMUL_STATE_NORMAL;
662 int nrc;
664 switch (c) {
665 case '%': /* probably portuguese */
666 newstate = VT100_EMUL_STATE_SCS96_PERCENT;
667 break;
668 case 'A': /* ISO-latin-1 supplemental */
669 edp->chartab_G[edp->designating] = edp->isolatin1tab;
670 break;
671 case '4': /* dutch */
672 nrc = 1;
673 goto setnrc;
674 case '5': case 'C': /* finnish */
675 nrc = 2;
676 goto setnrc;
677 case 'R': /* french */
678 nrc = 3;
679 goto setnrc;
680 case 'Q': /* french canadian */
681 nrc = 4;
682 goto setnrc;
683 case 'K': /* german */
684 nrc = 5;
685 goto setnrc;
686 case 'Y': /* italian */
687 nrc = 6;
688 goto setnrc;
689 case 'E': case '6': /* norwegian / danish */
690 nrc = 7;
691 goto setnrc;
692 case 'Z': /* spanish */
693 nrc = 9;
694 goto setnrc;
695 case '7': case 'H': /* swedish */
696 nrc = 10;
697 goto setnrc;
698 case '=': /* swiss */
699 nrc = 11;
700 setnrc:
701 vt100_setnrc(edp, nrc); /* what table ??? */
702 break;
703 default:
704 #ifdef VT100_PRINTUNKNOWN
705 printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c);
706 #endif
707 break;
709 return (newstate);
712 static u_int
713 wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp, u_char c)
715 switch (c) {
716 case '6': /* portuguese */
717 vt100_setnrc(edp, 8);
718 break;
719 default:
720 #ifdef VT100_PRINTUNKNOWN
721 printf("ESC%c%%%c unknown\n", edp->designating + '-', c);
722 #endif
723 break;
725 return (VT100_EMUL_STATE_NORMAL);
728 static u_int
729 wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp,
730 u_char c)
732 switch (c) {
733 case 'F': /* 7-bit controls */
734 case 'G': /* 8-bit controls */
735 #ifdef VT100_PRINTNOTIMPL
736 printf("ESC<SPC>%c ignored\n", c);
737 #endif
738 break;
739 default:
740 #ifdef VT100_PRINTUNKNOWN
741 printf("ESC<SPC>%c unknown\n", c);
742 #endif
743 break;
745 return (VT100_EMUL_STATE_NORMAL);
748 static u_int
749 wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp, u_char c)
751 if (edp->dcstype && edp->dcspos < DCS_MAXLEN)
752 edp->dcsarg[edp->dcspos++] = c;
753 return (VT100_EMUL_STATE_STRING);
756 static u_int
757 wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp, u_char c)
759 if (c == '\\') { /* ST complete */
760 wsemul_vt100_handle_dcs(edp);
761 return (VT100_EMUL_STATE_NORMAL);
762 } else
763 return (VT100_EMUL_STATE_STRING);
766 static u_int
767 wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp, u_char c)
769 u_int newstate = VT100_EMUL_STATE_DCS;
771 switch (c) {
772 case '0': case '1': case '2': case '3': case '4':
773 case '5': case '6': case '7': case '8': case '9':
774 /* argument digit */
775 if (edp->nargs > VT100_EMUL_NARGS - 1)
776 break;
777 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
778 (c - '0');
779 break;
780 case ';': /* argument terminator */
781 edp->nargs++;
782 break;
783 default:
784 edp->nargs++;
785 if (edp->nargs > VT100_EMUL_NARGS) {
786 #ifdef VT100_DEBUG
787 printf("vt100: too many arguments\n");
788 #endif
789 edp->nargs = VT100_EMUL_NARGS;
791 newstate = VT100_EMUL_STATE_STRING;
792 switch (c) {
793 case '$':
794 newstate = VT100_EMUL_STATE_DCS_DOLLAR;
795 break;
796 case '{': /* DECDLD soft charset */
797 case '!': /* DECRQUPSS user preferred supplemental set */
798 /* 'u' must follow - need another state */
799 case '|': /* DECUDK program F6..F20 */
800 #ifdef VT100_PRINTNOTIMPL
801 printf("DCS%c ignored\n", c);
802 #endif
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;
812 return (newstate);
815 static u_int
816 wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp, u_char c)
818 switch (c) {
819 case 'p': /* DECRSTS terminal state restore */
820 case 'q': /* DECRQSS control function request */
821 #ifdef VT100_PRINTNOTIMPL
822 printf("DCS$%c ignored\n", c);
823 #endif
824 break;
825 case 't': /* DECRSPS restore presentation state */
826 switch (ARG(0)) {
827 case 0: /* error */
828 break;
829 case 1: /* cursor information restore */
830 #ifdef VT100_PRINTNOTIMPL
831 printf("DCS1$t ignored\n");
832 #endif
833 break;
834 case 2: /* tab stop restore */
835 edp->dcspos = 0;
836 edp->dcstype = DCSTYPE_TABRESTORE;
837 break;
838 default:
839 #ifdef VT100_PRINTUNKNOWN
840 printf("DCS%d$t unknown\n", ARG(0));
841 #endif
842 break;
844 break;
845 default:
846 #ifdef VT100_PRINTUNKNOWN
847 printf("DCS$%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
848 #endif
849 break;
851 return (VT100_EMUL_STATE_STRING);
854 static u_int
855 wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp, u_char c)
857 int i, j;
859 switch (c) {
860 case '5': /* DECSWL single width, single height */
861 if (edp->dw) {
862 for (i = 0; i < edp->ncols / 2; i++)
863 (*edp->emulops->copycols)(edp->emulcookie,
864 edp->crow,
865 2 * i, i, 1);
866 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
867 i, edp->ncols - i,
868 edp->bkgdattr);
869 edp->dblwid[edp->crow] = 0;
870 edp->dw = 0;
872 break;
873 case '6': /* DECDWL double width, single height */
874 case '3': /* DECDHL double width, double height, top half */
875 case '4': /* DECDHL double width, double height, bottom half */
876 if (!edp->dw) {
877 for (i = edp->ncols / 2 - 1; i >= 0; i--)
878 (*edp->emulops->copycols)(edp->emulcookie,
879 edp->crow,
880 i, 2 * i, 1);
881 for (i = 0; i < edp->ncols / 2; i++)
882 (*edp->emulops->erasecols)(edp->emulcookie,
883 edp->crow,
884 2 * i + 1, 1,
885 edp->bkgdattr);
886 edp->dblwid[edp->crow] = 1;
887 edp->dw = 1;
888 if (edp->ccol > (edp->ncols >> 1) - 1)
889 edp->ccol = (edp->ncols >> 1) - 1;
891 break;
892 case '8': /* DECALN */
893 for (i = 0; i < edp->nrows; i++)
894 for (j = 0; j < edp->ncols; j++)
895 (*edp->emulops->putchar)(edp->emulcookie, i, j,
896 'E', edp->curattr);
897 edp->ccol = 0;
898 edp->crow = 0;
899 break;
900 default:
901 #ifdef VT100_PRINTUNKNOWN
902 printf("ESC#%c unknown\n", c);
903 #endif
904 break;
906 return (VT100_EMUL_STATE_NORMAL);
909 static u_int
910 wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp, u_char c)
912 u_int newstate = VT100_EMUL_STATE_CSI;
914 switch (c) {
915 case '0': case '1': case '2': case '3': case '4':
916 case '5': case '6': case '7': case '8': case '9':
917 /* argument digit */
918 if (edp->nargs > VT100_EMUL_NARGS - 1)
919 break;
920 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
921 (c - '0');
922 break;
923 case ';': /* argument terminator */
924 edp->nargs++;
925 break;
926 case '?': /* DEC specific */
927 case '>': /* DA query */
928 edp->modif1 = c;
929 break;
930 case '!':
931 case '"':
932 case '$':
933 case '&':
934 edp->modif2 = c;
935 break;
936 default: /* end of escape sequence */
937 edp->nargs++;
938 if (edp->nargs > VT100_EMUL_NARGS) {
939 #ifdef VT100_DEBUG
940 printf("vt100: too many arguments\n");
941 #endif
942 edp->nargs = VT100_EMUL_NARGS;
944 wsemul_vt100_handle_csi(edp, c);
945 newstate = VT100_EMUL_STATE_NORMAL;
946 break;
948 return (newstate);
951 void
952 wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
954 struct wsemul_vt100_emuldata *edp = cookie;
956 #ifdef DIAGNOSTIC
957 if (kernel && !edp->console)
958 panic("wsemul_vt100_output: kernel output, not console");
959 #endif
961 if (edp->flags & VTFL_CURSORON)
962 (*edp->emulops->cursor)(edp->emulcookie, 0,
963 edp->crow, edp->ccol << edp->dw);
964 for (; count > 0; data++, count--) {
965 if ((*data & 0x7f) < 0x20) {
966 wsemul_vt100_output_c0c1(edp, *data, kernel);
967 continue;
969 if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
970 wsemul_vt100_output_normal(edp, *data, kernel);
971 continue;
973 #ifdef DIAGNOSTIC
974 if (edp->state > sizeof(vt100_output) / sizeof(vt100_output[0]))
975 panic("wsemul_vt100: invalid state %d", edp->state);
976 #endif
977 edp->state = vt100_output[edp->state - 1](edp, *data);
979 if (edp->flags & VTFL_CURSORON)
980 (*edp->emulops->cursor)(edp->emulcookie, 1,
981 edp->crow, edp->ccol << edp->dw);
984 #ifdef WSDISPLAY_CUSTOM_OUTPUT
985 static void
986 wsemul_vt100_getmsgattrs(void *cookie, struct wsdisplay_msgattrs *ma)
988 struct wsemul_vt100_emuldata *edp = cookie;
990 *ma = edp->msgattrs;
993 static void
994 wsemul_vt100_setmsgattrs(void *cookie, const struct wsscreen_descr *type,
995 const struct wsdisplay_msgattrs *ma)
997 int error;
998 long tmp;
999 struct wsemul_vt100_emuldata *edp = cookie;
1001 edp->msgattrs = *ma;
1002 if (type->capabilities & WSSCREEN_WSCOLORS) {
1003 edp->msgattrs.default_attrs |= WSATTR_WSCOLORS;
1004 edp->msgattrs.kernel_attrs |= WSATTR_WSCOLORS;
1005 } else {
1006 edp->msgattrs.default_bg = edp->msgattrs.kernel_bg = 0;
1007 edp->msgattrs.default_fg = edp->msgattrs.kernel_fg = 0;
1010 error = (*edp->emulops->allocattr)(edp->emulcookie,
1011 edp->msgattrs.default_fg,
1012 edp->msgattrs.default_bg,
1013 edp->msgattrs.default_attrs,
1014 &tmp);
1015 #ifdef VT100_DEBUG
1016 if (error)
1017 printf("vt100: failed to allocate attribute for default "
1018 "messages\n");
1019 else
1020 #endif
1022 if (edp->curattr == edp->defattr) {
1023 edp->bkgdattr = edp->curattr = tmp;
1024 edp->attrflags = edp->msgattrs.default_attrs;
1025 edp->bgcol = edp->msgattrs.default_bg;
1026 edp->fgcol = edp->msgattrs.default_fg;
1027 } else {
1028 edp->savedbkgdattr = edp->savedattr = tmp;
1029 edp->savedattrflags = edp->msgattrs.default_attrs;
1030 edp->savedbgcol = edp->msgattrs.default_bg;
1031 edp->savedfgcol = edp->msgattrs.default_fg;
1033 if (edp->emulops->replaceattr != NULL)
1034 (*edp->emulops->replaceattr)(edp->emulcookie,
1035 edp->defattr, tmp);
1036 edp->defattr = tmp;
1039 error = (*edp->emulops->allocattr)(edp->emulcookie,
1040 edp->msgattrs.kernel_fg,
1041 edp->msgattrs.kernel_bg,
1042 edp->msgattrs.kernel_attrs,
1043 &tmp);
1044 #ifdef VT100_DEBUG
1045 if (error)
1046 printf("vt100: failed to allocate attribute for kernel "
1047 "messages\n");
1048 else
1049 #endif
1051 if (edp->emulops->replaceattr != NULL)
1052 (*edp->emulops->replaceattr)(edp->emulcookie,
1053 edp->kernattr, tmp);
1054 edp->kernattr = tmp;
1057 #endif /* WSDISPLAY_CUSTOM_OUTPUT */