Home | History | Annotate | Line # | Download | only in dev
ite.c revision 1.69
      1 /*	$NetBSD: ite.c,v 1.69 2022/06/25 03:18:38 tsutsui Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988 University of Utah.
      5  * Copyright (c) 1990 The Regents of the University of California.
      6  * All rights reserved.
      7  *
      8  * This code is derived from software contributed to Berkeley by
      9  * the Systems Programming Group of the University of Utah Computer
     10  * Science Department.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  * from: Utah $Hdr: ite.c 1.1 90/07/09$
     37  *
     38  *	@(#)ite.c	7.6 (Berkeley) 5/16/91
     39  */
     40 
     41 /*
     42  * ite - bitmaped terminal.
     43  * Supports VT200, a few terminal features will be unavailable until
     44  * the system actually probes the device (i.e. not after consinit())
     45  */
     46 
     47 #include <sys/cdefs.h>
     48 __KERNEL_RCSID(0, "$NetBSD: ite.c,v 1.69 2022/06/25 03:18:38 tsutsui Exp $");
     49 
     50 #include "ite.h"
     51 #if NITE > 0
     52 
     53 #include "bell.h"
     54 #include "kbd.h"
     55 
     56 #include "opt_ite.h"
     57 
     58 #include <sys/param.h>
     59 #include <sys/conf.h>
     60 #include <sys/proc.h>
     61 #include <sys/ioctl.h>
     62 #include <sys/tty.h>
     63 #include <sys/systm.h>
     64 #include <sys/device.h>
     65 #include <sys/malloc.h>
     66 #include <sys/kauth.h>
     67 #include <sys/device_impl.h>	/* XXX autoconf abuse */
     68 
     69 #include <machine/cpu.h>
     70 #include <machine/kbio.h>
     71 #include <machine/bus.h>
     72 #include <machine/autoconf.h>
     73 #include <machine/grfioctl.h>
     74 #include <machine/iteioctl.h>
     75 
     76 #include <arch/x68k/dev/grfvar.h>
     77 #include <arch/x68k/dev/itevar.h>
     78 #include <arch/x68k/dev/kbdmap.h>
     79 #include <arch/x68k/dev/mfp.h>
     80 
     81 #include "ioconf.h"
     82 
     83 #if NBELL > 0
     84 void opm_bell(void);
     85 #endif
     86 
     87 #define SUBR_INIT(ip)		ip->isw->ite_init(ip)
     88 #define SUBR_DEINIT(ip)		ip->isw->ite_deinit(ip)
     89 #define SUBR_PUTC(ip,c,dy,dx,m)	ip->isw->ite_putc(ip,c,dy,dx,m)
     90 #define SUBR_CURSOR(ip,flg)	ip->isw->ite_cursor(ip,flg)
     91 #define SUBR_CLEAR(ip,sy,sx,h,w)	ip->isw->ite_clear(ip,sy,sx,h,w)
     92 #define SUBR_SCROLL(ip,sy,sx,count,dir)	\
     93     ip->isw->ite_scroll(ip,sy,sx,count,dir)
     94 
     95 struct consdev;
     96 
     97 static inline void itesendch(int);
     98 static inline void alignment_display(struct ite_softc *);
     99 static inline void snap_cury(struct ite_softc *);
    100 static inline void ite_dnchar(struct ite_softc *, int);
    101 static void ite_inchar(struct ite_softc *,	int);
    102 static inline void ite_clrtoeol(struct ite_softc *);
    103 static inline void ite_clrtobol(struct ite_softc *);
    104 static inline void ite_clrline(struct ite_softc *);
    105 static inline void ite_clrtoeos(struct ite_softc *);
    106 static inline void ite_clrtobos(struct ite_softc *);
    107 static inline void ite_clrscreen(struct ite_softc *);
    108 static inline void ite_dnline(struct ite_softc *, int);
    109 static inline void ite_inline(struct ite_softc *, int);
    110 static inline void ite_index(struct ite_softc *);
    111 static inline void ite_lf(struct ite_softc *);
    112 static inline void ite_crlf(struct ite_softc *);
    113 static inline void ite_cr(struct ite_softc *);
    114 static inline void ite_rlf(struct ite_softc *);
    115 static void iteprecheckwrap(struct ite_softc *);
    116 static void itecheckwrap(struct ite_softc *);
    117 static int ite_argnum(struct ite_softc *);
    118 static int ite_zargnum(struct ite_softc *);
    119 static void ite_sendstr(struct ite_softc *, const char *);
    120 static inline int atoi(const char *);
    121 static struct ite_softc *getitesp(dev_t);
    122 
    123 static struct itesw itesw[] = {
    124 	{0,	tv_init,	tv_deinit,	0,
    125 	 0,	0,		0}
    126 };
    127 
    128 /*
    129  * # of chars are output in a single itestart() call.
    130  * If this is too big, user processes will be blocked out for
    131  * long periods of time while we are emptying the queue in itestart().
    132  * If it is too small, console output will be very ragged.
    133  */
    134 #define ITEBURST 64
    135 
    136 struct	tty *ite_tty[NITE];
    137 
    138 static struct ite_softc *kbd_ite = NULL;
    139 static struct ite_softc con_itesoftc;
    140 static struct device con_itedev;
    141 
    142 static struct tty *kbd_tty = NULL;
    143 
    144 static int start_repeat_timeo = 20;	/* /100: initial timeout till pressed
    145 						 key repeats */
    146 static int next_repeat_timeo  = 3;	/* /100: timeout when repeating for
    147 						 next char */
    148 
    149 static u_char cons_tabs[MAX_TABS];
    150 
    151 static void itestart(struct tty *);
    152 
    153 static void iteputchar(int, struct ite_softc *);
    154 static void ite_putstr(const u_char *, int, dev_t);
    155 
    156 static int itematch(device_t, cfdata_t, void *);
    157 static void iteattach(device_t, device_t, void *);
    158 
    159 CFATTACH_DECL_NEW(ite, sizeof(struct ite_softc),
    160     itematch, iteattach, NULL, NULL);
    161 
    162 static dev_type_open(iteopen);
    163 static dev_type_close(iteclose);
    164 static dev_type_read(iteread);
    165 static dev_type_write(itewrite);
    166 static dev_type_ioctl(iteioctl);
    167 static dev_type_tty(itetty);
    168 static dev_type_poll(itepoll);
    169 
    170 const struct cdevsw ite_cdevsw = {
    171 	.d_open = iteopen,
    172 	.d_close = iteclose,
    173 	.d_read = iteread,
    174 	.d_write = itewrite,
    175 	.d_ioctl = iteioctl,
    176 	.d_stop = nostop,
    177 	.d_tty = itetty,
    178 	.d_poll = itepoll,
    179 	.d_mmap = nommap,
    180 	.d_kqfilter = ttykqfilter,
    181 	.d_discard = nodiscard,
    182 	.d_flag = D_TTY
    183 };
    184 
    185 static int
    186 itematch(device_t parent, cfdata_t cf, void *aux)
    187 {
    188 	struct grf_softc *gp;
    189 
    190 	gp = aux;
    191 	if (cf->cf_loc[GRFCF_GRFADDR] != gp->g_cfaddr)
    192 		return 0;
    193 
    194 	return 1;
    195 }
    196 
    197 /*
    198  * iteinit() is the standard entry point for initialization of
    199  * an ite device, it is also called from ite_cninit().
    200  */
    201 static void
    202 iteattach(device_t parent, device_t self, void *aux)
    203 {
    204 	struct ite_softc *ip;
    205 	struct grf_softc *gp;
    206 
    207 	gp = aux;
    208 	ip = device_private(self);
    209 	ip->device = self;
    210 	if(con_itesoftc.grf != NULL
    211 		/*&& con_itesoftc.grf->g_unit == gp->g_unit*/) {
    212 		/*
    213 		 * console reinit copy params over.
    214 		 * and console always gets keyboard
    215 		 */
    216 		memcpy(&ip->grf, &con_itesoftc.grf,
    217 		    (char *)&ip[1] - (char *)&ip->grf);
    218 		con_itesoftc.grf = NULL;
    219 		kbd_ite = ip;
    220 	}
    221 	ip->grf = gp;
    222 	iteinit(device_unit(self)); /* XXX */
    223 	aprint_normal(": rows %d cols %d", ip->rows, ip->cols);
    224 	if (kbd_ite == NULL)
    225 		kbd_ite = ip;
    226 	aprint_normal("\n");
    227 }
    228 
    229 static struct ite_softc *
    230 getitesp(dev_t dev)
    231 {
    232 
    233 	if (x68k_realconfig && con_itesoftc.grf == NULL)
    234 		return device_lookup_private(&ite_cd, UNIT(dev));
    235 
    236 	if (con_itesoftc.grf == NULL)
    237 		panic("no ite_softc for console");
    238 	return &con_itesoftc;
    239 }
    240 
    241 void
    242 iteinit(dev_t dev)
    243 {
    244 	struct ite_softc *ip;
    245 
    246 	ip = getitesp(dev);
    247 
    248 	if (ip->flags & ITE_INITED)
    249 		return;
    250 	memcpy(&kbdmap, &ascii_kbdmap, sizeof(struct kbdmap));
    251 
    252 	ip->curx = 0;
    253 	ip->cury = 0;
    254 	ip->cursorx = 0;
    255 	ip->cursory = 0;
    256 
    257 	ip->isw = &itesw[device_unit(ip->device)]; /* XXX */
    258 	SUBR_INIT(ip);
    259 	SUBR_CURSOR(ip, DRAW_CURSOR);
    260 	if (ip->tabs == NULL)
    261 		ip->tabs = malloc(MAX_TABS * sizeof(u_char),
    262 		    M_DEVBUF, M_WAITOK);
    263 	ite_reset(ip);
    264 	ip->flags |= ITE_INITED;
    265 }
    266 
    267 void
    268 ite_config_console(void)
    269 {
    270 	struct grf_softc *gp = &congrf;
    271 
    272 	if (con_itesoftc.grf != NULL)
    273 		return;
    274 	con_itesoftc.grf = gp;
    275 	con_itesoftc.tabs = cons_tabs;
    276 	con_itesoftc.device = &con_itedev;
    277 }
    278 
    279 /*
    280  * Perform functions necessary to setup device as a terminal emulator.
    281  */
    282 int
    283 iteon(dev_t dev, int flag)
    284 {
    285 	int unit = UNIT(dev);
    286 	struct ite_softc *ip;
    287 
    288 	if (unit < 0 || unit >= ite_cd.cd_ndevs ||
    289 	    (ip = getitesp(dev)) == NULL || (ip->flags & ITE_ALIVE) == 0)
    290 		return ENXIO;
    291 	/* force ite active, overriding graphics mode */
    292 	if ((flag & 1) != 0) {
    293 		ip->flags |= ITE_ACTIVE;
    294 		ip->flags &= ~(ITE_INGRF|ITE_INITED);
    295 	}
    296 	/* leave graphics mode */
    297 	if ((flag & 2) != 0) {
    298 		ip->flags &= ~ITE_INGRF;
    299 		if ((ip->flags & ITE_ACTIVE) == 0)
    300 			return 0;
    301 	}
    302 	ip->flags |= ITE_ACTIVE;
    303 	if ((ip->flags & ITE_INGRF) != 0)
    304 		return 0;
    305 	iteinit(dev);
    306 	if ((flag & 2) != 0)
    307 		ite_reset(ip);
    308 #if NKBD > 0
    309 	mfp_send_usart(0x49);	/* XXX */
    310 #endif
    311 	return 0;
    312 }
    313 
    314 /*
    315  * "Shut down" device as terminal emulator.
    316  * Note that we do not deinit the console device unless forced.
    317  * Deinit'ing the console every time leads to a very active
    318  * screen when processing /etc/rc.
    319  */
    320 void
    321 iteoff(dev_t dev, int flag)
    322 {
    323 	int unit = UNIT(dev);
    324 	struct ite_softc *ip;
    325 
    326 	/* XXX check whether when call from grf.c */
    327 	if (unit < 0 || unit >= ite_cd.cd_ndevs ||
    328 	    (ip = getitesp(dev)) == NULL || (ip->flags & ITE_ALIVE) == 0)
    329 		return;
    330 	if ((flag & 2) != 0)
    331 		ip->flags |= ITE_INGRF;
    332 
    333 	if ((ip->flags & ITE_ACTIVE) == 0)
    334 		return;
    335 	if ((flag & 1) != 0 ||
    336 	    (ip->flags & (ITE_INGRF | ITE_ISCONS | ITE_INITED)) == ITE_INITED)
    337 		SUBR_DEINIT(ip);
    338 
    339 	/*
    340 	 * XXX When the system is rebooted with "reboot", init(8)
    341 	 * kills the last process to have the console open.
    342 	 * If we don't revent the ITE_ACTIVE bit from being
    343 	 * cleared, we will never see messages printed during
    344 	 * the process of rebooting.
    345 	 */
    346 	if ((flag & 2) == 0 && (ip->flags & ITE_ISCONS) == 0) {
    347 		ip->flags &= ~ITE_ACTIVE;
    348 #if NKBD > 0
    349 		mfp_send_usart(0x48);	/* XXX */
    350 #endif
    351 	}
    352 }
    353 
    354 /*
    355  * standard entry points to the device.
    356  */
    357 
    358 /* ARGSUSED */
    359 static int
    360 iteopen(dev_t dev, int mode, int devtype, struct lwp *l)
    361 {
    362 	int unit = UNIT(dev);
    363 	struct tty *tp;
    364 	struct ite_softc *ip;
    365 	int error;
    366 	int first = 0;
    367 
    368 	if (unit >= ite_cd.cd_ndevs || (ip = getitesp(dev)) == NULL)
    369 		return ENXIO;
    370 	if (ite_tty[unit] == NULL) {
    371 		tp = ite_tty[unit] = tty_alloc();
    372 		tty_attach(tp);
    373 	} else
    374 		tp = ite_tty[unit];
    375 	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
    376 		return EBUSY;
    377 	if ((ip->flags & ITE_ACTIVE) == 0) {
    378 		error = iteon(dev, 0);
    379 		if (error)
    380 			return error;
    381 		first = 1;
    382 	}
    383 	tp->t_oproc = itestart;
    384 	tp->t_param = NULL;
    385 	tp->t_dev = dev;
    386 	if ((tp->t_state&TS_ISOPEN) == 0) {
    387 		ttychars(tp);
    388 		tp->t_iflag = TTYDEF_IFLAG;
    389 		tp->t_oflag = TTYDEF_OFLAG;
    390 		tp->t_cflag = TTYDEF_CFLAG;
    391 		tp->t_lflag = TTYDEF_LFLAG;
    392 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
    393 		tp->t_state = TS_ISOPEN|TS_CARR_ON;
    394 		ttsetwater(tp);
    395 	}
    396 	error = (*tp->t_linesw->l_open)(dev, tp);
    397 	if (error == 0) {
    398 		tp->t_winsize.ws_row = ip->rows;
    399 		tp->t_winsize.ws_col = ip->cols;
    400 	} else if (first)
    401 		iteoff(dev, 0);
    402 	return error;
    403 }
    404 
    405 /*ARGSUSED*/
    406 static int
    407 iteclose(dev_t dev, int flag, int mode, struct lwp *l)
    408 {
    409 	struct tty *tp = ite_tty[UNIT(dev)];
    410 
    411 	(*tp->t_linesw->l_close)(tp, flag);
    412 	ttyclose(tp);
    413 	iteoff(dev, 0);
    414 #if 0
    415 	tty_free(tp);
    416 	ite_tty[UNIT(dev)] = NULL;
    417 #endif
    418 	return 0;
    419 }
    420 
    421 static int
    422 iteread(dev_t dev, struct uio *uio, int flag)
    423 {
    424 	struct tty *tp = ite_tty[UNIT(dev)];
    425 
    426 	return (*tp->t_linesw->l_read)(tp, uio, flag);
    427 }
    428 
    429 static int
    430 itewrite(dev_t dev, struct uio *uio, int flag)
    431 {
    432 	struct tty *tp = ite_tty[UNIT(dev)];
    433 
    434 	return (*tp->t_linesw->l_write)(tp, uio, flag);
    435 }
    436 
    437 static int
    438 itepoll(dev_t dev, int events, struct lwp *l)
    439 {
    440 	struct tty *tp = ite_tty[UNIT(dev)];
    441 
    442 	return (*tp->t_linesw->l_poll)(tp, events, l);
    443 }
    444 
    445 static struct tty *
    446 itetty(dev_t dev)
    447 {
    448 
    449 	return ite_tty[UNIT(dev)];
    450 }
    451 
    452 static int
    453 iteioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
    454 {
    455 	struct iterepeat *irp;
    456 	struct tty *tp = ite_tty[UNIT(dev)];
    457 	int error;
    458 
    459 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, addr, flag, l);
    460 	if (error != EPASSTHROUGH)
    461 		return error;
    462 
    463 	error = ttioctl(tp, cmd, addr, flag, l);
    464 	if (error != EPASSTHROUGH)
    465 		return error;
    466 
    467 	switch (cmd) {
    468 	case ITEIOCSKMAP:
    469 		if (addr == NULL)
    470 			return EFAULT;
    471 		memcpy(&kbdmap, addr, sizeof(struct kbdmap));
    472 		return 0;
    473 
    474 	case ITEIOCGKMAP:
    475 		if (addr == NULL)
    476 			return EFAULT;
    477 		memcpy(addr, &kbdmap, sizeof(struct kbdmap));
    478 		return 0;
    479 
    480 	case ITEIOCGREPT:
    481 		irp = (struct iterepeat *)addr;
    482 		irp->start = start_repeat_timeo;
    483 		irp->next = next_repeat_timeo;
    484 
    485 	case ITEIOCSREPT:
    486 		irp = (struct iterepeat *)addr;
    487 		if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
    488 			return(EINVAL);
    489 		start_repeat_timeo = irp->start;
    490 		next_repeat_timeo = irp->next;
    491 #if x68k
    492 	case ITELOADFONT:
    493 		if (addr != NULL) {
    494 			memcpy(kern_font, addr, 4096 /*sizeof(kernel_font)*/);
    495 			ite_set_glyph();
    496 			return 0;
    497 		} else
    498 			return EFAULT;
    499 
    500 	case ITETVCTRL:
    501 		if (addr != NULL && *(uint8_t *)addr < 0x40) {
    502 			return mfp_send_usart(*(uint8_t *)addr);
    503 		} else {
    504 			return EFAULT;
    505 		}
    506 #endif
    507 	}
    508 	return EPASSTHROUGH;
    509 }
    510 
    511 static void
    512 itestart(struct tty *tp)
    513 {
    514 	struct clist *rbp;
    515 	uint8_t buf[ITEBURST];
    516 	int s, len;
    517 
    518 	getitesp(tp->t_dev);
    519 	/*
    520 	 * (Potentially) lower priority.  We only need to protect ourselves
    521 	 * from keyboard interrupts since that is all that can affect the
    522 	 * state of our tty (kernel printf doesn't go through this routine).
    523 	 */
    524 	s = spltty();
    525 	if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) != 0)
    526 		goto out;
    527 	tp->t_state |= TS_BUSY;
    528 	rbp = &tp->t_outq;
    529 	len = q_to_b(rbp, buf, ITEBURST);
    530 	/*splx(s);*/
    531 
    532 	/* Here is a really good place to implement pre/jumpscroll() */
    533 	ite_putstr(buf, len, tp->t_dev);
    534 
    535 	/*s = spltty();*/
    536 	tp->t_state &= ~TS_BUSY;
    537 	/* we have characters remaining. */
    538 	if (ttypull(tp)) {
    539 		tp->t_state |= TS_TIMEOUT;
    540 		callout_schedule(&tp->t_rstrt_ch, 1);
    541 	}
    542  out:
    543 	splx(s);
    544 }
    545 
    546 /* XXX called after changes made in underlying grf layer. */
    547 /* I want to nuke this */
    548 void
    549 ite_reinit(dev_t dev)
    550 {
    551 	struct ite_softc *ip;
    552 	int unit = UNIT(dev);
    553 
    554 	/* XXX check whether when call from grf.c */
    555 	if (unit < 0 || unit >= ite_cd.cd_ndevs ||
    556 	    (ip = getitesp(dev)) == NULL)
    557 		return;
    558 
    559 	ip->flags &= ~ITE_INITED;
    560 	iteinit(dev);
    561 }
    562 
    563 void
    564 ite_reset(struct ite_softc *ip)
    565 {
    566 	int i;
    567 
    568 	ip->curx = 0;
    569 	ip->cury = 0;
    570 	ip->attribute = 0;
    571 	ip->save_curx = 0;
    572 	ip->save_cury = 0;
    573 	ip->save_attribute = 0;
    574 	ip->ap = ip->argbuf;
    575 	ip->emul_level = EMUL_VT300_8;
    576 	ip->eightbit_C1 = 0;
    577 	ip->top_margin = 0;
    578 	ip->bottom_margin = ip->rows - 1;
    579 	ip->inside_margins = 0; /* origin mode == absolute */
    580 	ip->linefeed_newline = 0;
    581 	ip->auto_wrap = 1;
    582 	ip->cursor_appmode = 0;
    583 	ip->keypad_appmode = 0;
    584 	ip->imode = 0;
    585 	ip->key_repeat = 1;
    586 	ip->G0 = CSET_ASCII;
    587 	ip->G1 = CSET_JIS1983;
    588 	ip->G2 = CSET_JISKANA;
    589 	ip->G3 = CSET_JIS1990;
    590 	ip->GL = &ip->G0;
    591 	ip->GR = &ip->G1;
    592 	ip->save_GL = 0;
    593 	ip->save_char = 0;
    594 	ip->fgcolor = 7;
    595 	ip->bgcolor = 0;
    596 	for (i = 0; i < ip->cols; i++)
    597 		ip->tabs[i] = ((i & 7) == 0);
    598 	/* XXX clear screen */
    599 	SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
    600 	attrclr(ip, 0, 0, ip->rows, ip->cols);
    601 }
    602 
    603 /* Used in console at startup only */
    604 int
    605 ite_cnfilter(u_char c)
    606 {
    607 	static u_char mod = 0;
    608 	struct key key;
    609 	uint8_t code, up, mask;
    610 	int s;
    611 
    612 	up = c & 0x80 ? 1 : 0;
    613 	c &= 0x7f;
    614 	code = 0;
    615 
    616 	s = spltty();
    617 
    618 	mask = 0;
    619 	if (c >= KBD_LEFT_ALT &&
    620 	    !(c >= 0x63 && c <= 0x6c)) {	/* 0x63: F1, 0x6c:F10 */
    621 		switch (c) {
    622 		case KBD_LEFT_SHIFT:
    623 			mask = KBD_MOD_SHIFT;
    624 			break;
    625 
    626 		case KBD_LEFT_ALT:
    627 			mask = KBD_MOD_LALT;
    628 			break;
    629 
    630 		case KBD_RIGHT_ALT:
    631 			mask = KBD_MOD_RALT;
    632 			break;
    633 
    634 		case KBD_LEFT_META:
    635 			mask = KBD_MOD_LMETA;
    636 			break;
    637 
    638 		case KBD_RIGHT_META:
    639 			mask = KBD_MOD_RMETA;
    640 			break;
    641 
    642 		case KBD_CAPS_LOCK:
    643 			/*
    644 			 * capslock already behaves `right', don't need to
    645 			 * keep track of the state in here.
    646 			 */
    647 			mask = KBD_MOD_CAPS;
    648 			break;
    649 
    650 		case KBD_CTRL:
    651 			mask = KBD_MOD_CTRL;
    652 			break;
    653 
    654 		case KBD_RECONNECT:
    655 			/* ite got 0xff */
    656 			if (up)
    657 				kbd_setLED();
    658 			break;
    659 		}
    660 		if (mask & KBD_MOD_CAPS) {
    661 			if (!up) {
    662 				mod ^= KBD_MOD_CAPS;
    663 				kbdled ^= LED_CAPS_LOCK;
    664 				kbd_setLED();
    665 			}
    666 		} else if (up)
    667 			mod &= ~mask;
    668 		else
    669 			mod |= mask;
    670 		splx(s);
    671 		return -1;
    672 	}
    673 
    674 	if (up) {
    675 		splx(s);
    676 		return -1;
    677 	}
    678 
    679 	/* translate modifiers */
    680 	if ((mod & KBD_MOD_SHIFT) != 0) {
    681 		if ((mod & KBD_MOD_ALT) != 0)
    682 			key = kbdmap.alt_shift_keys[c];
    683 		else
    684 			key = kbdmap.shift_keys[c];
    685 	} else if ((mod & KBD_MOD_ALT) != 0)
    686 		key = kbdmap.alt_keys[c];
    687 	else {
    688 		key = kbdmap.keys[c];
    689 		/* if CAPS and key is CAPable (no pun intended) */
    690 		if ((mod & KBD_MOD_CAPS) != 0 &&
    691 		    (key.mode & KBD_MODE_CAPS) != 0)
    692 			key = kbdmap.shift_keys[c];
    693 	}
    694 	code = key.code;
    695 
    696 	/* if string return */
    697 	if ((key.mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) != 0) {
    698 		splx(s);
    699 		return -1;
    700 	}
    701 	/* handle dead keys */
    702 	if ((key.mode & KBD_MODE_DEAD) != 0) {
    703 		splx(s);
    704 		return -1;
    705 	}
    706 	if ((mod & KBD_MOD_CTRL) != 0)
    707 		code &= 0x1f;
    708 	if ((mod & KBD_MOD_META) != 0)
    709 		code |= 0x80;
    710 
    711 	/* do console mapping. */
    712 	code = code == '\r' ? '\n' : code;
    713 
    714 	splx(s);
    715 	return code;
    716 }
    717 
    718 /* And now the old stuff. */
    719 static inline void
    720 itesendch(int ch)
    721 {
    722 
    723 	(*kbd_tty->t_linesw->l_rint)(ch, kbd_tty);
    724 }
    725 
    726 void
    727 ite_filter(u_char c)
    728 {
    729 	static uint16_t mod = 0;
    730 	uint8_t code, *str;
    731 	uint16_t up, mask;
    732 	struct key key;
    733 	int s, i;
    734 
    735 	if (kbd_ite == NULL ||
    736 	    (kbd_tty = ite_tty[device_unit(kbd_ite->device)]) == NULL)
    737 		return;
    738 
    739 	/* have to make sure we're at spltty in here */
    740 	s = spltty();
    741 
    742 	up = c & 0x80 ? 1 : 0;
    743 	c &= 0x7f;
    744 	code = 0;
    745 
    746 	mask = 0;
    747 	if (c >= KBD_LEFT_ALT &&
    748 	    !(c >= 0x63 && c <= 0x6c)) {	/* 0x63: F1, 0x6c:F10 */
    749 		switch (c) {
    750 		case KBD_LEFT_SHIFT:
    751 			mask = KBD_MOD_SHIFT;
    752 			break;
    753 
    754 		case KBD_LEFT_ALT:
    755 			mask = KBD_MOD_LALT;
    756 			break;
    757 
    758 		case KBD_RIGHT_ALT:
    759 			mask = KBD_MOD_RALT;
    760 			break;
    761 
    762 		case KBD_LEFT_META:
    763 			mask = KBD_MOD_LMETA;
    764 			break;
    765 
    766 		case KBD_RIGHT_META:
    767 			mask = KBD_MOD_RMETA;
    768 			break;
    769 
    770 		case KBD_CAPS_LOCK:
    771 			/*
    772 			 * capslock already behaves `right', don't need to keep
    773 			 * track of the state in here.
    774 			 */
    775 			mask = KBD_MOD_CAPS;
    776 			break;
    777 
    778 		case KBD_CTRL:
    779 			mask = KBD_MOD_CTRL;
    780 			break;
    781 
    782 		case KBD_OPT1:
    783 			mask = KBD_MOD_OPT1;
    784 			break;
    785 
    786 		case KBD_OPT2:
    787 			mask = KBD_MOD_OPT2;
    788 			break;
    789 
    790 		case KBD_RECONNECT:
    791 			if (up) { /* ite got 0xff */
    792 				kbd_setLED();
    793 			}
    794 			break;
    795 		}
    796 
    797 		if ((mask & KBD_MOD_CAPS) != 0) {
    798 			if (!up) {
    799 				mod ^= KBD_MOD_CAPS;
    800 				kbdled ^= LED_CAPS_LOCK;
    801 				kbd_setLED();
    802 			}
    803 		} else if (up) {
    804 			mod &= ~mask;
    805 		} else
    806 			mod |= mask;
    807 
    808 		/*
    809 		 * return even if it wasn't a modifier key, the other
    810 		 * codes up here are either special (like reset warning),
    811 		 * or not yet defined
    812 		 */
    813 		splx(s);
    814 		return;
    815 	}
    816 
    817 	if (up) {
    818 		splx(s);
    819 		return;
    820 	}
    821 
    822 	/*
    823 	 * intercept LAlt-LMeta-F1 here to switch back to original ascii-keymap.
    824 	 * this should probably be configurable..
    825 	 */
    826 	if (mod == (KBD_MOD_LALT|KBD_MOD_LMETA) && c == 0x63) {
    827 		memcpy(&kbdmap, &ascii_kbdmap, sizeof(struct kbdmap));
    828 		splx(s);
    829 		return;
    830 	}
    831 
    832 	/* translate modifiers */
    833 	if ((mod & KBD_MOD_SHIFT) != 0) {
    834 		if ((mod & KBD_MOD_ALT) != 0)
    835 			key = kbdmap.alt_shift_keys[c];
    836 		else
    837 			key = kbdmap.shift_keys[c];
    838 	} else if ((mod & KBD_MOD_ALT) != 0)
    839 		key = kbdmap.alt_keys[c];
    840 	else {
    841 		key = kbdmap.keys[c];
    842 		/* if CAPS and key is CAPable (no pun intended) */
    843 		if ((mod & KBD_MOD_CAPS) != 0 &&
    844 		    (key.mode & KBD_MODE_CAPS) != 0)
    845 			key = kbdmap.shift_keys[c];
    846 		else if ((mod & KBD_MOD_OPT2) != 0 &&
    847 		    	 (key.mode & KBD_MODE_KPAD) != 0)
    848 			key = kbdmap.shift_keys[c];
    849 	}
    850 	code = key.code;
    851 
    852 	/* handle dead keys */
    853 	if ((key.mode & KBD_MODE_DEAD) != 0) {
    854 		splx(s);
    855 		return;
    856 	}
    857 	/* if not string, apply META and CTRL modifiers */
    858 	if ((key.mode & KBD_MODE_STRING) == 0 &&
    859 	    ((key.mode & KBD_MODE_KPAD) == 0 ||
    860 	     (kbd_ite != NULL && kbd_ite->keypad_appmode == 0))) {
    861 		if ((mod & KBD_MOD_CTRL) != 0 &&
    862 		    (code == ' ' || (code >= '@' && code <= 'z')))
    863 			code &= 0x1f;
    864 		if ((mod & KBD_MOD_META) != 0)
    865 			code |= 0x80;
    866 	} else if ((key.mode & KBD_MODE_KPAD) != 0 &&
    867 	       (kbd_ite != NULL && kbd_ite->keypad_appmode != 0)) {
    868 		static const char * const in = "0123456789-+.\r()/*";
    869 		static const char * const out = "pqrstuvwxymlnMPQRS";
    870 		char *cp = strchr(in, code);
    871 
    872 		/*
    873 		 * keypad-appmode sends SS3 followed by the above
    874 		 * translated character
    875 		 */
    876 		(*kbd_tty->t_linesw->l_rint)(27, kbd_tty);
    877 		(*kbd_tty->t_linesw->l_rint)('O', kbd_tty);
    878 		(*kbd_tty->t_linesw->l_rint)(out[cp - in], kbd_tty);
    879 		splx(s);
    880 		return;
    881 	} else {
    882 		/* *NO* I don't like this.... */
    883 		static u_char app_cursor[] = {
    884 		  3, 27, 'O', 'A',
    885 		  3, 27, 'O', 'B',
    886 		  3, 27, 'O', 'C',
    887 		  3, 27, 'O', 'D'
    888 		};
    889 
    890 		str = kbdmap.strings + code;
    891 		/*
    892 		 * if this is a cursor key, AND it has the default
    893 		 * keymap setting, AND we're in app-cursor mode, switch
    894 		 * to the above table. This is *nasty* !
    895 		 */
    896 		if (c >= 0x3b && c <= 0x3e && kbd_ite->cursor_appmode != 0 &&
    897 		    memcmp(str, "\x03\x1b[", 3) == 0 &&
    898 		    strchr("ABCD", str[3]) != 0)
    899 			str = app_cursor + 4 * (str[3] - 'A');
    900 
    901 		/*
    902 		 * using a length-byte instead of 0-termination allows
    903 		 * to embed \0 into strings, although this is not used
    904 		 * in the default keymap
    905 		 */
    906 		for (i = *str++; i; i--)
    907 			(*kbd_tty->t_linesw->l_rint)(*str++, kbd_tty);
    908 		splx(s);
    909 		return;
    910 	}
    911 	(*kbd_tty->t_linesw->l_rint)(code, kbd_tty);
    912 
    913 	splx(s);
    914 	return;
    915 }
    916 
    917 /* helper functions, makes the code below more readable */
    918 static inline void
    919 ite_sendstr(struct ite_softc *ip, const char *str)
    920 {
    921 
    922 	while (*str != 0)
    923 		itesendch(*str++);
    924 }
    925 
    926 static inline void
    927 alignment_display(struct ite_softc *ip)
    928 {
    929 	int i, j;
    930 
    931 	for (j = 0; j < ip->rows; j++)
    932 		for (i = 0; i < ip->cols; i++)
    933 			SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
    934 	attrclr(ip, 0, 0, ip->rows, ip->cols);
    935 }
    936 
    937 static inline void
    938 snap_cury(struct ite_softc *ip)
    939 {
    940 
    941 	if (ip->inside_margins != 0) {
    942 		if (ip->cury < ip->top_margin)
    943 			ip->cury = ip->top_margin;
    944 		if (ip->cury > ip->bottom_margin)
    945 			ip->cury = ip->bottom_margin;
    946 	}
    947 }
    948 
    949 static inline void
    950 ite_dnchar(struct ite_softc *ip, int n)
    951 {
    952 
    953 	n = uimin(n, ip->cols - ip->curx);
    954 	if (n < ip->cols - ip->curx) {
    955 		SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
    956 		attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
    957 		    1, ip->cols - ip->curx - n);
    958 		attrclr(ip, ip->cury, ip->cols - n, 1, n);
    959 	}
    960 	while (n-- > 0)
    961 		SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
    962 }
    963 
    964 static void
    965 ite_inchar(struct ite_softc *ip, int n)
    966 {
    967 	int c = ip->save_char;
    968 
    969 	ip->save_char = 0;
    970 	n = uimin(n, ip->cols - ip->curx);
    971 	if (n < ip->cols - ip->curx) {
    972 		SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
    973 		attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
    974 		    1, ip->cols - ip->curx - n);
    975 		attrclr(ip, ip->cury, ip->curx, 1, n);
    976 	}
    977 	while (n-- != 0)
    978 		SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
    979 	ip->save_char = c;
    980 }
    981 
    982 static inline void
    983 ite_clrtoeol(struct ite_softc *ip)
    984 {
    985 	int y = ip->cury, x = ip->curx;
    986 
    987 	if (ip->cols - x > 0) {
    988 		SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
    989 		attrclr(ip, y, x, 1, ip->cols - x);
    990 	}
    991 }
    992 
    993 static inline void
    994 ite_clrtobol(struct ite_softc *ip)
    995 {
    996 	int y = ip->cury, x = uimin(ip->curx + 1, ip->cols);
    997 
    998 	SUBR_CLEAR(ip, y, 0, 1, x);
    999 	attrclr(ip, y, 0, 1, x);
   1000 }
   1001 
   1002 static inline void
   1003 ite_clrline(struct ite_softc *ip)
   1004 {
   1005 	int y = ip->cury;
   1006 
   1007 	SUBR_CLEAR(ip, y, 0, 1, ip->cols);
   1008 	attrclr(ip, y, 0, 1, ip->cols);
   1009 }
   1010 
   1011 static inline void
   1012 ite_clrtoeos(struct ite_softc *ip)
   1013 {
   1014 
   1015 	ite_clrtoeol(ip);
   1016 	if (ip->cury < ip->rows - 1) {
   1017 		SUBR_CLEAR(ip, ip->cury + 1, 0,
   1018 		    ip->rows - 1 - ip->cury, ip->cols);
   1019 		attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
   1020 	}
   1021 }
   1022 
   1023 static inline void
   1024 ite_clrtobos(struct ite_softc *ip)
   1025 {
   1026 
   1027 	ite_clrtobol(ip);
   1028 	if (ip->cury > 0) {
   1029 		SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
   1030 		attrclr(ip, 0, 0, ip->cury, ip->cols);
   1031 	}
   1032 }
   1033 
   1034 static inline void
   1035 ite_clrscreen(struct ite_softc *ip)
   1036 {
   1037 
   1038 	SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
   1039 	attrclr(ip, 0, 0, ip->rows, ip->cols);
   1040 }
   1041 
   1042 static inline void
   1043 ite_dnline(struct ite_softc *ip, int n)
   1044 {
   1045 
   1046 	/*
   1047 	 * interesting.. if the cursor is outside the scrolling
   1048 	 * region, this command is simply ignored..
   1049 	 */
   1050 	if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
   1051 		return;
   1052 
   1053 	n = uimin(n, ip->bottom_margin + 1 - ip->cury);
   1054 	if (n <= ip->bottom_margin - ip->cury) {
   1055 		SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
   1056 		attrmov(ip, ip->cury + n, 0, ip->cury, 0,
   1057 		    ip->bottom_margin + 1 - ip->cury - n, ip->cols);
   1058 	}
   1059 	SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
   1060 	attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
   1061 }
   1062 
   1063 static inline void
   1064 ite_inline(struct ite_softc *ip, int n)
   1065 {
   1066 
   1067 	/*
   1068 	 * interesting.. if the cursor is outside the scrolling
   1069 	 * region, this command is simply ignored..
   1070 	 */
   1071 	if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
   1072 		return;
   1073 
   1074 	if (n <= 0)
   1075 		n = 1;
   1076 	else
   1077 		n = uimin(n, ip->bottom_margin + 1 - ip->cury);
   1078 	if (n <= ip->bottom_margin  - ip->cury) {
   1079 		SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
   1080 		attrmov(ip, ip->cury, 0, ip->cury + n, 0,
   1081 		    ip->bottom_margin + 1 - ip->cury - n, ip->cols);
   1082 	}
   1083 	SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
   1084 	attrclr(ip, ip->cury, 0, n, ip->cols);
   1085 	ip->curx = 0;
   1086 }
   1087 
   1088 static inline void
   1089 ite_index(struct ite_softc *ip)
   1090 {
   1091 
   1092 	++ip->cury;
   1093 	if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows)) {
   1094 		ip->cury--;
   1095 		SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
   1096 		ite_clrline(ip);
   1097 	}
   1098 	/*clr_attr(ip, ATTR_INV);*/
   1099 }
   1100 
   1101 static inline void
   1102 ite_lf(struct ite_softc *ip)
   1103 {
   1104 
   1105 	++ip->cury;
   1106 	if (ip->cury > ip->bottom_margin) {
   1107 		ip->cury--;
   1108 		SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
   1109 		ite_clrline(ip);
   1110 	}
   1111 	/*SUBR_CURSOR(ip, MOVE_CURSOR);*/
   1112 	/*clr_attr(ip, ATTR_INV);*/
   1113 	/* reset character set ... thanks for mohta. */
   1114 	ip->G0 = CSET_ASCII;
   1115 	ip->G1 = CSET_JIS1983;
   1116 	ip->G2 = CSET_JISKANA;
   1117 	ip->G3 = CSET_JIS1990;
   1118 	ip->GL = &ip->G0;
   1119 	ip->GR = &ip->G1;
   1120 	ip->save_GL = 0;
   1121 	ip->save_char = 0;
   1122 }
   1123 
   1124 static inline void
   1125 ite_crlf(struct ite_softc *ip)
   1126 {
   1127 
   1128 	ip->curx = 0;
   1129 	ite_lf(ip);
   1130 }
   1131 
   1132 static inline void
   1133 ite_cr(struct ite_softc *ip)
   1134 {
   1135 
   1136 	if (ip->curx != 0) {
   1137 		ip->curx = 0;
   1138 	}
   1139 }
   1140 
   1141 static inline void
   1142 ite_rlf(struct ite_softc *ip)
   1143 {
   1144 
   1145 	ip->cury--;
   1146 	if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1)) {
   1147 		ip->cury++;
   1148 		SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
   1149 		ite_clrline(ip);
   1150 	}
   1151 	clr_attr(ip, ATTR_INV);
   1152 }
   1153 
   1154 static inline int
   1155 atoi(const char *cp)
   1156 {
   1157 	int n;
   1158 
   1159 	for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
   1160 		n = n * 10 + *cp - '0';
   1161 	return n;
   1162 }
   1163 
   1164 static inline int
   1165 ite_argnum(struct ite_softc *ip)
   1166 {
   1167 	char ch;
   1168 	int n;
   1169 
   1170 	/* convert argument string into number */
   1171 	if (ip->ap == ip->argbuf)
   1172 		return 1;
   1173 	ch = *ip->ap;
   1174 	*ip->ap = 0;
   1175 	n = atoi(ip->argbuf);
   1176 	*ip->ap = ch;
   1177 
   1178 	return n;
   1179 }
   1180 
   1181 static inline int
   1182 ite_zargnum(struct ite_softc *ip)
   1183 {
   1184 	char ch;
   1185 	int n;
   1186 
   1187 	/* convert argument string into number */
   1188 	if (ip->ap == ip->argbuf)
   1189 		return 0;
   1190 	ch = *ip->ap;
   1191 	*ip->ap = 0;	/* terminate string */
   1192 	n = atoi(ip->argbuf);
   1193 	*ip->ap = ch;
   1194 
   1195 	return n;	/* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
   1196 }
   1197 
   1198 static void
   1199 ite_putstr(const u_char *s, int len, dev_t dev)
   1200 {
   1201 	struct ite_softc *ip;
   1202 	int i;
   1203 
   1204 	ip = getitesp(dev);
   1205 
   1206 	/* XXX avoid problems */
   1207 	if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
   1208 	  	return;
   1209 
   1210 	SUBR_CURSOR(ip, START_CURSOROPT);
   1211 	for (i = 0; i < len; i++)
   1212 		if (s[i] != 0)
   1213 			iteputchar(s[i], ip);
   1214 	SUBR_CURSOR(ip, END_CURSOROPT);
   1215 }
   1216 
   1217 static void
   1218 iteputchar(int c, struct ite_softc *ip)
   1219 {
   1220 	int n, x, y;
   1221 	char *cp;
   1222 
   1223 	if (c >= 0x20 && ip->escape != 0) {
   1224 		switch (ip->escape) {
   1225 
   1226 		case ESC:
   1227 			switch (c) {
   1228 			/*
   1229 			 * first 7bit equivalents for the 8bit control
   1230 			 * characters
   1231 			 */
   1232 
   1233 			case 'D':
   1234 				c = IND;
   1235 				ip->escape = 0;
   1236 				break;
   1237 				/*
   1238 				 * and fall into the next switch below
   1239 				 * (same for all `break')
   1240 				 */
   1241 
   1242 			case 'E':
   1243 				/* next line */
   1244 				c = NEL;
   1245 				ip->escape = 0;
   1246 				break;
   1247 
   1248 			case 'H':
   1249 				/* set TAB at current col */
   1250 				c = HTS;
   1251 				ip->escape = 0;
   1252 				break;
   1253 
   1254 			case 'M':
   1255 				/* reverse index */
   1256 				c = RI;
   1257 				ip->escape = 0;
   1258 				break;
   1259 
   1260 			case 'N':
   1261 				/* single shift G2 */
   1262 				c = SS2;
   1263 				ip->escape = 0;
   1264 				break;
   1265 
   1266 			case 'O':
   1267 				/* single shift G3 */
   1268 				c = SS3;
   1269 				ip->escape = 0;
   1270 				break;
   1271 
   1272 			case 'P':
   1273 				/* DCS detected */
   1274 				c = DCS;
   1275 				ip->escape = 0;
   1276 				break;
   1277 
   1278 			case '[':
   1279 				c = CSI;
   1280 				ip->escape = 0;
   1281 				break;
   1282 
   1283 			case '\\':
   1284 				/* String Terminator */
   1285 				c = ST;
   1286 				ip->escape = 0;
   1287 				break;
   1288 
   1289 			case ']':
   1290 				c = OSC;
   1291 				ip->escape = 0;
   1292 				break;
   1293 
   1294 			case '^':
   1295 				c = PM;
   1296 				ip->escape = 0;
   1297 				break;
   1298 
   1299 			case '_':
   1300 				c = APC;
   1301 				ip->escape = 0;
   1302 				break;
   1303 
   1304 			/* introduces 7/8bit control */
   1305 			case ' ':
   1306 				/* can be followed by either F or G */
   1307 				ip->escape = ' ';
   1308 				break;
   1309 
   1310 			/* a lot of character set selections, not yet used... */
   1311 			/* 94-character sets: */
   1312 			case '(':	/* G0 */
   1313 			case ')':	/* G1 */
   1314 				ip->escape = c;
   1315 				return;
   1316 
   1317 			case '*':	/* G2 */
   1318 			case '+':	/* G3 */
   1319 			case 'B':	/* ASCII */
   1320 			case 'A':	/* ISO latin 1 */
   1321 			case '<':	/* user preferred suplemental */
   1322 			case '0':	/* dec special graphics */
   1323 
   1324 			/* 96-character sets: */
   1325 			case '-':	/* G1 */
   1326 			case '.':	/* G2 */
   1327 			case '/':	/* G3 */
   1328 
   1329 			/* national character sets: */
   1330 			case '4':	/* dutch */
   1331 			case '5':
   1332 			case 'C':	/* finnish */
   1333 			case 'R':	/* french */
   1334 			case 'Q':	/* french canadian */
   1335 			case 'K':	/* german */
   1336 			case 'Y':	/* italian */
   1337 			case '6':	/* norwegian/danish */
   1338 			/* note: %5 and %6 are not supported (two chars..) */
   1339 
   1340 				ip->escape = 0;
   1341 				/* just ignore for now */
   1342 				return;
   1343 
   1344 			/* 94-multibyte character sets designate */
   1345 			case '$':
   1346 				ip->escape = '$';
   1347 				return;
   1348 
   1349 			/* locking shift modes */
   1350 			case '`':
   1351 				ip->GR = &ip->G1;
   1352 				ip->escape = 0;
   1353 				return;
   1354 
   1355 			case 'n':
   1356 				ip->GL = &ip->G2;
   1357 				ip->escape = 0;
   1358 				return;
   1359 
   1360 			case '}':
   1361 				ip->GR = &ip->G2;
   1362 				ip->escape = 0;
   1363 				return;
   1364 
   1365 			case 'o':
   1366 				ip->GL = &ip->G3;
   1367 				ip->escape = 0;
   1368 				return;
   1369 
   1370 			case '|':
   1371 				ip->GR = &ip->G3;
   1372 				ip->escape = 0;
   1373 				return;
   1374 
   1375 			case '~':
   1376 				ip->GR = &ip->G1;
   1377 				ip->escape = 0;
   1378 				return;
   1379 
   1380 			/* font width/height control */
   1381 			case '#':
   1382 				ip->escape = '#';
   1383 				return;
   1384 
   1385 			case 'c':
   1386 				/* hard terminal reset .. */
   1387 				ite_reset(ip);
   1388 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1389 				ip->escape = 0;
   1390 				return;
   1391 
   1392 			case '7':
   1393 				/* save cursor */
   1394 				ip->save_curx = ip->curx;
   1395 				ip->save_cury = ip->cury;
   1396 				ip->save_attribute = ip->attribute;
   1397 				ip->sc_om = ip->inside_margins;
   1398 				ip->sc_G0 = ip->G0;
   1399 				ip->sc_G1 = ip->G1;
   1400 				ip->sc_G2 = ip->G2;
   1401 				ip->sc_G3 = ip->G3;
   1402 				ip->sc_GL = ip->GL;
   1403 				ip->sc_GR = ip->GR;
   1404 				ip->escape = 0;
   1405 				return;
   1406 
   1407 			case '8':
   1408 				/* restore cursor */
   1409 				ip->curx = ip->save_curx;
   1410 				ip->cury = ip->save_cury;
   1411 				ip->attribute = ip->save_attribute;
   1412 				ip->inside_margins = ip->sc_om;
   1413 				ip->G0 = ip->sc_G0;
   1414 				ip->G1 = ip->sc_G1;
   1415 				ip->G2 = ip->sc_G2;
   1416 				ip->G3 = ip->sc_G3;
   1417 				ip->GL = ip->sc_GL;
   1418 				ip->GR = ip->sc_GR;
   1419 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1420 				ip->escape = 0;
   1421 				return;
   1422 
   1423 			case '=':
   1424 				/* keypad application mode */
   1425 				ip->keypad_appmode = 1;
   1426 				ip->escape = 0;
   1427 				return;
   1428 
   1429 			case '>':
   1430 				/* keypad numeric mode */
   1431 				ip->keypad_appmode = 0;
   1432 				ip->escape = 0;
   1433 				return;
   1434 
   1435 			case 'Z':	/* request ID */
   1436 				if (ip->emul_level == EMUL_VT100) {
   1437 					/* XXX not clean */
   1438 					ite_sendstr(ip, "\033[61;0c");
   1439 				} else {
   1440 					/* XXX not clean */
   1441 					ite_sendstr(ip, "\033[63;0c");
   1442 				}
   1443 				ip->escape = 0;
   1444 				return;
   1445 
   1446 			/* default catch all for not recognized ESC sequences */
   1447 			default:
   1448 				ip->escape = 0;
   1449 				return;
   1450 			}
   1451 			break;
   1452 
   1453 		case '(': /* designate G0 */
   1454 			switch (c) {
   1455 			case 'B': /* USASCII */
   1456 				ip->G0 = CSET_ASCII;
   1457 				ip->escape = 0;
   1458 				return;
   1459 			case 'I':
   1460 				ip->G0 = CSET_JISKANA;
   1461 				ip->escape = 0;
   1462 				return;
   1463 			case 'J':
   1464 				ip->G0 = CSET_JISROMA;
   1465 				ip->escape = 0;
   1466 				return;
   1467 			case '0': /* dec special graphics */
   1468 				ip->G0 = CSET_DECGRAPH;
   1469 				ip->escape = 0;
   1470 				return;
   1471 			case 'A': /* British or ISO-Latin-1 */
   1472 			case 'H': /* Swedish */
   1473 			case 'K': /* German */
   1474 			case 'R': /* French */
   1475 			case 'Y': /* Italian */
   1476 			case 'Z': /* Spanish */
   1477 			default:
   1478 				/* not supported */
   1479 				ip->escape = 0;
   1480 				return;
   1481 			}
   1482 
   1483 		case ')': /* designate G1 */
   1484 			switch (c) {
   1485 			case 'B': /* USASCII */
   1486 				ip->G1 = CSET_ASCII;
   1487 				ip->escape = 0;
   1488 				return;
   1489 			case 'I':
   1490 				ip->G1 = CSET_JISKANA;
   1491 				ip->escape = 0;
   1492 				return;
   1493 			case 'J':
   1494 				ip->G1 = CSET_JISROMA;
   1495 				ip->escape = 0;
   1496 				return;
   1497 			case '0': /* dec special graphics */
   1498 				ip->G1 = CSET_DECGRAPH;
   1499 				ip->escape = 0;
   1500 				return;
   1501 			case 'A': /* British or ISO-Latin-1 */
   1502 			case 'H': /* Swedish */
   1503 			case 'K': /* German */
   1504 			case 'R': /* French */
   1505 			case 'Y': /* Italian */
   1506 			case 'Z': /* Spanish */
   1507 			default:
   1508 				/* not supported */
   1509 				ip->escape = 0;
   1510 				return;
   1511 			}
   1512 			return;
   1513 
   1514 		case '$': /* 94-multibyte character set */
   1515 			switch (c) {
   1516 			case '@':
   1517 				ip->G0 = CSET_JIS1978;
   1518 				ip->escape = 0;
   1519 				return;
   1520 			case 'B':
   1521 				ip->G0 = CSET_JIS1983;
   1522 				ip->escape = 0;
   1523 				return;
   1524 			case 'D':
   1525 				ip->G0 = CSET_JIS1990;
   1526 				ip->escape = 0;
   1527 				return;
   1528 			default:
   1529 				/* not supported */
   1530 				ip->escape = 0;
   1531 				return;
   1532 			}
   1533 
   1534 		case ' ':
   1535 			switch (c) {
   1536 			case 'F':
   1537 				ip->eightbit_C1 = 0;
   1538 				ip->escape = 0;
   1539 				return;
   1540 
   1541 			case 'G':
   1542 				ip->eightbit_C1 = 1;
   1543 				ip->escape = 0;
   1544 				return;
   1545 
   1546 			default:
   1547 				/* not supported */
   1548 				ip->escape = 0;
   1549 				return;
   1550 			}
   1551 			break;
   1552 
   1553 		case '#':
   1554 			switch (c) {
   1555 			case '5':
   1556 				/* single height, single width */
   1557 				ip->escape = 0;
   1558 				return;
   1559 
   1560 			case '6':
   1561 				/* double width, single height */
   1562 				ip->escape = 0;
   1563 				return;
   1564 
   1565 			case '3':
   1566 				/* top half */
   1567 				ip->escape = 0;
   1568 				return;
   1569 
   1570 			case '4':
   1571 				/* bottom half */
   1572 				ip->escape = 0;
   1573 				return;
   1574 
   1575 			case '8':
   1576 				/* screen alignment pattern... */
   1577 				alignment_display(ip);
   1578 				ip->escape = 0;
   1579 				return;
   1580 
   1581 			default:
   1582 				ip->escape = 0;
   1583 				return;
   1584 			}
   1585 			break;
   1586 
   1587 		case CSI:
   1588 			/* the biggie... */
   1589 			switch (c) {
   1590 			case '0':
   1591 			case '1':
   1592 			case '2':
   1593 			case '3':
   1594 			case '4':
   1595 			case '5':
   1596 			case '6':
   1597 			case '7':
   1598 			case '8':
   1599 			case '9':
   1600 			case ';':
   1601 			case '\"':
   1602 			case '$':
   1603 			case '>':
   1604 				if (ip->ap < ip->argbuf + MAX_ARGSIZE)
   1605 					*ip->ap++ = c;
   1606 				return;
   1607 
   1608 			case 'p':
   1609 				*ip->ap = 0;
   1610 				if (!strncmp(ip->argbuf, "61\"", 3))
   1611 					ip->emul_level = EMUL_VT100;
   1612 				else if (!strncmp(ip->argbuf, "63;1\"", 5) ||
   1613 					 !strncmp(ip->argbuf, "62;1\"", 5))
   1614 					ip->emul_level = EMUL_VT300_7;
   1615 				else
   1616 					ip->emul_level = EMUL_VT300_8;
   1617 				ip->escape = 0;
   1618 				return;
   1619 
   1620 			case '?':
   1621 				*ip->ap = 0;
   1622 				ip->escape = '?';
   1623 				ip->ap = ip->argbuf;
   1624 				return;
   1625 
   1626 			case 'c':
   1627 				/* device attributes */
   1628 				*ip->ap = 0;
   1629 				if (ip->argbuf[0] == '>') {
   1630 					ite_sendstr(ip, "\033[>24;0;0;0c");
   1631 				} else {
   1632 					switch (ite_zargnum(ip)) {
   1633 					case 0:
   1634 						/*
   1635 						 * primary DA request, send
   1636 						 * primary DA response
   1637 						 */
   1638 						if (ip->emul_level ==
   1639 						    EMUL_VT100)
   1640 							ite_sendstr(ip,
   1641 							    "\033[?1;1c");
   1642 						else
   1643 							ite_sendstr(ip,
   1644 							    "\033[63;0c");
   1645 						break;
   1646 					}
   1647 				}
   1648 				ip->escape = 0;
   1649 				return;
   1650 
   1651 			case 'n':
   1652 				switch (ite_zargnum(ip)) {
   1653 				case 5:
   1654 					/* no malfunction */
   1655 					ite_sendstr(ip, "\033[0n");
   1656 					break;
   1657 				case 6:
   1658 					/* cursor position report */
   1659 					snprintf(ip->argbuf, sizeof(ip->argbuf),
   1660 					    "\033[%d;%dR",
   1661 					     ip->cury + 1, ip->curx + 1);
   1662 					ite_sendstr(ip, ip->argbuf);
   1663 					break;
   1664 				}
   1665 				ip->escape = 0;
   1666 				return;
   1667 
   1668 			case 'x':
   1669 				switch (ite_zargnum(ip)) {
   1670 				case 0:
   1671 					/* Fake some terminal parameters.  */
   1672 					ite_sendstr(ip,
   1673 					    "\033[2;1;1;112;112;1;0x");
   1674 					break;
   1675 				case 1:
   1676 					ite_sendstr(ip,
   1677 					    "\033[3;1;1;112;112;1;0x");
   1678 					break;
   1679 				}
   1680 				ip->escape = 0;
   1681 				return;
   1682 
   1683 			case 'g':
   1684 				/* clear tabs */
   1685 				switch (ite_zargnum(ip)) {
   1686 				case 0:
   1687 					if (ip->curx < ip->cols)
   1688 						ip->tabs[ip->curx] = 0;
   1689 					break;
   1690 				case 3:
   1691 					for (n = 0; n < ip->cols; n++)
   1692 						ip->tabs[n] = 0;
   1693 					break;
   1694 
   1695 				default:
   1696 					/* ignore */
   1697 					break;
   1698 				}
   1699 				ip->escape = 0;
   1700 				return;
   1701 
   1702 			case 'h': /* set mode */
   1703 			case 'l': /* reset mode */
   1704 				n = ite_zargnum(ip);
   1705 				switch (n) {
   1706 				case 4:
   1707 					/* insert/replace mode */
   1708 					ip->imode = (c == 'h');
   1709 					break;
   1710 				case 20:
   1711 					ip->linefeed_newline = (c == 'h');
   1712 					break;
   1713 				}
   1714 				ip->escape = 0;
   1715 				return;
   1716 
   1717 			case 'M':
   1718 				/* delete line */
   1719 				ite_dnline(ip, ite_argnum(ip));
   1720 				ip->escape = 0;
   1721 				return;
   1722 
   1723 			case 'L':
   1724 				/* insert line */
   1725 				ite_inline(ip, ite_argnum(ip));
   1726 				ip->escape = 0;
   1727 				return;
   1728 
   1729 			case 'P':
   1730 				/* delete char */
   1731 				ite_dnchar(ip, ite_argnum(ip));
   1732 				ip->escape = 0;
   1733 				return;
   1734 
   1735 			case '@':
   1736 				/* insert char(s) */
   1737 				ite_inchar(ip, ite_argnum(ip));
   1738 				ip->escape = 0;
   1739 				return;
   1740 
   1741 			case '!':
   1742 				/* soft terminal reset */
   1743 				ip->escape = 0; /* XXX */
   1744 				return;
   1745 
   1746 			case 'G':
   1747 				/*
   1748 				 * this one was *not* in my vt320 manual but
   1749 				 * in a vt320 termcap entry.. who is right?
   1750 				 * It's supposed to set the horizontal cursor
   1751 				 * position.
   1752 				 */
   1753 				*ip->ap = 0;
   1754 				x = atoi(ip->argbuf);
   1755 				if (x != 0)
   1756 					x--;
   1757 				ip->curx = uimin(x, ip->cols - 1);
   1758 				ip->escape = 0;
   1759 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1760 				clr_attr(ip, ATTR_INV);
   1761 				return;
   1762 
   1763 			case 'd':
   1764 				/*
   1765 				 * same thing here, this one's for setting
   1766 				 * the absolute vertical cursor position.
   1767 				 * Not documented...
   1768 				 */
   1769 				*ip->ap = 0;
   1770 				y = atoi(ip->argbuf);
   1771 				if (y)
   1772 					y--;
   1773 				if (ip->inside_margins)
   1774 					y += ip->top_margin;
   1775 				ip->cury = uimin(y, ip->rows - 1);
   1776 				ip->escape = 0;
   1777 				snap_cury(ip);
   1778 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1779 				clr_attr(ip, ATTR_INV);
   1780 				return;
   1781 
   1782 			case 'H':
   1783 			case 'f':
   1784 				*ip->ap = 0;
   1785 				y = atoi(ip->argbuf);
   1786 				x = 0;
   1787 				cp = strchr(ip->argbuf, ';');
   1788 				if (cp != NULL)
   1789 					x = atoi(cp + 1);
   1790 				if (x != 0)
   1791 					x--;
   1792 				if (y != 0)
   1793 					y--;
   1794 				if (ip->inside_margins != 0)
   1795 					y += ip->top_margin;
   1796 				ip->cury = uimin(y, ip->rows - 1);
   1797 				ip->curx = uimin(x, ip->cols - 1);
   1798 				ip->escape = 0;
   1799 				snap_cury(ip);
   1800 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1801 				/*clr_attr(ip, ATTR_INV);*/
   1802 				return;
   1803 
   1804 			case 'A':
   1805 				/* cursor up */
   1806 				n = ite_argnum(ip);
   1807 				n = ip->cury - (n ? n : 1);
   1808 				if (n < 0)
   1809 					n = 0;
   1810 				if (ip->inside_margins)
   1811 					n = uimax(ip->top_margin, n);
   1812 				else if (n == ip->top_margin - 1)
   1813 					/*
   1814 					 * allow scrolling outside region,
   1815 					 * but don't scroll out of active
   1816 					 * region without explicit CUP
   1817 					 */
   1818 					n = ip->top_margin;
   1819 				ip->cury = n;
   1820 				ip->escape = 0;
   1821 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1822 				clr_attr(ip, ATTR_INV);
   1823 				return;
   1824 
   1825 			case 'B':
   1826 				/* cursor down */
   1827 				n = ite_argnum(ip);
   1828 				n = ip->cury + (n ? n : 1);
   1829 				n = uimin(ip->rows - 1, n);
   1830 #if 0
   1831 				if (ip->inside_margins)
   1832 #endif
   1833 					n = uimin(ip->bottom_margin, n);
   1834 #if 0
   1835 				else if (n == ip->bottom_margin + 1)
   1836 					/*
   1837 					 * allow scrolling outside region,
   1838 					 * but don't scroll out of active
   1839 					 * region without explicit CUP
   1840 					 */
   1841 					n = ip->bottom_margin;
   1842 #endif
   1843 				ip->cury = n;
   1844 				ip->escape = 0;
   1845 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1846 				clr_attr(ip, ATTR_INV);
   1847 				return;
   1848 
   1849 			case 'C':
   1850 				/* cursor forward */
   1851 				n = ite_argnum(ip);
   1852 				n = n ? n : 1;
   1853 				ip->curx = uimin(ip->curx + n, ip->cols - 1);
   1854 				ip->escape = 0;
   1855 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1856 				clr_attr(ip, ATTR_INV);
   1857 				return;
   1858 
   1859 			case 'D':
   1860 				/* cursor backward */
   1861 				n = ite_argnum(ip);
   1862 				n = n ? n : 1;
   1863 				n = ip->curx - n;
   1864 				ip->curx = n >= 0 ? n : 0;
   1865 				ip->escape = 0;
   1866 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1867 				clr_attr(ip, ATTR_INV);
   1868 				return;
   1869 
   1870 			case 'J':
   1871 				/* erase screen */
   1872 				*ip->ap = 0;
   1873 				n = ite_zargnum(ip);
   1874 				if (n == 0)
   1875 					ite_clrtoeos(ip);
   1876 				else if (n == 1)
   1877 					ite_clrtobos(ip);
   1878 				else if (n == 2)
   1879 					ite_clrscreen(ip);
   1880 				ip->escape = 0;
   1881 				return;
   1882 
   1883 			case 'K':
   1884 				/* erase line */
   1885 				n = ite_zargnum(ip);
   1886 				if (n == 0)
   1887 					ite_clrtoeol(ip);
   1888 				else if (n == 1)
   1889 					ite_clrtobol(ip);
   1890 				else if (n == 2)
   1891 					ite_clrline(ip);
   1892 				ip->escape = 0;
   1893 				return;
   1894 
   1895 			case 'S':
   1896 				/* scroll up */
   1897 				n = ite_zargnum(ip);
   1898 				if (n <= 0)
   1899 					n = 1;
   1900 				else if (n > ip->rows-1)
   1901 					n = ip->rows-1;
   1902 				SUBR_SCROLL(ip, ip->rows-1, 0, n, SCROLL_UP);
   1903 				ip->escape = 0;
   1904 				return;
   1905 
   1906 			case 'T':
   1907 				/* scroll down */
   1908 				n = ite_zargnum(ip);
   1909 				if (n <= 0)
   1910 					n = 1;
   1911 				else if (n > ip->rows-1)
   1912 					n = ip->rows-1;
   1913 				SUBR_SCROLL(ip, 0, 0, n, SCROLL_DOWN);
   1914 				ip->escape = 0;
   1915 				return;
   1916 
   1917 			case 'X':
   1918 				/* erase character */
   1919 				n = ite_argnum(ip) - 1;
   1920 				n = uimin(n, ip->cols - 1 - ip->curx);
   1921 				for (; n >= 0; n--) {
   1922 					attrclr(ip, ip->cury, ip->curx + n,
   1923 					    1, 1);
   1924 					SUBR_PUTC(ip, ' ',
   1925 					    ip->cury, ip->curx + n, ATTR_NOR);
   1926 				}
   1927 				ip->escape = 0;
   1928 				return;
   1929 
   1930 			case '}': case '`':
   1931 				/* status line control */
   1932 				ip->escape = 0;
   1933 				return;
   1934 
   1935 			case 'r':
   1936 				/* set scrolling region */
   1937 				ip->escape = 0;
   1938 				*ip->ap = 0;
   1939 				x = atoi(ip->argbuf);
   1940 				x = x ? x : 1;
   1941 				y = ip->rows;
   1942 				cp = strchr(ip->argbuf, ';');
   1943 				if (cp) {
   1944 					y = atoi(cp + 1);
   1945 					y = y ? y : ip->rows;
   1946 				}
   1947 				if (y <= x)
   1948 					return;
   1949 				x--;
   1950 				y--;
   1951 				ip->top_margin = uimin(x, ip->rows - 2);
   1952 				ip->bottom_margin = uimin(y, ip->rows - 1);
   1953 				if (ip->inside_margins) {
   1954 					ip->cury = ip->top_margin;
   1955 				} else
   1956 					ip->cury = 0;
   1957 				ip->curx = 0;
   1958 				return;
   1959 
   1960 			case 'm':
   1961 				/* big attribute setter/resetter */
   1962 			{
   1963 				char *c_p;
   1964 
   1965 				*ip->ap = 0;
   1966 				/* kludge to make CSIm work (== CSI0m) */
   1967 				if (ip->ap == ip->argbuf)
   1968 					ip->ap++;
   1969 				for (c_p = ip->argbuf; c_p < ip->ap; ) {
   1970 					switch (*c_p) {
   1971 					case 0:
   1972 					case '0':
   1973 						clr_attr(ip, ATTR_ALL);
   1974 						ip->fgcolor = 7;
   1975 						ip->bgcolor = 0;
   1976 						c_p++;
   1977 						break;
   1978 
   1979 					case '1':
   1980 						set_attr(ip, ATTR_BOLD);
   1981 						c_p++;
   1982 						break;
   1983 
   1984 					case '2':
   1985 						switch (c_p[1]) {
   1986 						case '2':
   1987 							clr_attr(ip, ATTR_BOLD);
   1988 							c_p += 2;
   1989 							break;
   1990 
   1991 						case '4':
   1992 							clr_attr(ip, ATTR_UL);
   1993 							c_p += 2;
   1994 							break;
   1995 
   1996 						case '5':
   1997 							clr_attr(ip,
   1998 							    ATTR_BLINK);
   1999 							c_p += 2;
   2000 							break;
   2001 
   2002 						case '7':
   2003 							clr_attr(ip, ATTR_INV);
   2004 							c_p += 2;
   2005 							break;
   2006 
   2007 						default:
   2008 							c_p++;
   2009 							break;
   2010 						}
   2011 						break;
   2012 
   2013 					case '3':
   2014 						switch (c_p[1]) {
   2015 						case '0':
   2016 						case '1':
   2017 						case '2':
   2018 						case '3':
   2019 						case '4':
   2020 						case '5':
   2021 						case '6':
   2022 						case '7':
   2023 							/* foreground colors */
   2024 							ip->fgcolor =
   2025 							    c_p[1] - '0';
   2026 							c_p += 2;
   2027 							break;
   2028 						default:
   2029 							c_p++;
   2030 							break;
   2031 						}
   2032 						break;
   2033 
   2034 					case '4':
   2035 						switch (c_p[1]) {
   2036 						case '0':
   2037 						case '1':
   2038 						case '2':
   2039 						case '3':
   2040 						case '4':
   2041 						case '5':
   2042 						case '6':
   2043 						case '7':
   2044 							/* background colors */
   2045 							ip->bgcolor =
   2046 							    c_p[1] - '0';
   2047 							c_p += 2;
   2048 							break;
   2049 						default:
   2050 							set_attr(ip, ATTR_UL);
   2051 							c_p++;
   2052 							break;
   2053 						}
   2054 						break;
   2055 
   2056 					case '5':
   2057 						set_attr(ip, ATTR_BLINK);
   2058 						c_p++;
   2059 						break;
   2060 
   2061 					case '7':
   2062 						set_attr(ip, ATTR_INV);
   2063 						c_p++;
   2064 						break;
   2065 
   2066 					default:
   2067 						c_p++;
   2068 						break;
   2069 					}
   2070 				}
   2071 
   2072 			}
   2073 				ip->escape = 0;
   2074 				return;
   2075 
   2076 			case 'u':
   2077 				/* DECRQTSR */
   2078 				ite_sendstr(ip, "\033P\033\\");
   2079 				ip->escape = 0;
   2080 				return;
   2081 
   2082 			default:
   2083 				ip->escape = 0;
   2084 				return;
   2085 			}
   2086 			break;
   2087 
   2088 		case '?':	/* CSI ? */
   2089 			switch (c) {
   2090 			case '0':
   2091 			case '1':
   2092 			case '2':
   2093 			case '3':
   2094 			case '4':
   2095 			case '5':
   2096 			case '6':
   2097 			case '7':
   2098 			case '8':
   2099 			case '9':
   2100 			case ';':
   2101 			case '\"':
   2102 			case '$':
   2103 				/*
   2104 				 * Don't fill the last character; it's needed.
   2105 				 */
   2106 				/* XXX yeah, where ?? */
   2107 				if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
   2108 					*ip->ap++ = c;
   2109 				return;
   2110 
   2111 			case 'n':
   2112 				/* Terminal Reports */
   2113 				*ip->ap = 0;
   2114 				if (ip->ap == &ip->argbuf[2]) {
   2115 					if (!strncmp(ip->argbuf, "15", 2))
   2116 						/* printer status: no printer */
   2117 						ite_sendstr(ip, "\033[13n");
   2118 					else if (!strncmp(ip->argbuf, "25", 2))
   2119 						/* udk status */
   2120 						ite_sendstr(ip, "\033[20n");
   2121 					else if (!strncmp(ip->argbuf, "26", 2))
   2122 						/* keyboard dialect: US */
   2123 						ite_sendstr(ip, "\033[27;1n");
   2124 				}
   2125 				ip->escape = 0;
   2126 				return;
   2127 
   2128 			case 'h': /* set dec private modes */
   2129 			case 'l': /* reset dec private modes */
   2130 				n = ite_zargnum(ip);
   2131 				switch (n) {
   2132 				case 1:
   2133 					/* CKM - cursor key mode */
   2134 					ip->cursor_appmode = (c == 'h');
   2135 					break;
   2136 
   2137 				case 3:
   2138 					/* 132/80 columns (132 == 'h') */
   2139 					break;
   2140 
   2141 				case 4: /* smooth scroll */
   2142 					break;
   2143 
   2144 				case 5:
   2145 					/*
   2146 					 * light background (=='h') /
   2147 					 * dark background (=='l')
   2148 					 */
   2149 					break;
   2150 
   2151 				case 6: /* origin mode */
   2152 					ip->inside_margins = (c == 'h');
   2153 #if 0
   2154 					ip->curx = 0;
   2155 					ip->cury = ip->inside_margins ?
   2156 					    ip->top_margin : 0;
   2157 					SUBR_CURSOR(ip, MOVE_CURSOR);
   2158 #endif
   2159 					break;
   2160 
   2161 				case 7: /* auto wraparound */
   2162 					ip->auto_wrap = (c == 'h');
   2163 					break;
   2164 
   2165 				case 8: /* keyboard repeat */
   2166 					ip->key_repeat = (c == 'h');
   2167 					break;
   2168 
   2169 				case 20: /* newline mode */
   2170 					ip->linefeed_newline = (c == 'h');
   2171 					break;
   2172 
   2173 				case 25: /* cursor on/off */
   2174 					SUBR_CURSOR(ip, (c == 'h') ?
   2175 					    DRAW_CURSOR : ERASE_CURSOR);
   2176 					break;
   2177 				}
   2178 				ip->escape = 0;
   2179 				return;
   2180 
   2181 			case 'K':
   2182 				/* selective erase in line */
   2183 			case 'J':
   2184 				/* selective erase in display */
   2185 
   2186 			default:
   2187 				ip->escape = 0;
   2188 				return;
   2189 			}
   2190 			break;
   2191 
   2192 		default:
   2193 			ip->escape = 0;
   2194 			return;
   2195 		}
   2196 	}
   2197 
   2198 	switch (c) {
   2199 	case 0x00:	/* NUL */
   2200 	case 0x01:	/* SOH */
   2201 	case 0x02:	/* STX */
   2202 	case 0x03:	/* ETX */
   2203 	case 0x04:	/* EOT */
   2204 	case 0x05:	/* ENQ */
   2205 	case 0x06:	/* ACK */
   2206 		break;
   2207 
   2208 	case BEL:
   2209 #if NBELL > 0
   2210 		if (kbd_ite && ite_tty[device_unit(kbd_ite->device)])
   2211 			opm_bell();
   2212 #endif
   2213 		break;
   2214 
   2215 	case BS:
   2216 		if (--ip->curx < 0)
   2217 			ip->curx = 0;
   2218 		else
   2219 			SUBR_CURSOR(ip, MOVE_CURSOR);
   2220 		break;
   2221 
   2222 	case HT:
   2223 		for (n = ip->curx + 1; n < ip->cols; n++) {
   2224 			if (ip->tabs[n]) {
   2225 				ip->curx = n;
   2226 				SUBR_CURSOR(ip, MOVE_CURSOR);
   2227 				break;
   2228 			}
   2229 		}
   2230 		break;
   2231 
   2232 	case VT:	/* VT is treated like LF */
   2233 	case FF:	/* so is FF */
   2234 	case LF:
   2235 		/*
   2236 		 * cr->crlf distinction is done here, on output,
   2237 		 * not on input!
   2238 		 */
   2239 		if (ip->linefeed_newline)
   2240 			ite_crlf(ip);
   2241 		else
   2242 			ite_lf(ip);
   2243 		break;
   2244 
   2245 	case CR:
   2246 		ite_cr(ip);
   2247 		break;
   2248 
   2249 	case SO:
   2250 		ip->GL = &ip->G1;
   2251 		break;
   2252 
   2253 	case SI:
   2254 		ip->GL = &ip->G0;
   2255 		break;
   2256 
   2257 	case 0x10:	/* DLE */
   2258 	case 0x11:	/* DC1/XON */
   2259 	case 0x12:	/* DC2 */
   2260 	case 0x13:	/* DC3/XOFF */
   2261 	case 0x14:	/* DC4 */
   2262 	case 0x15:	/* NAK */
   2263 	case 0x16:	/* SYN */
   2264 	case 0x17:	/* ETB */
   2265 		break;
   2266 
   2267 	case CAN:
   2268 		ip->escape = 0;	/* cancel any escape sequence in progress */
   2269 		break;
   2270 
   2271 	case 0x19:	/* EM */
   2272 		break;
   2273 
   2274 	case SUB:
   2275 		ip->escape = 0;	/* dito, but see below */
   2276 		/* should also display a reverse question mark!! */
   2277 		break;
   2278 
   2279 	case ESC:
   2280 		ip->escape = ESC;
   2281 		break;
   2282 
   2283 	case 0x1c:	/* FS */
   2284 	case 0x1d:	/* GS */
   2285 	case 0x1e:	/* RS */
   2286 	case 0x1f:	/* US */
   2287 		break;
   2288 
   2289 	/* now it gets weird.. 8bit control sequences.. */
   2290 	case IND:	/* index: move cursor down, scroll */
   2291 		ite_index(ip);
   2292 		break;
   2293 
   2294 	case NEL:	/* next line. next line, first pos. */
   2295 		ite_crlf(ip);
   2296 		break;
   2297 
   2298 	case HTS:	/* set horizontal tab */
   2299 		if (ip->curx < ip->cols)
   2300 			ip->tabs[ip->curx] = 1;
   2301 		break;
   2302 
   2303 	case RI:	/* reverse index */
   2304 		ite_rlf(ip);
   2305 		break;
   2306 
   2307 	case SS2:	/* go into G2 for one character */
   2308 		ip->save_GL = ip->GR;	/* GL XXX EUC */
   2309 		ip->GR = &ip->G2;	/* GL XXX */
   2310 		break;
   2311 
   2312 	case SS3:	/* go into G3 for one character */
   2313 		ip->save_GL = ip->GR;	/* GL XXX EUC */
   2314 		ip->GR = &ip->G3;	/* GL XXX */
   2315 		break;
   2316 
   2317 	case DCS:	/* device control string introducer */
   2318 		ip->escape = DCS;
   2319 		ip->ap = ip->argbuf;
   2320 		break;
   2321 
   2322 	case CSI:	/* control sequence introducer */
   2323 		ip->escape = CSI;
   2324 		ip->ap = ip->argbuf;
   2325 		break;
   2326 
   2327 	case ST:	/* string terminator */
   2328 		/* ignore, if not used as terminator */
   2329 		break;
   2330 
   2331 	case OSC:	/* introduces OS command. */
   2332 		/* Ignore everything upto ST */
   2333 		ip->escape = OSC;
   2334 		break;
   2335 
   2336 	case PM:	/* privacy message */
   2337 		/* ignore everything upto ST */
   2338 		ip->escape = PM;
   2339 		break;
   2340 
   2341 	case APC:	/* application program command */
   2342 		/* ignore everything upto ST */
   2343 		ip->escape = APC;
   2344 		break;
   2345 
   2346 	case DEL:
   2347 		break;
   2348 
   2349 	default:
   2350 		if (ip->save_char == 0 &&
   2351 		    (*((c & 0x80) ? ip->GR : ip->GL) & CSET_MULTI) != 0) {
   2352 			ip->save_char = c;
   2353 			break;
   2354 		}
   2355 		if (ip->imode != 0)
   2356 			ite_inchar(ip, ip->save_char ? 2 : 1);
   2357 		iteprecheckwrap(ip);
   2358 #ifdef DO_WEIRD_ATTRIBUTES
   2359 		if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
   2360 			attrset(ip, ATTR_INV);
   2361 			SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
   2362 		}
   2363 		else
   2364 			SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
   2365 #else
   2366 		SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
   2367 #endif
   2368 		/*SUBR_CURSOR(ip, DRAW_CURSOR);*/
   2369 		itecheckwrap(ip);
   2370 		if (ip->save_char) {
   2371 			itecheckwrap(ip);
   2372 			ip->save_char = 0;
   2373 		}
   2374 		if (ip->save_GL) {
   2375 			/*
   2376 			 * reset single shift
   2377 			 */
   2378 			ip->GR = ip->save_GL;
   2379 			ip->save_GL = 0;
   2380 		}
   2381 		break;
   2382 	}
   2383 }
   2384 
   2385 static void
   2386 iteprecheckwrap(struct ite_softc *ip)
   2387 {
   2388 
   2389 	if (ip->auto_wrap && ip->curx + (ip->save_char ? 1 : 0) == ip->cols) {
   2390 		ip->curx = 0;
   2391 		clr_attr(ip, ATTR_INV);
   2392 		if (++ip->cury >= ip->bottom_margin + 1) {
   2393 			ip->cury = ip->bottom_margin;
   2394 			/*SUBR_CURSOR(ip, MOVE_CURSOR);*/
   2395 			SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
   2396 			ite_clrtoeol(ip);
   2397 		} /*else
   2398 			SUBR_CURSOR(ip, MOVE_CURSOR);*/
   2399 	}
   2400 }
   2401 
   2402 static void
   2403 itecheckwrap(struct ite_softc *ip)
   2404 {
   2405 
   2406 #if 0
   2407 	if (++ip->curx == ip->cols) {
   2408 		if (ip->auto_wrap) {
   2409 			ip->curx = 0;
   2410 			clr_attr(ip, ATTR_INV);
   2411 			if (++ip->cury >= ip->bottom_margin + 1) {
   2412 				ip->cury = ip->bottom_margin;
   2413 				SUBR_CURSOR(ip, MOVE_CURSOR);
   2414 				SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1,
   2415 				    SCROLL_UP);
   2416 				ite_clrtoeol(ip);
   2417 				return;
   2418 			}
   2419 		} else
   2420 			/* stay there if no autowrap.. */
   2421 			ip->curx--;
   2422 	}
   2423 #else
   2424 	if (ip->curx < ip->cols) {
   2425 		ip->curx++;
   2426 		/*SUBR_CURSOR(ip, MOVE_CURSOR);*/
   2427 	}
   2428 #endif
   2429 }
   2430 
   2431 /*
   2432  * A convertion table from DEC special graphics characters to ASCII characters.
   2433  * Mostly for box drawing on sysinst(8).
   2434  */
   2435 const uint8_t ite_decgraph2ascii[128] = {
   2436 	/* same as ASCII from 0x00 to 0x5e */
   2437 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   2438 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   2439 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   2440 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   2441 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
   2442 	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   2443 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
   2444 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   2445 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
   2446 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
   2447 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
   2448 	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
   2449 
   2450 	/* special graphics characters from 0x5f to 0x7e */
   2451 	' ',	/* 0x5f NBSP */
   2452 	'*',	/* 0x60 diamond */
   2453 	' ',	/* 0x61 medium shade */
   2454 	' ',	/* 0x62 HT */
   2455 	' ',	/* 0x63 FF */
   2456 	' ',	/* 0x64 CR */
   2457 	' ',	/* 0x65 LF */
   2458 	' ',	/* 0x66 degree symbol */
   2459 	' ',	/* 0x67 plus-minus sign */
   2460 	' ',	/* 0x68 NL */
   2461 	' ',	/* 0x69 VT */
   2462 	'+',	/* 0x6a box drawings up left */
   2463 	'+',	/* 0x6b box drawings down left */
   2464 	'+',	/* 0x6c box drawings down right */
   2465 	'+',	/* 0x6d box drawings up right */
   2466 	'+',	/* 0x6e box drawings vertical horizontal */
   2467 	'~',	/* 0x6f scan line 1 */
   2468 	'-',	/* 0x70 scan line 3 */
   2469 	'-',	/* 0x71 scan line 5 */
   2470 	'-',	/* 0x72 scan line 7 */
   2471 	'_',	/* 0x73 scan line 9 */
   2472 	'+',	/* 0x74 box drawings vertical right */
   2473 	'+',	/* 0x75 box drawings vertical left */
   2474 	'+',	/* 0x76 box drawings horizontal up */
   2475 	'+',	/* 0x77 box drawings horizontal down */
   2476 	'|',	/* 0x78 box drawings vertical */
   2477 	'<',	/* 0x79 less than or equal to */
   2478 	'>',	/* 0x7a greater than or equal to */
   2479 	' ',	/* 0x7b pi */
   2480 	' ',	/* 0x7c not equal */
   2481 	' ',	/* 0x7d pound sign */
   2482 	'.',	/* 0x7e middle dot */
   2483 	/* end of special graphics characters */
   2484 	0x7f
   2485 };
   2486 
   2487 #endif
   2488 
   2489 #if NITE > 0 && NKBD > 0
   2490 
   2491 /*
   2492  * Console functions
   2493  */
   2494 #include <dev/cons.h>
   2495 extern void kbdenable(int);
   2496 extern int kbdcngetc(void);
   2497 
   2498 /*
   2499  * Return a priority in consdev->cn_pri field highest wins.  This function
   2500  * is called before any devices have been probed.
   2501  */
   2502 void
   2503 itecnprobe(struct consdev *cd)
   2504 {
   2505 	int maj;
   2506 
   2507 	/* locate the major number */
   2508 	maj = cdevsw_lookup_major(&ite_cdevsw);
   2509 
   2510 	/*
   2511 	 * return priority of the best ite (already picked from attach)
   2512 	 * or CN_DEAD.
   2513 	 */
   2514 	if (con_itesoftc.grf == NULL)
   2515 		cd->cn_pri = CN_DEAD;
   2516 	else {
   2517 		con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
   2518 		/*
   2519 		 * hardcode the minor number.
   2520 		 * currently we support only one ITE, it is enough for now.
   2521 		 */
   2522 		con_itesoftc.isw = &itesw[0];
   2523 		cd->cn_pri = CN_INTERNAL;
   2524 		cd->cn_dev = makedev(maj, 0);
   2525 	}
   2526 }
   2527 
   2528 void
   2529 itecninit(struct consdev *cd)
   2530 {
   2531 	struct ite_softc *ip;
   2532 
   2533 	ip = getitesp(cd->cn_dev);
   2534 	iteinit(cd->cn_dev);	       /* init console unit */
   2535 	ip->flags |= ITE_ACTIVE | ITE_ISCONS;
   2536 	kbdenable(0);
   2537 	mfp_send_usart(0x49);
   2538 }
   2539 
   2540 /*
   2541  * itecnfinish() is called in ite_init() when the device is
   2542  * being probed in the normal fashion, thus we can finish setting
   2543  * up this ite now that the system is more functional.
   2544  */
   2545 void
   2546 itecnfinish(struct ite_softc *ip)
   2547 {
   2548 	static int done;
   2549 
   2550 	if (done)
   2551 		return;
   2552 	done = 1;
   2553 }
   2554 
   2555 /*ARGSUSED*/
   2556 int
   2557 itecngetc(dev_t dev)
   2558 {
   2559 	int c;
   2560 
   2561 	do {
   2562 		c = kbdcngetc();
   2563 		c = ite_cnfilter(c);
   2564 	} while (c == -1);
   2565 	return (c);
   2566 }
   2567 
   2568 void
   2569 itecnputc(dev_t dev, int c)
   2570 {
   2571 	static int paniced = 0;
   2572 	struct ite_softc *ip = getitesp(dev);
   2573 	char ch = c;
   2574 #ifdef ITE_KERNEL_ATTR
   2575 	short save_attribute;
   2576 #endif
   2577 
   2578 	if (panicstr && !paniced &&
   2579 	    (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
   2580 		(void) iteon(dev, 3);
   2581 		paniced = 1;
   2582 	}
   2583 #ifdef ITE_KERNEL_ATTR
   2584 	save_attribute = ip->attribute;
   2585 	ip->attribute = ITE_KERNEL_ATTR;
   2586 #endif
   2587 	ite_putstr(&ch, 1, dev);
   2588 #ifdef ITE_KERNEL_ATTR
   2589 	ip->attribute = save_attribute;
   2590 #endif
   2591 }
   2592 #endif
   2593