No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / rcons / rcons_subr.c
blob91aa32544595f98fc470cb8de558d4c77677ca68
1 /* $NetBSD: rcons_subr.c,v 1.17 2009/03/14 15:36:20 dsl Exp $ */
3 /*
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
18 * are met:
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
38 * SUCH DAMAGE.
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>
47 #ifdef _KERNEL
48 #include <sys/device.h>
49 #include <sys/systm.h>
50 #else
51 #include "myfbdevice.h"
52 #endif
54 #include <dev/rcons/rcons.h>
55 #include <dev/wscons/wsdisplayvar.h>
57 extern void rcons_bell(struct rconsole *);
59 #if 0
60 #define RCONS_ISPRINT(c) ((((c) >= ' ') && ((c) <= '~')) || ((c) > 160))
61 #else
62 #define RCONS_ISPRINT(c) (((((c) >= ' ') && ((c) <= '~'))) || ((c) > 127))
63 #endif
64 #define RCONS_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
66 /* Initialize our operations set */
67 void
68 rcons_init_ops(struct rconsole *rc)
70 long tmp;
71 int i, m;
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;
81 #endif
82 #ifdef RASTERCONSOLE_BGCOL
83 rc->rc_defbgcolor = RASTERCONSOLE_BGCOL;
84 #endif
85 rc->rc_fgcolor = rc->rc_deffgcolor;
86 rc->rc_bgcolor = rc->rc_defbgcolor;
87 rc->rc_supwsflg = 0;
89 for (i = 1; i < 256; i <<= 1)
90 if (rc->rc_ops->allocattr(rc->rc_cookie, 0, 0, i, &tmp) == 0)
91 rc->rc_supwsflg |= i;
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;
98 rc->rc_wsflg = 0;
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 */
104 void
105 rcons_puts(struct rconsole *rc, const unsigned char *str, int n)
107 int c, i, j;
108 const unsigned char *cp;
110 /* Jump scroll */
111 /* XXX maybe this should be an option? */
112 if ((rc->rc_bits & FB_INESC) == 0) {
113 /* Count newlines up to an escape sequence */
114 i = 0;
115 j = 0;
116 for (cp = str; j++ < n && *cp != '\033'; ++cp) {
117 if (*cp == '\n')
118 ++i;
119 else if (*cp == '\013')
120 --i;
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)
127 rcons_cursor(rc);
129 rcons_scroll(rc, i);
133 /* Process characters */
134 while (--n >= 0) {
135 c = *str;
136 if (c == '\033') {
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) {
144 rcons_esc(rc, c);
145 } else {
146 /* Erase the cursor (if necessary) */
147 if (rc->rc_bits & FB_CURSOR)
148 rcons_cursor(rc);
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;
154 if (j > n)
155 j = n;
156 for (i = 1; i < j && RCONS_ISPRINT(str[i]); ++i)
157 continue;
158 rcons_text(rc, str, i);
159 --i;
160 str += i;
161 n -= i;
162 } else
163 rcons_pctrl(rc, c);
165 ++str;
167 /* Redraw the cursor (if necessary) */
168 if ((rc->rc_bits & FB_CURSOR) == 0)
169 rcons_cursor(rc);
173 /* Handle a control character sent to the console */
174 void
175 rcons_pctrl(struct rconsole *rc, int c)
178 switch (c) {
179 case '\r': /* Carriage return */
180 rc->rc_col = 0;
181 break;
183 case '\b': /* Backspace */
184 if (rc->rc_col > 0)
185 (rc->rc_col)--;
186 break;
188 case '\v': /* Vertical tab */
189 if (rc->rc_row > 0)
190 (rc->rc_row)--;
191 break;
193 case '\f': /* Formfeed */
194 rc->rc_row = rc->rc_col = 0;
195 rcons_clear2eop(rc);
196 break;
198 case '\n': /* Linefeed */
199 (rc->rc_row)++;
200 if (rc->rc_row >= rc->rc_maxrow)
201 rcons_scroll(rc, 1);
202 break;
204 case '\a': /* Bell */
205 rcons_bell(rc);
206 break;
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;
212 break;
216 /* Handle the next character in an escape sequence */
217 void
218 rcons_esc(struct rconsole *rc, int c)
221 if (c == '[') {
222 /* Parameter 0 */
223 rc->rc_bits &= ~FB_P1;
224 rc->rc_bits |= FB_P0;
225 } else if (c == ';') {
226 /* Parameter 1 */
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) {
232 /* Parameter 0 */
233 if (rc->rc_bits & FB_P0_DEFAULT) {
234 rc->rc_bits &= ~FB_P0_DEFAULT;
235 rc->rc_p0 = 0;
237 rc->rc_p0 *= 10;
238 rc->rc_p0 += c - '0';
239 } else if (rc->rc_bits & FB_P1) {
240 /* Parameter 1 */
241 if (rc->rc_bits & FB_P1_DEFAULT) {
242 rc->rc_bits &= ~FB_P1_DEFAULT;
243 rc->rc_p1 = 0;
245 rc->rc_p1 *= 10;
246 rc->rc_p1 += c - '0';
248 } else {
249 /* Erase the cursor (if necessary) */
250 if (rc->rc_bits & FB_CURSOR)
251 rcons_cursor(rc);
253 /* Process the completed escape sequence */
254 rcons_doesc(rc, c);
255 rc->rc_bits &= ~FB_INESC;
260 /* Handle an SGR (Select Graphic Rendition) escape */
261 void
262 rcons_sgresc(struct rconsole *rc, int c)
265 switch (c) {
266 /* Clear all attributes || End underline */
267 case 0:
268 rc->rc_wsflg = 0;
269 rc->rc_fgcolor = rc->rc_deffgcolor;
270 rc->rc_bgcolor = rc->rc_defbgcolor;
271 rc->rc_attr = rc->rc_defattr;
272 break;
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);
278 break;
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);
284 break;
286 /* Begin reverse */
287 case 7:
288 rc->rc_wsflg |= WSATTR_REVERSE;
289 rcons_setcolor(rc, rc->rc_fgcolor, rc->rc_bgcolor);
290 break;
292 /* Begin bold */
293 case 1:
294 rc->rc_wsflg |= WSATTR_HILIT;
295 rcons_setcolor(rc, rc->rc_fgcolor, rc->rc_bgcolor);
296 break;
298 /* Begin underline */
299 case 4:
300 rc->rc_wsflg |= WSATTR_UNDERLINE;
301 rcons_setcolor(rc, rc->rc_fgcolor, rc->rc_bgcolor);
302 break;
307 /* Process a complete escape sequence */
308 void
309 rcons_doesc(struct rconsole *rc, int c)
312 #ifdef notdef
313 /* XXX add escape sequence to enable visual (and audible) bell */
314 rc->rc_bits = FB_VISBELL;
315 #endif
317 switch (c) {
319 case '@':
320 /* Insert Character (ICH) */
321 rcons_insertchar(rc, rc->rc_p0);
322 break;
324 case 'A':
325 /* Cursor Up (CUU) */
326 if (rc->rc_row >= rc->rc_p0)
327 rc->rc_row -= rc->rc_p0;
328 else
329 rc->rc_row = 0;
330 break;
332 case 'B':
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;
337 break;
339 case 'C':
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;
344 break;
346 case 'D':
347 /* Cursor Backward (CUB) */
348 if (rc->rc_col >= rc->rc_p0)
349 rc->rc_col -= rc->rc_p0;
350 else
351 rc->rc_col = 0;
352 break;
354 case 'E':
355 /* Cursor Next Line (CNL) */
356 rc->rc_col = 0;
357 rc->rc_row += rc->rc_p0;
358 if (rc->rc_row >= rc->rc_maxrow)
359 rc->rc_row = rc->rc_maxrow - 1;
360 break;
362 case 'f':
363 /* Horizontal And Vertical Position (HVP) */
364 case 'H':
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;
368 break;
370 case 'J':
371 /* Erase in Display (ED) */
372 rcons_clear2eop(rc);
373 break;
375 case 'K':
376 /* Erase in Line (EL) */
377 rcons_clear2eol(rc);
378 break;
380 case 'L':
381 /* Insert Line (IL) */
382 rcons_insertline(rc, rc->rc_p0);
383 break;
385 case 'M':
386 /* Delete Line (DL) */
387 rcons_delline(rc, rc->rc_p0);
388 break;
390 case 'P':
391 /* Delete Character (DCH) */
392 rcons_delchar(rc, rc->rc_p0);
393 break;
395 case 'm':
396 /* Select Graphic Rendition (SGR) */
397 /* (defaults to zero) */
398 if (rc->rc_bits & FB_P0_DEFAULT)
399 rc->rc_p0 = 0;
401 if (rc->rc_bits & FB_P1_DEFAULT)
402 rc->rc_p1 = 0;
404 rcons_sgresc(rc, rc->rc_p0);
406 if (rc->rc_bits & FB_P1)
407 rcons_sgresc(rc, rc->rc_p1);
409 break;
412 * XXX: setting SUNBOW and SUNWOB should probably affect
413 * deffgcolor, defbgcolor and defattr too.
415 case 'p':
416 /* Black On White (SUNBOW) */
417 rcons_setcolor(rc, WSCOL_BLACK, WSCOL_WHITE);
418 break;
420 case 'q':
421 /* White On Black (SUNWOB) */
422 rcons_setcolor(rc, WSCOL_WHITE, WSCOL_BLACK);
423 break;
425 case 'r':
426 /* Set scrolling (SUNSCRL) */
427 /* (defaults to zero) */
428 if (rc->rc_bits & FB_P0_DEFAULT)
429 rc->rc_p0 = 0;
430 /* XXX not implemented yet */
431 rc->rc_scroll = rc->rc_p0;
432 break;
434 case 's':
435 /* Reset terminal emulator (SUNRESET) */
436 rc->rc_wsflg = 0;
437 rc->rc_scroll = 0;
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)
444 rcons_invert(rc, 0);
445 break;
446 #ifdef notyet
448 * XXX following two read \E[?25h and \E[?25l. rcons
449 * can't currently handle the '?'.
451 case 'h':
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;
458 rcons_cursor(rc);
461 break;
463 case 'l':
464 /* Invisible cursor */
465 if (rc->rc_p0 == 25 && (rc->rc_bits & FB_NO_CURSOR) == 0) {
466 if (rc->rc_bits & FB_CURSOR)
467 rcons_cursor(rc);
469 rc->rc_bits |= FB_NO_CURSOR;
471 break;
472 #endif
476 /* Set ANSI colors */
477 void
478 rcons_setcolor(struct rconsole *rc, int fg, int bg)
480 int flg;
482 if (fg > WSCOL_WHITE || fg < 0)
483 return;
485 if (bg > WSCOL_WHITE || bg < 0)
486 return;
488 #ifdef RASTERCONS_WONB
489 flg = bg;
490 bg = fg;
491 fg = flg;
492 #endif
494 /* Emulate WSATTR_REVERSE attribute if it's not supported */
495 if ((rc->rc_wsflg & WSATTR_REVERSE) &&
496 !(rc->rc_supwsflg & WSATTR_REVERSE)) {
497 flg = bg;
498 bg = fg;
499 fg = flg;
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;
507 rc->rc_bgcolor = bg;
508 rc->rc_fgcolor = fg;
509 rc->rc_ops->allocattr(rc->rc_cookie, fg, bg, flg, &rc->rc_attr);
513 /* Actually write a string to the frame buffer */
514 void
515 rcons_text(struct rconsole *rc, const unsigned char *str, int n)
517 u_int uc;
519 while (n--) {
520 uc = rc->rc_charmap[*str++ & 255];
521 rc->rc_ops->putchar(rc->rc_cookie, rc->rc_row, rc->rc_col++,
522 uc, rc->rc_attr);
525 if (rc->rc_col >= rc->rc_maxcol) {
526 rc->rc_col = 0;
527 rc->rc_row++;
530 if (rc->rc_row >= rc->rc_maxrow)
531 rcons_scroll(rc, 1);
534 /* Paint (or unpaint) the cursor */
535 void
536 rcons_cursor(struct rconsole *rc)
538 rc->rc_bits ^= FB_CURSOR;
540 if (rc->rc_bits & FB_NO_CURSOR)
541 return;
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 */
548 void
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 */
557 void
558 rcons_clear2eop(struct rconsole *rc)
560 if (rc->rc_col || rc->rc_row) {
561 rcons_clear2eol(rc);
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);
566 } else
567 rc->rc_ops->eraserows(rc->rc_cookie, 0, rc->rc_maxrow,
568 rc->rc_attr);
571 /* Clear to the end of the line */
572 void
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);
580 /* Scroll up */
581 void
582 rcons_scroll(struct rconsole *rc, int n)
584 /* Can't scroll more than the whole screen */
585 if (n > rc->rc_maxrow)
586 n = rc->rc_maxrow;
588 /* Calculate new row */
589 if (rc->rc_row >= n)
590 rc->rc_row -= n;
591 else
592 rc->rc_row = 0;
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 */
599 void
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 */
614 void
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,
625 rc->rc_attr);
628 /* Insert some characters */
629 void
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,
640 n, rc->rc_attr);
643 /* Insert some lines */
644 void
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,
655 rc->rc_attr);
658 /* end of rcons_subr.c */