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