xref: /netbsd-src/sys/arch/amiga/dev/ite_cc.c (revision 30cef4176aa67ca1212781d850e3a324bfc9b4ef)
1 /*	$NetBSD: ite_cc.c,v 1.29 2000/06/21 21:28:39 is Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 Christian E. Hopps
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Christian E. Hopps.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "opt_amigaccgrf.h"
34 
35 #include "grfcc.h"
36 #if NGRFCC > 0
37 
38 #include <sys/param.h>
39 #include <sys/conf.h>
40 #include <sys/proc.h>
41 #include <sys/device.h>
42 #include <sys/ioctl.h>
43 #include <sys/tty.h>
44 #include <sys/systm.h>
45 #include <sys/queue.h>
46 #include <sys/termios.h>
47 #include <dev/cons.h>
48 #include <machine/cpu.h>
49 #include <amiga/dev/itevar.h>
50 #include <amiga/dev/iteioctl.h>
51 #include <amiga/amiga/cc.h>
52 #include <amiga/amiga/device.h>
53 #include <amiga/dev/grfabs_reg.h>
54 #include <amiga/dev/grfioctl.h>
55 #include <amiga/dev/grfvar.h>
56 #include <amiga/dev/grf_ccreg.h>
57 #include <amiga/dev/viewioctl.h>
58 #include <amiga/dev/viewvar.h>
59 
60 #ifndef KFONT_CUSTOM
61 #ifdef KFONT_8X11
62 #define kernel_font_width       kernel_font_width_8x11
63 #define kernel_font_height      kernel_font_height_8x11
64 #define kernel_font_baseline    kernel_font_baseline_8x11
65 #define kernel_font_boldsmear   kernel_font_boldsmear_8x11
66 #define kernel_font_lo  kernel_font_lo_8x11
67 #define kernel_font_hi  kernel_font_hi_8x11
68 #define kernel_font     kernel_font_8x11
69 #define kernel_cursor   kernel_cursor_8x11
70 #else
71 #define kernel_font_width       kernel_font_width_8x8
72 #define kernel_font_height      kernel_font_height_8x8
73 #define kernel_font_baseline    kernel_font_baseline_8x8
74 #define kernel_font_boldsmear   kernel_font_boldsmear_8x8
75 #define kernel_font_lo  kernel_font_lo_8x8
76 #define kernel_font_hi  kernel_font_hi_8x8
77 #define kernel_font     kernel_font_8x8
78 #define kernel_cursor   kernel_cursor_8x8
79 #endif
80 #endif
81 
82 extern u_char kernel_font_width, kernel_font_height, kernel_font_baseline;
83 extern short  kernel_font_boldsmear;
84 extern u_char kernel_font_lo, kernel_font_hi;
85 extern u_char kernel_font[], kernel_cursor[];
86 
87 
88 #if !defined(USE_C_BFOPS) && !defined(__m68k__)
89 #define USE_C_BFOPS
90 #endif
91 
92 #if !defined(USE_C_BFOPS)
93 #define BFEXT(v,p,o,w)	asm("bfextu %1@{%2:%3},%0" : "=d" (v) : \
94 		"a"(p), "d"(o), "d"(w))
95 #define BFINS(v,p,o,w)	asm("bfins %0,%1@{%2:%3}" : /* no output */ : \
96 		"d"(v), "a"(p), "d"(o), "d"(w))
97 #define BFCLR(p,o,w)	asm("bfclr %0@{%1:%2}" : /* no output */ : \
98 		"a"(p), "d"(o), "d"(w))
99 #define BFCHG(p,o,w)	asm("bfchg %0@{%1:%2}" : /* no output */ : \
100 		"a"(p), "d"(o), "d"(w))
101 #define BFSET(p,o,w)	asm("bfset %0@{%1:%2}" : /* no output */ : \
102 		"a"(p), "d"(o), "d"(w))
103 #else
104 #define BFEXT(v,p,o,w)	do {v = ((u_int8_t *)(p))[(o)>>3];} while (0)
105 #define BFINS(v,p,o,w)	do {((u_int8_t *)(p))[(o)>>3] = (v);} while (0)
106 #define BFCLR(p,o,w)	BFINS(0x00,p,o,w)
107 #define BFSET(p,o,w)	BFINS(0xff,p,o,w)
108 #define BFCHG(p,o,w)	do {((u_int8_t *)(p))[(o)>>3] ^= 0xff;} while (0)
109 #endif
110 
111 /*
112  * This is what ip->priv points to;
113  * it contains local variables for custom-chip ites.
114  */
115 struct ite_priv {
116 	view_t *view;		/* the view for this ite. */
117 	u_char **row_ptr;	/* array of pointers into the bitmap  */
118 	u_long row_bytes;
119 	u_long cursor_opt;
120 	u_int  *column_offset;	/* array of offsets for columns */
121 	u_int  row_offset;	/* the row offset */
122 	u_short width;		/* the bitmap width */
123 	u_short underline;	/* where the underline goes */
124 	u_short ft_x;		/* the font width */
125 	u_short ft_y;		/* the font height */
126 	u_char *font_cell[256];	/* the font pointer */
127 };
128 typedef struct ite_priv ipriv_t;
129 
130 void view_deinit __P((struct ite_softc *));
131 void view_init __P((struct ite_softc *));
132 
133 static void putc8 __P((struct ite_softc *, int, int, int, int));
134 static void clear8 __P((struct ite_softc *, int, int, int, int));
135 static void scroll8 __P((struct ite_softc *, int, int, int, int));
136 static void cursor32 __P((struct ite_softc *, int));
137 static void scrollbmap __P((bmap_t *, u_short, u_short, u_short, u_short,
138     short, short, u_char));
139 
140 /* patchable */
141 int ite_default_x = 0;		/* def leftedge offset */
142 int ite_default_y = 0;		/* def topedge offset */
143 int ite_default_width = 640;	/* def width */
144 int ite_default_depth = 2;	/* def depth */
145 #if defined (GRF_NTSC)
146 int ite_default_height = 400;	/* def NTSC height */
147 #elif defined (GRF_PAL)
148 int ite_default_height = 512;	/* def PAL height */
149 #else
150 int ite_default_height = 400;	/* def NON-PAL/NTSC height (?) */
151 #endif
152 
153 int ite_newsize __P((struct ite_softc *, struct itewinsize *));
154 static void putc_nm __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
155 			u_int, u_int));
156 static void putc_in __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
157 			u_int, u_int));
158 static void putc_ul __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
159 			u_int, u_int));
160 static void putc_ul_in __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
161 			u_int, u_int));
162 static void putc_bd __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
163 			u_int, u_int));
164 static void putc_bd_in __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
165 			u_int, u_int));
166 static void putc_bd_ul __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
167 			u_int, u_int));
168 static void putc_bd_ul_in __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
169 			u_int, u_int));
170 
171 /*
172  * called from grf_cc to return console priority
173  */
174 int
175 grfcc_cnprobe()
176 {
177 	return(CN_INTERNAL);
178 }
179 
180 /*
181  * called from grf_cc to init ite portion of
182  * grf_softc struct
183  */
184 void
185 grfcc_iteinit(gp)
186 	struct grf_softc *gp;
187 {
188 	gp->g_itecursor = cursor32;
189 	gp->g_iteputc = putc8;
190 	gp->g_iteclear = clear8;
191 	gp->g_itescroll = scroll8;
192 	gp->g_iteinit = view_init;
193 	gp->g_itedeinit = view_deinit;
194 }
195 
196 int
197 ite_newsize(ip, winsz)
198 	struct ite_softc *ip;
199 	struct itewinsize *winsz;
200 {
201 	extern struct view_softc views[];
202 	struct view_size vs;
203 	ipriv_t *cci = ip->priv;
204 	u_long i;
205 	int error;
206 
207 	vs.x = winsz->x;
208 	vs.y = winsz->y;
209 	vs.width = winsz->width;
210 	vs.height = winsz->height;
211 	vs.depth = winsz->depth;
212 	error = viewioctl(0, VIOCSSIZE, (caddr_t)&vs, -1, NULL); /* XXX type of vs ? */
213 
214 	/*
215 	 * Reinitialize our structs
216 	 */
217 	cci->view = views[0].view;
218 
219 	ip->cols = cci->view->display.width / ip->ftwidth;
220 	ip->rows = cci->view->display.height / ip->ftheight;
221 
222 	/*
223 	 * save new values so that future opens use them
224 	 * this may not be correct when we implement Virtual Consoles
225 	 */
226 	ite_default_height = cci->view->display.height;
227 	ite_default_width = cci->view->display.width;
228 	ite_default_x = cci->view->display.x;
229 	ite_default_y = cci->view->display.y;
230 	ite_default_depth = cci->view->bitmap->depth;
231 
232 	if (cci->row_ptr)
233 		free_chipmem(cci->row_ptr);
234 	if (cci->column_offset)
235 		free_chipmem(cci->column_offset);
236 
237 	cci->row_ptr = alloc_chipmem(sizeof(u_char *) * ip->rows);
238 	cci->column_offset = alloc_chipmem(sizeof(u_int) * ip->cols);
239 
240 	if (cci->row_ptr == NULL || cci->column_offset == NULL)
241 		panic("no chipmem for itecc data");
242 
243 
244 	cci->width = cci->view->bitmap->bytes_per_row << 3;
245 	cci->underline = ip->ftbaseline + 1;
246 	cci->row_offset = cci->view->bitmap->bytes_per_row
247 	    + cci->view->bitmap->row_mod;
248 	cci->ft_x = ip->ftwidth;
249 	cci->ft_y = ip->ftheight;
250 
251 	cci->row_bytes = cci->row_offset * ip->ftheight;
252 
253 	cci->row_ptr[0] = VDISPLAY_LINE (cci->view, 0, 0);
254 	for (i = 1; i < ip->rows; i++)
255 		cci->row_ptr[i] = cci->row_ptr[i-1] + cci->row_bytes;
256 
257 	/* initialize the column offsets */
258 	cci->column_offset[0] = 0;
259 	for (i = 1; i < ip->cols; i++)
260 		cci->column_offset[i] = cci->column_offset[i - 1] + cci->ft_x;
261 
262 	/* initialize the font cell pointers */
263 	cci->font_cell[ip->font_lo] = ip->font;
264 	for (i=ip->font_lo+1; i<=ip->font_hi; i++)
265 		cci->font_cell[i] = cci->font_cell[i-1] + ip->ftheight;
266 
267 	return (error);
268 }
269 
270 void
271 view_init(ip)
272 	register struct ite_softc *ip;
273 {
274 	struct itewinsize wsz;
275 	ipriv_t *cci;
276 
277 	cci = ip->priv;
278 
279 	if (cci)
280 		return;
281 
282 	ip->font     = kernel_font;
283 	ip->font_lo  = kernel_font_lo;
284 	ip->font_hi  = kernel_font_hi;
285 	ip->ftwidth  = kernel_font_width;
286 	ip->ftheight = kernel_font_height;
287 	ip->ftbaseline = kernel_font_baseline;
288 	ip->ftboldsmear = kernel_font_boldsmear;
289 
290 	/* Find the correct set of rendering routines for this font.  */
291 	if (ip->ftwidth > 8)
292 		panic("kernel font size not supported");
293 	cci = alloc_chipmem(sizeof (*cci));
294 	if (cci == NULL)
295 		panic("no memory for console device.");
296 
297 	ip->priv = cci;
298 	cci->cursor_opt = 0;
299 	cci->view = NULL;
300 	cci->row_ptr = NULL;
301 	cci->column_offset = NULL;
302 
303 	wsz.x = ite_default_x;
304 	wsz.y = ite_default_y;
305 	wsz.width = ite_default_width;
306 	wsz.height = ite_default_height;
307 	wsz.depth = ite_default_depth;
308 
309 	ite_newsize (ip, &wsz);
310 	cc_mode(ip->grf, GM_GRFON, NULL, 0, 0);
311 }
312 
313 int
314 ite_grf_ioctl (ip, cmd, addr, flag, p)
315 	struct ite_softc *ip;
316 	u_long cmd;
317 	caddr_t addr;
318 	int flag;
319 	struct proc *p;
320 {
321 	struct winsize ws;
322 	struct itewinsize *is;
323 	ipriv_t *cci;
324 	int error;
325 
326 	cci = ip->priv;
327 	error = 0;
328 
329 	switch (cmd) {
330 	case ITEIOCGWINSZ:
331 		is = (struct itewinsize *)addr;
332 		is->x = cci->view->display.x;
333 		is->y = cci->view->display.y;
334 		is->width = cci->view->display.width;
335 		is->height = cci->view->display.height;
336 		is->depth = cci->view->bitmap->depth;
337 		break;
338 	case ITEIOCSWINSZ:
339 		is = (struct itewinsize *)addr;
340 
341 		if (ite_newsize(ip, is))
342 			error = ENOMEM;
343 		else {
344 			ws.ws_row = ip->rows;
345 			ws.ws_col = ip->cols;
346 			ws.ws_xpixel = cci->view->display.width;
347 			ws.ws_ypixel = cci->view->display.height;
348 			ite_reset (ip);
349 			/*
350 			 * XXX tell tty about the change
351 			 * XXX this is messy, but works
352 			 */
353 			iteioctl(0, TIOCSWINSZ, (caddr_t)&ws, 0, p);
354 		}
355 		break;
356 	case ITEIOCDSPWIN:
357 		cc_mode(ip->grf, GM_GRFON, NULL, 0, 0);
358 		break;
359 	case ITEIOCREMWIN:
360 		cc_mode(ip->grf, GM_GRFOFF, NULL, 0, 0);
361 		break;
362 	case VIOCSCMAP:
363 	case VIOCGCMAP:
364 		/*
365 		 * XXX needs to be fixed when multiple console implemented
366 		 * XXX watchout for that -1 its not really the kernel talking
367 		 * XXX these two commands don't use the proc pointer though
368 		 */
369 		error = viewioctl(0, cmd, addr, -1, p);
370 		break;
371 	default:
372 		error = -1;
373 		break;
374 	}
375 	return (error);
376 }
377 
378 void
379 view_deinit(ip)
380 	struct ite_softc *ip;
381 {
382 	ip->flags &= ~ITE_INITED;
383 }
384 
385 /*** (M<8)-by-N routines ***/
386 
387 static void
388 cursor32(struct ite_softc *ip, int flag)
389 {
390 	int cend, ofs, h, cstart, dr_plane;
391 	u_char *pl;
392 	ipriv_t *cci;
393 	bmap_t *bm;
394 	view_t *v;
395 
396 	cci = ip->priv;
397 	v = cci->view;
398    	bm = v->bitmap;
399 	dr_plane = (bm->depth > 1 ? bm->depth-1 : 0);
400 
401 	if (flag == END_CURSOROPT)
402 		cci->cursor_opt--;
403 	else if (flag == START_CURSOROPT) {
404 		if (!cci->cursor_opt)
405 			cursor32 (ip, ERASE_CURSOR);
406 		cci->cursor_opt++;
407 		return;		  /* if we are already opted. */
408 	}
409 
410 	if (cci->cursor_opt)
411 		return;		  /* if we are still nested. */
412 				  /* else we draw the cursor. */
413 	cstart = 0;
414 	cend = ip->ftheight-1;
415 	pl = VDISPLAY_LINE(v, dr_plane, (ip->cursory * ip->ftheight + cstart));
416 	ofs = (ip->cursorx * ip->ftwidth);
417 
418 	if (flag != DRAW_CURSOR && flag != END_CURSOROPT) {
419 		/*
420 		 * erase the cursor
421 		 */
422 		int h;
423 
424 		if (dr_plane) {
425 			for (h = cend; h >= 0; h--) {
426 				BFCLR(pl, ofs, ip->ftwidth);
427 				pl += cci->row_offset;
428 			}
429 		} else {
430 			for (h = cend; h >= 0; h--) {
431 				BFCHG(pl, ofs, ip->ftwidth);
432 				pl += cci->row_offset;
433 			}
434 		}
435 	}
436 
437 	if (flag != DRAW_CURSOR && flag != MOVE_CURSOR &&
438 	    flag != END_CURSOROPT)
439 		return;
440 
441 	/*
442 	 * draw the cursor
443 	 */
444 
445 	ip->cursorx = min(ip->curx, ip->cols-1);
446 	ip->cursory = ip->cury;
447 	cstart = 0;
448 	cend = ip->ftheight-1;
449 	pl = VDISPLAY_LINE(v, dr_plane, ip->cursory * ip->ftheight + cstart);
450 	ofs = ip->cursorx * ip->ftwidth;
451 
452 	if (dr_plane) {
453 		for (h = cend; h >= 0; h--) {
454 			BFSET(pl, ofs, ip->ftwidth);
455 			pl += cci->row_offset;
456 		}
457 	} else {
458 		for (h = cend; h >= 0; h--) {
459 			BFCHG(pl, ofs, ip->ftwidth);
460 			pl += cci->row_offset;
461 		}
462 	}
463 }
464 
465 
466 static inline
467 int expbits (int data)
468 {
469 	int i, nd = 0;
470 
471 	if (data & 1)
472 		nd |= 0x02;
473 	for (i=1; i < 32; i++) {
474 		if (data & (1 << i))
475 			nd |= 0x5 << (i-1);
476 	}
477 	nd &= ~data;
478 	return(~nd);
479 }
480 
481 
482 /* Notes: optimizations given the kernel_font_(width|height) #define'd.
483  *        the dbra loops could be elminated and unrolled using height,
484  *        the :width in the bfxxx instruction could be made immediate instead
485  *        of a data register as it now is.
486  *        the underline could be added when the loop is unrolled
487  *
488  *        It would look like hell but be very fast.*/
489 
490 static void
491 putc_nm (cci,p,f,co,ro,fw,fh)
492     register ipriv_t *cci;
493     register u_char  *p;
494     register u_char  *f;
495     register u_int    co;
496     register u_int    ro;
497     register u_int    fw;
498     register u_int    fh;
499 {
500     while (fh--) {
501 	BFINS(*f++, p, co, fw);
502 	p += ro;
503     }
504 }
505 
506 static void
507 putc_in (cci,p,f,co,ro,fw,fh)
508     register ipriv_t *cci;
509     register u_char  *p;
510     register u_char  *f;
511     register u_int    co;
512     register u_int    ro;
513     register u_int    fw;
514     register u_int    fh;
515 {
516     while (fh--) {
517 	BFINS(~(*f++),p,co,fw);
518 	p += ro;
519     }
520 }
521 
522 
523 static void
524 putc_ul (cci,p,f,co,ro,fw,fh)
525     register ipriv_t *cci;
526     register u_char  *p;
527     register u_char  *f;
528     register u_int    co;
529     register u_int    ro;
530     register u_int    fw;
531     register u_int    fh;
532 {
533     int underline = cci->underline;
534     while (underline--) {
535 	BFINS(*f++,p,co,fw);
536 	p += ro;
537     }
538 
539     BFINS(expbits(*f++),p,co,fw);
540     p += ro;
541 
542     underline = fh - cci->underline - 1;
543     while (underline--) {
544 	BFINS(*f++,p,co,fw);
545 	p += ro;
546     }
547 }
548 
549 
550 static void
551 putc_ul_in (cci,p,f,co,ro,fw,fh)
552     register ipriv_t *cci;
553     register u_char  *p;
554     register u_char  *f;
555     register u_int    co;
556     register u_int    ro;
557     register u_int    fw;
558     register u_int    fh;
559 {
560     int underline = cci->underline;
561     while (underline--) {
562 	BFINS(~(*f++),p,co,fw);
563 	p += ro;
564     }
565 
566     BFINS(~expbits(*f++),p,co,fw);
567     p += ro;
568 
569     underline = fh - cci->underline - 1;
570     while (underline--) {
571 	BFINS(~(*f++),p,co,fw);
572 	p += ro;
573     }
574 }
575 
576 /* bold */
577 static void
578 putc_bd (cci,p,f,co,ro,fw,fh)
579     register ipriv_t *cci;
580     register u_char  *p;
581     register u_char  *f;
582     register u_int    co;
583     register u_int    ro;
584     register u_int    fw;
585     register u_int    fh;
586 {
587     u_short ch;
588 
589     while (fh--) {
590 	ch = *f++;
591 	ch |= ch >> 1;
592 	BFINS(ch,p,co,fw);
593 	p += ro;
594     }
595 }
596 
597 static void
598 putc_bd_in (cci,p,f,co,ro,fw,fh)
599     register ipriv_t *cci;
600     register u_char  *p;
601     register u_char  *f;
602     register u_int    co;
603     register u_int    ro;
604     register u_int    fw;
605     register u_int    fh;
606 {
607     u_short ch;
608 
609     while (fh--) {
610 	ch = *f++;
611 	ch |= ch >> 1;
612 	BFINS(~ch,p,co,fw);
613 	p += ro;
614     }
615 }
616 
617 
618 static void
619 putc_bd_ul (cci,p,f,co,ro,fw,fh)
620     register ipriv_t *cci;
621     register u_char  *p;
622     register u_char  *f;
623     register u_int    co;
624     register u_int    ro;
625     register u_int    fw;
626     register u_int    fh;
627 {
628     int underline = cci->underline;
629     u_short ch;
630 
631     while (underline--) {
632 	ch = *f++;
633 	ch |= ch >> 1;
634 	BFINS(ch,p,co,fw);
635 	p += ro;
636     }
637 
638     ch = *f++;
639     ch |= ch >> 1;
640     BFINS(expbits(ch),p,co,fw);
641     p += ro;
642 
643     underline = fh - cci->underline - 1;
644     while (underline--) {
645 	ch = *f++;
646 	ch |= ch >> 1;
647 	BFINS(ch,p,co,fw);
648 	p += ro;
649     }
650 }
651 
652 
653 static void
654 putc_bd_ul_in (cci,p,f,co,ro,fw,fh)
655     register ipriv_t *cci;
656     register u_char  *p;
657     register u_char  *f;
658     register u_int    co;
659     register u_int    ro;
660     register u_int    fw;
661     register u_int    fh;
662 {
663     int underline = cci->underline;
664     u_short ch;
665 
666     while (underline--) {
667 	ch = *f++;
668 	ch |= ch >> 1;
669 	BFINS(~ch,p,co,fw);
670 	p += ro;
671     }
672 
673     ch = *f++;
674     ch |= ch >> 1;
675     BFINS(~expbits(ch),p,co,fw);
676     p += ro;
677 
678     underline = fh - cci->underline - 1;
679     while (underline--) {
680 	ch = *f++;
681 	ch |= ch >> 1;
682 	BFINS(~ch,p,co,fw);
683 	p += ro;
684     }
685 }
686 
687 
688 typedef void cc_putc_func __P((ipriv_t *, u_char *, u_char *, u_int, u_int,
689 			u_int, u_int));
690 
691 cc_putc_func *put_func[ATTR_ALL+1] = {
692     putc_nm,
693     putc_in,
694     putc_ul,
695     putc_ul_in,
696     putc_bd,
697     putc_bd_in,
698     putc_bd_ul,
699     putc_bd_ul_in,
700 /* no support for blink */
701     putc_nm,
702     putc_in,
703     putc_ul,
704     putc_ul_in,
705     putc_bd,
706     putc_bd_in,
707     putc_bd_ul,
708     putc_bd_ul_in
709 };
710 
711 
712 /* FIX: shouldn't this advance the cursor even if the character to
713         be output is not available in the font? -ch */
714 
715 static void
716 putc8(ip, c, dy, dx, mode)
717 	struct ite_softc *ip;
718 	int c, dy, dx, mode;
719 {
720 	ipriv_t *cci = (ipriv_t *) ip->priv;
721 	/*
722 	 * if character is higher than font has glyphs, substitute
723 	 * highest glyph.
724 	 */
725 	c = (u_char)c;
726 	if (c < ip->font_lo || c > ip->font_hi)
727 		c = ip->font_hi;
728 	put_func[mode](cci, cci->row_ptr[dy], cci->font_cell[c],
729 	    cci->column_offset[dx], cci->row_offset, cci->ft_x, cci->ft_y);
730 }
731 
732 static void
733 clear8(struct ite_softc *ip, int sy, int sx, int h, int w)
734 {
735   ipriv_t *cci = (ipriv_t *) ip->priv;
736   bmap_t *bm = cci->view->bitmap;
737 
738   if ((sx == 0) && (w == ip->cols))
739     {
740       /* common case: clearing whole lines */
741       while (h--)
742 	{
743 	  int i;
744 	  u_char *ptr = cci->row_ptr[sy];
745 	  for (i=0; i < ip->ftheight; i++) {
746             bzero(ptr, bm->bytes_per_row);
747             ptr += bm->bytes_per_row + bm->row_mod;			/* don't get any smart
748                                                    ideas, becuase this is for
749                                                    interleaved bitmaps */
750           }
751 	  sy++;
752 	}
753     }
754   else
755     {
756       /* clearing only part of a line */
757       /* XXX could be optimized MUCH better, but is it worth the trouble? */
758       while (h--)
759 	{
760 	  u_char *pl = cci->row_ptr[sy];
761           int ofs = sx * ip->ftwidth;
762 	  int i, j;
763 	  for (i = w-1; i >= 0; i--)
764 	    {
765 	      u_char *ppl = pl;
766               for (j = ip->ftheight-1; j >= 0; j--)
767 	        {
768 		  BFCLR(ppl, ofs, ip->ftwidth);
769 	          ppl += bm->row_mod + bm->bytes_per_row;
770 	        }
771 	      ofs += ip->ftwidth;
772 	    }
773 	  sy++;
774 	}
775     }
776 }
777 
778 /* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT.  */
779 static void
780 scroll8(ip, sy, sx, count, dir)
781         register struct ite_softc *ip;
782         register int sy;
783         int dir, sx, count;
784 {
785   bmap_t *bm = ((ipriv_t *)ip->priv)->view->bitmap;
786   u_char *pl = ((ipriv_t *)ip->priv)->row_ptr[sy];
787 
788   if (dir == SCROLL_UP)
789     {
790       int dy = sy - count;
791 
792       /*FIX: add scroll bitmap call */
793         cursor32(ip, ERASE_CURSOR);
794 	scrollbmap (bm, 0, dy*ip->ftheight,
795 		       bm->bytes_per_row >> 3, (ip->bottom_margin-dy+1)*ip->ftheight,
796 		       0, -(count*ip->ftheight), 0x1);
797 /*	if (ip->cursory <= bot || ip->cursory >= dy) {
798 	    ip->cursory -= count;
799 	} */
800     }
801   else if (dir == SCROLL_DOWN)
802     {
803 
804       /* FIX: add scroll bitmap call */
805         cursor32(ip, ERASE_CURSOR);
806 	scrollbmap (bm, 0, sy*ip->ftheight,
807 		       bm->bytes_per_row >> 3, (ip->bottom_margin-sy+1)*ip->ftheight,
808 		       0, count*ip->ftheight, 0x1);
809 /*	if (ip->cursory <= bot || ip->cursory >= sy) {
810 	    ip->cursory += count;
811 	} */
812     }
813   else if (dir == SCROLL_RIGHT)
814     {
815       int sofs = (ip->cols - count) * ip->ftwidth;
816       int dofs = (ip->cols) * ip->ftwidth;
817       int i, j;
818 
819       cursor32(ip, ERASE_CURSOR);
820       for (j = ip->ftheight-1; j >= 0; j--)
821 	{
822 	  int sofs2 = sofs, dofs2 = dofs;
823 	  for (i = (ip->cols - (sx + count))-1; i >= 0; i--)
824 	    {
825 	      int t;
826 	      sofs2 -= ip->ftwidth;
827 	      dofs2 -= ip->ftwidth;
828 	      BFEXT(t, pl, sofs2, ip->ftwidth);
829 	      BFINS(t, pl, dofs2, ip->ftwidth);
830 	    }
831 	  pl += bm->row_mod + bm->bytes_per_row;
832 	}
833     }
834   else /* SCROLL_LEFT */
835     {
836       int sofs = (sx) * ip->ftwidth;
837       int dofs = (sx - count) * ip->ftwidth;
838       int i, j;
839 
840       cursor32(ip, ERASE_CURSOR);
841       for (j = ip->ftheight-1; j >= 0; j--)
842 	{
843 	  int sofs2 = sofs, dofs2 = dofs;
844 	  for (i = (ip->cols - sx)-1; i >= 0; i--)
845 	    {
846 	      int t;
847 	      BFEXT(t, pl, sofs2, ip->ftwidth);
848 	      BFINS(t, pl, dofs2, ip->ftwidth);
849 	      sofs2 += ip->ftwidth;
850 	      dofs2 += ip->ftwidth;
851 	    }
852 	  pl += bm->row_mod + bm->bytes_per_row;
853 	}
854     }
855 }
856 
857 void
858 scrollbmap (bmap_t *bm, u_short x, u_short y, u_short width, u_short height, short dx, short dy, u_char mask)
859 {
860     u_short depth = bm->depth;
861     u_short lwpr = bm->bytes_per_row >> 2;
862     if (dx) {
863     	/* FIX: */ panic ("delta x not supported in scroll bitmap yet.");
864     }
865     if (bm->flags & BMF_INTERLEAVED) {
866 	height *= depth;
867 	depth = 1;
868     }
869     if (dy == 0) {
870         return;
871     }
872     if (dy > 0) {
873     	int i;
874     	for (i=0; i < depth && mask; i++, mask >>= 1) {
875     	    if (0x1 & mask) {
876 	    	u_long *pl = (u_long *)bm->plane[i];
877 		u_long *src_y = pl + (lwpr*y);
878 		u_long *dest_y = pl + (lwpr*(y+dy));
879 		u_long count = lwpr*(height-dy);
880 		u_long *clr_y = src_y;
881 		u_long clr_count = dest_y - src_y;
882 		u_long bc, cbc;
883 
884 		src_y += count - 1;
885 		dest_y += count - 1;
886 
887 		bc = count >> 4;
888 		count &= 0xf;
889 
890 		while (bc--) {
891 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
892 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
893 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
894 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
895 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
896 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
897 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
898 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
899 		}
900 		while (count--) {
901 		    *dest_y-- = *src_y--;
902 		}
903 
904 		cbc = clr_count >> 4;
905 		clr_count &= 0xf;
906 
907 		while (cbc--) {
908 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
909 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
910 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
911 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
912 		}
913 		while (clr_count--) {
914 		    *clr_y++ = 0;
915 		}
916     	    }
917 	}
918     } else if (dy < 0) {
919     	int i;
920     	for (i=0; i < depth && mask; i++, mask >>= 1) {
921     	    if (0x1 & mask) {
922     		u_long *pl = (u_long *)bm->plane[i];
923     		u_long *src_y = pl + (lwpr*(y-dy));
924     		u_long *dest_y = pl + (lwpr*y);
925 		long count = lwpr*(height + dy);
926 		u_long *clr_y = dest_y + count;
927 		u_long clr_count = src_y - dest_y;
928 		u_long bc, cbc;
929 
930 		bc = count >> 4;
931 		count &= 0xf;
932 
933 		while (bc--) {
934 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
935 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
936 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
937 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
938 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
939 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
940 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
941 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
942 		}
943 		while (count--) {
944 		    *dest_y++ = *src_y++;
945 		}
946 
947 		cbc = clr_count >> 4;
948 		clr_count &= 0xf;
949 
950 		while (cbc--) {
951 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
952 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
953 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
954 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
955 		}
956 		while (clr_count--) {
957 		    *clr_y++ = 0;
958 		}
959 	    }
960 	}
961     }
962 }
963 
964 #endif /* NGRFCC */
965