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