Home | History | Annotate | Line # | Download | only in dev
ite.c revision 1.1
      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 1993/07/05 19:19:43 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