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