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