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