rcons_subr.c revision 1.1 1 /* $NetBSD: rcons_subr.c,v 1.1 1995/09/17 19:56:41 pk 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 #else
51 #include <sys/types.h>
52 #include "myfbdevice.h"
53 #endif
54
55 #include <dev/rcons/rcons.h>
56 #include <dev/rcons/raster.h>
57
58 void rcons_text(struct rconsole *, char *, int);
59 void rcons_pctrl(struct rconsole *, int);
60 void rcons_esc(struct rconsole *, int);
61 void rcons_doesc(struct rconsole *, int);
62 void rcons_cursor(struct rconsole *);
63 void rcons_invert(struct rconsole *, int);
64 void rcons_clear2eop(struct rconsole *);
65 void rcons_clear2eol(struct rconsole *);
66 void rcons_scroll(struct rconsole *, int);
67 void rcons_delchar(struct rconsole *, int);
68 void rcons_delline(struct rconsole *, int);
69 void rcons_insertchar(struct rconsole *, int);
70 void rcons_insertline(struct rconsole *, int);
71
72 extern void rcons_bell(struct rconsole *);
73
74 #define RCONS_ISPRINT(c) ((c) >= ' ' && (c) <= '~')
75 #define RCONS_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
76
77 /* Output (or at least handle) a string sent to the console */
78 void
79 rcons_puts(rc, str, n)
80 register struct rconsole *rc;
81 register char *str;
82 register int n;
83 {
84 register int c, i, j;
85 register char *cp;
86
87 /* Jump scroll */
88 /* XXX maybe this should be an option? */
89 if ((rc->rc_bits & FB_INESC) == 0) {
90 /* Count newlines up to an escape sequence */
91 i = 0;
92 j = 0;
93 for (cp = str; j++ < n && *cp != '\033'; ++cp) {
94 if (*cp == '\n')
95 ++i;
96 else if (*cp == '\013')
97 --i;
98 }
99
100 /* Only jump scroll two or more rows */
101 if (*rc->rc_row + i >= rc->rc_maxrow + 1) {
102 /* Erase the cursor (if necessary) */
103 if (rc->rc_bits & FB_CURSOR)
104 rcons_cursor(rc);
105
106 rcons_scroll(rc, i);
107 }
108 }
109
110 /* Process characters */
111 while (--n >= 0) {
112 c = *str;
113 if (c == '\033') {
114 /* Start an escape (perhaps aborting one in progress) */
115 rc->rc_bits |= FB_INESC | FB_P0_DEFAULT | FB_P1_DEFAULT;
116 rc->rc_bits &= ~(FB_P0 | FB_P1);
117
118 /* Most parameters default to 1 */
119 rc->rc_p0 = rc->rc_p1 = 1;
120 } else if (rc->rc_bits & FB_INESC) {
121 rcons_esc(rc, c);
122 } else {
123 /* Erase the cursor (if necessary) */
124 if (rc->rc_bits & FB_CURSOR)
125 rcons_cursor(rc);
126
127 /* Display the character */
128 if (RCONS_ISPRINT(c)) {
129 /* Try to output as much as possible */
130 j = rc->rc_maxcol - (*rc->rc_col + 1);
131 if (j > n)
132 j = n;
133 for (i = 1; i < j && RCONS_ISPRINT(str[i]); ++i)
134 continue;
135 rcons_text(rc, str, i);
136 --i;
137 str += i;
138 n -= i;
139 } else
140 rcons_pctrl(rc, c);
141 }
142 ++str;
143 }
144 /* Redraw the cursor (if necessary) */
145 if ((rc->rc_bits & FB_CURSOR) == 0)
146 rcons_cursor(rc);
147 }
148
149 /* Actually write a string to the frame buffer */
150 void
151 rcons_text(rc, str, n)
152 register struct rconsole *rc;
153 register char *str;
154 register int n;
155 {
156 register int x, y, op;
157
158 x = *rc->rc_col * rc->rc_font->width + rc->rc_xorigin;
159 y = *rc->rc_row * rc->rc_font->height +
160 rc->rc_font_ascent + rc->rc_yorigin;
161 op = RAS_SRC;
162 if (((rc->rc_bits & FB_STANDOUT) != 0) ^
163 ((rc->rc_bits & FB_INVERT) != 0))
164 op = RAS_NOT(op);
165 raster_textn(rc->rc_sp, x, y, op, rc->rc_font, str, n);
166 *rc->rc_col += n;
167 if (*rc->rc_col >= rc->rc_maxcol) {
168 *rc->rc_col = 0;
169 (*rc->rc_row)++;
170 }
171 if (*rc->rc_row >= rc->rc_maxrow)
172 rcons_scroll(rc, 1);
173 }
174
175 /* Handle a control character sent to the console */
176 void
177 rcons_pctrl(rc, c)
178 register struct rconsole *rc;
179 register int c;
180 {
181
182 switch (c) {
183
184 case '\r': /* Carriage return */
185 *rc->rc_col = 0;
186 break;
187
188 case '\b': /* Backspace */
189 if (*rc->rc_col > 0)
190 (*rc->rc_col)--;
191 break;
192
193 case '\013': /* Vertical tab */
194 if (*rc->rc_row > 0)
195 (*rc->rc_row)--;
196 break;
197
198 case '\f': /* Formfeed */
199 *rc->rc_row = *rc->rc_col = 0;
200 rcons_clear2eop(rc);
201 break;
202
203 case '\n': /* Linefeed */
204 (*rc->rc_row)++;
205 if (*rc->rc_row >= rc->rc_maxrow)
206 rcons_scroll(rc, 1);
207 break;
208
209 case '\007': /* Bell */
210 rcons_bell(rc);
211 break;
212
213 case '\t': /* Horizontal tab */
214 *rc->rc_col = (*rc->rc_col + 8) & ~7;
215 if (*rc->rc_col >= rc->rc_maxcol)
216 *rc->rc_col = rc->rc_maxcol - 1;
217 break;
218 }
219 }
220
221 /* Handle the next character in an escape sequence */
222 void
223 rcons_esc(rc, c)
224 register struct rconsole *rc;
225 register int c;
226 {
227
228 if (c == '[') {
229 /* Parameter 0 */
230 rc->rc_bits &= ~FB_P1;
231 rc->rc_bits |= FB_P0;
232 } else if (c == ';') {
233 /* Parameter 1 */
234 rc->rc_bits &= ~FB_P0;
235 rc->rc_bits |= FB_P1;
236 } else if (RCONS_ISDIGIT(c)) {
237 /* Add a digit to a parameter */
238 if (rc->rc_bits & FB_P0) {
239 /* Parameter 0 */
240 if (rc->rc_bits & FB_P0_DEFAULT) {
241 rc->rc_bits &= ~FB_P0_DEFAULT;
242 rc->rc_p0 = 0;
243 }
244 rc->rc_p0 *= 10;
245 rc->rc_p0 += c - '0';
246 } else if (rc->rc_bits & FB_P1) {
247 /* Parameter 1 */
248 if (rc->rc_bits & FB_P1_DEFAULT) {
249 rc->rc_bits &= ~FB_P1_DEFAULT;
250 rc->rc_p1 = 0;
251 }
252 rc->rc_p1 *= 10;
253 rc->rc_p1 += c - '0';
254 }
255 } else {
256 /* Erase the cursor (if necessary) */
257 if (rc->rc_bits & FB_CURSOR)
258 rcons_cursor(rc);
259
260 /* Process the completed escape sequence */
261 rcons_doesc(rc, c);
262 rc->rc_bits &= ~FB_INESC;
263 }
264 }
265
266 /* Process a complete escape sequence */
267 void
268 rcons_doesc(rc, c)
269 register struct rconsole *rc;
270 register int c;
271 {
272
273 #ifdef notdef
274 /* XXX add escape sequence to enable visual (and audible) bell */
275 rc->rc_bits = FB_VISBELL;
276 #endif
277
278 switch (c) {
279
280 case '@':
281 /* Insert Character (ICH) */
282 rcons_insertchar(rc, rc->rc_p0);
283 break;
284
285 case 'A':
286 /* Cursor Up (CUU) */
287 *rc->rc_row -= rc->rc_p0;
288 if (*rc->rc_row < 0)
289 *rc->rc_row = 0;
290 break;
291
292 case 'B':
293 /* Cursor Down (CUD) */
294 *rc->rc_row += rc->rc_p0;
295 if (*rc->rc_row >= rc->rc_maxrow)
296 *rc->rc_row = rc->rc_maxrow - 1;
297 break;
298
299 case 'C':
300 /* Cursor Forward (CUF) */
301 *rc->rc_col += rc->rc_p0;
302 if (*rc->rc_col >= rc->rc_maxcol)
303 *rc->rc_col = rc->rc_maxcol - 1;
304 break;
305
306 case 'D':
307 /* Cursor Backward (CUB) */
308 *rc->rc_col -= rc->rc_p0;
309 if (*rc->rc_col < 0)
310 *rc->rc_col = 0;
311 break;
312
313 case 'E':
314 /* Cursor Next Line (CNL) */
315 *rc->rc_col = 0;
316 *rc->rc_row += rc->rc_p0;
317 if (*rc->rc_row >= rc->rc_maxrow)
318 *rc->rc_row = rc->rc_maxrow - 1;
319 break;
320
321 case 'f':
322 /* Horizontal And Vertical Position (HVP) */
323 case 'H':
324 /* Cursor Position (CUP) */
325 *rc->rc_col = rc->rc_p1 - 1;
326 if (*rc->rc_col < 0)
327 *rc->rc_col = 0;
328 else if (*rc->rc_col >= rc->rc_maxcol)
329 *rc->rc_col = rc->rc_maxcol - 1;
330
331 *rc->rc_row = rc->rc_p0 - 1;
332 if (*rc->rc_row < 0)
333 *rc->rc_row = 0;
334 else if (*rc->rc_row >= rc->rc_maxrow)
335 *rc->rc_row = rc->rc_maxrow - 1;
336 break;
337
338 case 'J':
339 /* Erase in Display (ED) */
340 rcons_clear2eop(rc);
341 break;
342
343 case 'K':
344 /* Erase in Line (EL) */
345 rcons_clear2eol(rc);
346 break;
347
348 case 'L':
349 /* Insert Line (IL) */
350 rcons_insertline(rc, rc->rc_p0);
351 break;
352
353 case 'M':
354 /* Delete Line (DL) */
355 rcons_delline(rc, rc->rc_p0);
356 break;
357
358 case 'P':
359 /* Delete Character (DCH) */
360 rcons_delchar(rc, rc->rc_p0);
361 break;
362
363 case 'm':
364 /* Select Graphic Rendition (SGR); */
365 /* (defaults to zero) */
366 if (rc->rc_bits & FB_P0_DEFAULT)
367 rc->rc_p0 = 0;
368 if (rc->rc_p0)
369 rc->rc_bits |= FB_STANDOUT;
370 else
371 rc->rc_bits &= ~FB_STANDOUT;
372 break;
373
374 case 'p':
375 /* Black On White (SUNBOW) */
376 rcons_invert(rc, 0);
377 break;
378
379 case 'q':
380 /* White On Black (SUNWOB) */
381 rcons_invert(rc, 1);
382 break;
383
384 case 'r':
385 /* Set scrolling (SUNSCRL) */
386 /* (defaults to zero) */
387 if (rc->rc_bits & FB_P0_DEFAULT)
388 rc->rc_p0 = 0;
389 /* XXX not implemented yet */
390 rc->rc_scroll = rc->rc_p0;
391 break;
392
393 case 's':
394 /* Reset terminal emulator (SUNRESET) */
395 rc->rc_bits &= ~FB_STANDOUT;
396 rc->rc_scroll = 0;
397 if (rc->rc_bits & FB_INVERT)
398 rcons_invert(rc, 0);
399 break;
400 }
401 }
402
403 /* Paint (or unpaint) the cursor */
404 void
405 rcons_cursor(rc)
406 register struct rconsole *rc;
407 {
408 register int x, y;
409
410 x = *rc->rc_col * rc->rc_font->width + rc->rc_xorigin;
411 y = *rc->rc_row * rc->rc_font->height + rc->rc_yorigin;
412 raster_op(rc->rc_sp, x, y,
413 #ifdef notdef
414 /* XXX This is the right way but too slow */
415 rc->rc_font->chars[(int)' '].r->width,
416 rc->rc_font->chars[(int)' '].r->height,
417 #else
418 rc->rc_font->width, rc->rc_font->height,
419 #endif
420 RAS_INVERT, (struct raster *) 0, 0, 0);
421 rc->rc_bits ^= FB_CURSOR;
422 }
423
424 /* Possibly change to SUNWOB or SUNBOW mode */
425 void
426 rcons_invert(rc, wob)
427 struct rconsole *rc;
428 int wob;
429 {
430 if (((rc->rc_bits & FB_INVERT) != 0) ^ wob) {
431 /* Invert the display */
432 raster_op(rc->rc_sp, 0, 0, rc->rc_sp->width, rc->rc_sp->height,
433 RAS_INVERT, (struct raster *) 0, 0, 0);
434
435 /* Swap things around */
436 rc->rc_ras_blank = RAS_NOT(rc->rc_ras_blank);
437 rc->rc_bits ^= FB_INVERT;
438 }
439 }
440
441 /* Clear to the end of the page */
442 void
443 rcons_clear2eop(rc)
444 register struct rconsole *rc;
445 {
446 register int y;
447
448 if (*rc->rc_col == 0 && *rc->rc_row == 0) {
449 /* Clear the entire frame buffer */
450 raster_op(rc->rc_sp, 0, 0,
451 rc->rc_sp->width, rc->rc_sp->height,
452 rc->rc_ras_blank, (struct raster *) 0, 0, 0);
453 } else {
454 /* Only clear what needs to be cleared */
455 rcons_clear2eol(rc);
456 y = (*rc->rc_row + 1) * rc->rc_font->height;
457
458 raster_op(rc->rc_sp, rc->rc_xorigin, rc->rc_yorigin + y,
459 rc->rc_emuwidth, rc->rc_emuheight - y,
460 rc->rc_ras_blank, (struct raster *) 0, 0, 0);
461 }
462 }
463
464 /* Clear to the end of the line */
465 void
466 rcons_clear2eol(rc)
467 register struct rconsole *rc;
468 {
469 register int x;
470
471 x = *rc->rc_col * rc->rc_font->width;
472
473 raster_op(rc->rc_sp,
474 rc->rc_xorigin + x,
475 *rc->rc_row * rc->rc_font->height + rc->rc_yorigin,
476 rc->rc_emuwidth - x, rc->rc_font->height,
477 rc->rc_ras_blank, (struct raster *) 0, 0, 0);
478 }
479
480 /* Scroll up one line */
481 void
482 rcons_scroll(rc, n)
483 register struct rconsole *rc;
484 register int n;
485 {
486 register int ydiv;
487
488 /* Can't scroll more than the whole screen */
489 if (n > rc->rc_maxrow)
490 n = rc->rc_maxrow;
491
492 /* Calculate new row */
493 *rc->rc_row -= n;
494 if (*rc->rc_row < 0)
495 *rc->rc_row = 0;
496
497 /* Calculate number of pixels to scroll */
498 ydiv = rc->rc_font->height * n;
499
500 raster_op(rc->rc_sp, rc->rc_xorigin, rc->rc_yorigin,
501 rc->rc_emuwidth, rc->rc_emuheight - ydiv,
502 RAS_SRC, rc->rc_sp, rc->rc_xorigin, ydiv + rc->rc_yorigin);
503
504 raster_op(rc->rc_sp,
505 rc->rc_xorigin, rc->rc_yorigin + rc->rc_emuheight - ydiv,
506 rc->rc_emuwidth, ydiv, rc->rc_ras_blank, (struct raster *) 0, 0, 0);
507 }
508
509 /* Delete characters */
510 void
511 rcons_delchar(rc, n)
512 register struct rconsole *rc;
513 register int n;
514 {
515 register int tox, fromx, y, width;
516
517 /* Can't delete more chars than there are */
518 if (n > rc->rc_maxcol - *rc->rc_col)
519 n = rc->rc_maxcol - *rc->rc_col;
520
521 fromx = (*rc->rc_col + n) * rc->rc_font->width;
522 tox = *rc->rc_col * rc->rc_font->width;
523 y = *rc->rc_row * rc->rc_font->height;
524 width = n * rc->rc_font->width;
525
526 raster_op(rc->rc_sp, tox + rc->rc_xorigin, y + rc->rc_yorigin,
527 rc->rc_emuwidth - fromx, rc->rc_font->height,
528 RAS_SRC, rc->rc_sp, fromx + rc->rc_xorigin, y + rc->rc_yorigin);
529
530 raster_op(rc->rc_sp,
531 rc->rc_emuwidth - width + rc->rc_xorigin, y + rc->rc_yorigin,
532 width, rc->rc_font->height,
533 rc->rc_ras_blank, (struct raster *) 0, 0, 0);
534 }
535
536 /* Delete a number of lines */
537 void
538 rcons_delline(rc, n)
539 register struct rconsole *rc;
540 register int n;
541 {
542 register int fromy, toy, height;
543
544 /* Can't delete more lines than there are */
545 if (n > rc->rc_maxrow - *rc->rc_row)
546 n = rc->rc_maxrow - *rc->rc_row;
547
548 fromy = (*rc->rc_row + n) * rc->rc_font->height;
549 toy = *rc->rc_row * rc->rc_font->height;
550 height = rc->rc_font->height * n;
551
552 raster_op(rc->rc_sp, rc->rc_xorigin, toy + rc->rc_yorigin,
553 rc->rc_emuwidth, rc->rc_emuheight - fromy, RAS_SRC,
554 rc->rc_sp, rc->rc_xorigin, fromy + rc->rc_yorigin);
555
556 raster_op(rc->rc_sp,
557 rc->rc_xorigin, rc->rc_emuheight - height + rc->rc_yorigin,
558 rc->rc_emuwidth, height,
559 rc->rc_ras_blank, (struct raster *) 0, 0, 0);
560 }
561
562 /* Insert some characters */
563 void
564 rcons_insertchar(rc, n)
565 register struct rconsole *rc;
566 register int n;
567 {
568 register int tox, fromx, y;
569
570 /* Can't insert more chars than can fit */
571 if (n > rc->rc_maxcol - *rc->rc_col)
572 n = rc->rc_maxcol - *rc->rc_col;
573
574 tox = (*rc->rc_col + n) * rc->rc_font->width;
575 fromx = *rc->rc_col * rc->rc_font->width;
576 y = *rc->rc_row * rc->rc_font->height;
577
578 raster_op(rc->rc_sp, tox + rc->rc_xorigin, y + rc->rc_yorigin,
579 rc->rc_emuwidth - tox, rc->rc_font->height,
580 RAS_SRC, rc->rc_sp, fromx + rc->rc_xorigin, y + rc->rc_yorigin);
581
582 raster_op(rc->rc_sp, fromx + rc->rc_xorigin, y + rc->rc_yorigin,
583 rc->rc_font->width * n, rc->rc_font->height,
584 rc->rc_ras_blank, (struct raster *) 0, 0, 0);
585 }
586
587 /* Insert some lines */
588 void
589 rcons_insertline(rc, n)
590 register struct rconsole *rc;
591 register int n;
592 {
593 register int fromy, toy;
594
595 /* Can't insert more lines than can fit */
596 if (n > rc->rc_maxrow - *rc->rc_row)
597 n = rc->rc_maxrow - *rc->rc_row;
598
599 toy = (*rc->rc_row + n) * rc->rc_font->height;
600 fromy = *rc->rc_row * rc->rc_font->height;
601
602 raster_op(rc->rc_sp, rc->rc_xorigin, toy + rc->rc_yorigin,
603 rc->rc_emuwidth, rc->rc_emuheight - toy,
604 RAS_SRC, rc->rc_sp, rc->rc_xorigin, fromy + rc->rc_yorigin);
605
606 raster_op(rc->rc_sp, rc->rc_xorigin, fromy + rc->rc_yorigin,
607 rc->rc_emuwidth, rc->rc_font->height * n,
608 rc->rc_ras_blank, (struct raster *) 0, 0, 0);
609 }
610