xref: /netbsd-src/sys/arch/amiga/dev/ite.c (revision ce0bb6e8d2e560ecacbe865a848624f94498063b)
1 /*	$NetBSD: ite.c,v 1.27 1995/04/10 09:11:41 mycroft 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. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *      This product includes software developed by the University of
23  *      California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  *	from: Utah Hdr: ite.c 1.1 90/07/09
41  *	@(#)ite.c 7.6 (Berkeley) 5/16/91
42  */
43 
44 /*
45  * ite - bitmaped terminal.
46  * Supports VT200, a few terminal features will be unavailable until
47  * the system actually probes the device (i.e. not after consinit())
48  */
49 
50 #include <sys/param.h>
51 #include <sys/kernel.h>
52 #include <sys/conf.h>
53 #include <sys/device.h>
54 #include <sys/malloc.h>
55 #include <sys/ioctl.h>
56 #include <sys/tty.h>
57 #include <sys/termios.h>
58 #include <sys/systm.h>
59 #include <sys/proc.h>
60 #include <dev/cons.h>
61 #include <amiga/amiga/kdassert.h>
62 #include <amiga/amiga/color.h>	/* DEBUG */
63 #include <amiga/amiga/device.h>
64 #include <amiga/dev/iteioctl.h>
65 #include <amiga/dev/itevar.h>
66 #include <amiga/dev/kbdmap.h>
67 #include <amiga/dev/grfioctl.h>
68 #include <amiga/dev/grfvar.h>
69 
70 
71 /*
72  * XXX go ask sys/kern/tty.c:ttselect()
73  */
74 #include "grf.h"
75 struct tty *ite_tty[NGRF];
76 
77 #define ITEUNIT(dev)	(minor(dev))
78 
79 #define SUBR_INIT(ip)		(ip)->grf->g_iteinit(ip)
80 #define SUBR_DEINIT(ip)		(ip)->grf->g_itedeinit(ip)
81 #define SUBR_PUTC(ip,c,dy,dx,m)	(ip)->grf->g_iteputc(ip,c,dy,dx,m)
82 #define SUBR_CURSOR(ip,flg)	(ip)->grf->g_itecursor(ip,flg)
83 #define SUBR_CLEAR(ip,sy,sx,h,w)	(ip)->grf->g_iteclear(ip,sy,sx,h,w)
84 #define SUBR_SCROLL(ip,sy,sx,count,dir)	\
85     (ip)->grf->g_itescroll(ip,sy,sx,count,dir)
86 
87 u_int	ite_confunits;			/* configured units */
88 
89 int	start_repeat_timeo = 30;	/* first repeat after x s/100 */
90 int	next_repeat_timeo = 10;		/* next repeat after x s/100 */
91 
92 int	ite_default_wrap = 1;		/* you want vtxxx-nam, binpatch */
93 
94 struct	ite_softc con_itesoftc;
95 u_char	cons_tabs[MAX_TABS];
96 
97 struct ite_softc *kbd_ite;
98 int kbd_init;
99 
100 static char *index __P((const char *, char));
101 static int inline atoi __P((const char *));
102 void iteputchar __P((int c, struct ite_softc *ip));
103 void ite_putstr __P((const char * s, int len, dev_t dev));
104 void iteattach __P((struct device *, struct device *, void *));
105 int itematch __P((struct device *, struct cfdata *, void *));
106 
107 struct cfdriver itecd = {
108 	NULL, "ite", (cfmatch_t)itematch, iteattach, DV_DULL,
109 	sizeof(struct ite_softc), NULL, 0 };
110 
111 int
112 itematch(pdp, cdp, auxp)
113 	struct device *pdp;
114 	struct cfdata *cdp;
115 	void *auxp;
116 {
117 	struct grf_softc *gp;
118 	int maj;
119 
120 	gp = auxp;
121 	/*
122 	 * all that our mask allows (more than enough no one
123 	 * has > 32 monitors for text consoles on one machine)
124 	 */
125 	if (cdp->cf_unit >= sizeof(ite_confunits) * NBBY)
126 		return(0);
127 	/*
128 	 * XXX
129 	 * normally this would be done in attach, however
130 	 * during early init we do not have a device pointer
131 	 * and thus no unit number.
132 	 */
133 	for(maj = 0; maj < nchrdev; maj++)
134 		if (cdevsw[maj].d_open == iteopen)
135 			break;
136 	gp->g_itedev = makedev(maj, cdp->cf_unit);
137 	return(1);
138 }
139 
140 void
141 iteattach(pdp, dp, auxp)
142 	struct device *pdp, *dp;
143 	void *auxp;
144 {
145 	extern int hz;
146 	struct grf_softc *gp;
147 	struct ite_softc *ip;
148 	int s;
149 
150 	gp = (struct grf_softc *)auxp;
151 
152 	/*
153 	 * mark unit as attached (XXX see itematch)
154 	 */
155 	ite_confunits |= 1 << ITEUNIT(gp->g_itedev);
156 
157 	if (dp) {
158 		ip = (struct ite_softc *)dp;
159 
160 		s = spltty();
161 		if (con_itesoftc.grf != NULL &&
162 		    con_itesoftc.grf->g_unit == gp->g_unit) {
163 			/*
164 			 * console reinit copy params over.
165 			 * and console always gets keyboard
166 			 */
167 			bcopy(&con_itesoftc.grf, &ip->grf,
168 			    (char *)&ip[1] - (char *)&ip->grf);
169 			con_itesoftc.grf = NULL;
170 			kbd_ite = ip;
171 		}
172 		ip->grf = gp;
173 		splx(s);
174 
175 		alloc_sicallback();
176 		iteinit(gp->g_itedev);
177 		printf(": rows %d cols %d", ip->rows, ip->cols);
178 		printf(" repeat at (%d/100)s next at (%d/100)s",
179 		    start_repeat_timeo, next_repeat_timeo);
180 
181 		if (kbd_ite == NULL)
182 			kbd_ite = ip;
183 		if (kbd_ite == ip)
184 			printf(" has keyboard");
185 		printf("\n");
186 	} else {
187 		if (con_itesoftc.grf != NULL &&
188 		    con_itesoftc.grf->g_conpri > gp->g_conpri)
189 			return;
190 		con_itesoftc.grf = gp;
191 		con_itesoftc.tabs = cons_tabs;
192 	}
193 }
194 
195 struct ite_softc *
196 getitesp(dev)
197 	dev_t dev;
198 {
199 	if (amiga_realconfig && con_itesoftc.grf == NULL)
200 		return(itecd.cd_devs[ITEUNIT(dev)]);
201 
202 	if (con_itesoftc.grf == NULL)
203 		panic("no ite_softc for console");
204 	return(&con_itesoftc);
205 }
206 
207 /*
208  * cons.c entry points into ite device.
209  */
210 
211 /*
212  * Return a priority in consdev->cn_pri field highest wins.  This function
213  * is called before any devices have been probed.
214  */
215 void
216 itecnprobe(cd)
217 	struct consdev *cd;
218 {
219 	/*
220 	 * bring graphics layer up.
221 	 */
222 	config_console();
223 
224 	/*
225 	 * return priority of the best ite (already picked from attach)
226 	 * or CN_DEAD.
227 	 */
228 	if (con_itesoftc.grf == NULL)
229 		cd->cn_pri = CN_DEAD;
230 	else {
231 		cd->cn_pri = con_itesoftc.grf->g_conpri;
232 		cd->cn_dev = con_itesoftc.grf->g_itedev;
233 	}
234 }
235 
236 void
237 itecninit(cd)
238 	struct consdev *cd;
239 {
240 	struct ite_softc *ip;
241 
242 	ip = getitesp(cd->cn_dev);
243 	iteinit(cd->cn_dev);
244 	ip->flags |= ITE_ACTIVE | ITE_ISCONS;
245 }
246 
247 /*
248  * ite_cnfinish() is called in ite_init() when the device is
249  * being probed in the normal fasion, thus we can finish setting
250  * up this ite now that the system is more functional.
251  */
252 void
253 ite_cnfinish(ip)
254 	struct ite_softc *ip;
255 {
256 	static int done;
257 
258 	if (done)
259 		return;
260 	done = 1;
261 }
262 
263 int
264 itecngetc(dev)
265 	dev_t dev;
266 {
267 	int c;
268 
269 	/* XXX this should be moved */
270 	if (!kbd_init) {
271 		kbd_init = 1;
272 		kbdenable();
273 	}
274 	do {
275 		c = kbdgetcn();
276 		c = ite_cnfilter(c, ITEFILT_CONSOLE);
277 	} while (c == -1);
278 	return (c);
279 }
280 
281 void
282 itecnputc(dev, c)
283 	dev_t dev;
284 	int c;
285 {
286 	static int paniced;
287 	struct ite_softc *ip;
288 	char ch;
289 
290 	ip = getitesp(dev);
291 	ch = c;
292 
293 	if (panicstr && !paniced &&
294 	    (ip->flags & (ITE_ACTIVE | ITE_INGRF)) != ITE_ACTIVE) {
295 		(void)ite_on(dev, 3);
296 		paniced = 1;
297 	}
298 	iteputchar(ch, ip);
299 }
300 
301 void
302 itecnpollc(dev, on)
303 	dev_t dev;
304 	int on;
305 {
306 
307 }
308 
309 /*
310  * standard entry points to the device.
311  */
312 
313 /*
314  * iteinit() is the standard entry point for initialization of
315  * an ite device, it is also called from ite_cninit().
316  *
317  */
318 void
319 iteinit(dev)
320 	dev_t dev;
321 {
322 	struct ite_softc *ip;
323 
324 	ip = getitesp(dev);
325 	if (ip->flags & ITE_INITED)
326 		return;
327 	bcopy(&ascii_kbdmap, &kbdmap, sizeof(struct kbdmap));
328 
329 	ip->cursorx = 0;
330 	ip->cursory = 0;
331 	SUBR_INIT(ip);
332 	SUBR_CURSOR(ip, DRAW_CURSOR);
333 	if (ip->tabs == NULL)
334 		ip->tabs = malloc(MAX_TABS * sizeof(u_char),M_DEVBUF,M_WAITOK);
335 	ite_reset(ip);
336 	ip->flags |= ITE_INITED;
337 }
338 
339 int
340 iteopen(dev, mode, devtype, p)
341 	dev_t dev;
342 	int mode, devtype;
343 	struct proc *p;
344 {
345 	struct ite_softc *ip;
346 	struct tty *tp;
347 	int error, first, unit;
348 
349 	unit = ITEUNIT(dev);
350 	first = 0;
351 
352 	if (((1 << unit) & ite_confunits) == 0)
353 		return (ENXIO);
354 
355 	ip = getitesp(dev);
356 
357 	if (ip->tp == NULL)
358 		tp = ite_tty[unit] = ip->tp = ttymalloc();
359 	else
360 		tp = ip->tp;
361 	if ((tp->t_state & (TS_ISOPEN | TS_XCLUDE)) == (TS_ISOPEN | TS_XCLUDE)
362 	    && p->p_ucred->cr_uid != 0)
363 		return (EBUSY);
364 	if ((ip->flags & ITE_ACTIVE) == 0) {
365 		error = ite_on(dev, 0);
366 		if (error)
367 			return (error);
368 		first = 1;
369 	}
370 	tp->t_oproc = itestart;
371 	tp->t_param = ite_param;
372 	tp->t_dev = dev;
373 	if ((tp->t_state & TS_ISOPEN) == 0) {
374 		ttychars(tp);
375 		tp->t_iflag = TTYDEF_IFLAG;
376 		tp->t_oflag = TTYDEF_OFLAG;
377 		tp->t_cflag = TTYDEF_CFLAG;
378 		tp->t_lflag = TTYDEF_LFLAG;
379 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
380 		tp->t_state = TS_WOPEN | TS_CARR_ON;
381 		ttsetwater(tp);
382 	}
383 	error = (*linesw[tp->t_line].l_open) (dev, tp);
384 	if (error == 0) {
385 		tp->t_winsize.ws_row = ip->rows;
386 		tp->t_winsize.ws_col = ip->cols;
387 		if (!kbd_init) {
388 			kbd_init = 1;
389 			kbdenable();
390 		}
391 	} else if (first)
392 		ite_off(dev, 0);
393 	return (error);
394 }
395 
396 int
397 iteclose(dev, flag, mode, p)
398 	dev_t dev;
399 	int flag, mode;
400 	struct proc *p;
401 {
402 	struct tty *tp;
403 
404 	tp = getitesp(dev)->tp;
405 
406 	KDASSERT(tp);
407 	(*linesw[tp->t_line].l_close) (tp, flag);
408 	ttyclose(tp);
409 	ite_off(dev, 0);
410 	return (0);
411 }
412 
413 int
414 iteread(dev, uio, flag)
415 	dev_t dev;
416 	struct uio *uio;
417 	int flag;
418 {
419 	struct tty *tp;
420 
421 	tp = getitesp(dev)->tp;
422 
423 	KDASSERT(tp);
424 	return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
425 }
426 
427 int
428 itewrite(dev, uio, flag)
429 	dev_t dev;
430 	struct uio *uio;
431 	int flag;
432 {
433 	struct tty *tp;
434 
435 	tp = getitesp(dev)->tp;
436 
437 	KDASSERT(tp);
438 	return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
439 }
440 
441 int
442 itestop(tp, flag)
443 	struct tty *tp;
444 	int flag;
445 {
446 
447 }
448 
449 int
450 iteioctl(dev, cmd, addr, flag, p)
451 	dev_t dev;
452 	u_long cmd;
453 	caddr_t addr;
454 	int flag;
455 	struct proc *p;
456 {
457 	struct iterepeat *irp;
458 	struct ite_softc *ip;
459 	struct tty *tp;
460 	int error;
461 
462 	ip = getitesp(dev);
463 	tp = ip->tp;
464 
465 	KDASSERT(tp);
466 
467 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p);
468 	if (error >= 0)
469 		return (error);
470 	error = ttioctl(tp, cmd, addr, flag, p);
471 	if (error >= 0)
472 		return (error);
473 
474 	switch (cmd) {
475 	case ITEIOCSKMAP:
476 		if (addr == 0)
477 			return(EFAULT);
478 		bcopy(addr, &kbdmap, sizeof(struct kbdmap));
479 		return(0);
480 	case ITEIOCGKMAP:
481 		if (addr == NULL)
482 			return(EFAULT);
483 		bcopy(&kbdmap, addr, sizeof(struct kbdmap));
484 		return(0);
485 	case ITEIOCGREPT:
486 		irp = (struct iterepeat *)addr;
487 		irp->start = start_repeat_timeo;
488 		irp->next = next_repeat_timeo;
489 	case ITEIOCSREPT:
490 		irp = (struct iterepeat *)addr;
491 		if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
492 			return(EINVAL);
493 		start_repeat_timeo = irp->start;
494 		next_repeat_timeo = irp->next;
495 		return(0);
496 	}
497 	/* XXX */
498 	if (minor(dev) == 0) {
499 		error = ite_grf_ioctl(ip, cmd, addr, flag, p);
500 		if (error >= 0)
501 			return (error);
502 	}
503 	return (ENOTTY);
504 }
505 
506 void
507 itestart(tp)
508 	struct tty *tp;
509 {
510 	struct clist *rbp;
511 	struct ite_softc *ip;
512 	u_char buf[ITEBURST];
513 	int s, len, n;
514 
515 	ip = getitesp(tp->t_dev);
516 
517 	KDASSERT(tp);
518 
519 	s = spltty(); {
520 		if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
521 			goto out;
522 
523 		tp->t_state |= TS_BUSY;
524 		rbp = &tp->t_outq;
525 
526 		len = q_to_b(rbp, buf, ITEBURST);
527 	} splx(s);
528 
529 	/* Here is a really good place to implement pre/jumpscroll() */
530 	ite_putstr(buf, len, tp->t_dev);
531 
532 	s = spltty(); {
533 		tp->t_state &= ~TS_BUSY;
534 		/* we have characters remaining. */
535 		if (rbp->c_cc) {
536 			tp->t_state |= TS_TIMEOUT;
537 			timeout(ttrstrt, tp, 1);
538 		}
539 		/* wakeup we are below */
540 		if (rbp->c_cc <= tp->t_lowat) {
541 			if (tp->t_state & TS_ASLEEP) {
542 				tp->t_state &= ~TS_ASLEEP;
543 				wakeup((caddr_t) rbp);
544 			}
545 			selwakeup(&tp->t_wsel);
546 		}
547 	      out:
548 	} splx(s);
549 }
550 
551 int
552 ite_on(dev, flag)
553 	dev_t dev;
554 	int flag;
555 {
556 	struct ite_softc *ip;
557 	int unit;
558 
559 	unit = ITEUNIT(dev);
560 	if (((1 << unit) & ite_confunits) == 0)
561 		return (ENXIO);
562 
563 	ip = getitesp(dev);
564 
565 	/* force ite active, overriding graphics mode */
566 	if (flag & 1) {
567 		ip->flags |= ITE_ACTIVE;
568 		ip->flags &= ~(ITE_INGRF | ITE_INITED);
569 	}
570 	/* leave graphics mode */
571 	if (flag & 2) {
572 		ip->flags &= ~ITE_INGRF;
573 		if ((ip->flags & ITE_ACTIVE) == 0)
574 			return (0);
575 	}
576 	ip->flags |= ITE_ACTIVE;
577 	if (ip->flags & ITE_INGRF)
578 		return (0);
579 	iteinit(dev);
580 	return (0);
581 }
582 
583 int
584 ite_off(dev, flag)
585 	dev_t dev;
586 	int flag;
587 {
588 	struct ite_softc *ip;
589 
590 	ip = getitesp(dev);
591 	if (flag & 2)
592 		ip->flags |= ITE_INGRF;
593 	if ((ip->flags & ITE_ACTIVE) == 0)
594 		return;
595 	if ((flag & 1) ||
596 	    (ip->flags & (ITE_INGRF | ITE_ISCONS | ITE_INITED)) == ITE_INITED)
597 		SUBR_DEINIT(ip);
598 	if ((flag & 2) == 0)	/* XXX hmm grfon() I think wants this to  go inactive. */
599 		ip->flags &= ~ITE_ACTIVE;
600 }
601 
602 /* XXX called after changes made in underlying grf layer. */
603 /* I want to nuke this */
604 void
605 ite_reinit(dev)
606 	dev_t dev;
607 {
608 	struct ite_softc *ip;
609 
610 	ip = getitesp(dev);
611 	ip->flags &= ~ITE_INITED;
612 	iteinit(dev);
613 }
614 
615 int
616 ite_param(tp, t)
617 	struct tty *tp;
618 	struct termios *t;
619 {
620 	tp->t_ispeed = t->c_ispeed;
621 	tp->t_ospeed = t->c_ospeed;
622 	tp->t_cflag = t->c_cflag;
623 	return (0);
624 }
625 
626 void
627 ite_reset(ip)
628 	struct ite_softc *ip;
629 {
630 	int i;
631 
632 	ip->curx = 0;
633 	ip->cury = 0;
634 	ip->attribute = ATTR_NOR;
635 	ip->save_curx = 0;
636 	ip->save_cury = 0;
637 	ip->save_attribute = ATTR_NOR;
638 	ip->ap = ip->argbuf;
639 	ip->emul_level = 0;
640 	ip->eightbit_C1 = 0;
641 	ip->top_margin = 0;
642 	ip->bottom_margin = ip->rows - 1;
643 	ip->inside_margins = 0;
644 	ip->linefeed_newline = 0;
645 	ip->auto_wrap = ite_default_wrap;
646 	ip->cursor_appmode = 0;
647 	ip->keypad_appmode = 0;
648 	ip->imode = 0;
649 	ip->key_repeat = 1;
650 	bzero(ip->tabs, ip->cols);
651 	for (i = 0; i < ip->cols; i++)
652 		ip->tabs[i] = ((i & 7) == 0);
653 }
654 
655 /*
656  * has to be global becuase of the shared filters.
657  */
658 static u_char key_mod;
659 static u_char last_dead;
660 
661 /* Used in console at startup only */
662 int
663 ite_cnfilter(c, caller)
664 	u_char c;
665 	enum caller caller;
666 {
667 	struct key key;
668 	u_char code, up, mask;
669 	int s, i;
670 
671 	up = c & 0x80 ? 1 : 0;
672 	c &= 0x7f;
673 	code = 0;
674 
675 	s = spltty();
676 
677 	i = (int)c - KBD_LEFT_SHIFT;
678 	if (i >= 0 && i <= (KBD_RIGHT_META - KBD_LEFT_SHIFT)) {
679 		mask = 1 << i;
680 		if (up)
681 			key_mod &= ~mask;
682 		else
683 			key_mod |= mask;
684 		splx(s);
685 		return -1;
686 	}
687 
688 	if (up) {
689 		splx(s);
690 		return -1;
691 	}
692 
693 	/* translate modifiers */
694 	if (key_mod & KBD_MOD_SHIFT) {
695 		if (key_mod & KBD_MOD_ALT)
696 			key = kbdmap.alt_shift_keys[c];
697 		else
698 			key = kbdmap.shift_keys[c];
699 	} else if (key_mod & KBD_MOD_ALT)
700 		key = kbdmap.alt_keys[c];
701 	else {
702 		key = kbdmap.keys[c];
703 		/* if CAPS and key is CAPable (no pun intended) */
704 		if ((key_mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
705 			key = kbdmap.shift_keys[c];
706 	}
707 	code = key.code;
708 
709 	/* if string return */
710 	if (key.mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) {
711 		splx(s);
712 		return -1;
713 	}
714 	/* handle dead keys */
715 	if (key.mode & KBD_MODE_DEAD) {
716 		/* if entered twice, send accent itself */
717 		if (last_dead == key.mode & KBD_MODE_ACCMASK)
718 			last_dead = 0;
719 		else {
720 			last_dead = key.mode & KBD_MODE_ACCMASK;
721 			splx(s);
722 			return -1;
723 		}
724 	}
725 	if (last_dead) {
726 		/* can't apply dead flag to string-keys */
727 		if (code >= '@' && code < 0x7f)
728 			code =
729 			    acctable[KBD_MODE_ACCENT(last_dead)][code - '@'];
730 		last_dead = 0;
731 	}
732 	if (key_mod & KBD_MOD_CTRL)
733 		code &= 0x1f;
734 	if (key_mod & KBD_MOD_META)
735 		code |= 0x80;
736 
737 	/* do console mapping. */
738 	code = code == '\r' ? '\n' : code;
739 
740 	splx(s);
741 	return (code);
742 }
743 
744 /* And now the old stuff. */
745 
746 /* these are used to implement repeating keys.. */
747 static u_char last_char;
748 static u_char tout_pending;
749 
750 /*ARGSUSED*/
751 static void
752 repeat_handler(arg)
753 	void *arg;
754 {
755 	tout_pending = 0;
756 	if (last_char)
757 		add_sicallback(ite_filter, last_char, ITEFILT_REPEATER);
758 }
759 
760 void
761 ite_filter(c, caller)
762 	u_char c;
763 	enum caller caller;
764 {
765 	struct tty *kbd_tty;
766 	u_char code, *str, up, mask;
767 	struct key key;
768 	int s, i;
769 
770 	if (kbd_ite == NULL)
771 		return;
772 
773 	kbd_tty = kbd_ite->tp;
774 
775 	/* have to make sure we're at spltty in here */
776 	s = spltty();
777 
778 	/*
779 	 * keyboard interrupts come at priority 2, while softint
780 	 * generated keyboard-repeat interrupts come at level 1.  So,
781 	 * to not allow a key-up event to get thru before a repeat for
782 	 * the key-down, we remove any outstanding callout requests..
783 	 */
784 	rem_sicallback(ite_filter);
785 
786 	up = c & 0x80 ? 1 : 0;
787 	c &= 0x7f;
788 	code = 0;
789 
790 	i = (int)c - KBD_LEFT_SHIFT;
791 	if (i >= 0 && i <= (KBD_RIGHT_META - KBD_LEFT_SHIFT)) {
792 		mask = 1 << i;
793 		if (up)
794 			key_mod &= ~mask;
795 		else
796 			key_mod |= mask;
797 		splx(s);
798 		return;
799 	}
800 	/* stop repeating on up event */
801 	if (up) {
802 		if (tout_pending) {
803 			untimeout(repeat_handler, 0);
804 			tout_pending = 0;
805 			last_char = 0;
806 		}
807 		splx(s);
808 		return;
809 	} else if (tout_pending && last_char != c) {
810 		/* different character, stop also */
811 		untimeout(repeat_handler, 0);
812 		tout_pending = 0;
813 		last_char = 0;
814 	}
815 	/* Safety button, switch back to ascii keymap. */
816 	if (key_mod == (KBD_MOD_LALT | KBD_MOD_LMETA) && c == 0x50) {
817 		bcopy(&ascii_kbdmap, &kbdmap, sizeof(struct kbdmap));
818 
819 		splx(s);
820 		return;
821 #ifdef DDB
822 	} else if (key_mod == (KBD_MOD_LALT | KBD_MOD_LMETA) && c == 0x59) {
823 		extern int Debugger();
824 		Debugger();
825 		splx(s);
826 		return;
827 #endif
828 	}
829 	/* translate modifiers */
830 	if (key_mod & KBD_MOD_SHIFT) {
831 		if (key_mod & KBD_MOD_ALT)
832 			key = kbdmap.alt_shift_keys[c];
833 		else
834 			key = kbdmap.shift_keys[c];
835 	} else if (key_mod & KBD_MOD_ALT)
836 		key = kbdmap.alt_keys[c];
837 	else {
838 		key = kbdmap.keys[c];
839 		/* if CAPS and key is CAPable (no pun intended) */
840 		if ((key_mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
841 			key = kbdmap.shift_keys[c];
842 	}
843 	code = key.code;
844 
845 	/*
846 	 * arrange to repeat the keystroke. By doing this at the level
847 	 * of scan-codes, we can have function keys, and keys that
848 	 * send strings, repeat too. This also entitles an additional
849 	 * overhead, since we have to do the conversion each time, but
850 	 * I guess that's ok.
851 	 */
852 	if (!tout_pending && caller == ITEFILT_TTY && kbd_ite->key_repeat) {
853 		tout_pending = 1;
854 		last_char = c;
855 		timeout(repeat_handler, 0, start_repeat_timeo * hz / 100);
856 	} else if (!tout_pending && caller == ITEFILT_REPEATER &&
857 	    kbd_ite->key_repeat) {
858 		tout_pending = 1;
859 		last_char = c;
860 		timeout(repeat_handler, 0, next_repeat_timeo * hz / 100);
861 	}
862 	/* handle dead keys */
863 	if (key.mode & KBD_MODE_DEAD) {
864 		/* if entered twice, send accent itself */
865 		if (last_dead == key.mode & KBD_MODE_ACCMASK)
866 			last_dead = 0;
867 		else {
868 			last_dead = key.mode & KBD_MODE_ACCMASK;
869 			splx(s);
870 			return;
871 		}
872 	}
873 	if (last_dead) {
874 		/* can't apply dead flag to string-keys */
875 		if (!(key.mode & KBD_MODE_STRING) && code >= '@' &&
876 		    code < 0x7f)
877 			code = acctable[KBD_MODE_ACCENT(last_dead)][code - '@'];
878 		last_dead = 0;
879 	}
880 	/* if not string, apply META and CTRL modifiers */
881 	if (!(key.mode & KBD_MODE_STRING)
882 	    && (!(key.mode & KBD_MODE_KPAD) ||
883 		(kbd_ite && !kbd_ite->keypad_appmode))) {
884 		if (key_mod & KBD_MOD_CTRL)
885 			code &= 0x1f;
886 		if (key_mod & KBD_MOD_META)
887 			code |= 0x80;
888 	} else if ((key.mode & KBD_MODE_KPAD) &&
889 	    (kbd_ite && kbd_ite->keypad_appmode)) {
890 		static char *in = "0123456789-+.\r()/*";
891 		static char *out = "pqrstuvwxymlnMPQRS";
892 		char *cp = index (in, code);
893 
894 		/*
895 		 * keypad-appmode sends SS3 followed by the above
896 		 * translated character
897 		 */
898 		(*linesw[kbd_tty->t_line].l_rint) (27, kbd_tty);
899 		(*linesw[kbd_tty->t_line].l_rint) ('O', kbd_tty);
900 		(*linesw[kbd_tty->t_line].l_rint) (out[cp - in], kbd_tty);
901 		splx(s);
902 		return;
903 	} else {
904 		/* *NO* I don't like this.... */
905 		static u_char app_cursor[] =
906 		{
907 		    3, 27, 'O', 'A',
908 		    3, 27, 'O', 'B',
909 		    3, 27, 'O', 'C',
910 		    3, 27, 'O', 'D'};
911 
912 		str = kbdmap.strings + code;
913 		/*
914 		 * if this is a cursor key, AND it has the default
915 		 * keymap setting, AND we're in app-cursor mode, switch
916 		 * to the above table. This is *nasty* !
917 		 */
918 		if (c >= 0x4c && c <= 0x4f && kbd_ite->cursor_appmode
919 		    && !bcmp(str, "\x03\x1b[", 3) &&
920 		    index("ABCD", str[3]))
921 			str = app_cursor + 4 * (str[3] - 'A');
922 
923 		/*
924 		 * using a length-byte instead of 0-termination allows
925 		 * to embed \0 into strings, although this is not used
926 		 * in the default keymap
927 		 */
928 		for (i = *str++; i; i--)
929 			(*linesw[kbd_tty->t_line].l_rint) (*str++, kbd_tty);
930 		splx(s);
931 		return;
932 	}
933 	(*linesw[kbd_tty->t_line].l_rint) (code, kbd_tty);
934 
935 	splx(s);
936 	return;
937 }
938 
939 /* helper functions, makes the code below more readable */
940 static void inline
941 ite_sendstr(str)
942 	char *str;
943 {
944 	struct tty *kbd_tty;
945 
946 	kbd_tty = kbd_ite->tp;
947 	KDASSERT(kbd_tty);
948 	while (*str)
949 		(*linesw[kbd_tty->t_line].l_rint) (*str++, kbd_tty);
950 }
951 
952 static void
953 alignment_display(ip)
954 	struct ite_softc *ip;
955 {
956   int i, j;
957 
958   for (j = 0; j < ip->rows; j++)
959     for (i = 0; i < ip->cols; i++)
960       SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
961   attrclr(ip, 0, 0, ip->rows, ip->cols);
962   SUBR_CURSOR(ip, DRAW_CURSOR);
963 }
964 
965 static void inline
966 snap_cury(ip)
967 	struct ite_softc *ip;
968 {
969   if (ip->inside_margins)
970     {
971       if (ip->cury < ip->top_margin)
972 	ip->cury = ip->top_margin;
973       if (ip->cury > ip->bottom_margin)
974 	ip->cury = ip->bottom_margin;
975     }
976 }
977 
978 static void inline
979 ite_dnchar(ip, n)
980      struct ite_softc *ip;
981      int n;
982 {
983   n = min(n, ip->cols - ip->curx);
984   if (n < ip->cols - ip->curx)
985     {
986       SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
987       attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
988 	      1, ip->cols - ip->curx - n);
989       attrclr(ip, ip->cury, ip->cols - n, 1, n);
990     }
991   while (n-- > 0)
992     SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
993   SUBR_CURSOR(ip, DRAW_CURSOR);
994 }
995 
996 static void inline
997 ite_inchar(ip, n)
998      struct ite_softc *ip;
999      int n;
1000 {
1001   n = min(n, ip->cols - ip->curx);
1002   if (n < ip->cols - ip->curx)
1003     {
1004       SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
1005       attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
1006 	      1, ip->cols - ip->curx - n);
1007       attrclr(ip, ip->cury, ip->curx, 1, n);
1008     }
1009   while (n--)
1010     SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1011   SUBR_CURSOR(ip, DRAW_CURSOR);
1012 }
1013 
1014 static void inline
1015 ite_clrtoeol(ip)
1016      struct ite_softc *ip;
1017 {
1018   int y = ip->cury, x = ip->curx;
1019   if (ip->cols - x > 0)
1020     {
1021       SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
1022       attrclr(ip, y, x, 1, ip->cols - x);
1023       SUBR_CURSOR(ip, DRAW_CURSOR);
1024     }
1025 }
1026 
1027 static void inline
1028 ite_clrtobol(ip)
1029      struct ite_softc *ip;
1030 {
1031   int y = ip->cury, x = min(ip->curx + 1, ip->cols);
1032   SUBR_CLEAR(ip, y, 0, 1, x);
1033   attrclr(ip, y, 0, 1, x);
1034   SUBR_CURSOR(ip, DRAW_CURSOR);
1035 }
1036 
1037 static void inline
1038 ite_clrline(ip)
1039      struct ite_softc *ip;
1040 {
1041   int y = ip->cury;
1042   SUBR_CLEAR(ip, y, 0, 1, ip->cols);
1043   attrclr(ip, y, 0, 1, ip->cols);
1044   SUBR_CURSOR(ip, DRAW_CURSOR);
1045 }
1046 
1047 
1048 
1049 static void inline
1050 ite_clrtoeos(ip)
1051      struct ite_softc *ip;
1052 {
1053   ite_clrtoeol(ip);
1054   if (ip->cury < ip->rows - 1)
1055     {
1056       SUBR_CLEAR(ip, ip->cury + 1, 0, ip->rows - 1 - ip->cury, ip->cols);
1057       attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
1058       SUBR_CURSOR(ip, DRAW_CURSOR);
1059     }
1060 }
1061 
1062 static void inline
1063 ite_clrtobos(ip)
1064      struct ite_softc *ip;
1065 {
1066   ite_clrtobol(ip);
1067   if (ip->cury > 0)
1068     {
1069       SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
1070       attrclr(ip, 0, 0, ip->cury, ip->cols);
1071       SUBR_CURSOR(ip, DRAW_CURSOR);
1072     }
1073 }
1074 
1075 static void inline
1076 ite_clrscreen(ip)
1077      struct ite_softc *ip;
1078 {
1079   SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
1080   attrclr(ip, 0, 0, ip->rows, ip->cols);
1081   SUBR_CURSOR(ip, DRAW_CURSOR);
1082 }
1083 
1084 
1085 
1086 static void inline
1087 ite_dnline(ip, n)
1088      struct ite_softc *ip;
1089      int n;
1090 {
1091   /* interesting.. if the cursor is outside the scrolling
1092      region, this command is simply ignored.. */
1093   if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1094     return;
1095 
1096   n = min(n, ip->bottom_margin + 1 - ip->cury);
1097   if (n <= ip->bottom_margin - ip->cury)
1098     {
1099       SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
1100       attrmov(ip, ip->cury + n, 0, ip->cury, 0,
1101 	      ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1102     }
1103   SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1104   attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1105   SUBR_CURSOR(ip, DRAW_CURSOR);
1106 }
1107 
1108 static void inline
1109 ite_inline(ip, n)
1110      struct ite_softc *ip;
1111      int n;
1112 {
1113   /* interesting.. if the cursor is outside the scrolling
1114      region, this command is simply ignored.. */
1115   if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1116     return;
1117 
1118   n = min(n, ip->bottom_margin + 1 - ip->cury);
1119   if (n <= ip->bottom_margin - ip->cury)
1120     {
1121       SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
1122       attrmov(ip, ip->cury, 0, ip->cury + n, 0,
1123 	      ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1124     }
1125   SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
1126   attrclr(ip, ip->cury, 0, n, ip->cols);
1127   SUBR_CURSOR(ip, DRAW_CURSOR);
1128 }
1129 
1130 static void inline
1131 ite_lf (ip)
1132      struct ite_softc *ip;
1133 {
1134   ++ip->cury;
1135   if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows))
1136     {
1137       ip->cury--;
1138       SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1139       ite_clrline(ip);
1140     }
1141   SUBR_CURSOR(ip, MOVE_CURSOR);
1142   clr_attr(ip, ATTR_INV);
1143 }
1144 
1145 static void inline
1146 ite_crlf (ip)
1147      struct ite_softc *ip;
1148 {
1149   ip->curx = 0;
1150   ite_lf (ip);
1151 }
1152 
1153 static void inline
1154 ite_cr (ip)
1155      struct ite_softc *ip;
1156 {
1157   if (ip->curx)
1158     {
1159       ip->curx = 0;
1160       SUBR_CURSOR(ip, MOVE_CURSOR);
1161     }
1162 }
1163 
1164 static void inline
1165 ite_rlf (ip)
1166      struct ite_softc *ip;
1167 {
1168   ip->cury--;
1169   if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1))
1170     {
1171       ip->cury++;
1172       SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
1173       ite_clrline(ip);
1174     }
1175   SUBR_CURSOR(ip, MOVE_CURSOR);
1176   clr_attr(ip, ATTR_INV);
1177 }
1178 
1179 static int inline
1180 atoi (cp)
1181     const char *cp;
1182 {
1183   int n;
1184 
1185   for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
1186     n = n * 10 + *cp - '0';
1187 
1188   return n;
1189 }
1190 
1191 static char *
1192 index (cp, ch)
1193     const char *cp;
1194     char ch;
1195 {
1196   while (*cp && *cp != ch) cp++;
1197   return *cp ? (char *) cp : 0;
1198 }
1199 
1200 
1201 
1202 static int inline
1203 ite_argnum (ip)
1204     struct ite_softc *ip;
1205 {
1206   char ch;
1207   int n;
1208 
1209   /* convert argument string into number */
1210   if (ip->ap == ip->argbuf)
1211     return 1;
1212   ch = *ip->ap;
1213   *ip->ap = 0;
1214   n = atoi (ip->argbuf);
1215   *ip->ap = ch;
1216 
1217   return n;
1218 }
1219 
1220 static int inline
1221 ite_zargnum (ip)
1222     struct ite_softc *ip;
1223 {
1224   char ch, *cp;
1225   int n;
1226 
1227   /* convert argument string into number */
1228   if (ip->ap == ip->argbuf)
1229     return 0;
1230   ch = *ip->ap;
1231   *ip->ap = 0;
1232   n = atoi (ip->argbuf);
1233   *ip->ap = ch;
1234 
1235   return n;	/* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
1236 }
1237 
1238 static int inline
1239 strncmp (a, b, l)
1240     const char *a, *b;
1241     int l;
1242 {
1243   for (;l--; a++, b++)
1244     if (*a != *b)
1245       return *a - *b;
1246   return 0;
1247 }
1248 
1249 void
1250 ite_putstr(s, len, dev)
1251 	const char *s;
1252 	int len;
1253 	dev_t dev;
1254 {
1255 	struct ite_softc *ip;
1256 	int i;
1257 
1258 	ip = getitesp(dev);
1259 
1260 	/* XXX avoid problems */
1261 	if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
1262 	  	return;
1263 
1264 	SUBR_CURSOR(ip, START_CURSOROPT);
1265 	for (i = 0; i < len; i++)
1266 		if (s[i])
1267 			iteputchar(s[i], ip);
1268 	SUBR_CURSOR(ip, END_CURSOROPT);
1269 }
1270 
1271 
1272 void
1273 iteputchar(c, ip)
1274 	register int c;
1275 	struct ite_softc *ip;
1276 {
1277 	struct tty *kbd_tty;
1278 	int n, x, y;
1279 	char *cp;
1280 
1281 	if (kbd_ite == NULL)
1282 		kbd_tty = NULL;
1283 	else
1284 		kbd_tty = kbd_ite->tp;
1285 
1286 	if (ip->escape) {
1287 doesc:
1288 		switch (ip->escape) {
1289 		case ESC:
1290 			switch (c) {
1291 				/*
1292 				 * first 7bit equivalents for the
1293 				 * 8bit control characters
1294 				 */
1295 			case 'D':
1296 				c = IND;
1297 				ip->escape = 0;
1298 				break;
1299 				/*
1300 				 * and fall into the next
1301 				 * switch below (same for all `break')
1302 				 */
1303 			case 'E':
1304 				c = NEL;
1305 				ip->escape = 0;
1306 				break;
1307 			case 'H':
1308 				c = HTS;
1309 				ip->escape = 0;
1310 				break;
1311 			case 'M':
1312 				c = RI;
1313 				ip->escape = 0;
1314 				break;
1315 			case 'N':
1316 				c = SS2;
1317 				ip->escape = 0;
1318 				break;
1319 			case 'O':
1320 				c = SS3;
1321 				ip->escape = 0;
1322 				break;
1323 			case 'P':
1324 				c = DCS;
1325 				ip->escape = 0;
1326 				break;
1327 			case '[':
1328 				c = CSI;
1329 				ip->escape = 0;
1330 				break;
1331 			case '\\':
1332 				c = ST;
1333 				ip->escape = 0;
1334 				break;
1335 			case ']':
1336 				c = OSC;
1337 				ip->escape = 0;
1338 				break;
1339 			case '^':
1340 				c = PM;
1341 				ip->escape = 0;
1342 				break;
1343 			case '_':
1344 				c = APC;
1345 				ip->escape = 0;
1346 				break;
1347 				/* introduces 7/8bit control */
1348 			case ' ':
1349 				/* can be followed by either F or G */
1350 				ip->escape = ' ';
1351 				break;
1352 			/*
1353 			 * a lot of character set selections, not yet
1354 			 * used... 94-character sets:
1355 			 */
1356 			case '(':	/* G0 */
1357 			case ')':	/* G1 */
1358 				ip->escape = c;
1359 				return;
1360 			case '*':	/* G2 */
1361 			case '+':	/* G3 */
1362 			case 'B':	/* ASCII */
1363 			case 'A':	/* ISO latin 1 */
1364 			case '<':	/* user preferred suplemental */
1365 			case '0':	/* dec special graphics */
1366 			/*
1367 			 * 96-character sets:
1368 			 */
1369 			case '-':	/* G1 */
1370 			case '.':	/* G2 */
1371 			case '/':	/* G3 */
1372 			/*
1373 			 * national character sets:
1374 			 */
1375 			case '4':	/* dutch */
1376 			case '5':
1377 			case 'C':	/* finnish */
1378 			case 'R':	/* french */
1379 			case 'Q':	/* french canadian */
1380 			case 'K':	/* german */
1381 			case 'Y':	/* italian */
1382 			case '6':	/* norwegian/danish */
1383 				/*
1384 				 * note: %5 and %6 are not supported (two
1385 				 * chars..)
1386 				 */
1387 				ip->escape = 0;
1388 				/* just ignore for now */
1389 				return;
1390 			/*
1391 			 * locking shift modes (as you might guess, not
1392 			 * yet supported..)
1393 			 */
1394 			case '`':
1395 				ip->GR = ip->G1;
1396 				ip->escape = 0;
1397 				return;
1398 			case 'n':
1399 				ip->GL = ip->G2;
1400 				ip->escape = 0;
1401 				return;
1402 			case '}':
1403 				ip->GR = ip->G2;
1404 				ip->escape = 0;
1405 				return;
1406 			case 'o':
1407 				ip->GL = ip->G3;
1408 				ip->escape = 0;
1409 				return;
1410 			case '|':
1411 				ip->GR = ip->G3;
1412 				ip->escape = 0;
1413 				return;
1414 			case '#':
1415 				/* font width/height control */
1416 				ip->escape = '#';
1417 				return;
1418 			case 'c':
1419 				/* hard terminal reset .. */
1420 				ite_reset(ip);
1421 				SUBR_CURSOR(ip, MOVE_CURSOR);
1422 				ip->escape = 0;
1423 				return;
1424 			case '7':
1425 				ip->save_curx = ip->curx;
1426 				ip->save_cury = ip->cury;
1427 				ip->save_attribute = ip->attribute;
1428 				ip->escape = 0;
1429 				return;
1430 			case '8':
1431 				ip->curx = ip->save_curx;
1432 				ip->cury = ip->save_cury;
1433 				ip->attribute = ip->save_attribute;
1434 				SUBR_CURSOR(ip, MOVE_CURSOR);
1435 				ip->escape = 0;
1436 				return;
1437 			case '=':
1438 				ip->keypad_appmode = 1;
1439 				ip->escape = 0;
1440 				return;
1441 			case '>':
1442 				ip->keypad_appmode = 0;
1443 				ip->escape = 0;
1444 				return;
1445 			case 'Z':	/* request ID */
1446 				/* XXX not clean */
1447 				if (ip->emul_level == EMUL_VT100)
1448 					ite_sendstr("\033[?61;0c");
1449 				else
1450 					ite_sendstr("\033[?63;0c");
1451 				ip->escape = 0;
1452 				return;
1453 			default:
1454 				/*
1455 				 * default catch all for not recognized ESC
1456 				 * sequences
1457 				 */
1458 				ip->escape = 0;
1459 				return;
1460 			}
1461 			break;
1462 		case '(':
1463 		case ')':
1464 			ip->escape = 0;
1465 			return;
1466 		case ' ':
1467 			switch (c) {
1468 			case 'F':
1469 				ip->eightbit_C1 = 0;
1470 				ip->escape = 0;
1471 				return;
1472 			case 'G':
1473 				ip->eightbit_C1 = 1;
1474 				ip->escape = 0;
1475 				return;
1476 			default:
1477 				/* not supported */
1478 				ip->escape = 0;
1479 				return;
1480 			}
1481 			break;
1482 		case '#':
1483 			switch (c) {
1484 			case '5':
1485 				/* single height, single width */
1486 				ip->escape = 0;
1487 				return;
1488 			case '6':
1489 				/* double width, single height */
1490 				ip->escape = 0;
1491 				return;
1492 			case '3':
1493 				/* top half */
1494 				ip->escape = 0;
1495 				return;
1496 			case '4':
1497 				/* bottom half */
1498 				ip->escape = 0;
1499 				return;
1500 			case '8':
1501 				/* screen alignment pattern... */
1502 				alignment_display(ip);
1503 				ip->escape = 0;
1504 				return;
1505 			default:
1506 				ip->escape = 0;
1507 				return;
1508 			}
1509 			break;
1510 		case CSI:
1511 			/* the biggie... */
1512 			switch (c) {
1513 			case '0':
1514 			case '1':
1515 			case '2':
1516 			case '3':
1517 			case '4':
1518 			case '5':
1519 			case '6':
1520 			case '7':
1521 			case '8':
1522 			case '9':
1523 			case ';':
1524 			case '\"':
1525 			case '$':
1526 			case '>':
1527 				if (ip->ap < ip->argbuf + MAX_ARGSIZE)
1528 					*ip->ap++ = c;
1529 				return;
1530 			case BS:
1531 				/*
1532 				 * you wouldn't believe such perversion is
1533 				 * possible? it is.. BS is allowed in between
1534 				 * cursor sequences (at least), according to
1535 				 * vttest..
1536 				 */
1537 				if (--ip->curx < 0)
1538 					ip->curx = 0;
1539 				else
1540 					SUBR_CURSOR(ip, MOVE_CURSOR);
1541 				break;
1542 			case 'p':
1543 				*ip->ap = 0;
1544 				if (!strncmp(ip->argbuf, "61\"", 3))
1545 					ip->emul_level = EMUL_VT100;
1546 				else if (!strncmp(ip->argbuf, "63;1\"", 5)
1547 				    || !strncmp(ip->argbuf, "62;1\"", 5))
1548 					ip->emul_level = EMUL_VT300_7;
1549 				else
1550 					ip->emul_level = EMUL_VT300_8;
1551 				ip->escape = 0;
1552 				return;
1553 			case '?':
1554 				*ip->ap = 0;
1555 				ip->escape = '?';
1556 				ip->ap = ip->argbuf;
1557 				return;
1558 			case 'c':
1559 				*ip->ap = 0;
1560 				if (ip->argbuf[0] == '>') {
1561 					ite_sendstr("\033[>24;0;0;0c");
1562 				} else
1563 					switch (ite_zargnum(ip)) {
1564 					case 0:
1565 						/*
1566 						 * primary DA request, send
1567 						 * primary DA response
1568 						 */
1569 						if (ip->emul_level
1570 						    == EMUL_VT100)
1571 							ite_sendstr(
1572 							    "\033[?1;1c");
1573 						else
1574 							ite_sendstr(
1575 							    "\033[?63;1c");
1576 						break;
1577 					}
1578 				ip->escape = 0;
1579 				return;
1580 			case 'n':
1581 				switch (ite_zargnum(ip)) {
1582 				case 5:
1583 					/* no malfunction */
1584 					ite_sendstr("\033[0n");
1585 					break;
1586 				case 6:
1587 					/* cursor position report */
1588 					sprintf(ip->argbuf, "\033[%d;%dR",
1589 					    ip->cury + 1, ip->curx + 1);
1590 					ite_sendstr(ip->argbuf);
1591 					break;
1592 				}
1593 				ip->escape = 0;
1594 				return;
1595 			case 'x':
1596 				switch (ite_zargnum(ip)) {
1597 				case 0:
1598 					/* Fake some terminal parameters.  */
1599 					ite_sendstr("\033[2;1;1;112;112;1;0x");
1600 					break;
1601 				case 1:
1602 					ite_sendstr("\033[3;1;1;112;112;1;0x");
1603 					break;
1604 				}
1605 				ip->escape = 0;
1606 				return;
1607 			case 'g':
1608 				switch (ite_zargnum(ip)) {
1609 				case 0:
1610 					if (ip->curx < ip->cols)
1611 						ip->tabs[ip->curx] = 0;
1612 					break;
1613 				case 3:
1614 					for (n = 0; n < ip->cols; n++)
1615 						ip->tabs[n] = 0;
1616 					break;
1617 				}
1618 				ip->escape = 0;
1619 				return;
1620 			case 'h':
1621 			case 'l':
1622 				n = ite_zargnum(ip);
1623 				switch (n) {
1624 				case 4:
1625 					/* insert/replace mode */
1626 					ip->imode = (c == 'h');
1627 					break;
1628 				case 20:
1629 					ip->linefeed_newline = (c == 'h');
1630 					break;
1631 				}
1632 				ip->escape = 0;
1633 				return;
1634 			case 'M':
1635 				ite_dnline(ip, ite_argnum(ip));
1636 				ip->escape = 0;
1637 				return;
1638 			case 'L':
1639 				ite_inline(ip, ite_argnum(ip));
1640 				ip->escape = 0;
1641 				return;
1642 			case 'P':
1643 				ite_dnchar(ip, ite_argnum(ip));
1644 				ip->escape = 0;
1645 				return;
1646 			case '@':
1647 				ite_inchar(ip, ite_argnum(ip));
1648 				ip->escape = 0;
1649 				return;
1650 			case 'G':
1651 				/*
1652 				 * this one was *not* in my vt320 manual but in
1653 				 * a vt320 termcap entry.. who is right? It's
1654 				 * supposed to set the horizontal cursor
1655 				 * position.
1656 				 */
1657 				*ip->ap = 0;
1658 				x = atoi(ip->argbuf);
1659 				if (x)
1660 					x--;
1661 				ip->curx = min(x, ip->cols - 1);
1662 				ip->escape = 0;
1663 				SUBR_CURSOR(ip, MOVE_CURSOR);
1664 				clr_attr(ip, ATTR_INV);
1665 				return;
1666 			case 'd':
1667 				/*
1668 				 * same thing here, this one's for setting the
1669 				 * absolute vertical cursor position. Not
1670 				 * documented...
1671 				 */
1672 				*ip->ap = 0;
1673 				y = atoi(ip->argbuf);
1674 				if (y)
1675 					y--;
1676 				if (ip->inside_margins)
1677 					y += ip->top_margin;
1678 				ip->cury = min(y, ip->rows - 1);
1679 				ip->escape = 0;
1680 				snap_cury(ip);
1681 				SUBR_CURSOR(ip, MOVE_CURSOR);
1682 				clr_attr(ip, ATTR_INV);
1683 				return;
1684 			case 'H':
1685 			case 'f':
1686 				*ip->ap = 0;
1687 				y = atoi(ip->argbuf);
1688 				x = 0;
1689 				cp = index(ip->argbuf, ';');
1690 				if (cp)
1691 					x = atoi(cp + 1);
1692 				if (x)
1693 					x--;
1694 				if (y)
1695 					y--;
1696 				if (ip->inside_margins)
1697 					y += ip->top_margin;
1698 				ip->cury = min(y, ip->rows - 1);
1699 				ip->curx = min(x, ip->cols - 1);
1700 				ip->escape = 0;
1701 				snap_cury(ip);
1702 				SUBR_CURSOR(ip, MOVE_CURSOR);
1703 				clr_attr(ip, ATTR_INV);
1704 				return;
1705 			case 'A':
1706 				n = ite_argnum(ip);
1707 				n = ip->cury - (n ? n : 1);
1708 				if (n < 0)
1709 					n = 0;
1710 				if (ip->inside_margins)
1711 					n = max(ip->top_margin, n);
1712 				else if (n == ip->top_margin - 1)
1713 					/*
1714 					 * allow scrolling outside region, but
1715 					 * don't scroll out of active region
1716 					 * without explicit CUP
1717 					 */
1718 					n = ip->top_margin;
1719 				ip->cury = n;
1720 				ip->escape = 0;
1721 				SUBR_CURSOR(ip, MOVE_CURSOR);
1722 				clr_attr(ip, ATTR_INV);
1723 				return;
1724 			case 'B':
1725 				n = ite_argnum(ip);
1726 				n = ip->cury + (n ? n : 1);
1727 				n = min(ip->rows - 1, n);
1728 				if (ip->inside_margins)
1729 					n = min(ip->bottom_margin, n);
1730 				else if (n == ip->bottom_margin + 1)
1731 					/*
1732 					 * allow scrolling outside region, but
1733 					 * don't scroll out of active region
1734 					 * without explicit CUP
1735 					 */
1736 					n = ip->bottom_margin;
1737 				ip->cury = n;
1738 				ip->escape = 0;
1739 				SUBR_CURSOR(ip, MOVE_CURSOR);
1740 				clr_attr(ip, ATTR_INV);
1741 				return;
1742 			case 'C':
1743 				n = ite_argnum(ip);
1744 				n = n ? n : 1;
1745 				ip->curx = min(ip->curx + n, ip->cols - 1);
1746 				ip->escape = 0;
1747 				SUBR_CURSOR(ip, MOVE_CURSOR);
1748 				clr_attr(ip, ATTR_INV);
1749 				return;
1750 			case 'D':
1751 				n = ite_argnum(ip);
1752 				n = n ? n : 1;
1753 				n = ip->curx - n;
1754 				ip->curx = n >= 0 ? n : 0;
1755 				ip->escape = 0;
1756 				SUBR_CURSOR(ip, MOVE_CURSOR);
1757 				clr_attr(ip, ATTR_INV);
1758 				return;
1759 			case 'J':
1760 				*ip->ap = 0;
1761 				n = ite_zargnum(ip);
1762 				if (n == 0)
1763 					ite_clrtoeos(ip);
1764 				else if (n == 1)
1765 					ite_clrtobos(ip);
1766 				else if (n == 2)
1767 					ite_clrscreen(ip);
1768 				ip->escape = 0;
1769 				return;
1770 			case 'K':
1771 				n = ite_zargnum(ip);
1772 				if (n == 0)
1773 					ite_clrtoeol(ip);
1774 				else if (n == 1)
1775 					ite_clrtobol(ip);
1776 				else if (n == 2)
1777 					ite_clrline(ip);
1778 				ip->escape = 0;
1779 				return;
1780 			case 'X':
1781 				n = ite_argnum(ip) - 1;
1782 				n = min(n, ip->cols - 1 - ip->curx);
1783 				for (; n >= 0; n--) {
1784 					attrclr(ip, ip->cury, ip->curx + n, 1, 1);
1785 					SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1786 				}
1787 				ip->escape = 0;
1788 				return;
1789 			case '}':
1790 			case '`':
1791 				/* status line control */
1792 				ip->escape = 0;
1793 				return;
1794 			case 'r':
1795 				*ip->ap = 0;
1796 				x = atoi(ip->argbuf);
1797 				x = x ? x : 1;
1798 				y = ip->rows;
1799 				cp = index(ip->argbuf, ';');
1800 				if (cp) {
1801 					y = atoi(cp + 1);
1802 					y = y ? y : ip->rows;
1803 				}
1804 				if (y - x < 2) {
1805 					/*
1806 					 * if illegal scrolling region, reset
1807 					 * to defaults
1808 					 */
1809 					x = 1;
1810 					y = ip->rows;
1811 				}
1812 				x--;
1813 				y--;
1814 				ip->top_margin = min(x, ip->rows - 1);
1815 				ip->bottom_margin = min(y, ip->rows - 1);
1816 				if (ip->inside_margins) {
1817 					ip->cury = ip->top_margin;
1818 					ip->curx = 0;
1819 					SUBR_CURSOR(ip, MOVE_CURSOR);
1820 				}
1821 				ip->escape = 0;
1822 				return;
1823 			case 'm':
1824 				/* big attribute setter/resetter */
1825 				{ char *cp;
1826 				*ip->ap = 0;
1827 				/* kludge to make CSIm work (== CSI0m) */
1828 				if (ip->ap == ip->argbuf)
1829 					ip->ap++;
1830 				for (cp = ip->argbuf; cp < ip->ap;) {
1831 					switch (*cp) {
1832 					case 0:
1833 					case '0':
1834 						clr_attr(ip, ATTR_ALL);
1835 						cp++;
1836 						break;
1837 
1838 					case '1':
1839 						set_attr(ip, ATTR_BOLD);
1840 						cp++;
1841 						break;
1842 
1843 					case '2':
1844 						switch (cp[1]) {
1845 						case '2':
1846 							clr_attr(ip, ATTR_BOLD);
1847 							cp += 2;
1848 							break;
1849 
1850 						case '4':
1851 							clr_attr(ip, ATTR_UL);
1852 							cp += 2;
1853 							break;
1854 
1855 						case '5':
1856 							clr_attr(ip, ATTR_BLINK);
1857 							cp += 2;
1858 							break;
1859 
1860 						case '7':
1861 							clr_attr(ip, ATTR_INV);
1862 							cp += 2;
1863 							break;
1864 
1865 						default:
1866 							cp++;
1867 							break;
1868 						}
1869 						break;
1870 
1871 					case '4':
1872 						set_attr(ip, ATTR_UL);
1873 						cp++;
1874 						break;
1875 
1876 					case '5':
1877 						set_attr(ip, ATTR_BLINK);
1878 						cp++;
1879 						break;
1880 
1881 					case '7':
1882 						set_attr(ip, ATTR_INV);
1883 						cp++;
1884 						break;
1885 
1886 					default:
1887 						cp++;
1888 						break;
1889 					}
1890 				}
1891 				ip->escape = 0;
1892 				return; }
1893 			case 'u':
1894 				/* DECRQTSR */
1895 				ite_sendstr("\033P\033\\");
1896 				ip->escape = 0;
1897 				return;
1898 			default:
1899 				ip->escape = 0;
1900 				return;
1901 			}
1902 			break;
1903 		case '?':	/* CSI ? */
1904 			switch (c) {
1905 			case '0':
1906 			case '1':
1907 			case '2':
1908 			case '3':
1909 			case '4':
1910 			case '5':
1911 			case '6':
1912 			case '7':
1913 			case '8':
1914 			case '9':
1915 			case ';':
1916 			case '\"':
1917 			case '$':
1918 				/*
1919 				 * Don't fill the last character;
1920 				 * it's needed.
1921 				 * XXX yeah, where ??
1922 				 */
1923 				if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
1924 					*ip->ap++ = c;
1925 				return;
1926 			case 'n':
1927 				*ip->ap = 0;
1928 				if (ip->ap == &ip->argbuf[2]) {
1929 					if (!strncmp(ip->argbuf, "15", 2))
1930 						/* printer status: no printer */
1931 						ite_sendstr("\033[13n");
1932 
1933 					else if (!strncmp(ip->argbuf, "25", 2))
1934 						/* udk status */
1935 						ite_sendstr("\033[20n");
1936 
1937 					else if (!strncmp(ip->argbuf, "26", 2))
1938 						/* keyboard dialect: US */
1939 						ite_sendstr("\033[27;1n");
1940 				}
1941 				ip->escape = 0;
1942 				return;
1943 			case 'h':
1944 			case 'l':
1945 				n = ite_zargnum(ip);
1946 				switch (n) {
1947 				case 1:
1948 					ip->cursor_appmode = (c == 'h');
1949 					break;
1950 				case 3:
1951 					/* 132/80 columns (132 == 'h') */
1952 					break;
1953 				case 4:	/* smooth scroll */
1954 					break;
1955 				case 5:
1956 					/*
1957 					 * light background (=='h') /dark
1958 					 * background(=='l')
1959 					 */
1960 					break;
1961 				case 6:	/* origin mode */
1962 					ip->inside_margins = (c == 'h');
1963 					ip->curx = 0;
1964 					ip->cury = ip->inside_margins ?
1965 					    ip->top_margin : 0;
1966 					SUBR_CURSOR(ip, MOVE_CURSOR);
1967 					break;
1968 				case 7:	/* auto wraparound */
1969 					ip->auto_wrap = (c == 'h');
1970 					break;
1971 				case 8:	/* keyboard repeat */
1972 					ip->key_repeat = (c == 'h');
1973 					break;
1974 				case 20:	/* newline mode */
1975 					ip->linefeed_newline = (c == 'h');
1976 					break;
1977 				case 25:	/* cursor on/off */
1978 					SUBR_CURSOR(ip, (c == 'h') ?
1979 					    DRAW_CURSOR : ERASE_CURSOR);
1980 					break;
1981 				}
1982 				ip->escape = 0;
1983 				return;
1984 			default:
1985 				ip->escape = 0;
1986 				return;
1987 			}
1988 			break;
1989 		default:
1990 			ip->escape = 0;
1991 			return;
1992 		}
1993 	}
1994 	switch (c) {
1995 	case VT:		/* VT is treated like LF */
1996 	case FF:		/* so is FF */
1997 	case LF:
1998 		/*
1999 		 * cr->crlf distinction is done here, on output, not on input!
2000 		 */
2001 		if (ip->linefeed_newline)
2002 			ite_crlf(ip);
2003 		else
2004 			ite_lf(ip);
2005 		break;
2006 	case CR:
2007 		ite_cr(ip);
2008 		break;
2009 	case BS:
2010 		if (--ip->curx < 0)
2011 			ip->curx = 0;
2012 		else
2013 			SUBR_CURSOR(ip, MOVE_CURSOR);
2014 		break;
2015 	case HT:
2016 		for (n = ip->curx + 1; n < ip->cols; n++) {
2017 			if (ip->tabs[n]) {
2018 				ip->curx = n;
2019 				SUBR_CURSOR(ip, MOVE_CURSOR);
2020 				break;
2021 			}
2022 		}
2023 		break;
2024 	case BEL:
2025 		if (kbd_tty && kbd_ite && kbd_ite->tp == kbd_tty)
2026 			kbdbell();
2027 		break;
2028 	case SO:
2029 		ip->GL = ip->G1;
2030 		break;
2031 	case SI:
2032 		ip->GL = ip->G0;
2033 		break;
2034 	case ENQ:
2035 		/* send answer-back message !! */
2036 		break;
2037 	case CAN:
2038 		ip->escape = 0;	/* cancel any escape sequence in progress */
2039 		break;
2040 	case SUB:
2041 		ip->escape = 0;	/* dito, but see below */
2042 		/* should also display a reverse question mark!! */
2043 		break;
2044 	case ESC:
2045 		ip->escape = ESC;
2046 		break;
2047 	/*
2048 	 * now it gets weird.. 8bit control sequences..
2049 	 */
2050 	case IND:
2051 		/* index: move cursor down, scroll */
2052 		ite_lf(ip);
2053 		break;
2054 	case NEL:
2055 		/* next line. next line, first pos. */
2056 		ite_crlf(ip);
2057 		break;
2058 	case HTS:
2059 		/* set horizontal tab */
2060 		if (ip->curx < ip->cols)
2061 			ip->tabs[ip->curx] = 1;
2062 		break;
2063 	case RI:
2064 		/* reverse index */
2065 		ite_rlf(ip);
2066 		break;
2067 	case SS2:
2068 		/* go into G2 for one character */
2069 		/* not yet supported */
2070 		break;
2071 	case SS3:
2072 		/* go into G3 for one character */
2073 		break;
2074 	case DCS:
2075 		/* device control string introducer */
2076 		ip->escape = DCS;
2077 		ip->ap = ip->argbuf;
2078 		break;
2079 	case CSI:
2080 		/* control sequence introducer */
2081 		ip->escape = CSI;
2082 		ip->ap = ip->argbuf;
2083 		break;
2084 	case ST:
2085 		/* string terminator */
2086 		/* ignore, if not used as terminator */
2087 		break;
2088 	case OSC:
2089 		/*
2090 		 * introduces OS command. Ignore everything
2091 		 * upto ST
2092 		 */
2093 		ip->escape = OSC;
2094 		break;
2095 	case PM:
2096 		/* privacy message, ignore everything upto ST */
2097 		ip->escape = PM;
2098 		break;
2099 	case APC:
2100 		/*
2101 		 * application program command, ignore * everything upto ST
2102 		 */
2103 		ip->escape = APC;
2104 		break;
2105 	default:
2106 		if ((c & 0x7f) < ' ' || c == DEL)
2107 			break;
2108 		if (ip->imode)
2109 			ite_inchar(ip, 1);
2110 		iteprecheckwrap(ip);
2111 #ifdef DO_WEIRD_ATTRIBUTES
2112 		if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
2113 			attrset(ip, ATTR_INV);
2114 			SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
2115 		} else
2116 			SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
2117 #else
2118 		SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
2119 #endif
2120 		SUBR_CURSOR(ip, DRAW_CURSOR);
2121 		itecheckwrap(ip);
2122 		break;
2123 	}
2124 }
2125 
2126 int
2127 iteprecheckwrap(ip)
2128 	struct ite_softc *ip;
2129 {
2130 	if (ip->auto_wrap && ip->curx == ip->cols) {
2131 		ip->curx = 0;
2132 		clr_attr(ip, ATTR_INV);
2133 		if (++ip->cury >= ip->bottom_margin + 1) {
2134 			ip->cury = ip->bottom_margin;
2135 			SUBR_CURSOR(ip, MOVE_CURSOR);
2136 			SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2137 			ite_clrtoeol(ip);
2138 		} else
2139 			SUBR_CURSOR(ip, MOVE_CURSOR);
2140 	}
2141 }
2142 
2143 int
2144 itecheckwrap(ip)
2145 	struct ite_softc *ip;
2146 {
2147 #if 0
2148 	if (++ip->curx == ip->cols) {
2149 		if (ip->auto_wrap) {
2150 			ip->curx = 0;
2151 			clr_attr(ip, ATTR_INV);
2152 			if (++ip->cury >= ip->bottom_margin + 1) {
2153 				ip->cury = ip->bottom_margin;
2154 				SUBR_CURSOR(ip, MOVE_CURSOR);
2155 				SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2156 				ite_clrtoeol(ip);
2157 				return;
2158 			}
2159 		} else
2160 			/* stay there if no autowrap.. */
2161 			ip->curx--;
2162 	}
2163 #else
2164 	if (ip->curx < ip->cols) {
2165 		ip->curx++;
2166 		SUBR_CURSOR(ip, MOVE_CURSOR);
2167 	}
2168 #endif
2169 }
2170