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