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