1 /* $NetBSD: rcons_subr.c,v 1.17 2009/03/14 15:36:20 dsl Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * @(#)rcons_subr.c 8.1 (Berkeley) 6/11/93
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: rcons_subr.c,v 1.17 2009/03/14 15:36:20 dsl Exp $");
46 #include <sys/param.h>
48 #include <sys/device.h>
49 #include <sys/systm.h>
51 #include "myfbdevice.h"
54 #include <dev/rcons/rcons.h>
55 #include <dev/wscons/wsdisplayvar.h>
57 extern void rcons_bell(struct rconsole
*);
60 #define RCONS_ISPRINT(c) ((((c) >= ' ') && ((c) <= '~')) || ((c) > 160))
62 #define RCONS_ISPRINT(c) (((((c) >= ' ') && ((c) <= '~'))) || ((c) > 127))
64 #define RCONS_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
66 /* Initialize our operations set */
68 rcons_init_ops(struct rconsole
*rc
)
73 m
= sizeof(rc
->rc_charmap
) / sizeof(rc
->rc_charmap
[0]);
75 for (i
= 0; i
< m
; i
++)
76 rc
->rc_ops
->mapchar(rc
->rc_cookie
, i
, rc
->rc_charmap
+ i
);
78 /* Determine which attributes the device supports. */
79 #ifdef RASTERCONSOLE_FGCOL
80 rc
->rc_deffgcolor
= RASTERCONSOLE_FGCOL
;
82 #ifdef RASTERCONSOLE_BGCOL
83 rc
->rc_defbgcolor
= RASTERCONSOLE_BGCOL
;
85 rc
->rc_fgcolor
= rc
->rc_deffgcolor
;
86 rc
->rc_bgcolor
= rc
->rc_defbgcolor
;
89 for (i
= 1; i
< 256; i
<<= 1)
90 if (rc
->rc_ops
->allocattr(rc
->rc_cookie
, 0, 0, i
, &tmp
) == 0)
93 /* Allocate kernel output attribute */
94 rc
->rc_wsflg
= WSATTR_HILIT
;
95 rcons_setcolor(rc
, rc
->rc_deffgcolor
, rc
->rc_defbgcolor
);
96 rc
->rc_kern_attr
= rc
->rc_attr
;
99 rcons_setcolor(rc
, rc
->rc_deffgcolor
, rc
->rc_defbgcolor
);
100 rc
->rc_defattr
= rc
->rc_attr
;
103 /* Output (or at least handle) a string sent to the console */
105 rcons_puts(struct rconsole
*rc
, const unsigned char *str
, int n
)
108 const unsigned char *cp
;
111 /* XXX maybe this should be an option? */
112 if ((rc
->rc_bits
& FB_INESC
) == 0) {
113 /* Count newlines up to an escape sequence */
116 for (cp
= str
; j
++ < n
&& *cp
!= '\033'; ++cp
) {
119 else if (*cp
== '\013')
123 /* Only jump scroll two or more rows */
124 if (rc
->rc_row
+ i
> rc
->rc_maxrow
+ 1) {
125 /* Erase the cursor (if necessary) */
126 if (rc
->rc_bits
& FB_CURSOR
)
133 /* Process characters */
137 /* Start an escape (perhaps aborting one in progress) */
138 rc
->rc_bits
|= FB_INESC
| FB_P0_DEFAULT
| FB_P1_DEFAULT
;
139 rc
->rc_bits
&= ~(FB_P0
| FB_P1
);
141 /* Most parameters default to 1 */
142 rc
->rc_p0
= rc
->rc_p1
= 1;
143 } else if (rc
->rc_bits
& FB_INESC
) {
146 /* Erase the cursor (if necessary) */
147 if (rc
->rc_bits
& FB_CURSOR
)
150 /* Display the character */
151 if (RCONS_ISPRINT(c
)) {
152 /* Try to output as much as possible */
153 j
= rc
->rc_maxcol
- rc
->rc_col
;
156 for (i
= 1; i
< j
&& RCONS_ISPRINT(str
[i
]); ++i
)
158 rcons_text(rc
, str
, i
);
167 /* Redraw the cursor (if necessary) */
168 if ((rc
->rc_bits
& FB_CURSOR
) == 0)
173 /* Handle a control character sent to the console */
175 rcons_pctrl(struct rconsole
*rc
, int c
)
179 case '\r': /* Carriage return */
183 case '\b': /* Backspace */
188 case '\v': /* Vertical tab */
193 case '\f': /* Formfeed */
194 rc
->rc_row
= rc
->rc_col
= 0;
198 case '\n': /* Linefeed */
200 if (rc
->rc_row
>= rc
->rc_maxrow
)
204 case '\a': /* Bell */
208 case '\t': /* Horizontal tab */
209 rc
->rc_col
= (rc
->rc_col
+ 8) & ~7;
210 if (rc
->rc_col
>= rc
->rc_maxcol
)
211 rc
->rc_col
= rc
->rc_maxcol
;
216 /* Handle the next character in an escape sequence */
218 rcons_esc(struct rconsole
*rc
, int c
)
223 rc
->rc_bits
&= ~FB_P1
;
224 rc
->rc_bits
|= FB_P0
;
225 } else if (c
== ';') {
227 rc
->rc_bits
&= ~FB_P0
;
228 rc
->rc_bits
|= FB_P1
;
229 } else if (RCONS_ISDIGIT(c
)) {
230 /* Add a digit to a parameter */
231 if (rc
->rc_bits
& FB_P0
) {
233 if (rc
->rc_bits
& FB_P0_DEFAULT
) {
234 rc
->rc_bits
&= ~FB_P0_DEFAULT
;
238 rc
->rc_p0
+= c
- '0';
239 } else if (rc
->rc_bits
& FB_P1
) {
241 if (rc
->rc_bits
& FB_P1_DEFAULT
) {
242 rc
->rc_bits
&= ~FB_P1_DEFAULT
;
246 rc
->rc_p1
+= c
- '0';
249 /* Erase the cursor (if necessary) */
250 if (rc
->rc_bits
& FB_CURSOR
)
253 /* Process the completed escape sequence */
255 rc
->rc_bits
&= ~FB_INESC
;
260 /* Handle an SGR (Select Graphic Rendition) escape */
262 rcons_sgresc(struct rconsole
*rc
, int c
)
266 /* Clear all attributes || End underline */
269 rc
->rc_fgcolor
= rc
->rc_deffgcolor
;
270 rc
->rc_bgcolor
= rc
->rc_defbgcolor
;
271 rc
->rc_attr
= rc
->rc_defattr
;
274 /* ANSI foreground color */
275 case 30: case 31: case 32: case 33:
276 case 34: case 35: case 36: case 37:
277 rcons_setcolor(rc
, c
- 30, rc
->rc_bgcolor
);
280 /* ANSI background color */
281 case 40: case 41: case 42: case 43:
282 case 44: case 45: case 46: case 47:
283 rcons_setcolor(rc
, rc
->rc_fgcolor
, c
- 40);
288 rc
->rc_wsflg
|= WSATTR_REVERSE
;
289 rcons_setcolor(rc
, rc
->rc_fgcolor
, rc
->rc_bgcolor
);
294 rc
->rc_wsflg
|= WSATTR_HILIT
;
295 rcons_setcolor(rc
, rc
->rc_fgcolor
, rc
->rc_bgcolor
);
298 /* Begin underline */
300 rc
->rc_wsflg
|= WSATTR_UNDERLINE
;
301 rcons_setcolor(rc
, rc
->rc_fgcolor
, rc
->rc_bgcolor
);
307 /* Process a complete escape sequence */
309 rcons_doesc(struct rconsole
*rc
, int c
)
313 /* XXX add escape sequence to enable visual (and audible) bell */
314 rc
->rc_bits
= FB_VISBELL
;
320 /* Insert Character (ICH) */
321 rcons_insertchar(rc
, rc
->rc_p0
);
325 /* Cursor Up (CUU) */
326 if (rc
->rc_row
>= rc
->rc_p0
)
327 rc
->rc_row
-= rc
->rc_p0
;
333 /* Cursor Down (CUD) */
334 rc
->rc_row
+= rc
->rc_p0
;
335 if (rc
->rc_row
>= rc
->rc_maxrow
)
336 rc
->rc_row
= rc
->rc_maxrow
- 1;
340 /* Cursor Forward (CUF) */
341 rc
->rc_col
+= rc
->rc_p0
;
342 if (rc
->rc_col
>= rc
->rc_maxcol
)
343 rc
->rc_col
= rc
->rc_maxcol
- 1;
347 /* Cursor Backward (CUB) */
348 if (rc
->rc_col
>= rc
->rc_p0
)
349 rc
->rc_col
-= rc
->rc_p0
;
355 /* Cursor Next Line (CNL) */
357 rc
->rc_row
+= rc
->rc_p0
;
358 if (rc
->rc_row
>= rc
->rc_maxrow
)
359 rc
->rc_row
= rc
->rc_maxrow
- 1;
363 /* Horizontal And Vertical Position (HVP) */
365 /* Cursor Position (CUP) */
366 rc
->rc_col
= MIN(MAX(rc
->rc_p1
, 1), rc
->rc_maxcol
) - 1;
367 rc
->rc_row
= MIN(MAX(rc
->rc_p0
, 1), rc
->rc_maxrow
) - 1;
371 /* Erase in Display (ED) */
376 /* Erase in Line (EL) */
381 /* Insert Line (IL) */
382 rcons_insertline(rc
, rc
->rc_p0
);
386 /* Delete Line (DL) */
387 rcons_delline(rc
, rc
->rc_p0
);
391 /* Delete Character (DCH) */
392 rcons_delchar(rc
, rc
->rc_p0
);
396 /* Select Graphic Rendition (SGR) */
397 /* (defaults to zero) */
398 if (rc
->rc_bits
& FB_P0_DEFAULT
)
401 if (rc
->rc_bits
& FB_P1_DEFAULT
)
404 rcons_sgresc(rc
, rc
->rc_p0
);
406 if (rc
->rc_bits
& FB_P1
)
407 rcons_sgresc(rc
, rc
->rc_p1
);
412 * XXX: setting SUNBOW and SUNWOB should probably affect
413 * deffgcolor, defbgcolor and defattr too.
416 /* Black On White (SUNBOW) */
417 rcons_setcolor(rc
, WSCOL_BLACK
, WSCOL_WHITE
);
421 /* White On Black (SUNWOB) */
422 rcons_setcolor(rc
, WSCOL_WHITE
, WSCOL_BLACK
);
426 /* Set scrolling (SUNSCRL) */
427 /* (defaults to zero) */
428 if (rc
->rc_bits
& FB_P0_DEFAULT
)
430 /* XXX not implemented yet */
431 rc
->rc_scroll
= rc
->rc_p0
;
435 /* Reset terminal emulator (SUNRESET) */
438 rc
->rc_bits
&= ~FB_NO_CURSOR
;
439 rc
->rc_fgcolor
= rc
->rc_deffgcolor
;
440 rc
->rc_bgcolor
= rc
->rc_defbgcolor
;
441 rc
->rc_attr
= rc
->rc_defattr
;
443 if (rc
->rc_bits
& FB_INVERT
)
448 * XXX following two read \E[?25h and \E[?25l. rcons
449 * can't currently handle the '?'.
452 /* Normal/very visible cursor */
453 if (rc
->rc_p0
== 25) {
454 rc
->rc_bits
&= ~FB_NO_CURSOR
;
456 if (rc
->rc_bits
& FB_CURSOR
) {
457 rc
->rc_bits
^= FB_CURSOR
;
464 /* Invisible cursor */
465 if (rc
->rc_p0
== 25 && (rc
->rc_bits
& FB_NO_CURSOR
) == 0) {
466 if (rc
->rc_bits
& FB_CURSOR
)
469 rc
->rc_bits
|= FB_NO_CURSOR
;
476 /* Set ANSI colors */
478 rcons_setcolor(struct rconsole
*rc
, int fg
, int bg
)
482 if (fg
> WSCOL_WHITE
|| fg
< 0)
485 if (bg
> WSCOL_WHITE
|| bg
< 0)
488 #ifdef RASTERCONS_WONB
494 /* Emulate WSATTR_REVERSE attribute if it's not supported */
495 if ((rc
->rc_wsflg
& WSATTR_REVERSE
) &&
496 !(rc
->rc_supwsflg
& WSATTR_REVERSE
)) {
503 * Mask out unsupported flags and get attribute
504 * XXX - always ask for WSCOLORS if supported (why shouldn't we?)
506 flg
= (rc
->rc_wsflg
| WSATTR_WSCOLORS
) & rc
->rc_supwsflg
;
509 rc
->rc_ops
->allocattr(rc
->rc_cookie
, fg
, bg
, flg
, &rc
->rc_attr
);
513 /* Actually write a string to the frame buffer */
515 rcons_text(struct rconsole
*rc
, const unsigned char *str
, int n
)
520 uc
= rc
->rc_charmap
[*str
++ & 255];
521 rc
->rc_ops
->putchar(rc
->rc_cookie
, rc
->rc_row
, rc
->rc_col
++,
525 if (rc
->rc_col
>= rc
->rc_maxcol
) {
530 if (rc
->rc_row
>= rc
->rc_maxrow
)
534 /* Paint (or unpaint) the cursor */
536 rcons_cursor(struct rconsole
*rc
)
538 rc
->rc_bits
^= FB_CURSOR
;
540 if (rc
->rc_bits
& FB_NO_CURSOR
)
543 rc
->rc_ops
->cursor(rc
->rc_cookie
, rc
->rc_bits
& FB_CURSOR
,
544 rc
->rc_row
, rc
->rc_col
);
547 /* Possibly change to SUNWOB or SUNBOW mode */
549 rcons_invert(struct rconsole
*rc
, int wob
)
552 rc
->rc_bits
^= FB_INVERT
;
553 /* XXX how do we do we invert the framebuffer?? */
556 /* Clear to the end of the page */
558 rcons_clear2eop(struct rconsole
*rc
)
560 if (rc
->rc_col
|| rc
->rc_row
) {
563 if (rc
->rc_row
< (rc
->rc_maxrow
- 1))
564 rc
->rc_ops
->eraserows(rc
->rc_cookie
, rc
->rc_row
+ 1,
565 rc
->rc_maxrow
, rc
->rc_attr
);
567 rc
->rc_ops
->eraserows(rc
->rc_cookie
, 0, rc
->rc_maxrow
,
571 /* Clear to the end of the line */
573 rcons_clear2eol(struct rconsole
*rc
)
575 rc
->rc_ops
->erasecols(rc
->rc_cookie
, rc
->rc_row
, rc
->rc_col
,
576 rc
->rc_maxcol
- rc
->rc_col
, rc
->rc_attr
);
582 rcons_scroll(struct rconsole
*rc
, int n
)
584 /* Can't scroll more than the whole screen */
585 if (n
> rc
->rc_maxrow
)
588 /* Calculate new row */
594 rc
->rc_ops
->copyrows(rc
->rc_cookie
, n
, 0, rc
->rc_maxrow
- n
);
595 rc
->rc_ops
->eraserows(rc
->rc_cookie
, rc
->rc_maxrow
- n
, n
, rc
->rc_attr
);
598 /* Delete characters */
600 rcons_delchar(struct rconsole
*rc
, int n
)
602 /* Can't delete more chars than there are */
603 if (n
> rc
->rc_maxcol
- rc
->rc_col
)
604 n
= rc
->rc_maxcol
- rc
->rc_col
;
606 rc
->rc_ops
->copycols(rc
->rc_cookie
, rc
->rc_row
, rc
->rc_col
+ n
,
607 rc
->rc_col
, rc
->rc_maxcol
- rc
->rc_col
- n
);
609 rc
->rc_ops
->erasecols(rc
->rc_cookie
, rc
->rc_row
,
610 rc
->rc_maxcol
- n
, n
, rc
->rc_attr
);
613 /* Delete a number of lines */
615 rcons_delline(struct rconsole
*rc
, int n
)
617 /* Can't delete more lines than there are */
618 if (n
> rc
->rc_maxrow
- rc
->rc_row
)
619 n
= rc
->rc_maxrow
- rc
->rc_row
;
621 rc
->rc_ops
->copyrows(rc
->rc_cookie
, rc
->rc_row
+ n
, rc
->rc_row
,
622 rc
->rc_maxrow
- rc
->rc_row
- n
);
624 rc
->rc_ops
->eraserows(rc
->rc_cookie
, rc
->rc_maxrow
- n
, n
,
628 /* Insert some characters */
630 rcons_insertchar(struct rconsole
*rc
, int n
)
632 /* Can't insert more chars than can fit */
633 if (n
> rc
->rc_maxcol
- rc
->rc_col
)
634 n
= rc
->rc_maxcol
- rc
->rc_col
- 1;
636 rc
->rc_ops
->copycols(rc
->rc_cookie
, rc
->rc_row
, rc
->rc_col
,
637 rc
->rc_col
+ n
, rc
->rc_maxcol
- rc
->rc_col
- n
- 1);
639 rc
->rc_ops
->erasecols(rc
->rc_cookie
, rc
->rc_row
, rc
->rc_col
,
643 /* Insert some lines */
645 rcons_insertline(struct rconsole
*rc
, int n
)
647 /* Can't insert more lines than can fit */
648 if (n
> rc
->rc_maxrow
- rc
->rc_row
)
649 n
= rc
->rc_maxrow
- rc
->rc_row
;
651 rc
->rc_ops
->copyrows(rc
->rc_cookie
, rc
->rc_row
, rc
->rc_row
+ n
,
652 rc
->rc_maxrow
- rc
->rc_row
- n
);
654 rc
->rc_ops
->eraserows(rc
->rc_cookie
, rc
->rc_row
, n
,
658 /* end of rcons_subr.c */