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