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