1 /* $NetBSD: wsemul_sun.c,v 1.25 2006/10/12 01:32:06 christos Exp $ */
4 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christopher G. Demetriou
17 * for the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 /* XXX DESCRIPTION/SOURCE OF INFORMATION */
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: wsemul_sun.c,v 1.25 2006/10/12 01:32:06 christos Exp $");
38 #include <sys/param.h>
39 #include <sys/systm.h>
41 #include <sys/malloc.h>
42 #include <sys/fcntl.h>
44 #include <dev/wscons/wsconsio.h>
45 #include <dev/wscons/wsdisplayvar.h>
46 #include <dev/wscons/wsemulvar.h>
47 #include <dev/wscons/wsksymdef.h>
48 #include <dev/wscons/ascii.h>
50 void *wsemul_sun_cnattach(const struct wsscreen_descr
*, void *,
52 void *wsemul_sun_attach(int console
, const struct wsscreen_descr
*,
53 void *, int, int, void *, long);
54 void wsemul_sun_output(void *cookie
, const u_char
*data
, u_int count
,
56 int wsemul_sun_translate(void *cookie
, keysym_t
, const char **);
57 void wsemul_sun_detach(void *cookie
, u_int
*crowp
, u_int
*ccolp
);
58 void wsemul_sun_resetop(void *, enum wsemul_resetops
);
60 const struct wsemul_ops wsemul_sun_ops
= {
68 NULL
, /* getmsgattrs */
69 NULL
, /* setmsgattrs */
72 #define SUN_EMUL_STATE_NORMAL 0 /* normal processing */
73 #define SUN_EMUL_STATE_HAVEESC 1 /* seen start of ctl seq */
74 #define SUN_EMUL_STATE_CONTROL 2 /* processing ctl seq */
76 #define SUN_EMUL_NARGS 2 /* max # of args to a command */
78 struct wsemul_sun_emuldata
{
79 const struct wsdisplay_emulops
*emulops
;
83 u_int nrows
, ncols
, crow
, ccol
;
85 u_int state
; /* processing state */
86 u_int args
[SUN_EMUL_NARGS
]; /* command args, if CONTROL */
87 u_int scrolldist
; /* distance to scroll */
88 long defattr
; /* default attribute (rendition) */
89 long bowattr
; /* attribute for reversed mode */
93 long curattr
; /* currently used attribute */
94 long kernattr
; /* attribute for kernel output */
100 static u_int
wsemul_sun_output_normal(struct wsemul_sun_emuldata
*,
102 static u_int
wsemul_sun_output_haveesc(struct wsemul_sun_emuldata
*, u_char
);
103 static u_int
wsemul_sun_output_control(struct wsemul_sun_emuldata
*, u_char
);
104 static void wsemul_sun_control(struct wsemul_sun_emuldata
*, u_char
);
106 struct wsemul_sun_emuldata wsemul_sun_console_emuldata
;
108 /* some useful utility macros */
109 #define ARG(n) (edp->args[(n)])
110 #define NORMALIZE_ARG(n) (ARG(n) ? ARG(n) : 1)
111 #define COLS_LEFT (edp->ncols - edp->ccol - 1)
112 #define ROWS_LEFT (edp->nrows - edp->crow - 1)
115 wsemul_sun_cnattach(const struct wsscreen_descr
*type
, void *cookie
,
116 int ccol
, int crow
, long defattr
)
118 struct wsemul_sun_emuldata
*edp
;
121 edp
= &wsemul_sun_console_emuldata
;
123 edp
->emulops
= type
->textops
;
124 edp
->emulcookie
= cookie
;
125 edp
->scrcapabilities
= type
->capabilities
;
126 edp
->nrows
= type
->nrows
;
127 edp
->ncols
= type
->ncols
;
130 edp
->curattr
= edp
->defattr
= defattr
;
131 #if defined(WS_KERNEL_FG) || defined(WS_KERNEL_BG) || \
132 defined(WS_KERNEL_COLATTR) || defined(WS_KERNEL_MONOATTR)
134 #define WS_KERNEL_FG WSCOL_WHITE
137 #define WS_KERNEL_BG WSCOL_BLACK
139 #ifndef WS_KERNEL_COLATTR
140 #define WS_KERNEL_COLATTR 0
142 #ifndef WS_KERNEL_MONOATTR
143 #define WS_KERNEL_MONOATTR 0
145 if (type
->capabilities
& WSSCREEN_WSCOLORS
)
146 res
= (*edp
->emulops
->allocattr
)(cookie
,
147 WS_KERNEL_FG
, WS_KERNEL_BG
,
148 WS_KERNEL_COLATTR
| WSATTR_WSCOLORS
,
151 res
= (*edp
->emulops
->allocattr
)(cookie
, 0, 0,
156 res
= 0; /* XXX gcc */
158 edp
->kernattr
= defattr
;
160 edp
->cbcookie
= NULL
;
162 edp
->state
= SUN_EMUL_STATE_NORMAL
;
171 wsemul_sun_attach(int console
, const struct wsscreen_descr
*type
,
172 void *cookie
, int ccol
, int crow
, void *cbcookie
, long defattr
)
174 struct wsemul_sun_emuldata
*edp
;
177 edp
= &wsemul_sun_console_emuldata
;
179 KASSERT(edp
->console
== 1);
182 edp
= malloc(sizeof *edp
, M_DEVBUF
, M_WAITOK
);
184 edp
->emulops
= type
->textops
;
185 edp
->emulcookie
= cookie
;
186 edp
->scrcapabilities
= type
->capabilities
;
187 edp
->nrows
= type
->nrows
;
188 edp
->ncols
= type
->ncols
;
191 edp
->defattr
= defattr
;
193 edp
->state
= SUN_EMUL_STATE_NORMAL
;
200 edp
->cbcookie
= cbcookie
;
202 if ((!(edp
->scrcapabilities
& WSSCREEN_REVERSE
) ||
203 (*edp
->emulops
->allocattr
)(edp
->emulcookie
, 0, 0,
206 (!(edp
->scrcapabilities
& WSSCREEN_WSCOLORS
) ||
207 (*edp
->emulops
->allocattr
)(edp
->emulcookie
,
208 WSCOL_BLACK
, WSCOL_WHITE
,
211 edp
->bowattr
= edp
->defattr
;
213 edp
->curattr
= edp
->defattr
;
220 wsemul_sun_output_normal(struct wsemul_sun_emuldata
*edp
, u_char c
, int kernel
)
222 u_int newstate
= SUN_EMUL_STATE_NORMAL
;
226 case ASCII_BEL
: /* "Bell (BEL)" */
227 wsdisplay_emulbell(edp
->cbcookie
);
230 case ASCII_BS
: /* "Backspace (BS)" */
235 case ASCII_CR
: /* "Return (CR)" */
239 case ASCII_HT
: /* "Tab (TAB)" */
240 n
= min(8 - (edp
->ccol
& 7), COLS_LEFT
);
241 (*edp
->emulops
->erasecols
)(edp
->emulcookie
, edp
->crow
,
243 kernel
? edp
->kernattr
: edp
->curattr
);
247 case ASCII_FF
: /* "Form Feed (FF)" */
248 (*edp
->emulops
->eraserows
)(edp
->emulcookie
, 0, edp
->nrows
,
249 kernel
? edp
->kernattr
: edp
->curattr
);
250 /* XXX possible in kernel output? */
255 case ASCII_VT
: /* "Reverse Line Feed" */
260 case ASCII_ESC
: /* "Escape (ESC)" */
262 printf("wsemul_sun_output_normal: ESC in kernel output ignored\n");
263 break; /* ignore the ESC */
266 if (edp
->state
== SUN_EMUL_STATE_NORMAL
) {
267 newstate
= SUN_EMUL_STATE_HAVEESC
;
270 /* special case: fall through, we're printing one out */
273 default: /* normal character */
274 (*edp
->emulops
->putchar
)(edp
->emulcookie
, edp
->crow
, edp
->ccol
,
275 c
, kernel
? edp
->kernattr
: edp
->curattr
);
278 /* if cur col is still on cur line, done. */
279 if (edp
->ccol
< edp
->ncols
)
282 /* wrap the column around. */
287 case ASCII_LF
: /* "Line Feed (LF)" */
288 /* if the cur line isn't the last, incr and leave. */
289 if (edp
->crow
< edp
->nrows
- 1) {
295 * if we're in wrap-around mode, go to the first
298 if (edp
->scrolldist
== 0) {
300 (*edp
->emulops
->eraserows
)(edp
->emulcookie
, 0, 1,
305 /* scroll by the scrolling distance. */
306 (*edp
->emulops
->copyrows
)(edp
->emulcookie
, edp
->scrolldist
, 0,
307 edp
->nrows
- edp
->scrolldist
);
308 (*edp
->emulops
->eraserows
)(edp
->emulcookie
,
309 edp
->nrows
- edp
->scrolldist
, edp
->scrolldist
,
311 edp
->crow
-= edp
->scrolldist
- 1;
319 wsemul_sun_output_haveesc(struct wsemul_sun_emuldata
*edp
, u_char c
)
324 case '[': /* continuation of multi-char sequence */
325 memset(edp
->args
, 0, sizeof (edp
->args
));
326 newstate
= SUN_EMUL_STATE_CONTROL
;
330 /* spit out the escape char (???), then the new character */
331 wsemul_sun_output_normal(edp
, ASCII_ESC
, 0); /* ??? */
332 newstate
= wsemul_sun_output_normal(edp
, c
, 0);
340 wsemul_sun_control(struct wsemul_sun_emuldata
*edp
, u_char c
)
345 case '@': /* "Insert Character (ICH)" */
346 n
= min(NORMALIZE_ARG(0), COLS_LEFT
+ 1);
349 if (dst
< edp
->ncols
) {
350 (*edp
->emulops
->copycols
)(edp
->emulcookie
, edp
->crow
,
351 src
, dst
, edp
->ncols
- dst
);
353 (*edp
->emulops
->erasecols
)(edp
->emulcookie
, edp
->crow
,
354 src
, dst
- src
, edp
->curattr
);
357 case 'A': /* "Cursor Up (CUU)" */
358 edp
->crow
-= min(NORMALIZE_ARG(0), edp
->crow
);
361 case 'E': /* "Cursor Next Line (CNL)" */
364 case 'B': /* "Cursor Down (CUD)" */
365 edp
->crow
+= min(NORMALIZE_ARG(0), ROWS_LEFT
);
368 case 'C': /* "Cursor Forward (CUF)" */
369 edp
->ccol
+= min(NORMALIZE_ARG(0), COLS_LEFT
);
372 case 'D': /* "Cursor Backward (CUB)" */
373 edp
->ccol
-= min(NORMALIZE_ARG(0), edp
->ccol
);
376 case 'f': /* "Horizontal And Vertical Position (HVP)" */
377 case 'H': /* "Cursor Position (CUP)" */
378 edp
->crow
= min(NORMALIZE_ARG(1), edp
->nrows
) - 1;
379 edp
->ccol
= min(NORMALIZE_ARG(0), edp
->ncols
) - 1;
382 case 'J': /* "Erase in Display (ED)" */
384 (*edp
->emulops
->eraserows
)(edp
->emulcookie
,
385 edp
->crow
+ 1, ROWS_LEFT
, edp
->curattr
);
388 case 'K': /* "Erase in Line (EL)" */
389 (*edp
->emulops
->erasecols
)(edp
->emulcookie
, edp
->crow
,
390 edp
->ccol
, COLS_LEFT
+ 1, edp
->curattr
);
393 case 'L': /* "Insert Line (IL)" */
394 n
= min(NORMALIZE_ARG(0), ROWS_LEFT
+ 1);
397 if (dst
< edp
->nrows
) {
398 (*edp
->emulops
->copyrows
)(edp
->emulcookie
,
399 src
, dst
, edp
->nrows
- dst
);
401 (*edp
->emulops
->eraserows
)(edp
->emulcookie
,
402 src
, dst
- src
, edp
->curattr
);
405 case 'M': /* "Delete Line (DL)" */
406 n
= min(NORMALIZE_ARG(0), ROWS_LEFT
+ 1);
409 if (src
< edp
->nrows
) {
410 (*edp
->emulops
->copyrows
)(edp
->emulcookie
,
411 src
, dst
, edp
->nrows
- src
);
413 (*edp
->emulops
->eraserows
)(edp
->emulcookie
,
414 dst
+ edp
->nrows
- src
, src
- dst
, edp
->curattr
);
417 case 'P': /* "Delete Character (DCH)" */
418 n
= min(NORMALIZE_ARG(0), COLS_LEFT
+ 1);
421 if (src
< edp
->ncols
) {
422 (*edp
->emulops
->copycols
)(edp
->emulcookie
, edp
->crow
,
423 src
, dst
, edp
->ncols
- src
);
425 (*edp
->emulops
->erasecols
)(edp
->emulcookie
, edp
->crow
,
426 dst
+ edp
->ncols
- src
, src
- dst
, edp
->curattr
);
429 case 'm': /* "Select Graphic Rendition (SGR)" */
431 edp
->rendflags
|= REND_SO
;
433 edp
->rendflags
&= ~REND_SO
;
436 case 'p': /* "Black On White (SUNBOW)" */
437 edp
->rendflags
|= REND_BOW
;
440 case 'q': /* "White On Black (SUNWOB)" */
441 edp
->rendflags
&= ~REND_BOW
;
444 case 'r': /* "Set Scrolling (SUNSCRL)" */
445 edp
->scrolldist
= min(ARG(0), edp
->nrows
);
448 case 's': /* "Reset Terminal Emulator (SUNRESET)" */
452 if (((edp
->rendflags
& REND_BOW
) != 0) ^
453 ((edp
->rendflags
& REND_SO
) != 0))
454 edp
->curattr
= edp
->bowattr
;
456 edp
->curattr
= edp
->defattr
;
462 wsemul_sun_output_control(struct wsemul_sun_emuldata
*edp
, u_char c
)
464 u_int newstate
= SUN_EMUL_STATE_CONTROL
;
468 case '0': case '1': case '2': case '3': case '4': /* argument digit */
469 case '5': case '6': case '7': case '8': case '9':
470 edp
->args
[0] = (edp
->args
[0] * 10) + (c
- '0');
473 case ';': /* argument terminator */
474 for (i
= 1; i
< SUN_EMUL_NARGS
; i
++)
475 edp
->args
[i
] = edp
->args
[i
- 1];
479 default: /* end of escape sequence */
480 wsemul_sun_control(edp
, c
);
481 newstate
= SUN_EMUL_STATE_NORMAL
;
488 wsemul_sun_output(void *cookie
, const u_char
*data
, u_int count
, int kernel
)
490 struct wsemul_sun_emuldata
*edp
= cookie
;
494 if (kernel
&& !edp
->console
)
495 panic("wsemul_sun_output: kernel output, not console");
499 (*edp
->emulops
->cursor
)(edp
->emulcookie
, 0, edp
->crow
, edp
->ccol
);
500 for (; count
> 0; data
++, count
--) {
502 wsemul_sun_output_normal(edp
, *data
, 1);
505 switch (edp
->state
) {
506 case SUN_EMUL_STATE_NORMAL
:
507 /* XXX SCAN INPUT FOR NEWLINES, DO PRESCROLLING */
508 newstate
= wsemul_sun_output_normal(edp
, *data
, 0);
510 case SUN_EMUL_STATE_HAVEESC
:
511 newstate
= wsemul_sun_output_haveesc(edp
, *data
);
513 case SUN_EMUL_STATE_CONTROL
:
514 newstate
= wsemul_sun_output_control(edp
, *data
);
518 panic("wsemul_sun: invalid state %d", edp
->state
);
520 /* try to recover, if things get screwed up... */
521 newstate
= wsemul_sun_output_normal(edp
, *data
, 0);
524 edp
->state
= newstate
;
527 (*edp
->emulops
->cursor
)(edp
->emulcookie
, 1, edp
->crow
, edp
->ccol
);
530 static const char *sun_fkeys
[] = {
531 "\033[224z", /* F1 */
540 "\033[233z", /* F10 */
544 wsemul_sun_translate(void *cookie
, keysym_t in
, const char **out
)
548 if (KS_GROUP(in
) == KS_GROUP_Keypad
&& (in
& 0x80) == 0) {
549 c
= in
& 0xff; /* turn into ASCII */
554 if (in
>= KS_f1
&& in
<= KS_f10
) {
555 *out
= sun_fkeys
[in
- KS_f1
];
558 if (in
>= KS_F1
&& in
<= KS_F10
) {
559 *out
= sun_fkeys
[in
- KS_F1
];
562 if (in
>= KS_KP_F1
&& in
<= KS_KP_F4
) {
563 *out
= sun_fkeys
[in
- KS_KP_F1
];
605 wsemul_sun_detach(void *cookie
, u_int
*crowp
, u_int
*ccolp
)
607 struct wsemul_sun_emuldata
*edp
= cookie
;
611 if (edp
!= &wsemul_sun_console_emuldata
)
616 wsemul_sun_resetop(void *cookie
, enum wsemul_resetops op
)
618 struct wsemul_sun_emuldata
*edp
= cookie
;
622 edp
->state
= SUN_EMUL_STATE_NORMAL
;
625 edp
->curattr
= edp
->defattr
;
627 case WSEMUL_CLEARSCREEN
:
628 (*edp
->emulops
->eraserows
)(edp
->emulcookie
, 0, edp
->nrows
,
630 edp
->ccol
= edp
->crow
= 0;
631 (*edp
->emulops
->cursor
)(edp
->emulcookie
, 1, 0, 0);