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