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