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