1 /* $NetBSD: wsemul_vt100.c,v 1.30 2006/11/16 01:33:31 christos Exp $ */
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
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>
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 *,
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
= {
61 wsemul_vt100_cnattach
,
64 wsemul_vt100_translate
,
67 #ifdef WSDISPLAY_CUSTOM_OUTPUT
68 wsemul_vt100_getmsgattrs
,
69 wsemul_vt100_setmsgattrs
,
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
*,
84 static void wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata
*,
86 static void wsemul_vt100_nextline(struct wsemul_vt100_emuldata
*);
87 typedef u_int
vt100_handler(struct wsemul_vt100_emuldata
*, u_char
);
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
,
133 wsemul_vt100_init(struct wsemul_vt100_emuldata
*edp
,
134 const struct wsscreen_descr
*type
, void *cookie
, int ccol
, int crow
,
139 edp
->emulops
= type
->textops
;
140 edp
->emulcookie
= cookie
;
141 edp
->scrcapabilities
= type
->capabilities
;
142 edp
->nrows
= type
->nrows
;
143 edp
->ncols
= type
->ncols
;
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
|
155 edp
->msgattrs
.default_bg
= WS_DEFAULT_BG
;
156 edp
->msgattrs
.default_fg
= WS_DEFAULT_FG
;
158 edp
->msgattrs
.kernel_attrs
= WS_KERNEL_COLATTR
|
160 edp
->msgattrs
.kernel_bg
= WS_KERNEL_BG
;
161 edp
->msgattrs
.kernel_fg
= WS_KERNEL_FG
;
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
,
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
;
185 if (edp
->emulops
->replaceattr
!= NULL
)
186 (*edp
->emulops
->replaceattr
)(cookie
, 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
196 error
= (*edp
->emulops
->allocattr
)(cookie
,
197 edp
->msgattrs
.kernel_fg
,
198 edp
->msgattrs
.kernel_bg
,
199 edp
->msgattrs
.kernel_attrs
,
203 edp
->kernattr
= edp
->defattr
;
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
);
217 edp
->cbcookie
= NULL
;
223 edp
->isolatin1tab
= edp
->decgraphtab
= edp
->dectechtab
= 0;
225 wsemul_vt100_reset(edp
);
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
;
236 edp
= &wsemul_vt100_console_emuldata
;
238 KASSERT(edp
->console
== 1);
241 edp
= malloc(sizeof *edp
, M_DEVBUF
, M_WAITOK
);
242 wsemul_vt100_init(edp
, type
, cookie
, ccol
, crow
, defattr
);
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
);
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
);
263 wsemul_vt100_detach(void *cookie
, u_int
*crowp
, u_int
*ccolp
)
265 struct wsemul_vt100_emuldata
*edp
= cookie
;
269 #define f(ptr) if (ptr) {free(ptr, M_DEVBUF); ptr = 0;}
278 if (edp
!= &wsemul_vt100_console_emuldata
)
283 wsemul_vt100_resetop(void *cookie
, enum wsemul_resetops op
)
285 struct wsemul_vt100_emuldata
*edp
= cookie
;
289 wsemul_vt100_reset(edp
);
291 case WSEMUL_SYNCFONT
:
292 vt100_initchartables(edp
);
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);
306 wsemul_vt100_reset(struct wsemul_vt100_emuldata
*edp
)
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
;
319 memset(edp
->tabs
, 0, edp
->ncols
);
320 for (i
= 8; i
< edp
->ncols
; i
+= 8)
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
;
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.
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);
350 if ((edp
->crow
+1) < edp
->nrows
)
351 /* Cursor not at the bottom of the screen. */
358 wsemul_vt100_output_normal(struct wsemul_vt100_emuldata
*edp
, u_char c
,
363 if ((edp
->flags
& (VTFL_LASTCHAR
| VTFL_DECAWM
)) ==
364 (VTFL_LASTCHAR
| VTFL_DECAWM
)) {
365 wsemul_vt100_nextline(edp
);
367 edp
->flags
&= ~VTFL_LASTCHAR
;
372 ct
= edp
->chartab_G
[edp
->chartab1
];
374 if (edp
->sschartab
) {
375 ct
= edp
->chartab_G
[edp
->sschartab
];
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
);
392 edp
->flags
|= VTFL_LASTCHAR
;
396 wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata
*edp
, u_char c
,
407 wsdisplay_emulbell(edp
->cbcookie
);
412 edp
->flags
&= ~VTFL_LASTCHAR
;
417 edp
->flags
&= ~VTFL_LASTCHAR
;
423 for (n
= edp
->ccol
+ 1; n
< NCOLS
- 1; n
++)
427 n
= edp
->ccol
+ min(8 - (edp
->ccol
& 7), COLS_LEFT
);
431 case ASCII_SO
: /* LS1 */
434 case ASCII_SI
: /* LS0 */
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
;
447 /* XXX cancel current escape sequence */
448 edp
->state
= VT100_EMUL_STATE_ESC
;
452 case CSI
: /* 8-bit */
453 /* XXX cancel current escape sequence */
455 memset(edp
->args
, 0, sizeof (edp
->args
));
456 edp
->modif1
= edp
->modif2
= '\0';
457 edp
->state
= VT100_EMUL_STATE_CSI
;
459 case DCS
: /* 8-bit */
460 /* XXX cancel current escape sequence */
462 memset(edp
->args
, 0, sizeof (edp
->args
));
463 edp
->state
= VT100_EMUL_STATE_DCS
;
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
);
473 wsemul_vt100_nextline(edp
);
479 wsemul_vt100_output_esc(struct wsemul_vt100_emuldata
*edp
, u_char c
)
481 u_int newstate
= VT100_EMUL_STATE_NORMAL
;
487 memset(edp
->args
, 0, sizeof (edp
->args
));
488 edp
->modif1
= edp
->modif2
= '\0';
489 newstate
= VT100_EMUL_STATE_CSI
;
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
;
505 case '8': /* DECRC */
506 if ((edp
->flags
& VTFL_SAVEDCURS
) == 0)
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
;
520 case '=': /* DECKPAM application mode */
521 edp
->flags
|= VTFL_APPLKEYPAD
;
523 case '>': /* DECKPNM numeric mode */
524 edp
->flags
&= ~VTFL_APPLKEYPAD
;
530 wsemul_vt100_nextline(edp
);
533 KASSERT(edp
->tabs
!= 0);
534 edp
->tabs
[edp
->ccol
] = 1;
558 if (ROWS_ABOVE
> 0) {
563 wsemul_vt100_scrolldown(edp
, 1);
567 memset(edp
->args
, 0, sizeof (edp
->args
));
568 newstate
= VT100_EMUL_STATE_DCS
;
571 wsemul_vt100_reset(edp
);
572 wsemul_vt100_ed(edp
, 2);
573 edp
->ccol
= edp
->crow
= 0;
575 case '(': case ')': case '*': case '+': /* SCS */
576 edp
->designating
= c
- '(';
577 newstate
= VT100_EMUL_STATE_SCS94
;
579 case '-': case '.': case '/': /* SCS */
580 edp
->designating
= c
- '-' + 1;
581 newstate
= VT100_EMUL_STATE_SCS96
;
584 newstate
= VT100_EMUL_STATE_ESC_HASH
;
586 case ' ': /* 7/8 bit */
587 newstate
= VT100_EMUL_STATE_ESC_SPC
;
589 case ']': /* OSC operating system command */
590 case '^': /* PM privacy message */
591 case '_': /* APC application program command */
593 newstate
= VT100_EMUL_STATE_STRING
;
595 case '<': /* exit VT52 mode - ignored */
598 #ifdef VT100_PRINTUNKNOWN
599 printf("ESC%c unknown\n", c
);
608 wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata
*edp
, u_char c
)
610 u_int newstate
= VT100_EMUL_STATE_NORMAL
;
613 case '%': /* probably DEC supplemental graphic */
614 newstate
= VT100_EMUL_STATE_SCS94_PERCENT
;
616 case 'A': /* british / national */
617 edp
->chartab_G
[edp
->designating
] = edp
->nrctab
;
619 case 'B': /* ASCII */
620 edp
->chartab_G
[edp
->designating
] = 0;
622 case '<': /* user preferred supplemental */
623 /* XXX not really "user" preferred */
624 edp
->chartab_G
[edp
->designating
] = edp
->isolatin1tab
;
626 case '0': /* DEC special graphic */
627 edp
->chartab_G
[edp
->designating
] = edp
->decgraphtab
;
629 case '>': /* DEC tech */
630 edp
->chartab_G
[edp
->designating
] = edp
->dectechtab
;
633 #ifdef VT100_PRINTUNKNOWN
634 printf("ESC%c%c unknown\n", edp
->designating
+ '(', c
);
642 wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata
*edp
, u_char c
)
645 case '5': /* DEC supplemental graphic */
646 /* XXX there are differences */
647 edp
->chartab_G
[edp
->designating
] = edp
->isolatin1tab
;
650 #ifdef VT100_PRINTUNKNOWN
651 printf("ESC%c%%%c unknown\n", edp
->designating
+ '(', c
);
655 return (VT100_EMUL_STATE_NORMAL
);
659 wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata
*edp
, u_char c
)
661 u_int newstate
= VT100_EMUL_STATE_NORMAL
;
665 case '%': /* probably portuguese */
666 newstate
= VT100_EMUL_STATE_SCS96_PERCENT
;
668 case 'A': /* ISO-latin-1 supplemental */
669 edp
->chartab_G
[edp
->designating
] = edp
->isolatin1tab
;
671 case '4': /* dutch */
674 case '5': case 'C': /* finnish */
677 case 'R': /* french */
680 case 'Q': /* french canadian */
683 case 'K': /* german */
686 case 'Y': /* italian */
689 case 'E': case '6': /* norwegian / danish */
692 case 'Z': /* spanish */
695 case '7': case 'H': /* swedish */
698 case '=': /* swiss */
701 vt100_setnrc(edp
, nrc
); /* what table ??? */
704 #ifdef VT100_PRINTUNKNOWN
705 printf("ESC%c%c unknown\n", edp
->designating
+ '-' - 1, c
);
713 wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata
*edp
, u_char c
)
716 case '6': /* portuguese */
717 vt100_setnrc(edp
, 8);
720 #ifdef VT100_PRINTUNKNOWN
721 printf("ESC%c%%%c unknown\n", edp
->designating
+ '-', c
);
725 return (VT100_EMUL_STATE_NORMAL
);
729 wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata
*edp
,
733 case 'F': /* 7-bit controls */
734 case 'G': /* 8-bit controls */
735 #ifdef VT100_PRINTNOTIMPL
736 printf("ESC<SPC>%c ignored\n", c
);
740 #ifdef VT100_PRINTUNKNOWN
741 printf("ESC<SPC>%c unknown\n", c
);
745 return (VT100_EMUL_STATE_NORMAL
);
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
);
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
);
763 return (VT100_EMUL_STATE_STRING
);
767 wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata
*edp
, u_char c
)
769 u_int newstate
= VT100_EMUL_STATE_DCS
;
772 case '0': case '1': case '2': case '3': case '4':
773 case '5': case '6': case '7': case '8': case '9':
775 if (edp
->nargs
> VT100_EMUL_NARGS
- 1)
777 edp
->args
[edp
->nargs
] = (edp
->args
[edp
->nargs
] * 10) +
780 case ';': /* argument terminator */
785 if (edp
->nargs
> VT100_EMUL_NARGS
) {
787 printf("vt100: too many arguments\n");
789 edp
->nargs
= VT100_EMUL_NARGS
;
791 newstate
= VT100_EMUL_STATE_STRING
;
794 newstate
= VT100_EMUL_STATE_DCS_DOLLAR
;
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
);
805 #ifdef VT100_PRINTUNKNOWN
806 printf("DCS%c (%d, %d) unknown\n", c
, ARG(0), ARG(1));
816 wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata
*edp
, u_char 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
);
825 case 't': /* DECRSPS restore presentation state */
829 case 1: /* cursor information restore */
830 #ifdef VT100_PRINTNOTIMPL
831 printf("DCS1$t ignored\n");
834 case 2: /* tab stop restore */
836 edp
->dcstype
= DCSTYPE_TABRESTORE
;
839 #ifdef VT100_PRINTUNKNOWN
840 printf("DCS%d$t unknown\n", ARG(0));
846 #ifdef VT100_PRINTUNKNOWN
847 printf("DCS$%c (%d, %d) unknown\n", c
, ARG(0), ARG(1));
851 return (VT100_EMUL_STATE_STRING
);
855 wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata
*edp
, u_char c
)
860 case '5': /* DECSWL single width, single height */
862 for (i
= 0; i
< edp
->ncols
/ 2; i
++)
863 (*edp
->emulops
->copycols
)(edp
->emulcookie
,
866 (*edp
->emulops
->erasecols
)(edp
->emulcookie
, edp
->crow
,
869 edp
->dblwid
[edp
->crow
] = 0;
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 */
877 for (i
= edp
->ncols
/ 2 - 1; i
>= 0; i
--)
878 (*edp
->emulops
->copycols
)(edp
->emulcookie
,
881 for (i
= 0; i
< edp
->ncols
/ 2; i
++)
882 (*edp
->emulops
->erasecols
)(edp
->emulcookie
,
886 edp
->dblwid
[edp
->crow
] = 1;
888 if (edp
->ccol
> (edp
->ncols
>> 1) - 1)
889 edp
->ccol
= (edp
->ncols
>> 1) - 1;
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
,
901 #ifdef VT100_PRINTUNKNOWN
902 printf("ESC#%c unknown\n", c
);
906 return (VT100_EMUL_STATE_NORMAL
);
910 wsemul_vt100_output_csi(struct wsemul_vt100_emuldata
*edp
, u_char c
)
912 u_int newstate
= VT100_EMUL_STATE_CSI
;
915 case '0': case '1': case '2': case '3': case '4':
916 case '5': case '6': case '7': case '8': case '9':
918 if (edp
->nargs
> VT100_EMUL_NARGS
- 1)
920 edp
->args
[edp
->nargs
] = (edp
->args
[edp
->nargs
] * 10) +
923 case ';': /* argument terminator */
926 case '?': /* DEC specific */
927 case '>': /* DA query */
936 default: /* end of escape sequence */
938 if (edp
->nargs
> VT100_EMUL_NARGS
) {
940 printf("vt100: too many arguments\n");
942 edp
->nargs
= VT100_EMUL_NARGS
;
944 wsemul_vt100_handle_csi(edp
, c
);
945 newstate
= VT100_EMUL_STATE_NORMAL
;
952 wsemul_vt100_output(void *cookie
, const u_char
*data
, u_int count
, int kernel
)
954 struct wsemul_vt100_emuldata
*edp
= cookie
;
957 if (kernel
&& !edp
->console
)
958 panic("wsemul_vt100_output: kernel output, not console");
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
);
969 if (edp
->state
== VT100_EMUL_STATE_NORMAL
|| kernel
) {
970 wsemul_vt100_output_normal(edp
, *data
, kernel
);
974 if (edp
->state
> sizeof(vt100_output
) / sizeof(vt100_output
[0]))
975 panic("wsemul_vt100: invalid state %d", edp
->state
);
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
986 wsemul_vt100_getmsgattrs(void *cookie
, struct wsdisplay_msgattrs
*ma
)
988 struct wsemul_vt100_emuldata
*edp
= cookie
;
994 wsemul_vt100_setmsgattrs(void *cookie
, const struct wsscreen_descr
*type
,
995 const struct wsdisplay_msgattrs
*ma
)
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
;
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
,
1017 printf("vt100: failed to allocate attribute for default "
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
;
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
,
1039 error
= (*edp
->emulops
->allocattr
)(edp
->emulcookie
,
1040 edp
->msgattrs
.kernel_fg
,
1041 edp
->msgattrs
.kernel_bg
,
1042 edp
->msgattrs
.kernel_attrs
,
1046 printf("vt100: failed to allocate attribute for kernel "
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 */