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