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