1 /* $NetBSD: rcons_subr.c,v 1.12 2003/08/07 16:31:21 agc Exp $ */
2
3 /*
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
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.
10 *
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.
15 *
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.
27 *
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.
39 *
40 * @(#)rcons_subr.c 8.1 (Berkeley) 6/11/93
41 */
42
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: rcons_subr.c,v 1.12 2003/08/07 16:31:21 agc Exp $");
45
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
53
54 #include <dev/rcons/rcons.h>
55 #include <dev/wscons/wsdisplayvar.h>
56
57 extern void rcons_bell(struct rconsole *);
58
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) >= '' && (c) <= '9')
65
66 /* Initialize our operations set */
67 void
68 rcons_init_ops(rc)
69 struct rconsole *rc;
70 {
71 long tmp;
72 int i, m;
73
74 m = sizeof(rc->rc_charmap) / sizeof(rc->rc_charmap[0]);
75
76 for (i = 0; i < m; i++)
77 rc->rc_ops->mapchar(rc->rc_cookie, i, rc->rc_charmap + i);
78
79 /* Determine which attributes the device supports. */
80 #ifdef RASTERCONSOLE_FGCOL
81 rc->rc_deffgcolor = RASTERCONSOLE_FGCOL;
82 #endif
83 #ifdef RASTERCONSOLE_BGCOL
84 rc->rc_defbgcolor = RASTERCONSOLE_BGCOL;
85 #endif
86 rc->rc_fgcolor = rc->rc_deffgcolor;
87 rc->rc_bgcolor = rc->rc_defbgcolor;
88 rc->rc_supwsflg = 0;
89
90 for (i = 1; i < 256; i <<= 1)
91 if (rc->rc_ops->allocattr(rc->rc_cookie, 0, 0, i, &tmp) == 0)
92 rc->rc_supwsflg |= i;
93
94 /* Allocate kernel output attribute */
95 rc->rc_wsflg = WSATTR_HILIT;
96 rcons_setcolor(rc, rc->rc_deffgcolor, rc->rc_defbgcolor);
97 rc->rc_kern_attr = rc->rc_attr;
98
99 rc->rc_wsflg = 0;
100 rcons_setcolor(rc, rc->rc_deffgcolor, rc->rc_defbgcolor);
101 rc->rc_defattr = rc->rc_attr;
102 }
103
104 /* Output (or at least handle) a string sent to the console */
105 void
106 rcons_puts(rc, str, n)
107 struct rconsole *rc;
108 unsigned char *str;
109 int n;
110 {
111 int c, i, j;
112 unsigned char *cp;
113
114 /* Jump scroll */
115 /* XXX maybe this should be an option? */
116 if ((rc->rc_bits & FB_INESC) == 0) {
117 /* Count newlines up to an escape sequence */
118 i = 0;
119 j = 0;
120 for (cp = str; j++ < n && *cp != '\033'; ++cp) {
121 if (*cp == '\n')
122 ++i;
123 else if (*cp == '\013')
124 --i;
125 }
126
127 /* Only jump scroll two or more rows */
128 if (rc->rc_row + i > rc->rc_maxrow + 1) {
129 /* Erase the cursor (if necessary) */
130 if (rc->rc_bits & FB_CURSOR)
131 rcons_cursor(rc);
132
133 rcons_scroll(rc, i);
134 }
135 }
136
137 /* Process characters */
138 while (--n >= 0) {
139 c = *str;
140 if (c == '\033') {
141 /* Start an escape (perhaps aborting one in progress) */
142 rc->rc_bits |= FB_INESC | FB_P0_DEFAULT | FB_P1_DEFAULT;
143 rc->rc_bits &= ~(FB_P0 | FB_P1);
144
145 /* Most parameters default to 1 */
146 rc->rc_p0 = rc->rc_p1 = 1;
147 } else if (rc->rc_bits & FB_INESC) {
148 rcons_esc(rc, c);
149 } else {
150 /* Erase the cursor (if necessary) */
151 if (rc->rc_bits & FB_CURSOR)
152 rcons_cursor(rc);
153
154 /* Display the character */
155 if (RCONS_ISPRINT(c)) {
156 /* Try to output as much as possible */
157 j = rc->rc_maxcol - rc->rc_col;
158 if (j > n)
159 j = n;
160 for (i = 1; i < j && RCONS_ISPRINT(str[i]); ++i)
161 continue;
162 rcons_text(rc, str, i);
163 --i;
164 str += i;
165 n -= i;
166 } else
167 rcons_pctrl(rc, c);
168 }
169 ++str;
170 }
171 /* Redraw the cursor (if necessary) */
172 if ((rc->rc_bits & FB_CURSOR) == 0)
173 rcons_cursor(rc);
174 }
175
176
177 /* Handle a control character sent to the console */
178 void
179 rcons_pctrl(rc, c)
180 struct rconsole *rc;
181 int c;
182 {
183
184 switch (c) {
185 case '\r': /* Carriage return */
186 rc->rc_col = 0;
187 break;
188
189 case '\b': /* Backspace */
190 if (rc->rc_col > 0)
191 (rc->rc_col)--;
192 break;
193
194 case '\v': /* Vertical tab */
195 if (rc->rc_row > 0)
196 (rc->rc_row)--;
197 break;
198
199 case '\f': /* Formfeed */
200 rc->rc_row = rc->rc_col = 0;
201 rcons_clear2eop(rc);
202 break;
203
204 case '\n': /* Linefeed */
205 (rc->rc_row)++;
206 if (rc->rc_row >= rc->rc_maxrow)
207 rcons_scroll(rc, 1);
208 break;
209
210 case '\a': /* Bell */
211 rcons_bell(rc);
212 break;
213
214 case '\t': /* Horizontal tab */
215 rc->rc_col = (rc->rc_col + 8) & ~7;
216 if (rc->rc_col >= rc->rc_maxcol)
217 rc->rc_col = rc->rc_maxcol;
218 break;
219 }
220 }
221
222 /* Handle the next character in an escape sequence */
223 void
224 rcons_esc(rc, c)
225 struct rconsole *rc;
226 int c;
227 {
228
229 if (c == '[') {
230 /* Parameter 0 */
231 rc->rc_bits &= ~FB_P1;
232 rc->rc_bits |= FB_P0;
233 } else if (c == ';') {
234 /* Parameter 1 */
235 rc->rc_bits &= ~FB_P0;
236 rc->rc_bits |= FB_P1;
237 } else if (RCONS_ISDIGIT(c)) {
238 /* Add a digit to a parameter */
239 if (rc->rc_bits & FB_P0) {
240 /* Parameter 0 */
241 if (rc->rc_bits & FB_P0_DEFAULT) {
242 rc->rc_bits &= ~FB_P0_DEFAULT;
243 rc->rc_p0 = 0;
244 }
245 rc->rc_p0 *= 10;
246 rc->rc_p0 += c - '';
247 } else if (rc->rc_bits & FB_P1) {
248 /* Parameter 1 */
249 if (rc->rc_bits & FB_P1_DEFAULT) {
250 rc->rc_bits &= ~FB_P1_DEFAULT;
251 rc->rc_p1 = 0;
252 }
253 rc->rc_p1 *= 10;
254 rc->rc_p1 += c - '';
255 }
256 } else {
257 /* Erase the cursor (if necessary) */
258 if (rc->rc_bits & FB_CURSOR)
259 rcons_cursor(rc);
260
261 /* Process the completed escape sequence */
262 rcons_doesc(rc, c);
263 rc->rc_bits &= ~FB_INESC;
264 }
265 }
266
267
268 /* Handle an SGR (Select Graphic Rendition) escape */
269 void
270 rcons_sgresc(rc, c)
271 struct rconsole *rc;
272 int c;
273 {
274
275 switch (c) {
276 /* Clear all attributes || End underline */
277 case 0:
278 rc->rc_wsflg = 0;
279 rc->rc_fgcolor = rc->rc_deffgcolor;
280 rc->rc_bgcolor = rc->rc_defbgcolor;
281 rc->rc_attr = rc->rc_defattr;
282 break;
283
284 /* ANSI foreground color */
285 case 30: case 31: case 32: case 33:
286 case 34: case 35: case 36: case 37:
287 rcons_setcolor(rc, c - 30, rc->rc_bgcolor);
288 break;
289
290 /* ANSI background color */
291 case 40: case 41: case 42: case 43:
292 case 44: case 45: case 46: case 47:
293 rcons_setcolor(rc, rc->rc_fgcolor, c - 40);
294 break;
295
296 /* Begin reverse */
297 case 7:
298 rc->rc_wsflg |= WSATTR_REVERSE;
299 rcons_setcolor(rc, rc->rc_fgcolor, rc->rc_bgcolor);
300 break;
301
302 /* Begin bold */
303 case 1:
304 rc->rc_wsflg |= WSATTR_HILIT;
305 rcons_setcolor(rc, rc->rc_fgcolor, rc->rc_bgcolor);
306 break;
307
308 /* Begin underline */
309 case 4:
310 rc->rc_wsflg |= WSATTR_UNDERLINE;
311 rcons_setcolor(rc, rc->rc_fgcolor, rc->rc_bgcolor);
312 break;
313 }
314 }
315
316
317 /* Process a complete escape sequence */
318 void
319 rcons_doesc(rc, c)
320 struct rconsole *rc;
321 int c;
322 {
323
324 #ifdef notdef
325 /* XXX add escape sequence to enable visual (and audible) bell */
326 rc->rc_bits = FB_VISBELL;
327 #endif
328
329 switch (c) {
330
331 case '@':
332 /* Insert Character (ICH) */
333 rcons_insertchar(rc, rc->rc_p0);
334 break;
335
336 case 'A':
337 /* Cursor Up (CUU) */
338 rc->rc_row -= rc->rc_p0;
339 if (rc->rc_row < 0)
340 rc->rc_row = 0;
341 break;
342
343 case 'B':
344 /* Cursor Down (CUD) */
345 rc->rc_row += rc->rc_p0;
346 if (rc->rc_row >= rc->rc_maxrow)
347 rc->rc_row = rc->rc_maxrow - 1;
348 break;
349
350 case 'C':
351 /* Cursor Forward (CUF) */
352 rc->rc_col += rc->rc_p0;
353 if (rc->rc_col >= rc->rc_maxcol)
354 rc->rc_col = rc->rc_maxcol - 1;
355 break;
356
357 case 'D':
358 /* Cursor Backward (CUB) */
359 rc->rc_col -= rc->rc_p0;
360 if (rc->rc_col < 0)
361 rc->rc_col = 0;
362 break;
363
364 case 'E':
365 /* Cursor Next Line (CNL) */
366 rc->rc_col = 0;
367 rc->rc_row += rc->rc_p0;
368 if (rc->rc_row >= rc->rc_maxrow)
369 rc->rc_row = rc->rc_maxrow - 1;
370 break;
371
372 case 'f':
373 /* Horizontal And Vertical Position (HVP) */
374 case 'H':
375 /* Cursor Position (CUP) */
376 rc->rc_col = rc->rc_p1 - 1;
377 if (rc->rc_col < 0)
378 rc->rc_col = 0;
379 else if (rc->rc_col >= rc->rc_maxcol)
380 rc->rc_col = rc->rc_maxcol - 1;
381
382 rc->rc_row = rc->rc_p0 - 1;
383 if (rc->rc_row < 0)
384 rc->rc_row = 0;
385 else if (rc->rc_row >= rc->rc_maxrow)
386 rc->rc_row = rc->rc_maxrow - 1;
387 break;
388
389 case 'J':
390 /* Erase in Display (ED) */
391 rcons_clear2eop(rc);
392 break;
393
394 case 'K':
395 /* Erase in Line (EL) */
396 rcons_clear2eol(rc);
397 break;
398
399 case 'L':
400 /* Insert Line (IL) */
401 rcons_insertline(rc, rc->rc_p0);
402 break;
403
404 case 'M':
405 /* Delete Line (DL) */
406 rcons_delline(rc, rc->rc_p0);
407 break;
408
409 case 'P':
410 /* Delete Character (DCH) */
411 rcons_delchar(rc, rc->rc_p0);
412 break;
413
414 case 'm':
415 /* Select Graphic Rendition (SGR) */
416 /* (defaults to zero) */
417 if (rc->rc_bits & FB_P0_DEFAULT)
418 rc->rc_p0 = 0;
419
420 if (rc->rc_bits & FB_P1_DEFAULT)
421 rc->rc_p1 = 0;
422
423 rcons_sgresc(rc, rc->rc_p0);
424
425 if (rc->rc_bits & FB_P1)
426 rcons_sgresc(rc, rc->rc_p1);
427
428 break;
429
430 /*
431 * XXX: setting SUNBOW and SUNWOB should probably affect
432 * deffgcolor, defbgcolor and defattr too.
433 */
434 case 'p':
435 /* Black On White (SUNBOW) */
436 rcons_setcolor(rc, WSCOL_BLACK, WSCOL_WHITE);
437 break;
438
439 case 'q':
440 /* White On Black (SUNWOB) */
441 rcons_setcolor(rc, WSCOL_WHITE, WSCOL_BLACK);
442 break;
443
444 case 'r':
445 /* Set scrolling (SUNSCRL) */
446 /* (defaults to zero) */
447 if (rc->rc_bits & FB_P0_DEFAULT)
448 rc->rc_p0 = 0;
449 /* XXX not implemented yet */
450 rc->rc_scroll = rc->rc_p0;
451 break;
452
453 case 's':
454 /* Reset terminal emulator (SUNRESET) */
455 rc->rc_wsflg = 0;
456 rc->rc_scroll = 0;
457 rc->rc_bits &= ~FB_NO_CURSOR;
458 rc->rc_fgcolor = rc->rc_deffgcolor;
459 rc->rc_bgcolor = rc->rc_defbgcolor;
460 rc->rc_attr = rc->rc_defattr;
461
462 if (rc->rc_bits & FB_INVERT)
463 rcons_invert(rc, 0);
464 break;
465 #ifdef notyet
466 /*
467 * XXX following two read \E[?25h and \E[?25l. rcons
468 * can't currently handle the '?'.
469 */
470 case 'h':
471 /* Normal/very visible cursor */
472 if (rc->rc_p0 == 25) {
473 rc->rc_bits &= ~FB_NO_CURSOR;
474
475 if (rc->rc_bits & FB_CURSOR) {
476 rc->rc_bits ^= FB_CURSOR;
477 rcons_cursor(rc);
478 }
479 }
480 break;
481
482 case 'l':
483 /* Invisible cursor */
484 if (rc->rc_p0 == 25 && (rc->rc_bits & FB_NO_CURSOR) == 0) {
485 if (rc->rc_bits & FB_CURSOR)
486 rcons_cursor(rc);
487
488 rc->rc_bits |= FB_NO_CURSOR;
489 }
490 break;
491 #endif
492 }
493 }
494
495 /* Set ANSI colors */
496 void
497 rcons_setcolor(rc, fg, bg)
498 struct rconsole *rc;
499 int fg, bg;
500 {
501 int flg;
502
503 if (fg > WSCOL_WHITE || fg < 0)
504 return;
505
506 if (bg > WSCOL_WHITE || bg < 0)
507 return;
508
509 #ifdef RASTERCONS_WONB
510 flg = bg;
511 bg = fg;
512 fg = flg;
513 #endif
514
515 /* Emulate WSATTR_REVERSE attribute if it's not supported */
516 if ((rc->rc_wsflg & WSATTR_REVERSE) &&
517 !(rc->rc_supwsflg & WSATTR_REVERSE)) {
518 flg = bg;
519 bg = fg;
520 fg = flg;
521 }
522
523 /*
524 * Mask out unsupported flags and get attribute
525 * XXX - always ask for WSCOLORS if supported (why shouldn't we?)
526 */
527 flg = (rc->rc_wsflg | WSATTR_WSCOLORS) & rc->rc_supwsflg;
528 rc->rc_bgcolor = bg;
529 rc->rc_fgcolor = fg;
530 rc->rc_ops->allocattr(rc->rc_cookie, fg, bg, flg, &rc->rc_attr);
531 }
532
533
534 /* Actually write a string to the frame buffer */
535 void
536 rcons_text(rc, str, n)
537 struct rconsole *rc;
538 unsigned char *str;
539 int n;
540 {
541 u_int uc;
542
543 while (n--) {
544 uc = rc->rc_charmap[*str++ & 255];
545 rc->rc_ops->putchar(rc->rc_cookie, rc->rc_row, rc->rc_col++,
546 uc, rc->rc_attr);
547 }
548
549 if (rc->rc_col >= rc->rc_maxcol) {
550 rc->rc_col = 0;
551 rc->rc_row++;
552 }
553
554 if (rc->rc_row >= rc->rc_maxrow)
555 rcons_scroll(rc, 1);
556 }
557
558 /* Paint (or unpaint) the cursor */
559 void
560 rcons_cursor(rc)
561 struct rconsole *rc;
562 {
563 rc->rc_bits ^= FB_CURSOR;
564
565 if (rc->rc_bits & FB_NO_CURSOR)
566 return;
567
568 rc->rc_ops->cursor(rc->rc_cookie, rc->rc_bits & FB_CURSOR,
569 rc->rc_row, rc->rc_col);
570 }
571
572 /* Possibly change to SUNWOB or SUNBOW mode */
573 void
574 rcons_invert(rc, wob)
575 struct rconsole *rc;
576 int wob;
577 {
578
579 rc->rc_bits ^= FB_INVERT;
580 /* XXX how do we do we invert the framebuffer?? */
581 }
582
583 /* Clear to the end of the page */
584 void
585 rcons_clear2eop(rc)
586 struct rconsole *rc;
587 {
588 if (rc->rc_col || rc->rc_row) {
589 rcons_clear2eol(rc);
590
591 if (rc->rc_row < (rc->rc_maxrow - 1))
592 rc->rc_ops->eraserows(rc->rc_cookie, rc->rc_row + 1,
593 rc->rc_maxrow, rc->rc_attr);
594 } else
595 rc->rc_ops->eraserows(rc->rc_cookie, 0, rc->rc_maxrow,
596 rc->rc_attr);
597 }
598
599 /* Clear to the end of the line */
600 void
601 rcons_clear2eol(rc)
602 struct rconsole *rc;
603 {
604 rc->rc_ops->erasecols(rc->rc_cookie, rc->rc_row, rc->rc_col,
605 rc->rc_maxcol - rc->rc_col, rc->rc_attr);
606 }
607
608
609 /* Scroll up */
610 void
611 rcons_scroll(rc, n)
612 struct rconsole *rc;
613 int n;
614 {
615 /* Can't scroll more than the whole screen */
616 if (n > rc->rc_maxrow)
617 n = rc->rc_maxrow;
618
619 /* Calculate new row */
620 rc->rc_row -= n;
621
622 if (rc->rc_row < 0)
623 rc->rc_row = 0;
624
625 rc->rc_ops->copyrows(rc->rc_cookie, n, 0, rc->rc_maxrow - n);
626 rc->rc_ops->eraserows(rc->rc_cookie, rc->rc_maxrow - n, n, rc->rc_attr);
627 }
628
629 /* Delete characters */
630 void
631 rcons_delchar(rc, n)
632 struct rconsole *rc;
633 int n;
634 {
635 /* Can't delete more chars than there are */
636 if (n > rc->rc_maxcol - rc->rc_col)
637 n = rc->rc_maxcol - rc->rc_col;
638
639 rc->rc_ops->copycols(rc->rc_cookie, rc->rc_row, rc->rc_col + n,
640 rc->rc_col, rc->rc_maxcol - rc->rc_col - n);
641
642 rc->rc_ops->erasecols(rc->rc_cookie, rc->rc_row,
643 rc->rc_maxcol - n, n, rc->rc_attr);
644 }
645
646 /* Delete a number of lines */
647 void
648 rcons_delline(rc, n)
649 struct rconsole *rc;
650 int n;
651 {
652 /* Can't delete more lines than there are */
653 if (n > rc->rc_maxrow - rc->rc_row)
654 n = rc->rc_maxrow - rc->rc_row;
655
656 rc->rc_ops->copyrows(rc->rc_cookie, rc->rc_row + n, rc->rc_row,
657 rc->rc_maxrow - rc->rc_row - n);
658
659 rc->rc_ops->eraserows(rc->rc_cookie, rc->rc_maxrow - n, n,
660 rc->rc_attr);
661 }
662
663 /* Insert some characters */
664 void
665 rcons_insertchar(rc, n)
666 struct rconsole *rc;
667 int n;
668 {
669 /* Can't insert more chars than can fit */
670 if (n > rc->rc_maxcol - rc->rc_col)
671 n = rc->rc_maxcol - rc->rc_col - 1;
672
673 rc->rc_ops->copycols(rc->rc_cookie, rc->rc_row, rc->rc_col,
674 rc->rc_col + n, rc->rc_maxcol - rc->rc_col - n - 1);
675
676 rc->rc_ops->erasecols(rc->rc_cookie, rc->rc_row, rc->rc_col,
677 n, rc->rc_attr);
678 }
679
680 /* Insert some lines */
681 void
682 rcons_insertline(rc, n)
683 struct rconsole *rc;
684 int n;
685 {
686 /* Can't insert more lines than can fit */
687 if (n > rc->rc_maxrow - rc->rc_row)
688 n = rc->rc_maxrow - rc->rc_row;
689
690 rc->rc_ops->copyrows(rc->rc_cookie, rc->rc_row, rc->rc_row + n,
691 rc->rc_maxrow - rc->rc_row - n);
692
693 rc->rc_ops->eraserows(rc->rc_cookie, rc->rc_row, n,
694 rc->rc_attr);
695 }
696
697 /* end of rcons_subr.c */
Cache object: abc700e1f871c77c39ce37ff32712812
|