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