xref: /netbsd-src/sys/arch/amiga/dev/ite.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * from: Utah $Hdr: ite.c 1.1 90/07/09$
39  *
40  *	from: @(#)ite.c	7.6 (Berkeley) 5/16/91
41  *	$Id: ite.c,v 1.1.1.1 1993/07/05 19:19:44 mw Exp $
42  */
43 
44 /*
45  * Bit-mapped display terminal emulator machine independent code.
46  * This is a very rudimentary.  Much more can be abstracted out of
47  * the hardware dependent routines.
48  */
49 #include "ite.h"
50 #if NITE > 0
51 
52 #include "grf.h"
53 
54 #undef NITE
55 #define NITE	NGRF
56 
57 #include "param.h"
58 #include "conf.h"
59 #include "proc.h"
60 #include "ioctl.h"
61 #include "tty.h"
62 #include "systm.h"
63 #include "malloc.h"
64 
65 #include "itevar.h"
66 #include "iteioctl.h"
67 #include "kbdmap.h"
68 
69 #include "machine/cpu.h"
70 
71 #ifdef __STDC__
72 /* automatically generated, as you might guess:-) */
73 
74 struct consdev;
75 struct itesw;
76 
77 extern int iteon (dev_t dev, int flag);
78 extern int iteinit (dev_t dev);
79 extern int iteoff (dev_t dev, int flag);
80 extern int iteopen (dev_t dev, int mode, int devtype, struct proc *p);
81 extern int iteclose (dev_t dev, int flag, int mode, struct proc *p);
82 extern int iteread (dev_t dev, struct uio *uio, int flag);
83 extern int itewrite (dev_t dev, struct uio *uio, int flag);
84 extern int iteioctl (dev_t dev, int cmd, caddr_t addr, int flag);
85 extern int itestart (register struct tty *tp);
86 extern int itefilter (register u_char c, enum caller caller);
87 extern int iteputchar (register int c, dev_t dev);
88 extern int itecheckwrap (register struct ite_softc *ip, register struct itesw *sp);
89 extern int itecnprobe (struct consdev *cp);
90 extern int itecninit (struct consdev *cp);
91 extern int itecngetc (dev_t dev);
92 extern int itecnputc (dev_t dev, int c);
93 static void repeat_handler (int a0, int a1);
94 static void ite_dnchar (struct ite_softc *ip, struct itesw *sp, int n);
95 static void ite_inchar (struct ite_softc *ip, struct itesw *sp, int n);
96 static void ite_clrtoeol (struct ite_softc *ip, struct itesw *sp, int y, int x);
97 static void ite_clrtobol (struct ite_softc *ip, struct itesw *sp, int y, int x);
98 static void ite_clrline (struct ite_softc *ip, struct itesw *sp, int y, int x);
99 static void ite_clrtoeos (struct ite_softc *ip, struct itesw *sp);
100 static void ite_clrtobos (struct ite_softc *ip, struct itesw *sp);
101 static void ite_clrscreen (struct ite_softc *ip, struct itesw *sp);
102 static void ite_dnline (struct ite_softc *ip, struct itesw *sp, int n);
103 static void ite_inline (struct ite_softc *ip, struct itesw *sp, int n);
104 static void ite_lf (struct ite_softc *ip, struct itesw *sp);
105 static void ite_crlf (struct ite_softc *ip, struct itesw *sp);
106 static void ite_cr (struct ite_softc *ip, struct itesw *sp);
107 static void ite_rlf (struct ite_softc *ip, struct itesw *sp);
108 static int atoi (const char *cp);
109 static char *index (const char *cp, char ch);
110 static int ite_argnum (struct ite_softc *ip);
111 static int ite_zargnum (struct ite_softc *ip);
112 static void ite_sendstr (struct ite_softc *ip, char *str);
113 static int strncmp (const char *a, const char *b, int l);
114 #endif
115 
116 
117 #define set_attr(ip, attr)	((ip)->attribute |= (attr))
118 #define clr_attr(ip, attr)	((ip)->attribute &= ~(attr))
119 
120 extern  int nodev();
121 
122 int customc_scroll(),	customc_init(),		customc_deinit();
123 int customc_clear(),	customc_putc(),		customc_cursor();
124 
125 int tiga_scroll(),	tiga_init(),		tiga_deinit();
126 int tiga_clear(),	tiga_putc(),		tiga_cursor();
127 
128 
129 struct itesw itesw[] =
130 {
131 	customc_init,		customc_deinit,		customc_clear,
132 	customc_putc,		customc_cursor,		customc_scroll,
133 
134 	tiga_init,		tiga_deinit,		tiga_clear,
135 	tiga_putc,		tiga_cursor,		tiga_scroll,
136 };
137 
138 /*
139  * # of chars are output in a single itestart() call.
140  * If this is too big, user processes will be blocked out for
141  * long periods of time while we are emptying the queue in itestart().
142  * If it is too small, console output will be very ragged.
143  */
144 int	iteburst = 64;
145 
146 int	nite = NITE;
147 struct  tty *kbd_tty = NULL;
148 struct	tty ite_cons;
149 struct	tty *ite_tty[NITE] = { &ite_cons };
150 struct  ite_softc ite_softc[NITE];
151 
152 int	itestart();
153 extern	int ttrstrt();
154 extern	struct tty *constty;
155 
156 /* These are (later..) settable via an ioctl */
157 int	start_repeat_timo = 30;	/* /100: initial timeout till pressed key repeats */
158 int	next_repeat_timo  = 5;  /* /100: timeout when repeating for next char */
159 
160 /*
161  * Primary attribute buffer to be used by the first bitmapped console
162  * found. Secondary displays alloc the attribute buffer as needed.
163  * Size is based on a 68x128 display, which is currently our largest.
164  */
165 u_char  console_attributes[0x2200];
166 
167 /*
168  * Perform functions necessary to setup device as a terminal emulator.
169  */
170 iteon(dev, flag)
171 	dev_t dev;
172 {
173 	int unit = UNIT(dev);
174 	struct tty *tp = ite_tty[unit];
175 	struct ite_softc *ip = &ite_softc[unit];
176 
177 	if (unit < 0 || unit >= NITE || (ip->flags&ITE_ALIVE) == 0)
178 		return(ENXIO);
179 	/* force ite active, overriding graphics mode */
180 	if (flag & 1) {
181 		ip->flags |= ITE_ACTIVE;
182 		ip->flags &= ~(ITE_INGRF|ITE_INITED);
183 	}
184 	/* leave graphics mode */
185 	if (flag & 2) {
186 		ip->flags &= ~ITE_INGRF;
187 		if ((ip->flags & ITE_ACTIVE) == 0)
188 			return(0);
189 	}
190 	ip->flags |= ITE_ACTIVE;
191 	if (ip->flags & ITE_INGRF)
192 		return(0);
193 	if (kbd_tty == NULL || kbd_tty == tp) {
194 		kbd_tty = tp;
195 		kbdenable();
196 	}
197 	iteinit(dev);
198 	return(0);
199 }
200 
201 /* used by the grf layer to reinitialize ite after changing fb parameters */
202 itereinit(dev)
203      dev_t dev;
204 {
205   int unit = UNIT(dev);
206   struct ite_softc *ip = &ite_softc[unit];
207 
208   ip->flags &= ~ITE_INITED;
209   iteinit (dev);
210 }
211 
212 iteinit(dev)
213      dev_t dev;
214 {
215 	int unit = UNIT(dev);
216 	struct ite_softc *ip = &ite_softc[unit];
217 
218 	if (ip->flags & ITE_INITED)
219 		return;
220 
221 	ip->curx = 0;
222 	ip->cury = 0;
223 	ip->cursorx = 0;
224 	ip->cursory = 0;
225 	ip->save_curx = 0;
226 	ip->save_cury = 0;
227 	ip->ap = ip->argbuf;
228 	ip->emul_level = EMUL_VT300_7;
229 	ip->eightbit_C1 = 0;
230 	ip->inside_margins = 0;
231 	ip->linefeed_newline = 0;
232 
233 	(*itesw[ip->type].ite_init)(ip);
234 	(*itesw[ip->type].ite_cursor)(ip, DRAW_CURSOR);
235 
236 	/* ip->rows initialized by ite_init above */
237 	ip->top_margin = 0; ip->bottom_margin = ip->rows - 1;
238 
239 	ip->attribute = 0;
240 	if (ip->attrbuf == NULL)
241 		ip->attrbuf = (u_char *)
242 			malloc(ip->rows * ip->cols, M_DEVBUF, M_WAITOK);
243 	bzero(ip->attrbuf, (ip->rows * ip->cols));
244 
245 	ip->imode = 0;
246 	ip->flags |= ITE_INITED;
247 }
248 
249 /*
250  * "Shut down" device as terminal emulator.
251  * Note that we do not deinit the console device unless forced.
252  * Deinit'ing the console every time leads to a very active
253  * screen when processing /etc/rc.
254  */
255 iteoff(dev, flag)
256 	dev_t dev;
257 {
258 	register struct ite_softc *ip = &ite_softc[UNIT(dev)];
259 
260 	if (flag & 2)
261 		ip->flags |= ITE_INGRF;
262 	if ((ip->flags & ITE_ACTIVE) == 0)
263 		return;
264 	if ((flag & 1) ||
265 	    (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED)
266 		(*itesw[ip->type].ite_deinit)(ip);
267 	if ((flag & 2) == 0)
268 		ip->flags &= ~ITE_ACTIVE;
269 }
270 
271 /* ARGSUSED */
272 #ifdef __STDC__
273 iteopen(dev_t dev, int mode, int devtype, struct proc *p)
274 #else
275 iteopen(dev, mode, devtype, p)
276 	dev_t dev;
277 	int mode, devtype;
278 	struct proc *p;
279 #endif
280 {
281 	int unit = UNIT(dev);
282 	register struct tty *tp;
283 	register struct ite_softc *ip = &ite_softc[unit];
284 	register int error;
285 	int first = 0;
286 
287 	if(!ite_tty[unit]) {
288 		MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK);
289 		bzero(tp, sizeof(struct tty));
290 		ite_tty[unit] = tp;
291 	} else
292 		tp = ite_tty[unit];
293 
294 	if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE)
295 	    && p->p_ucred->cr_uid != 0)
296 		return (EBUSY);
297 	if ((ip->flags & ITE_ACTIVE) == 0) {
298 		error = iteon(dev, 0);
299 		if (error)
300 			return (error);
301 		first = 1;
302 	}
303 	tp->t_oproc = itestart;
304 	tp->t_param = NULL;
305 	tp->t_dev = dev;
306 	if ((tp->t_state&TS_ISOPEN) == 0) {
307 		ttychars(tp);
308 		tp->t_iflag = TTYDEF_IFLAG;
309 		tp->t_oflag = TTYDEF_OFLAG;
310 		tp->t_cflag = CS8|CREAD;
311 		tp->t_lflag = TTYDEF_LFLAG;
312 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
313 		/* don't set TS_ISOPEN  here, or the tty queues won't
314 		   be initialized in ttyopen()! */
315 		tp->t_state = TS_CARR_ON;
316 		ttsetwater(tp);
317 	}
318 	error = (*linesw[tp->t_line].l_open)(dev, tp);
319 	if (error == 0) {
320 		tp->t_winsize.ws_row = ip->rows;
321 		tp->t_winsize.ws_col = ip->cols;
322 	} else if (first)
323 		iteoff(dev, 0);
324 	return (error);
325 }
326 
327 /*ARGSUSED*/
328 iteclose(dev, flag, mode, p)
329 	dev_t dev;
330 	int flag, mode;
331 	struct proc *p;
332 {
333 	register struct tty *tp = ite_tty[UNIT(dev)];
334 
335 	(*linesw[tp->t_line].l_close)(tp, flag);
336 	ttyclose(tp);
337 	iteoff(dev, 0);
338 	if (tp != &ite_cons)
339 	  {
340 	    FREE(tp, M_TTYS);
341 	    ite_tty[UNIT(dev)] = (struct tty *)NULL;
342 	  }
343 	return(0);
344 }
345 
346 iteread(dev, uio, flag)
347 	dev_t dev;
348 	struct uio *uio;
349 {
350 	register struct tty *tp = ite_tty[UNIT(dev)];
351 	int rc;
352 
353 	rc = ((*linesw[tp->t_line].l_read)(tp, uio, flag));
354 	return rc;
355 }
356 
357 itewrite(dev, uio, flag)
358 	dev_t dev;
359 	struct uio *uio;
360 {
361 	int unit = UNIT(dev);
362 	register struct tty *tp = ite_tty[unit];
363 
364 	if ((ite_softc[unit].flags & ITE_ISCONS) && constty &&
365 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
366 		tp = constty;
367 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
368 }
369 
370 iteioctl(dev, cmd, addr, flag)
371 	dev_t dev;
372 	caddr_t addr;
373 {
374 	register struct tty *tp = ite_tty[UNIT(dev)];
375 	int error;
376 
377 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag);
378 	if (error >= 0)
379 		return (error);
380 	error = ttioctl(tp, cmd, addr, flag);
381 	if (error >= 0)
382 		return (error);
383 	return (ENOTTY);
384 }
385 
386 itestart(tp)
387 	register struct tty *tp;
388 {
389 	register int cc, s;
390 	int hiwat = 0;
391 
392 	s = spltty();
393 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
394 		splx(s);
395 		return;
396 	}
397 	tp->t_state |= TS_BUSY;
398 	cc = RB_LEN (&tp->t_out);
399 	if (cc <= tp->t_lowat) {
400 		if (tp->t_state & TS_ASLEEP) {
401 			tp->t_state &= ~TS_ASLEEP;
402 			wakeup(&tp->t_out);
403 		}
404 		selwakeup(&tp->t_wsel);
405 	}
406 	/*
407 	 * Limit the amount of output we do in one burst
408 	 * to prevent hogging the CPU.
409 	 */
410 	if (cc > iteburst) {
411 		hiwat++;
412 		cc = iteburst;
413 	}
414 	while (--cc >= 0) {
415 		register int c;
416 
417 		c = rbgetc(&tp->t_out);
418 		/*
419 		 * iteputchar() may take a long time and we don't want to
420 		 * block all interrupts for long periods of time.  Since
421 		 * there is no need to stay at high priority while outputing
422 		 * the character (since we don't have to worry about
423 		 * interrupts), we don't.  We just need to make sure that
424 		 * we don't reenter iteputchar, which is guarenteed by the
425 		 * earlier setting of TS_BUSY.
426 		 */
427 		splx(s);
428 		iteputchar(c, tp->t_dev);
429 		spltty();
430 	}
431 	if (hiwat) {
432 		tp->t_state |= TS_TIMEOUT;
433 		timeout(ttrstrt, tp, 1);
434 	}
435 	tp->t_state &= ~TS_BUSY;
436 	splx(s);
437 }
438 
439 /* these are used to implement repeating keys.. */
440 static u_char last_char = 0;
441 static u_char tout_pending = 0;
442 
443 static void
444 repeat_handler (a0, a1)
445     int a0, a1;
446 {
447   tout_pending = 0;
448   /* leave it up to itefilter() to possible install a new callout entry
449      to reinvoke repeat_handler() */
450   itefilter (last_char, ITEFILT_REPEATER);
451 }
452 
453 
454 int
455 itefilter(c, caller)
456      register u_char c;
457      enum caller caller;
458 {
459   static u_char mod = 0;
460   static u_char last_dead = 0;
461   register char code, *str;
462   u_char up, mask, i;
463   struct key key;
464 
465   if (caller != ITEFILT_CONSOLE && kbd_tty == NULL)
466      return;
467 
468   up = c & 0x80 ? 1 : 0;
469   c &= 0x7f;
470   code = 0;
471 
472   mask = 0;
473   if (c >= KBD_LEFT_SHIFT)
474     {
475       switch (c)
476         {
477         case KBD_LEFT_SHIFT:
478           mask = KBD_MOD_LSHIFT;
479           break;
480 
481         case KBD_RIGHT_SHIFT:
482           mask = KBD_MOD_RSHIFT;
483           break;
484 
485         case KBD_LEFT_ALT:
486           mask = KBD_MOD_LALT;
487           break;
488 
489         case KBD_RIGHT_ALT:
490           mask = KBD_MOD_RALT;
491           break;
492 
493         case KBD_LEFT_META:
494           mask = KBD_MOD_LMETA;
495           break;
496 
497         case KBD_RIGHT_META:
498           mask = KBD_MOD_RMETA;
499           break;
500 
501         case KBD_CAPS_LOCK:
502           /* capslock already behaves `right', don't need to keep track of the
503              state in here. */
504           mask = KBD_MOD_CAPS;
505           break;
506 
507         case KBD_CTRL:
508           mask = KBD_MOD_CTRL;
509           break;
510         }
511 
512       if (mask)
513         {
514           if (up)
515             mod &= ~mask;
516           else
517             mod |= mask;
518         }
519 
520       /* these keys should not repeat, so it's the Right Thing dealing with
521          repeaters only after this block. */
522 
523       /* return even if it wasn't a modifier key, the other codes up here
524          are either special (like reset warning), or not yet defined */
525       return -1;
526     }
527 
528   /* no matter which character we're repeating, stop it if we get a key-up
529      event. I think this is the same thing amigados does. */
530   if (up)
531     {
532       if (tout_pending)
533         {
534           untimeout (repeat_handler, 0);
535           tout_pending = 0;
536         }
537       return -1;
538     }
539 
540 
541   switch (mod & (KBD_MOD_ALT | KBD_MOD_SHIFT))
542     {
543     case 0:
544 	key = kbdmap.keys[c];
545 	if (!(mod & KBD_MOD_CAPS) || !(key.mode & KBD_MODE_CAPS))
546 	  break;
547 	/* FALL INTO */
548 
549     case KBD_MOD_LSHIFT:
550     case KBD_MOD_RSHIFT:
551     case KBD_MOD_SHIFT:
552         key = kbdmap.shift_keys[c];
553         break;
554 
555     case KBD_MOD_LALT:
556     case KBD_MOD_RALT:
557     case KBD_MOD_ALT:
558 	key = kbdmap.alt_keys[c];
559 	if (!(mod & KBD_MOD_CAPS) || !(key.mode & KBD_MODE_CAPS))
560 	  break;
561 	/* FALL INTO */
562 
563     case KBD_MOD_LALT|KBD_MOD_LSHIFT:
564     case KBD_MOD_LALT|KBD_MOD_RSHIFT:
565     case KBD_MOD_LALT|KBD_MOD_SHIFT:
566     case KBD_MOD_RALT|KBD_MOD_RSHIFT:
567     case KBD_MOD_RALT|KBD_MOD_SHIFT:
568     case KBD_MOD_ALT|KBD_MOD_RSHIFT:
569 	key = kbdmap.alt_shift_keys[c];
570 	break;
571     }
572 
573   code = key.code;
574 
575   /* arrange to repeat the keystroke. By doing this at the level of scan-codes,
576      we can have function keys, and keys that send strings, repeat too. This
577      also entitles an additional overhead, since we have to do the conversion
578      each time, but I guess that's ok. */
579   if (!tout_pending && caller == ITEFILT_TTY)
580     {
581       tout_pending = 1;
582       last_char = c;
583       timeout (repeat_handler, 0, start_repeat_timo);
584     }
585   else if (!tout_pending && caller == ITEFILT_REPEATER)
586     {
587       tout_pending = 1;
588       last_char = c;
589       timeout (repeat_handler, 0, next_repeat_timo);
590     }
591 
592   /* handle dead keys */
593   if (key.mode & KBD_MODE_DEAD)
594     {
595       /* if entered twice, send accent itself */
596       if (last_dead == key.mode & KBD_MODE_ACCMASK)
597         last_dead = 0;
598       else
599 	{
600 	  last_dead = key.mode & KBD_MODE_ACCMASK;
601 	  return -1;
602 	}
603     }
604   if (last_dead)
605     {
606       /* can't apply dead flag to string-keys */
607       if (! (key.mode & KBD_MODE_STRING) && code >= '@' && code < 0x7f)
608         code = acctable[KBD_MODE_ACCENT (last_dead)][code - '@'];
609 
610       last_dead = 0;
611     }
612 
613   /* if not string, apply META and CTRL modifiers */
614   if (! (key.mode & KBD_MODE_STRING))
615     {
616       if (mod & KBD_MOD_CTRL)
617         code &= 0x1f;
618 
619       if (mod & KBD_MOD_META)
620         code |= 0x80;
621     }
622   else
623     {
624       /* strings are only supported in normal tty mode, not in console mode */
625       if (caller != ITEFILT_CONSOLE)
626         {
627           str = kbdmap.strings + code;
628           /* using a length-byte instead of 0-termination allows to embed \0 into
629              strings, although this is not used in the default keymap */
630           for (i = *str++; i; i--)
631             (*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
632         }
633       return -1;
634     }
635 
636   if (caller == ITEFILT_CONSOLE)
637     return code;
638   else
639     (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
640 
641   return -1;
642 }
643 
644 
645 /* helper functions, makes the code below more readable */
646 static void inline
647 ite_dnchar(ip, sp, n)
648      struct ite_softc *ip;
649      struct itesw *sp;
650      int n;
651 {
652   (*sp->ite_scroll)(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
653   attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
654 	  1, ip->cols - ip->curx - n);
655   attrclr(ip, ip->cury, ip->cols - n, 1, n);
656   while (n--)
657     (*sp->ite_putc)(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
658   (*sp->ite_cursor)(ip, DRAW_CURSOR);
659 }
660 
661 static void inline
662 ite_inchar(ip, sp, n)
663      struct ite_softc *ip;
664      struct itesw *sp;
665      int n;
666 {
667   (*sp->ite_scroll)(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
668   attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
669 	  1, ip->cols - ip->curx - n);
670   attrclr(ip, ip->cury, ip->curx, 1, n);
671   while (n--)
672     (*sp->ite_putc)(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
673   (*sp->ite_cursor)(ip, DRAW_CURSOR);
674 }
675 
676 static void inline
677 ite_clrtoeol(ip, sp, y, x)
678      struct ite_softc *ip;
679      struct itesw *sp;
680      int y, x;
681 {
682   (*sp->ite_clear)(ip, y, x, 1, ip->cols - x);
683   attrclr(ip, y, x, 1, ip->cols - x);
684   (*sp->ite_cursor)(ip, DRAW_CURSOR);
685 }
686 
687 static void inline
688 ite_clrtobol(ip, sp, y, x)
689      struct ite_softc *ip;
690      struct itesw *sp;
691      int y, x;
692 {
693   (*sp->ite_clear)(ip, y, 0, 1, x);
694   attrclr(ip, y, 0, 1, x);
695   (*sp->ite_cursor)(ip, DRAW_CURSOR);
696 }
697 
698 static void inline
699 ite_clrline(ip, sp, y, x)
700      struct ite_softc *ip;
701      struct itesw *sp;
702      int y, x;
703 {
704   (*sp->ite_clear)(ip, y, 0, 1, ip->cols);
705   attrclr(ip, y, 0, 1, ip->cols);
706   (*sp->ite_cursor)(ip, DRAW_CURSOR);
707 }
708 
709 
710 
711 static void inline
712 ite_clrtoeos(ip, sp)
713      struct ite_softc *ip;
714      struct itesw *sp;
715 {
716   (*sp->ite_clear)(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
717   attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
718   (*sp->ite_cursor)(ip, DRAW_CURSOR);
719 }
720 
721 static void inline
722 ite_clrtobos(ip, sp)
723      struct ite_softc *ip;
724      struct itesw *sp;
725 {
726   (*sp->ite_clear)(ip, 0, 0, ip->cury, ip->cols);
727   attrclr(ip, 0, 0, ip->cury, ip->cols);
728   (*sp->ite_cursor)(ip, DRAW_CURSOR);
729 }
730 
731 static void inline
732 ite_clrscreen(ip, sp)
733      struct ite_softc *ip;
734      struct itesw *sp;
735 {
736   (*sp->ite_clear)(ip, 0, 0, ip->rows, ip->cols);
737   attrclr(ip, 0, 0, ip->rows, ip->cols);
738   (*sp->ite_cursor)(ip, DRAW_CURSOR);
739 }
740 
741 
742 
743 static void inline
744 ite_dnline(ip, sp, n)
745      struct ite_softc *ip;
746      struct itesw *sp;
747      int n;
748 {
749   (*sp->ite_scroll)(ip, ip->cury + n, 0, n, SCROLL_UP);
750   attrmov(ip, ip->cury + n, 0, ip->cury, 0,
751 	  ip->bottom_margin + 1 - ip->cury - n, ip->cols);
752   (*sp->ite_clear)(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
753   attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
754   (*sp->ite_cursor)(ip, DRAW_CURSOR);
755 }
756 
757 static void inline
758 ite_inline(ip, sp, n)
759      struct ite_softc *ip;
760      struct itesw *sp;
761      int n;
762 {
763   (*sp->ite_scroll)(ip, ip->cury, 0, n, SCROLL_DOWN);
764   attrmov(ip, ip->cury, 0, ip->cury + n, 0,
765 	  ip->bottom_margin + 1 - ip->cury - n, ip->cols);
766   (*sp->ite_clear)(ip, ip->cury, 0, n, ip->cols);
767   attrclr(ip, ip->cury, 0, n, ip->cols);
768   (*sp->ite_cursor)(ip, DRAW_CURSOR);
769 }
770 
771 static void inline
772 ite_lf (ip, sp)
773      struct ite_softc *ip;
774      struct itesw *sp;
775 {
776 #if 0
777   if (ip->inside_margins)
778     {
779 #endif
780       if (++ip->cury >= ip->bottom_margin + 1)
781         {
782           ip->cury = ip->bottom_margin;
783           (*sp->ite_scroll)(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
784           ite_clrtoeol(ip, sp, ip->cury, 0);
785         }
786       else
787         (*sp->ite_cursor)(ip, MOVE_CURSOR);
788 #if 0
789     }
790   else
791     {
792       if (++ip->cury == ip->rows)
793         {
794           --ip->cury;
795           (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
796           ite_clrtoeol(ip, sp, ip->cury, 0);
797         }
798       else
799         (*sp->ite_cursor)(ip, MOVE_CURSOR);
800     }
801 #endif
802   clr_attr(ip, ATTR_INV);
803 }
804 
805 static void inline
806 ite_crlf (ip, sp)
807      struct ite_softc *ip;
808      struct itesw *sp;
809 {
810   ip->curx = 0;
811   ite_lf (ip, sp);
812 }
813 
814 static void inline
815 ite_cr (ip, sp)
816      struct ite_softc *ip;
817      struct itesw *sp;
818 {
819   if (ip->curx)
820     {
821       ip->curx = 0;
822       (*sp->ite_cursor)(ip, MOVE_CURSOR);
823     }
824 }
825 
826 static void inline
827 ite_rlf (ip, sp)
828      struct ite_softc *ip;
829      struct itesw *sp;
830 {
831   if (ip->cury > 0)
832     {
833       ip->cury--;
834       (*sp->ite_cursor)(ip, MOVE_CURSOR);
835     }
836   else
837     ite_inline (ip, sp, 1);
838   clr_attr(ip, ATTR_INV);
839 }
840 
841 static int inline
842 atoi (cp)
843     const char *cp;
844 {
845   int n;
846 
847   for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
848     n = n * 10 + *cp - '0';
849 
850   return n;
851 }
852 
853 static char *
854 index (cp, ch)
855     const char *cp;
856     char ch;
857 {
858   while (*cp && *cp != ch) cp++;
859   return *cp ? cp : 0;
860 }
861 
862 
863 
864 static int inline
865 ite_argnum (ip)
866     struct ite_softc *ip;
867 {
868   char ch;
869   int n;
870 
871   /* convert argument string into number */
872   if (ip->ap == ip->argbuf)
873     return 1;
874   ch = *ip->ap;
875   *ip->ap = 0;
876   n = atoi (ip->argbuf);
877   *ip->ap = ch;
878 
879   return n;
880 }
881 
882 static int inline
883 ite_zargnum (ip)
884     struct ite_softc *ip;
885 {
886   char ch, *cp;
887   int n;
888 
889   /* convert argument string into number */
890   if (ip->ap == ip->argbuf)
891     return 0;
892   ch = *ip->ap;
893   *ip->ap = 0;
894   n = atoi (ip->argbuf);
895   *ip->ap = ch;
896 
897   return n;
898 }
899 
900 static void inline
901 ite_sendstr (ip, str)
902     struct ite_softc *ip;
903     char *str;
904 {
905   while (*str)
906     (*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
907 }
908 
909 static int inline
910 strncmp (a, b, l)
911     const char *a, *b;
912     int l;
913 {
914   for (;l--; a++, b++)
915     if (*a != *b)
916       return *a - *b;
917   return 0;
918 }
919 
920 static void inline
921 ite_reinit(ip)
922     struct ite_softc *ip;
923 {
924   ip->curx = 0;
925   ip->cury = 0;
926   ip->cursorx = 0;
927   ip->cursory = 0;
928   ip->save_curx = 0;
929   ip->save_cury = 0;
930   ip->ap = ip->argbuf;
931   ip->emul_level = EMUL_VT300_7;
932   ip->eightbit_C1 = 0;
933   ip->top_margin = 0; ip->bottom_margin = 23;
934   ip->inside_margins = 0;
935   ip->linefeed_newline = 0;
936 
937   (*itesw[ip->type].ite_cursor)(ip, DRAW_CURSOR);
938 
939   ip->attribute = 0;
940   bzero(ip->attrbuf, (ip->rows * ip->cols));
941 
942   ip->imode = 0;
943 }
944 
945 
946 
947 iteputchar(c, dev)
948 	register int c;
949 	dev_t dev;
950 {
951 	int unit = UNIT(dev);
952 	register struct ite_softc *ip = &ite_softc[unit];
953 	register struct itesw *sp = &itesw[ip->type];
954 	register int n;
955 	int x, y;
956 	char *cp;
957 
958 	if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
959 	  	return;
960 
961 	if ((ite_tty[unit]->t_cflag & CSIZE) == CS7
962 	    || (ite_tty[unit]->t_cflag & PARENB))
963 	  c &= 0x7f;
964 
965 	if (ip->escape)
966 	  {
967 doesc:
968 	    switch (ip->escape)
969 	      {
970 	      case ESC:
971 	        switch (c)
972 	          {
973 		  /* first 7bit equivalents for the 8bit control characters */
974 
975 	          case 'D':
976 		    c = IND;
977 		    ip->escape = 0;
978 		    break;
979 
980 		  case 'E':
981 		    c = NEL;
982 		    ip->escape = 0;
983 		    break;
984 
985 		  case 'H':
986 		    c = HTS;
987 		    ip->escape = 0;
988 		    break;
989 
990 		  case 'M':
991 		    c = RI;
992 		    ip->escape = 0;
993 		    break;
994 
995 		  case 'N':
996 		    c = SS2;
997 		    ip->escape = 0;
998 		    break;
999 
1000 		  case 'O':
1001 		    c = SS3;
1002 		    ip->escape = 0;
1003 		    break;
1004 
1005 		  case 'P':
1006 		    c = DCS;
1007 		    ip->escape = 0;
1008 		    break;
1009 
1010 		  case '[':
1011 		    c = CSI;
1012 		    ip->escape = 0;
1013 		    break;
1014 
1015 		  case '\\':
1016 		    c = ST;
1017 		    ip->escape = 0;
1018 		    break;
1019 
1020 		  case ']':
1021 		    c = OSC;
1022 		    ip->escape = 0;
1023 		    break;
1024 
1025 		  case '^':
1026 		    c = PM;
1027 		    ip->escape = 0;
1028 		    break;
1029 
1030 		  case '_':
1031 		    c = APC;
1032 		    ip->escape = 0;
1033 		    break;
1034 
1035 
1036 		  /* introduces 7/8bit control */
1037 		  case ' ':
1038 		     /* can be followed by either F or G */
1039 		     ip->escape = ' ';
1040 		     break;
1041 
1042 
1043 		  /* a lot of character set selections, not yet used...
1044 		     94-character sets: */
1045 		  case '(':	/* G0 */
1046 		  case ')':	/* G1 */
1047 		  case '*':	/* G2 */
1048 		  case '+':	/* G3 */
1049 		  case 'B':	/* ASCII */
1050 		  case 'A':	/* ISO latin 1 */
1051 		  case '<':	/* user preferred suplemental */
1052 		  case '0':	/* dec special graphics */
1053 
1054 		  /* 96-character sets: */
1055 		  case '-':	/* G1 */
1056 		  case '.':	/* G2 */
1057 		  case '/':	/* G3 */
1058 
1059 		  /* national character sets: */
1060 		  case '4':	/* dutch */
1061 		  case '5':
1062 		  case 'C':	/* finnish */
1063 		  case 'R':	/* french */
1064 		  case 'Q':	/* french canadian */
1065 		  case 'K':	/* german */
1066 		  case 'Y':	/* italian */
1067 		  case '6':	/* norwegian/danish */
1068 		  case 'Z':	/* spanish */
1069 		  case '=':	/* swiss */
1070 		  /* note: %5 and %6 are not supported (two chars..) */
1071 
1072 		    ip->escape = 0;
1073 		    /* just ignore for now */
1074 		    return -1;
1075 
1076 
1077 		  /* locking shift modes (as you might guess, not yet supported..) */
1078 		  case '`':
1079 		    ip->GR = ip->G1;
1080 		    ip->escape = 0;
1081 		    return -1;
1082 
1083 		  case 'n':
1084 		    ip->GL = ip->G2;
1085 		    ip->escape = 0;
1086 		    return -1;
1087 
1088 		  case '}':
1089 		    ip->GR = ip->G2;
1090 		    ip->escape = 0;
1091 		    return -1;
1092 
1093 		  case 'o':
1094 		    ip->GL = ip->G3;
1095 		    ip->escape = 0;
1096 		    return -1;
1097 
1098 		  case '|':
1099 		    ip->GR = ip->G3;
1100 		    ip->escape = 0;
1101 		    return -1;
1102 
1103 
1104 		  /* font width/height control */
1105 		  case '#':
1106 		    ip->escape = '#';
1107 		    return -1;
1108 
1109 
1110 		  /* hard terminal reset .. */
1111 		  case 'c':
1112 		    ite_reinit (ip);
1113 		    ip->escape = 0;
1114 		    return -1;
1115 
1116 
1117 		  case '7':
1118 		    ip->save_curx = ip->curx;
1119 		    ip->save_cury = ip->cury;
1120 		    ip->escape = 0;
1121 		    return -1;
1122 
1123 		  case '8':
1124 		    ip->curx = ip->save_curx;
1125 		    ip->cury = ip->save_cury;
1126 		    (*sp->ite_cursor)(ip, MOVE_CURSOR);
1127 		    ip->escape = 0;
1128 		    return -1;
1129 
1130 
1131 		  /* default catch all for not recognized ESC sequences */
1132 		  default:
1133 		    ip->escape = 0;
1134 		    return -1;
1135 		  }
1136 		break;
1137 
1138 
1139 	      case ' ':
1140 	        switch (c)
1141 	          {
1142 	          case 'F':
1143 		    ip->eightbit_C1 = 0;
1144 		    ip->escape = 0;
1145 		    return -1;
1146 
1147 		  case 'G':
1148 		    ip->eightbit_C1 = 1;
1149 		    ip->escape = 0;
1150 		    return -1;
1151 
1152 		  default:
1153 		    /* not supported */
1154 		    ip->escape = 0;
1155 		    return -1;
1156 		  }
1157 		break;
1158 
1159 
1160 	      case '#':
1161 		switch (c)
1162 		  {
1163 		  case '5':
1164 		    /* single height, single width */
1165 		    ip->escape = 0;
1166 		    return -1;
1167 
1168 		  case '6':
1169 		    /* double width, single height */
1170 		    ip->escape = 0;
1171 		    return -1;
1172 
1173 		  case '3':
1174 		    /* top half */
1175 		    ip->escape = 0;
1176 		    return -1;
1177 
1178 		  case '4':
1179 		    /* bottom half */
1180 		    ip->escape = 0;
1181 		    return -1;
1182 
1183 		  case '8':
1184 		    /* screen alignment pattern... */
1185 		    ip->escape = 0;
1186 		    return -1;
1187 
1188 		  default:
1189 		    ip->escape = 0;
1190 		    return -1;
1191 		  }
1192 		break;
1193 
1194 
1195 
1196 #if 0
1197 	      case DCS:
1198 	      case PM:
1199 	      case APC:
1200 	      case OSC:
1201 		switch (c)
1202 		  {
1203 		  case ST:
1204 		    ip->escape = 0;
1205 		    return -1;
1206 
1207 		  default:
1208 		    return -1;
1209 		  }
1210 		break;
1211 #endif
1212 
1213 
1214 	      case CSI:
1215 	        /* the biggie... */
1216 	        switch (c)
1217 	          {
1218 	          case '0': case '1': case '2': case '3': case '4':
1219 	          case '5': case '6': case '7': case '8': case '9':
1220 	          case ';': case '\"': case '$': case '>':
1221 	            if (ip->ap < ip->argbuf + ARGBUF_SIZE)
1222 	              *ip->ap++ = c;
1223 	            return -1;
1224 
1225 		  case CAN:
1226     		    ip->escape = 0;
1227 		    return -1;
1228 
1229 
1230 	          case 'p':
1231 		    *ip->ap = 0;
1232 	            if (! strncmp (ip->argbuf, "61\"", 3))
1233 	              ip->emul_level = EMUL_VT100;
1234 	            else if (! strncmp (ip->argbuf, "63;1\"", 5)
1235 	            	     || ! strncmp (ip->argbuf, "62;1\"", 5))
1236 	              ip->emul_level = EMUL_VT300_7;
1237 	            else
1238 	              ip->emul_level = EMUL_VT300_8;
1239 	            ip->escape = 0;
1240 	            return -1;
1241 
1242 
1243 	          case '?':
1244 		    *ip->ap = 0;
1245 	            ip->escape = '?';
1246 	            ip->ap = ip->argbuf;
1247 	            return -1;
1248 
1249 
1250 		  case 'c':
1251 		    *ip->ap = 0;
1252 		    if (ip->ap == ip->argbuf
1253 		        || (ip->ap == &ip->argbuf[1] && ip->argbuf[0] == '0'))
1254 		      {
1255 			/* primary DA request, send primary DA response */
1256 			if (ip->emul_level == EMUL_VT100)
1257 		          ite_sendstr (ip, "\033[61;0c");
1258 		        else
1259 		          ite_sendstr (ip, "\033[63;0c");
1260 		      }
1261 
1262 		    else if ((ip->ap == &ip->argbuf[1] && ip->argbuf[0] == '>')
1263 		        || (ip->ap == &ip->argbuf[2]
1264 			    && !strncmp (ip->argbuf, ">0", 2)))
1265 		      {
1266 		        ite_sendstr (ip, "\033[>24;0;0;0c");
1267 		      }
1268 
1269 		    ip->escape = 0;
1270 		    return -1;
1271 
1272 
1273 		  case 'n':
1274 		    *ip->ap = 0;
1275 		    if (ip->ap == &ip->argbuf[1])
1276 		      {
1277 		        if (ip->argbuf[0] == '5')
1278 		          ite_sendstr (ip, "\033[0n");	/* no malfunction */
1279 
1280 		        else if (ip->argbuf[0] == '6')
1281 		          {
1282 		            sprintf (ip->argbuf, "\033[%d;%dR",
1283 				     ip->cury + 1, ip->curx + 1);
1284 			    /* cursor position report */
1285 			    ite_sendstr (ip, ip->argbuf);
1286 		          }
1287 
1288 		      }
1289 		    ip->escape = 0;
1290 		    return -1;
1291 
1292 
1293 	          case 'h': case 'l':
1294 		    *ip->ap = 0;
1295 		    if (ip->ap == &ip->argbuf[1] && ip->argbuf[0] == '4')
1296 		      ip->imode = (c == 'h');	/* insert/replace mode */
1297 
1298 		    else if (ip->ap == &ip->argbuf[2]
1299 			     && !strncmp (ip->argbuf, "20", 2))
1300 		      ip->linefeed_newline = (c == 'h');
1301 
1302 
1303 	            /* various not supported commands */
1304 	            ip->escape = 0;
1305 	            return -1;
1306 
1307 
1308 		  case 'M':
1309 		    *ip->ap = 0;
1310 		    ite_dnline (ip, sp, ite_argnum (ip));
1311 	            ip->escape = 0;
1312 	            return -1;
1313 
1314 
1315 		  case 'L':
1316 		    *ip->ap = 0;
1317 		    ite_inline (ip, sp, ite_argnum (ip));
1318 	            ip->escape = 0;
1319 	            return -1;
1320 
1321 
1322 		  case 'P':
1323 		    *ip->ap = 0;
1324 		    ite_dnchar (ip, sp, ite_argnum (ip));
1325 	            ip->escape = 0;
1326 	            return -1;
1327 
1328 
1329 		  case '@':
1330 		    *ip->ap = 0;
1331 		    ite_inchar (ip, sp, ite_argnum (ip));
1332 	            ip->escape = 0;
1333 	            return -1;
1334 
1335 
1336 		  case 'H':
1337 		  case 'f':
1338 		    *ip->ap = 0;
1339 		    y = atoi (ip->argbuf);
1340 		    x = 0;
1341 		    cp = index (ip->argbuf, ';');
1342 		    if (cp)
1343 		      x = atoi (cp + 1);
1344 		    if (x) x--;
1345 		    if (y) y--;
1346 		    if (ip->inside_margins)
1347 		      {
1348 			y += ip->top_margin;
1349 			ip->cury = MIN(y, ip->bottom_margin);
1350 		      }
1351 		    else
1352 		      {
1353 			ip->cury = MIN(y, ip->rows - 1);
1354 		      }
1355 		    ip->curx = MIN(x, ip->cols - 1);
1356 		    ip->escape = 0;
1357 		    (*sp->ite_cursor)(ip, MOVE_CURSOR);
1358 		    clr_attr (ip, ATTR_INV);
1359 		    return -1;
1360 
1361 		  case 'A':
1362 		    *ip->ap = 0;
1363 		    n = ip->cury - ite_argnum (ip);
1364 		    ip->cury = n >= 0 ? n : 0;
1365 		    ip->escape = 0;
1366 		    (*sp->ite_cursor)(ip, MOVE_CURSOR);
1367 		    clr_attr (ip, ATTR_INV);
1368 		    return -1;
1369 
1370 		  case 'B':
1371 		    *ip->ap = 0;
1372 		    n = ite_argnum (ip) + ip->cury;
1373 		    ip->cury = MIN(n, ip->rows - 1);
1374 		    ip->escape = 0;
1375 		    (*sp->ite_cursor)(ip, MOVE_CURSOR);
1376 		    clr_attr (ip, ATTR_INV);
1377 		    return -1;
1378 
1379 		  case 'C':
1380 		    *ip->ap = 0;
1381 		    n = ite_argnum (ip) + ip->curx;
1382 		    ip->curx = MIN(n, ip->cols - 1);
1383 		    ip->escape = 0;
1384 		    (*sp->ite_cursor)(ip, MOVE_CURSOR);
1385 		    clr_attr (ip, ATTR_INV);
1386 		    return -1;
1387 
1388 		  case 'D':
1389 		    *ip->ap = 0;
1390 		    n = ip->curx - ite_argnum (ip);
1391 		    ip->curx = n >= 0 ? n : 0;
1392 		    ip->escape = 0;
1393 		    (*sp->ite_cursor)(ip, MOVE_CURSOR);
1394 		    clr_attr (ip, ATTR_INV);
1395 		    return -1;
1396 
1397 
1398 
1399 
1400 		  case 'J':
1401 		    *ip->ap = 0;
1402 		    n = ite_zargnum (ip);
1403 		    if (n == 0)
1404 	              ite_clrtoeos(ip, sp);
1405 		    else if (n == 1)
1406 		      ite_clrtobos(ip, sp);
1407 		    else if (n == 2)
1408 		      ite_clrscreen(ip, sp);
1409 	            ip->escape = 0;
1410 	            return -1;
1411 
1412 
1413 		  case 'K':
1414 		    *ip->ap = 0;
1415 		    n = ite_zargnum (ip);
1416 		    if (n == 0)
1417 		      ite_clrtoeol(ip, sp, ip->cury, ip->curx);
1418 		    else if (n == 1)
1419 		      ite_clrtobol(ip, sp, ip->cury, ip->curx);
1420 		    else if (n == 2)
1421 		      ite_clrline(ip, sp, ip->cury, ip->curx);
1422 		    ip->escape = 0;
1423 		    return -1;
1424 
1425 
1426 		  case 'X':
1427 		    *ip->ap = 0;
1428 		    for (n = ite_argnum (ip); n > 0; n--)
1429 		      {
1430 			attrclr(ip, ip->cury, ip->curx + n - 1, 1, 1);
1431 			(*sp->ite_putc)(ip, ' ', ip->cury, ip->curx + n - 1, ATTR_NOR);
1432 		      }
1433 		    ip->escape = 0;
1434 		    return -1;
1435 
1436 
1437 	          case '}': case '`':
1438 	            /* status line control */
1439 	            ip->escape = 0;
1440 	            return -1;
1441 
1442 
1443 		  case 'r':
1444 		    *ip->ap = 0;
1445 		    x = atoi (ip->argbuf);
1446 		    y = 0;
1447 		    cp = index (ip->argbuf, ';');
1448 		    if (cp)
1449 		      y = atoi (cp + 1);
1450 		    if (x) x--;
1451 		    if (y) y--;
1452 		    ip->top_margin = MIN(x, ip->rows - 1);
1453 		    ip->bottom_margin = MIN(y, ip->rows - 1);
1454 		    ip->escape = 0;
1455 		    return -1;
1456 
1457 
1458 		  case 'm':
1459 		    /* big attribute setter/resetter */
1460 		    {
1461 		      char *cp;
1462 		      *ip->ap = 0;
1463 		      for (cp = ip->argbuf; cp < ip->ap; )
1464 		        {
1465 			  switch (*cp)
1466 			    {
1467 			    case '0':
1468 			      clr_attr (ip, ATTR_ALL);
1469 			      cp++;
1470 			      break;
1471 
1472 			    case '1':
1473 			      set_attr (ip, ATTR_BOLD);
1474 			      cp++;
1475 			      break;
1476 
1477 			    case '2':
1478 			      switch (cp[1])
1479 			        {
1480 			        case '2':
1481 			          clr_attr (ip, ATTR_BOLD);
1482 			          cp += 2;
1483 			          break;
1484 
1485 			        case '4':
1486 			          clr_attr (ip, ATTR_UL);
1487 			          cp += 2;
1488 			          break;
1489 
1490 			        case '5':
1491 			          clr_attr (ip, ATTR_BLINK);
1492 			          cp += 2;
1493 			          break;
1494 
1495 			        case '7':
1496 			          clr_attr (ip, ATTR_INV);
1497 			          cp += 2;
1498 			          break;
1499 
1500 		        	default:
1501 		        	  cp++;
1502 		        	  break;
1503 		        	}
1504 			      break;
1505 
1506 			    case '4':
1507 			      set_attr (ip, ATTR_UL);
1508 			      cp++;
1509 			      break;
1510 
1511 			    case '5':
1512 			      set_attr (ip, ATTR_BLINK);
1513 			      cp++;
1514 			      break;
1515 
1516 			    case '7':
1517 			      set_attr (ip, ATTR_INV);
1518 			      cp++;
1519 			      break;
1520 
1521 			    default:
1522 			      cp++;
1523 			      break;
1524 			    }
1525 		        }
1526 
1527 		    }
1528 		    ip->escape = 0;
1529 		    return -1;
1530 
1531 
1532 		  case 'u':
1533 		    /* DECRQTSR */
1534 		    ite_sendstr (ip, "\033P\033\\");
1535 		    ip->escape = 0;
1536 		    return -1;
1537 
1538 
1539 
1540 		  default:
1541 		    ip->escape = 0;
1542 		    return -1;
1543 		  }
1544 		break;
1545 
1546 
1547 
1548 	      case '?':	/* CSI ? */
1549 	      	switch (c)
1550 	      	  {
1551 	          case '0': case '1': case '2': case '3': case '4':
1552 	          case '5': case '6': case '7': case '8': case '9':
1553 	          case ';': case '\"': case '$':
1554 	            if (ip->ap < ip->argbuf + ARGBUF_SIZE)
1555 	              *ip->ap++ = c;
1556 	            return -1;
1557 
1558 
1559 		  case CAN:
1560     		    ip->escape = 0;
1561 		    return -1;
1562 
1563 
1564 		  case 'n':
1565 		    *ip->ap = 0;
1566 		    if (ip->ap == &ip->argbuf[2])
1567 		      {
1568 		        if (! strncmp (ip->argbuf, "15", 2))
1569 		          /* printer status: no printer */
1570 		          ite_sendstr (ip, "\033[13n");
1571 
1572 		        else if (! strncmp (ip->argbuf, "25", 2))
1573 		          /* udk status */
1574 		          ite_sendstr (ip, "\033[20n");
1575 
1576 		        else if (! strncmp (ip->argbuf, "26", 2))
1577 		          /* keyboard dialect: US */
1578 		          ite_sendstr (ip, "\033[27;1n");
1579 		      }
1580 		    ip->escape = 0;
1581 		    return -1;
1582 
1583 
1584 		  case 'h': case 'l':
1585 		    *ip->ap = 0;
1586 		    if (ip->ap[0] == '6')
1587 		      ip->inside_margins = (c == 'h');
1588 
1589 		    else if (! strncmp (ip->ap, "25", 2))
1590 		      (*itesw[ip->type].ite_cursor)(ip,
1591 						    (c == 'h') ? DRAW_CURSOR : ERASE_CURSOR);
1592 
1593 		    /* others.. */
1594 
1595 		  default:
1596 		    ip->escape = 0;
1597 		    return -1;
1598 		  }
1599 		break;
1600 
1601 
1602 	      default:
1603 	        ip->escape = 0;
1604 	        return -1;
1605 	      }
1606           }
1607 
1608 
1609 	switch (c) {
1610 
1611 	case VT:	/* VT is treated like LF */
1612 	case FF:	/* so is FF */
1613 	case LF:
1614 		if (ip->linefeed_newline)
1615 		  ite_crlf (ip, sp);
1616 		else
1617 		  ite_lf (ip, sp);
1618 		break;
1619 
1620 	case CR:
1621 		ite_cr (ip, sp);
1622 		break;
1623 
1624 	case BS:
1625 		if (--ip->curx < 0)
1626 			ip->curx = 0;
1627 		else
1628 			(*sp->ite_cursor)(ip, MOVE_CURSOR);
1629 		break;
1630 
1631 	case HT:
1632 		if (ip->curx < TABEND(unit)) {
1633 			n = TABSIZE - (ip->curx & (TABSIZE - 1));
1634 			ip->curx += n;
1635 			(*sp->ite_cursor)(ip, MOVE_CURSOR);
1636 		} else
1637 			itecheckwrap(ip, sp);
1638 		break;
1639 
1640 	case BEL:
1641 		if (ite_tty[unit] == kbd_tty)
1642 			kbdbell();
1643 		break;
1644 
1645 	case SO:
1646 		ip->GL = ip->G1;
1647 		break;
1648 
1649 	case SI:
1650 		ip->GL = ip->G0;
1651 		break;
1652 
1653 	case ENQ:
1654 		/* send answer-back message !! */
1655 		break;
1656 
1657 	case CAN:
1658 		ip->escape = 0;	/* cancel any escape sequence in progress */
1659 		break;
1660 
1661 	case SUB:
1662 		ip->escape = 0;	/* dito, but see below */
1663 		/* should also display a reverse question mark!! */
1664 		break;
1665 
1666 	case ESC:
1667 		ip->escape = ESC;
1668 		break;
1669 
1670 
1671 	/* now it gets weird.. 8bit control sequences.. */
1672 	case IND:	/* index: move cursor down, scroll */
1673 		ite_lf (ip, sp);
1674 		break;
1675 
1676 	case NEL:	/* next line. next line, first pos. */
1677 		ite_crlf (ip, sp);
1678 		break;
1679 
1680 	case HTS:	/* set horizontal tab */
1681 		/* not yet supported */
1682 		break;
1683 
1684 	case RI:	/* reverse index */
1685 		ite_rlf (ip, sp);
1686 		break;
1687 
1688 	case SS2:	/* go into G2 for one character */
1689 		/* not yet supported */
1690 		break;
1691 
1692 	case SS3:	/* go into G3 for one character */
1693 		break;
1694 
1695 	case DCS:	/* device control string introducer */
1696 		ip->escape = DCS;
1697 		ip->ap = ip->argbuf;
1698 		break;
1699 
1700 	case CSI:	/* control sequence introducer */
1701 		ip->escape = CSI;
1702 		ip->ap = ip->argbuf;
1703 		break;
1704 
1705 	case ST:	/* string terminator */
1706 		/* ignore, if not used as terminator */
1707 		break;
1708 
1709 	case OSC:	/* introduces OS command. Ignore everything upto ST */
1710 		ip->escape = OSC;
1711 		break;
1712 
1713 	case PM:	/* privacy message, ignore everything upto ST */
1714 		ip->escape = PM;
1715 		break;
1716 
1717 	case APC:	/* application program command, ignore everything upto ST */
1718 		ip->escape = APC;
1719 		break;
1720 
1721 	default:
1722 		if (c < ' ' || c == DEL)
1723 			break;
1724 		if (ip->imode)
1725 			ite_inchar(ip, sp, 1);
1726 		if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
1727 			attrset(ip, ATTR_INV);
1728 			(*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_INV);
1729 		}
1730 		else
1731 			(*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_NOR);
1732 		(*sp->ite_cursor)(ip, DRAW_CURSOR);
1733 		itecheckwrap(ip, sp);
1734 		break;
1735 	}
1736 }
1737 
1738 itecheckwrap(ip, sp)
1739      register struct ite_softc *ip;
1740      register struct itesw *sp;
1741 {
1742 	if (++ip->curx == ip->cols) {
1743 		ip->curx = 0;
1744 		clr_attr(ip, ATTR_INV);
1745 		if (++ip->cury >= ip->bottom_margin + 1) {
1746 			ip->cury = ip->bottom_margin;
1747 			(*sp->ite_scroll)(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1748 			ite_clrtoeol(ip, sp, ip->cury, 0);
1749 			return;
1750 		}
1751 	}
1752 	(*sp->ite_cursor)(ip, MOVE_CURSOR);
1753 }
1754 
1755 /*
1756  * Console functions
1757  */
1758 #include "../amiga/cons.h"
1759 #include "grfioctl.h"
1760 #include "grfvar.h"
1761 
1762 #ifdef DEBUG
1763 /*
1764  * Minimum ITE number at which to start looking for a console.
1765  * Setting to 0 will do normal search, 1 will skip first ITE device,
1766  * NITE will skip ITEs and use serial port.
1767  */
1768 int	whichconsole = 0;
1769 #endif
1770 
1771 itecnprobe(cp)
1772 	struct consdev *cp;
1773 {
1774 	register struct ite_softc *ip;
1775 	int i, maj, unit, pri;
1776 
1777 	/* locate the major number */
1778 	for (maj = 0; maj < nchrdev; maj++)
1779 		if (cdevsw[maj].d_open == iteopen)
1780 			break;
1781 
1782 	/* urk! */
1783 	grfconfig();
1784 
1785 	/* check all the individual displays and find the best */
1786 	unit = -1;
1787 	pri = CN_DEAD;
1788 	for (i = 0; i < NITE; i++) {
1789 		struct grf_softc *gp = &grf_softc[i];
1790 
1791 		ip = &ite_softc[i];
1792 		if ((gp->g_flags & GF_ALIVE) == 0)
1793 			continue;
1794 		ip->flags = (ITE_ALIVE|ITE_CONSOLE);
1795 
1796 		/* XXX - we need to do something about mapping these */
1797 		switch (gp->g_type) {
1798 		case GT_CUSTOMCHIPS:
1799 		        ip->type = ITE_CUSTOMCHIPS;
1800 		        break;
1801 
1802 		case GT_TIGA_A2410:
1803 		        ip->type = ITE_TIGA_A2410;
1804 		        break;
1805 		}
1806 #ifdef DEBUG
1807 		if (i < whichconsole)
1808 			continue;
1809 #endif
1810 		if ((int)gp->g_type == GT_CUSTOMCHIPS) {
1811 			pri = CN_INTERNAL;
1812 			unit = i;
1813 		} else if (unit < 0) {
1814 			pri = CN_NORMAL;
1815 			unit = i;
1816 		}
1817 	}
1818 
1819 	/* initialize required fields */
1820 	cp->cn_dev = makedev(maj, unit);
1821 	cp->cn_tp = ite_tty[unit];
1822 	cp->cn_pri = pri;
1823 }
1824 
1825 itecninit(cp)
1826 	struct consdev *cp;
1827 {
1828 	int unit = UNIT(cp->cn_dev);
1829 	struct ite_softc *ip = &ite_softc[unit];
1830 	ip->attrbuf = console_attributes;
1831 	iteinit(cp->cn_dev);
1832 	ip->flags |= (ITE_ACTIVE|ITE_ISCONS);
1833 	kbd_tty = ite_tty[unit];
1834 	kbdenable();
1835 }
1836 
1837 /*ARGSUSED*/
1838 itecngetc(dev)
1839 	dev_t dev;
1840 {
1841 	register int c;
1842 
1843         do
1844           {
1845             c = kbdgetcn ();
1846             c = itefilter (c, ITEFILT_CONSOLE);
1847           }
1848         while (c == -1);
1849 
1850 	return(c);
1851 }
1852 
1853 itecnputc(dev, c)
1854 	dev_t dev;
1855 	int c;
1856 {
1857 	static int paniced = 0;
1858 	struct ite_softc *ip = &ite_softc[UNIT(dev)];
1859 	extern char *panicstr;
1860 
1861 	if (panicstr && !paniced &&
1862 	    (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
1863 		(void) iteon(dev, 3);
1864 		paniced = 1;
1865 	}
1866 	iteputchar(c, dev);
1867 }
1868 #endif
1869