Home | History | Annotate | Line # | Download | only in dev
ite.c revision 1.70
      1 /*	$NetBSD: ite.c,v 1.70 2022/06/25 05:01:31 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.70 2022/06/25 05:01:31 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 			ip->escape = 0;
   1485 			return;
   1486 
   1487 		case '$': /* 94-multibyte character set */
   1488 			switch (c) {
   1489 			case '@':
   1490 				ip->G0 = CSET_JIS1978;
   1491 				ip->escape = 0;
   1492 				return;
   1493 			case 'B':
   1494 				ip->G0 = CSET_JIS1983;
   1495 				ip->escape = 0;
   1496 				return;
   1497 			case 'D':
   1498 				ip->G0 = CSET_JIS1990;
   1499 				ip->escape = 0;
   1500 				return;
   1501 			default:
   1502 				/* not supported */
   1503 				ip->escape = 0;
   1504 				return;
   1505 			}
   1506 
   1507 		case ' ':
   1508 			switch (c) {
   1509 			case 'F':
   1510 				ip->eightbit_C1 = 0;
   1511 				ip->escape = 0;
   1512 				return;
   1513 
   1514 			case 'G':
   1515 				ip->eightbit_C1 = 1;
   1516 				ip->escape = 0;
   1517 				return;
   1518 
   1519 			default:
   1520 				/* not supported */
   1521 				ip->escape = 0;
   1522 				return;
   1523 			}
   1524 			break;
   1525 
   1526 		case '#':
   1527 			switch (c) {
   1528 			case '5':
   1529 				/* single height, single width */
   1530 				ip->escape = 0;
   1531 				return;
   1532 
   1533 			case '6':
   1534 				/* double width, single height */
   1535 				ip->escape = 0;
   1536 				return;
   1537 
   1538 			case '3':
   1539 				/* top half */
   1540 				ip->escape = 0;
   1541 				return;
   1542 
   1543 			case '4':
   1544 				/* bottom half */
   1545 				ip->escape = 0;
   1546 				return;
   1547 
   1548 			case '8':
   1549 				/* screen alignment pattern... */
   1550 				alignment_display(ip);
   1551 				ip->escape = 0;
   1552 				return;
   1553 
   1554 			default:
   1555 				ip->escape = 0;
   1556 				return;
   1557 			}
   1558 			break;
   1559 
   1560 		case CSI:
   1561 			/* the biggie... */
   1562 			switch (c) {
   1563 			case '0':
   1564 			case '1':
   1565 			case '2':
   1566 			case '3':
   1567 			case '4':
   1568 			case '5':
   1569 			case '6':
   1570 			case '7':
   1571 			case '8':
   1572 			case '9':
   1573 			case ';':
   1574 			case '\"':
   1575 			case '$':
   1576 			case '>':
   1577 				if (ip->ap < ip->argbuf + MAX_ARGSIZE)
   1578 					*ip->ap++ = c;
   1579 				return;
   1580 
   1581 			case 'p':
   1582 				*ip->ap = 0;
   1583 				if (!strncmp(ip->argbuf, "61\"", 3))
   1584 					ip->emul_level = EMUL_VT100;
   1585 				else if (!strncmp(ip->argbuf, "63;1\"", 5) ||
   1586 					 !strncmp(ip->argbuf, "62;1\"", 5))
   1587 					ip->emul_level = EMUL_VT300_7;
   1588 				else
   1589 					ip->emul_level = EMUL_VT300_8;
   1590 				ip->escape = 0;
   1591 				return;
   1592 
   1593 			case '?':
   1594 				*ip->ap = 0;
   1595 				ip->escape = '?';
   1596 				ip->ap = ip->argbuf;
   1597 				return;
   1598 
   1599 			case 'c':
   1600 				/* device attributes */
   1601 				*ip->ap = 0;
   1602 				if (ip->argbuf[0] == '>') {
   1603 					ite_sendstr(ip, "\033[>24;0;0;0c");
   1604 				} else {
   1605 					switch (ite_zargnum(ip)) {
   1606 					case 0:
   1607 						/*
   1608 						 * primary DA request, send
   1609 						 * primary DA response
   1610 						 */
   1611 						if (ip->emul_level ==
   1612 						    EMUL_VT100)
   1613 							ite_sendstr(ip,
   1614 							    "\033[?1;1c");
   1615 						else
   1616 							ite_sendstr(ip,
   1617 							    "\033[63;0c");
   1618 						break;
   1619 					}
   1620 				}
   1621 				ip->escape = 0;
   1622 				return;
   1623 
   1624 			case 'n':
   1625 				switch (ite_zargnum(ip)) {
   1626 				case 5:
   1627 					/* no malfunction */
   1628 					ite_sendstr(ip, "\033[0n");
   1629 					break;
   1630 				case 6:
   1631 					/* cursor position report */
   1632 					snprintf(ip->argbuf, sizeof(ip->argbuf),
   1633 					    "\033[%d;%dR",
   1634 					     ip->cury + 1, ip->curx + 1);
   1635 					ite_sendstr(ip, ip->argbuf);
   1636 					break;
   1637 				}
   1638 				ip->escape = 0;
   1639 				return;
   1640 
   1641 			case 'x':
   1642 				switch (ite_zargnum(ip)) {
   1643 				case 0:
   1644 					/* Fake some terminal parameters.  */
   1645 					ite_sendstr(ip,
   1646 					    "\033[2;1;1;112;112;1;0x");
   1647 					break;
   1648 				case 1:
   1649 					ite_sendstr(ip,
   1650 					    "\033[3;1;1;112;112;1;0x");
   1651 					break;
   1652 				}
   1653 				ip->escape = 0;
   1654 				return;
   1655 
   1656 			case 'g':
   1657 				/* clear tabs */
   1658 				switch (ite_zargnum(ip)) {
   1659 				case 0:
   1660 					if (ip->curx < ip->cols)
   1661 						ip->tabs[ip->curx] = 0;
   1662 					break;
   1663 				case 3:
   1664 					for (n = 0; n < ip->cols; n++)
   1665 						ip->tabs[n] = 0;
   1666 					break;
   1667 
   1668 				default:
   1669 					/* ignore */
   1670 					break;
   1671 				}
   1672 				ip->escape = 0;
   1673 				return;
   1674 
   1675 			case 'h': /* set mode */
   1676 			case 'l': /* reset mode */
   1677 				n = ite_zargnum(ip);
   1678 				switch (n) {
   1679 				case 4:
   1680 					/* insert/replace mode */
   1681 					ip->imode = (c == 'h');
   1682 					break;
   1683 				case 20:
   1684 					ip->linefeed_newline = (c == 'h');
   1685 					break;
   1686 				}
   1687 				ip->escape = 0;
   1688 				return;
   1689 
   1690 			case 'M':
   1691 				/* delete line */
   1692 				ite_dnline(ip, ite_argnum(ip));
   1693 				ip->escape = 0;
   1694 				return;
   1695 
   1696 			case 'L':
   1697 				/* insert line */
   1698 				ite_inline(ip, ite_argnum(ip));
   1699 				ip->escape = 0;
   1700 				return;
   1701 
   1702 			case 'P':
   1703 				/* delete char */
   1704 				ite_dnchar(ip, ite_argnum(ip));
   1705 				ip->escape = 0;
   1706 				return;
   1707 
   1708 			case '@':
   1709 				/* insert char(s) */
   1710 				ite_inchar(ip, ite_argnum(ip));
   1711 				ip->escape = 0;
   1712 				return;
   1713 
   1714 			case '!':
   1715 				/* soft terminal reset */
   1716 				ip->escape = 0; /* XXX */
   1717 				return;
   1718 
   1719 			case 'G':
   1720 				/*
   1721 				 * this one was *not* in my vt320 manual but
   1722 				 * in a vt320 termcap entry.. who is right?
   1723 				 * It's supposed to set the horizontal cursor
   1724 				 * position.
   1725 				 */
   1726 				*ip->ap = 0;
   1727 				x = atoi(ip->argbuf);
   1728 				if (x != 0)
   1729 					x--;
   1730 				ip->curx = uimin(x, ip->cols - 1);
   1731 				ip->escape = 0;
   1732 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1733 				clr_attr(ip, ATTR_INV);
   1734 				return;
   1735 
   1736 			case 'd':
   1737 				/*
   1738 				 * same thing here, this one's for setting
   1739 				 * the absolute vertical cursor position.
   1740 				 * Not documented...
   1741 				 */
   1742 				*ip->ap = 0;
   1743 				y = atoi(ip->argbuf);
   1744 				if (y)
   1745 					y--;
   1746 				if (ip->inside_margins)
   1747 					y += ip->top_margin;
   1748 				ip->cury = uimin(y, ip->rows - 1);
   1749 				ip->escape = 0;
   1750 				snap_cury(ip);
   1751 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1752 				clr_attr(ip, ATTR_INV);
   1753 				return;
   1754 
   1755 			case 'H':
   1756 			case 'f':
   1757 				*ip->ap = 0;
   1758 				y = atoi(ip->argbuf);
   1759 				x = 0;
   1760 				cp = strchr(ip->argbuf, ';');
   1761 				if (cp != NULL)
   1762 					x = atoi(cp + 1);
   1763 				if (x != 0)
   1764 					x--;
   1765 				if (y != 0)
   1766 					y--;
   1767 				if (ip->inside_margins != 0)
   1768 					y += ip->top_margin;
   1769 				ip->cury = uimin(y, ip->rows - 1);
   1770 				ip->curx = uimin(x, ip->cols - 1);
   1771 				ip->escape = 0;
   1772 				snap_cury(ip);
   1773 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1774 				/*clr_attr(ip, ATTR_INV);*/
   1775 				return;
   1776 
   1777 			case 'A':
   1778 				/* cursor up */
   1779 				n = ite_argnum(ip);
   1780 				n = ip->cury - (n ? n : 1);
   1781 				if (n < 0)
   1782 					n = 0;
   1783 				if (ip->inside_margins)
   1784 					n = uimax(ip->top_margin, n);
   1785 				else if (n == ip->top_margin - 1)
   1786 					/*
   1787 					 * allow scrolling outside region,
   1788 					 * but don't scroll out of active
   1789 					 * region without explicit CUP
   1790 					 */
   1791 					n = ip->top_margin;
   1792 				ip->cury = n;
   1793 				ip->escape = 0;
   1794 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1795 				clr_attr(ip, ATTR_INV);
   1796 				return;
   1797 
   1798 			case 'B':
   1799 				/* cursor down */
   1800 				n = ite_argnum(ip);
   1801 				n = ip->cury + (n ? n : 1);
   1802 				n = uimin(ip->rows - 1, n);
   1803 #if 0
   1804 				if (ip->inside_margins)
   1805 #endif
   1806 					n = uimin(ip->bottom_margin, n);
   1807 #if 0
   1808 				else if (n == ip->bottom_margin + 1)
   1809 					/*
   1810 					 * allow scrolling outside region,
   1811 					 * but don't scroll out of active
   1812 					 * region without explicit CUP
   1813 					 */
   1814 					n = ip->bottom_margin;
   1815 #endif
   1816 				ip->cury = n;
   1817 				ip->escape = 0;
   1818 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1819 				clr_attr(ip, ATTR_INV);
   1820 				return;
   1821 
   1822 			case 'C':
   1823 				/* cursor forward */
   1824 				n = ite_argnum(ip);
   1825 				n = n ? n : 1;
   1826 				ip->curx = uimin(ip->curx + n, ip->cols - 1);
   1827 				ip->escape = 0;
   1828 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1829 				clr_attr(ip, ATTR_INV);
   1830 				return;
   1831 
   1832 			case 'D':
   1833 				/* cursor backward */
   1834 				n = ite_argnum(ip);
   1835 				n = n ? n : 1;
   1836 				n = ip->curx - n;
   1837 				ip->curx = n >= 0 ? n : 0;
   1838 				ip->escape = 0;
   1839 				SUBR_CURSOR(ip, MOVE_CURSOR);
   1840 				clr_attr(ip, ATTR_INV);
   1841 				return;
   1842 
   1843 			case 'J':
   1844 				/* erase screen */
   1845 				*ip->ap = 0;
   1846 				n = ite_zargnum(ip);
   1847 				if (n == 0)
   1848 					ite_clrtoeos(ip);
   1849 				else if (n == 1)
   1850 					ite_clrtobos(ip);
   1851 				else if (n == 2)
   1852 					ite_clrscreen(ip);
   1853 				ip->escape = 0;
   1854 				return;
   1855 
   1856 			case 'K':
   1857 				/* erase line */
   1858 				n = ite_zargnum(ip);
   1859 				if (n == 0)
   1860 					ite_clrtoeol(ip);
   1861 				else if (n == 1)
   1862 					ite_clrtobol(ip);
   1863 				else if (n == 2)
   1864 					ite_clrline(ip);
   1865 				ip->escape = 0;
   1866 				return;
   1867 
   1868 			case 'S':
   1869 				/* scroll up */
   1870 				n = ite_zargnum(ip);
   1871 				if (n <= 0)
   1872 					n = 1;
   1873 				else if (n > ip->rows-1)
   1874 					n = ip->rows-1;
   1875 				SUBR_SCROLL(ip, ip->rows-1, 0, n, SCROLL_UP);
   1876 				ip->escape = 0;
   1877 				return;
   1878 
   1879 			case 'T':
   1880 				/* scroll down */
   1881 				n = ite_zargnum(ip);
   1882 				if (n <= 0)
   1883 					n = 1;
   1884 				else if (n > ip->rows-1)
   1885 					n = ip->rows-1;
   1886 				SUBR_SCROLL(ip, 0, 0, n, SCROLL_DOWN);
   1887 				ip->escape = 0;
   1888 				return;
   1889 
   1890 			case 'X':
   1891 				/* erase character */
   1892 				n = ite_argnum(ip) - 1;
   1893 				n = uimin(n, ip->cols - 1 - ip->curx);
   1894 				for (; n >= 0; n--) {
   1895 					attrclr(ip, ip->cury, ip->curx + n,
   1896 					    1, 1);
   1897 					SUBR_PUTC(ip, ' ',
   1898 					    ip->cury, ip->curx + n, ATTR_NOR);
   1899 				}
   1900 				ip->escape = 0;
   1901 				return;
   1902 
   1903 			case '}': case '`':
   1904 				/* status line control */
   1905 				ip->escape = 0;
   1906 				return;
   1907 
   1908 			case 'r':
   1909 				/* set scrolling region */
   1910 				ip->escape = 0;
   1911 				*ip->ap = 0;
   1912 				x = atoi(ip->argbuf);
   1913 				x = x ? x : 1;
   1914 				y = ip->rows;
   1915 				cp = strchr(ip->argbuf, ';');
   1916 				if (cp) {
   1917 					y = atoi(cp + 1);
   1918 					y = y ? y : ip->rows;
   1919 				}
   1920 				if (y <= x)
   1921 					return;
   1922 				x--;
   1923 				y--;
   1924 				ip->top_margin = uimin(x, ip->rows - 2);
   1925 				ip->bottom_margin = uimin(y, ip->rows - 1);
   1926 				if (ip->inside_margins) {
   1927 					ip->cury = ip->top_margin;
   1928 				} else
   1929 					ip->cury = 0;
   1930 				ip->curx = 0;
   1931 				return;
   1932 
   1933 			case 'm':
   1934 				/* big attribute setter/resetter */
   1935 			{
   1936 				char *c_p;
   1937 
   1938 				*ip->ap = 0;
   1939 				/* kludge to make CSIm work (== CSI0m) */
   1940 				if (ip->ap == ip->argbuf)
   1941 					ip->ap++;
   1942 				for (c_p = ip->argbuf; c_p < ip->ap; ) {
   1943 					switch (*c_p) {
   1944 					case 0:
   1945 					case '0':
   1946 						clr_attr(ip, ATTR_ALL);
   1947 						ip->fgcolor = 7;
   1948 						ip->bgcolor = 0;
   1949 						c_p++;
   1950 						break;
   1951 
   1952 					case '1':
   1953 						set_attr(ip, ATTR_BOLD);
   1954 						c_p++;
   1955 						break;
   1956 
   1957 					case '2':
   1958 						switch (c_p[1]) {
   1959 						case '2':
   1960 							clr_attr(ip, ATTR_BOLD);
   1961 							c_p += 2;
   1962 							break;
   1963 
   1964 						case '4':
   1965 							clr_attr(ip, ATTR_UL);
   1966 							c_p += 2;
   1967 							break;
   1968 
   1969 						case '5':
   1970 							clr_attr(ip,
   1971 							    ATTR_BLINK);
   1972 							c_p += 2;
   1973 							break;
   1974 
   1975 						case '7':
   1976 							clr_attr(ip, ATTR_INV);
   1977 							c_p += 2;
   1978 							break;
   1979 
   1980 						default:
   1981 							c_p++;
   1982 							break;
   1983 						}
   1984 						break;
   1985 
   1986 					case '3':
   1987 						switch (c_p[1]) {
   1988 						case '0':
   1989 						case '1':
   1990 						case '2':
   1991 						case '3':
   1992 						case '4':
   1993 						case '5':
   1994 						case '6':
   1995 						case '7':
   1996 							/* foreground colors */
   1997 							ip->fgcolor =
   1998 							    c_p[1] - '0';
   1999 							c_p += 2;
   2000 							break;
   2001 						default:
   2002 							c_p++;
   2003 							break;
   2004 						}
   2005 						break;
   2006 
   2007 					case '4':
   2008 						switch (c_p[1]) {
   2009 						case '0':
   2010 						case '1':
   2011 						case '2':
   2012 						case '3':
   2013 						case '4':
   2014 						case '5':
   2015 						case '6':
   2016 						case '7':
   2017 							/* background colors */
   2018 							ip->bgcolor =
   2019 							    c_p[1] - '0';
   2020 							c_p += 2;
   2021 							break;
   2022 						default:
   2023 							set_attr(ip, ATTR_UL);
   2024 							c_p++;
   2025 							break;
   2026 						}
   2027 						break;
   2028 
   2029 					case '5':
   2030 						set_attr(ip, ATTR_BLINK);
   2031 						c_p++;
   2032 						break;
   2033 
   2034 					case '7':
   2035 						set_attr(ip, ATTR_INV);
   2036 						c_p++;
   2037 						break;
   2038 
   2039 					default:
   2040 						c_p++;
   2041 						break;
   2042 					}
   2043 				}
   2044 
   2045 			}
   2046 				ip->escape = 0;
   2047 				return;
   2048 
   2049 			case 'u':
   2050 				/* DECRQTSR */
   2051 				ite_sendstr(ip, "\033P\033\\");
   2052 				ip->escape = 0;
   2053 				return;
   2054 
   2055 			default:
   2056 				ip->escape = 0;
   2057 				return;
   2058 			}
   2059 			break;
   2060 
   2061 		case '?':	/* CSI ? */
   2062 			switch (c) {
   2063 			case '0':
   2064 			case '1':
   2065 			case '2':
   2066 			case '3':
   2067 			case '4':
   2068 			case '5':
   2069 			case '6':
   2070 			case '7':
   2071 			case '8':
   2072 			case '9':
   2073 			case ';':
   2074 			case '\"':
   2075 			case '$':
   2076 				/*
   2077 				 * Don't fill the last character; it's needed.
   2078 				 */
   2079 				/* XXX yeah, where ?? */
   2080 				if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
   2081 					*ip->ap++ = c;
   2082 				return;
   2083 
   2084 			case 'n':
   2085 				/* Terminal Reports */
   2086 				*ip->ap = 0;
   2087 				if (ip->ap == &ip->argbuf[2]) {
   2088 					if (!strncmp(ip->argbuf, "15", 2))
   2089 						/* printer status: no printer */
   2090 						ite_sendstr(ip, "\033[13n");
   2091 					else if (!strncmp(ip->argbuf, "25", 2))
   2092 						/* udk status */
   2093 						ite_sendstr(ip, "\033[20n");
   2094 					else if (!strncmp(ip->argbuf, "26", 2))
   2095 						/* keyboard dialect: US */
   2096 						ite_sendstr(ip, "\033[27;1n");
   2097 				}
   2098 				ip->escape = 0;
   2099 				return;
   2100 
   2101 			case 'h': /* set dec private modes */
   2102 			case 'l': /* reset dec private modes */
   2103 				n = ite_zargnum(ip);
   2104 				switch (n) {
   2105 				case 1:
   2106 					/* CKM - cursor key mode */
   2107 					ip->cursor_appmode = (c == 'h');
   2108 					break;
   2109 
   2110 				case 3:
   2111 					/* 132/80 columns (132 == 'h') */
   2112 					break;
   2113 
   2114 				case 4: /* smooth scroll */
   2115 					break;
   2116 
   2117 				case 5:
   2118 					/*
   2119 					 * light background (=='h') /
   2120 					 * dark background (=='l')
   2121 					 */
   2122 					break;
   2123 
   2124 				case 6: /* origin mode */
   2125 					ip->inside_margins = (c == 'h');
   2126 #if 0
   2127 					ip->curx = 0;
   2128 					ip->cury = ip->inside_margins ?
   2129 					    ip->top_margin : 0;
   2130 					SUBR_CURSOR(ip, MOVE_CURSOR);
   2131 #endif
   2132 					break;
   2133 
   2134 				case 7: /* auto wraparound */
   2135 					ip->auto_wrap = (c == 'h');
   2136 					break;
   2137 
   2138 				case 8: /* keyboard repeat */
   2139 					ip->key_repeat = (c == 'h');
   2140 					break;
   2141 
   2142 				case 20: /* newline mode */
   2143 					ip->linefeed_newline = (c == 'h');
   2144 					break;
   2145 
   2146 				case 25: /* cursor on/off */
   2147 					SUBR_CURSOR(ip, (c == 'h') ?
   2148 					    DRAW_CURSOR : ERASE_CURSOR);
   2149 					break;
   2150 				}
   2151 				ip->escape = 0;
   2152 				return;
   2153 
   2154 			case 'K':
   2155 				/* selective erase in line */
   2156 			case 'J':
   2157 				/* selective erase in display */
   2158 
   2159 			default:
   2160 				ip->escape = 0;
   2161 				return;
   2162 			}
   2163 			break;
   2164 
   2165 		default:
   2166 			ip->escape = 0;
   2167 			return;
   2168 		}
   2169 	}
   2170 
   2171 	switch (c) {
   2172 	case 0x00:	/* NUL */
   2173 	case 0x01:	/* SOH */
   2174 	case 0x02:	/* STX */
   2175 	case 0x03:	/* ETX */
   2176 	case 0x04:	/* EOT */
   2177 	case 0x05:	/* ENQ */
   2178 	case 0x06:	/* ACK */
   2179 		break;
   2180 
   2181 	case BEL:
   2182 #if NBELL > 0
   2183 		if (kbd_ite && ite_tty[device_unit(kbd_ite->device)])
   2184 			opm_bell();
   2185 #endif
   2186 		break;
   2187 
   2188 	case BS:
   2189 		if (--ip->curx < 0)
   2190 			ip->curx = 0;
   2191 		else
   2192 			SUBR_CURSOR(ip, MOVE_CURSOR);
   2193 		break;
   2194 
   2195 	case HT:
   2196 		for (n = ip->curx + 1; n < ip->cols; n++) {
   2197 			if (ip->tabs[n]) {
   2198 				ip->curx = n;
   2199 				SUBR_CURSOR(ip, MOVE_CURSOR);
   2200 				break;
   2201 			}
   2202 		}
   2203 		break;
   2204 
   2205 	case VT:	/* VT is treated like LF */
   2206 	case FF:	/* so is FF */
   2207 	case LF:
   2208 		/*
   2209 		 * cr->crlf distinction is done here, on output,
   2210 		 * not on input!
   2211 		 */
   2212 		if (ip->linefeed_newline)
   2213 			ite_crlf(ip);
   2214 		else
   2215 			ite_lf(ip);
   2216 		break;
   2217 
   2218 	case CR:
   2219 		ite_cr(ip);
   2220 		break;
   2221 
   2222 	case SO:
   2223 		ip->GL = &ip->G1;
   2224 		break;
   2225 
   2226 	case SI:
   2227 		ip->GL = &ip->G0;
   2228 		break;
   2229 
   2230 	case 0x10:	/* DLE */
   2231 	case 0x11:	/* DC1/XON */
   2232 	case 0x12:	/* DC2 */
   2233 	case 0x13:	/* DC3/XOFF */
   2234 	case 0x14:	/* DC4 */
   2235 	case 0x15:	/* NAK */
   2236 	case 0x16:	/* SYN */
   2237 	case 0x17:	/* ETB */
   2238 		break;
   2239 
   2240 	case CAN:
   2241 		ip->escape = 0;	/* cancel any escape sequence in progress */
   2242 		break;
   2243 
   2244 	case 0x19:	/* EM */
   2245 		break;
   2246 
   2247 	case SUB:
   2248 		ip->escape = 0;	/* dito, but see below */
   2249 		/* should also display a reverse question mark!! */
   2250 		break;
   2251 
   2252 	case ESC:
   2253 		ip->escape = ESC;
   2254 		break;
   2255 
   2256 	case 0x1c:	/* FS */
   2257 	case 0x1d:	/* GS */
   2258 	case 0x1e:	/* RS */
   2259 	case 0x1f:	/* US */
   2260 		break;
   2261 
   2262 	/* now it gets weird.. 8bit control sequences.. */
   2263 	case IND:	/* index: move cursor down, scroll */
   2264 		ite_index(ip);
   2265 		break;
   2266 
   2267 	case NEL:	/* next line. next line, first pos. */
   2268 		ite_crlf(ip);
   2269 		break;
   2270 
   2271 	case HTS:	/* set horizontal tab */
   2272 		if (ip->curx < ip->cols)
   2273 			ip->tabs[ip->curx] = 1;
   2274 		break;
   2275 
   2276 	case RI:	/* reverse index */
   2277 		ite_rlf(ip);
   2278 		break;
   2279 
   2280 	case SS2:	/* go into G2 for one character */
   2281 		ip->save_GL = ip->GR;	/* GL XXX EUC */
   2282 		ip->GR = &ip->G2;	/* GL XXX */
   2283 		break;
   2284 
   2285 	case SS3:	/* go into G3 for one character */
   2286 		ip->save_GL = ip->GR;	/* GL XXX EUC */
   2287 		ip->GR = &ip->G3;	/* GL XXX */
   2288 		break;
   2289 
   2290 	case DCS:	/* device control string introducer */
   2291 		ip->escape = DCS;
   2292 		ip->ap = ip->argbuf;
   2293 		break;
   2294 
   2295 	case CSI:	/* control sequence introducer */
   2296 		ip->escape = CSI;
   2297 		ip->ap = ip->argbuf;
   2298 		break;
   2299 
   2300 	case ST:	/* string terminator */
   2301 		/* ignore, if not used as terminator */
   2302 		break;
   2303 
   2304 	case OSC:	/* introduces OS command. */
   2305 		/* Ignore everything upto ST */
   2306 		ip->escape = OSC;
   2307 		break;
   2308 
   2309 	case PM:	/* privacy message */
   2310 		/* ignore everything upto ST */
   2311 		ip->escape = PM;
   2312 		break;
   2313 
   2314 	case APC:	/* application program command */
   2315 		/* ignore everything upto ST */
   2316 		ip->escape = APC;
   2317 		break;
   2318 
   2319 	case DEL:
   2320 		break;
   2321 
   2322 	default:
   2323 		if (ip->save_char == 0 &&
   2324 		    (*((c & 0x80) ? ip->GR : ip->GL) & CSET_MULTI) != 0) {
   2325 			ip->save_char = c;
   2326 			break;
   2327 		}
   2328 		if (ip->imode != 0)
   2329 			ite_inchar(ip, ip->save_char ? 2 : 1);
   2330 		iteprecheckwrap(ip);
   2331 #ifdef DO_WEIRD_ATTRIBUTES
   2332 		if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
   2333 			attrset(ip, ATTR_INV);
   2334 			SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
   2335 		}
   2336 		else
   2337 			SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
   2338 #else
   2339 		SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
   2340 #endif
   2341 		/*SUBR_CURSOR(ip, DRAW_CURSOR);*/
   2342 		itecheckwrap(ip);
   2343 		if (ip->save_char) {
   2344 			itecheckwrap(ip);
   2345 			ip->save_char = 0;
   2346 		}
   2347 		if (ip->save_GL) {
   2348 			/*
   2349 			 * reset single shift
   2350 			 */
   2351 			ip->GR = ip->save_GL;
   2352 			ip->save_GL = 0;
   2353 		}
   2354 		break;
   2355 	}
   2356 }
   2357 
   2358 static void
   2359 iteprecheckwrap(struct ite_softc *ip)
   2360 {
   2361 
   2362 	if (ip->auto_wrap && ip->curx + (ip->save_char ? 1 : 0) == ip->cols) {
   2363 		ip->curx = 0;
   2364 		clr_attr(ip, ATTR_INV);
   2365 		if (++ip->cury >= ip->bottom_margin + 1) {
   2366 			ip->cury = ip->bottom_margin;
   2367 			/*SUBR_CURSOR(ip, MOVE_CURSOR);*/
   2368 			SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
   2369 			ite_clrtoeol(ip);
   2370 		} /*else
   2371 			SUBR_CURSOR(ip, MOVE_CURSOR);*/
   2372 	}
   2373 }
   2374 
   2375 static void
   2376 itecheckwrap(struct ite_softc *ip)
   2377 {
   2378 
   2379 #if 0
   2380 	if (++ip->curx == ip->cols) {
   2381 		if (ip->auto_wrap) {
   2382 			ip->curx = 0;
   2383 			clr_attr(ip, ATTR_INV);
   2384 			if (++ip->cury >= ip->bottom_margin + 1) {
   2385 				ip->cury = ip->bottom_margin;
   2386 				SUBR_CURSOR(ip, MOVE_CURSOR);
   2387 				SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1,
   2388 				    SCROLL_UP);
   2389 				ite_clrtoeol(ip);
   2390 				return;
   2391 			}
   2392 		} else
   2393 			/* stay there if no autowrap.. */
   2394 			ip->curx--;
   2395 	}
   2396 #else
   2397 	if (ip->curx < ip->cols) {
   2398 		ip->curx++;
   2399 		/*SUBR_CURSOR(ip, MOVE_CURSOR);*/
   2400 	}
   2401 #endif
   2402 }
   2403 
   2404 /*
   2405  * A convertion table from DEC special graphics characters to ASCII characters.
   2406  * Mostly for box drawing on sysinst(8).
   2407  */
   2408 const uint8_t ite_decgraph2ascii[128] = {
   2409 	/* same as ASCII from 0x00 to 0x5e */
   2410 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   2411 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   2412 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   2413 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   2414 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
   2415 	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   2416 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
   2417 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   2418 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
   2419 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
   2420 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
   2421 	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
   2422 
   2423 	/* special graphics characters from 0x5f to 0x7e */
   2424 	' ',	/* 0x5f NBSP */
   2425 	'*',	/* 0x60 diamond */
   2426 	' ',	/* 0x61 medium shade */
   2427 	' ',	/* 0x62 HT */
   2428 	' ',	/* 0x63 FF */
   2429 	' ',	/* 0x64 CR */
   2430 	' ',	/* 0x65 LF */
   2431 	' ',	/* 0x66 degree symbol */
   2432 	' ',	/* 0x67 plus-minus sign */
   2433 	' ',	/* 0x68 NL */
   2434 	' ',	/* 0x69 VT */
   2435 	'+',	/* 0x6a box drawings up left */
   2436 	'+',	/* 0x6b box drawings down left */
   2437 	'+',	/* 0x6c box drawings down right */
   2438 	'+',	/* 0x6d box drawings up right */
   2439 	'+',	/* 0x6e box drawings vertical horizontal */
   2440 	'~',	/* 0x6f scan line 1 */
   2441 	'-',	/* 0x70 scan line 3 */
   2442 	'-',	/* 0x71 scan line 5 */
   2443 	'-',	/* 0x72 scan line 7 */
   2444 	'_',	/* 0x73 scan line 9 */
   2445 	'+',	/* 0x74 box drawings vertical right */
   2446 	'+',	/* 0x75 box drawings vertical left */
   2447 	'+',	/* 0x76 box drawings horizontal up */
   2448 	'+',	/* 0x77 box drawings horizontal down */
   2449 	'|',	/* 0x78 box drawings vertical */
   2450 	'<',	/* 0x79 less than or equal to */
   2451 	'>',	/* 0x7a greater than or equal to */
   2452 	' ',	/* 0x7b pi */
   2453 	' ',	/* 0x7c not equal */
   2454 	' ',	/* 0x7d pound sign */
   2455 	'.',	/* 0x7e middle dot */
   2456 	/* end of special graphics characters */
   2457 	0x7f
   2458 };
   2459 
   2460 #endif
   2461 
   2462 #if NITE > 0 && NKBD > 0
   2463 
   2464 /*
   2465  * Console functions
   2466  */
   2467 #include <dev/cons.h>
   2468 extern void kbdenable(int);
   2469 extern int kbdcngetc(void);
   2470 
   2471 /*
   2472  * Return a priority in consdev->cn_pri field highest wins.  This function
   2473  * is called before any devices have been probed.
   2474  */
   2475 void
   2476 itecnprobe(struct consdev *cd)
   2477 {
   2478 	int maj;
   2479 
   2480 	/* locate the major number */
   2481 	maj = cdevsw_lookup_major(&ite_cdevsw);
   2482 
   2483 	/*
   2484 	 * return priority of the best ite (already picked from attach)
   2485 	 * or CN_DEAD.
   2486 	 */
   2487 	if (con_itesoftc.grf == NULL)
   2488 		cd->cn_pri = CN_DEAD;
   2489 	else {
   2490 		con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
   2491 		/*
   2492 		 * hardcode the minor number.
   2493 		 * currently we support only one ITE, it is enough for now.
   2494 		 */
   2495 		con_itesoftc.isw = &itesw[0];
   2496 		cd->cn_pri = CN_INTERNAL;
   2497 		cd->cn_dev = makedev(maj, 0);
   2498 	}
   2499 }
   2500 
   2501 void
   2502 itecninit(struct consdev *cd)
   2503 {
   2504 	struct ite_softc *ip;
   2505 
   2506 	ip = getitesp(cd->cn_dev);
   2507 	iteinit(cd->cn_dev);	       /* init console unit */
   2508 	ip->flags |= ITE_ACTIVE | ITE_ISCONS;
   2509 	kbdenable(0);
   2510 	mfp_send_usart(0x49);
   2511 }
   2512 
   2513 /*
   2514  * itecnfinish() is called in ite_init() when the device is
   2515  * being probed in the normal fashion, thus we can finish setting
   2516  * up this ite now that the system is more functional.
   2517  */
   2518 void
   2519 itecnfinish(struct ite_softc *ip)
   2520 {
   2521 	static int done;
   2522 
   2523 	if (done)
   2524 		return;
   2525 	done = 1;
   2526 }
   2527 
   2528 /*ARGSUSED*/
   2529 int
   2530 itecngetc(dev_t dev)
   2531 {
   2532 	int c;
   2533 
   2534 	do {
   2535 		c = kbdcngetc();
   2536 		c = ite_cnfilter(c);
   2537 	} while (c == -1);
   2538 	return (c);
   2539 }
   2540 
   2541 void
   2542 itecnputc(dev_t dev, int c)
   2543 {
   2544 	static int paniced = 0;
   2545 	struct ite_softc *ip = getitesp(dev);
   2546 	char ch = c;
   2547 #ifdef ITE_KERNEL_ATTR
   2548 	short save_attribute;
   2549 #endif
   2550 
   2551 	if (panicstr && !paniced &&
   2552 	    (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
   2553 		(void) iteon(dev, 3);
   2554 		paniced = 1;
   2555 	}
   2556 #ifdef ITE_KERNEL_ATTR
   2557 	save_attribute = ip->attribute;
   2558 	ip->attribute = ITE_KERNEL_ATTR;
   2559 #endif
   2560 	ite_putstr(&ch, 1, dev);
   2561 #ifdef ITE_KERNEL_ATTR
   2562 	ip->attribute = save_attribute;
   2563 #endif
   2564 }
   2565 #endif
   2566