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