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