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