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