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