ite.c revision 1.68 1 /* $NetBSD: ite.c,v 1.68 2005/01/19 02:08:40 chs 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.68 2005/01/19 02:08:40 chs 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 <amiga/amiga/cc.h>
101 #include <amiga/amiga/color.h> /* DEBUG */
102 #include <amiga/amiga/custom.h> /* DEBUG */
103 #include <amiga/amiga/device.h>
104 #if defined(__m68k__)
105 #include <amiga/amiga/isr.h>
106 #endif
107 #include <amiga/dev/iteioctl.h>
108 #include <amiga/dev/itevar.h>
109 #include <amiga/dev/kbdmap.h>
110 #include <amiga/dev/grfioctl.h>
111 #include <amiga/dev/grfvar.h>
112
113 #include <machine/cpu.h> /* for is_draco() */
114
115 #include <sys/conf.h>
116
117 #include "grfcc.h"
118 #include "ite.h"
119
120 /*
121 * XXX go ask sys/kern/tty.c:ttselect()
122 */
123
124 #define ITEUNIT(dev) (minor(dev))
125
126 #define SUBR_INIT(ip) (ip)->grf->g_iteinit(ip)
127 #define SUBR_DEINIT(ip) (ip)->grf->g_itedeinit(ip)
128 #define SUBR_PUTC(ip,c,dy,dx,m) (ip)->grf->g_iteputc(ip,c,dy,dx,m)
129 #define SUBR_CURSOR(ip,flg) (ip)->grf->g_itecursor(ip,flg)
130 #define SUBR_CLEAR(ip,sy,sx,h,w) (ip)->grf->g_iteclear(ip,sy,sx,h,w)
131 #define SUBR_SCROLL(ip,sy,sx,count,dir) \
132 (ip)->grf->g_itescroll(ip,sy,sx,count,dir)
133
134 int start_repeat_timeo = 30; /* first repeat after x s/100 */
135 int next_repeat_timeo = 10; /* next repeat after x s/100 */
136
137 int ite_default_wrap = 1; /* you want vtxxx-nam, binpatch */
138
139 struct ite_softc con_itesoftc;
140 u_char cons_tabs[MAX_TABS];
141
142 struct ite_softc *kbd_ite;
143
144 /* audio bell stuff */
145 u_int bvolume = 10;
146 u_int bpitch = 660;
147 u_int bmsec = 75;
148
149 static char *bsamplep;
150 static char sample[20] = {
151 0,39,75,103,121,127,121,103,75,39,0,
152 -39,-75,-103,-121,-127,-121,-103,-75,-39
153 };
154
155 void iteputchar(int c, struct ite_softc *ip);
156 void ite_putstr(const char * s, int len, dev_t dev);
157 void iteattach(struct device *, struct device *, void *);
158 int itematch(struct device *, struct cfdata *, void *);
159 static void iteprecheckwrap(struct ite_softc *);
160 static void itecheckwrap(struct ite_softc *);
161 struct ite_softc *getitesp(dev_t);
162 void init_bell(void);
163 void ite_bell(void);
164 void itecnpollc(dev_t, int);
165 static void repeat_handler(void *);
166 inline static void ite_sendstr(char *);
167 static void alignment_display(struct ite_softc *);
168 inline static void snap_cury(struct ite_softc *);
169 inline static void ite_dnchar(struct ite_softc *, int);
170 inline static void ite_inchar(struct ite_softc *, int);
171 inline static void ite_clrtoeol(struct ite_softc *);
172 inline static void ite_clrtobol(struct ite_softc *);
173 inline static void ite_clrline(struct ite_softc *);
174 inline static void ite_clrtoeos(struct ite_softc *);
175 inline static void ite_clrtobos(struct ite_softc *);
176 inline static void ite_clrscreen(struct ite_softc *);
177 inline static void ite_dnline(struct ite_softc *, int);
178 inline static void ite_inline(struct ite_softc *, int);
179 inline static void ite_lf(struct ite_softc *);
180 inline static void ite_crlf(struct ite_softc *);
181 inline static void ite_cr(struct ite_softc *);
182 inline static void ite_rlf(struct ite_softc *);
183 inline static int atoi(const char *);
184 inline static int ite_argnum(struct ite_softc *);
185 inline static int ite_zargnum(struct ite_softc *);
186
187 CFATTACH_DECL(ite, sizeof(struct ite_softc),
188 itematch, iteattach, NULL, NULL);
189
190 extern struct cfdriver ite_cd;
191
192 dev_type_open(iteopen);
193 dev_type_close(iteclose);
194 dev_type_read(iteread);
195 dev_type_write(itewrite);
196 dev_type_ioctl(iteioctl);
197 dev_type_tty(itetty);
198 dev_type_poll(itepoll);
199
200 const struct cdevsw ite_cdevsw = {
201 iteopen, iteclose, iteread, itewrite, iteioctl,
202 nostop, itetty, itepoll, nommap, ttykqfilter, D_TTY
203 };
204
205 int
206 itematch(struct device *pdp, struct cfdata *cfp, void *auxp)
207 {
208 struct grf_softc *gp;
209 int maj;
210
211 gp = auxp;
212
213 /*
214 * XXX
215 * normally this would be done in attach, however
216 * during early init we do not have a device pointer
217 * and thus no unit number.
218 */
219 maj = cdevsw_lookup_major(&ite_cdevsw);
220 gp->g_itedev = makedev(maj, cfp->cf_unit);
221 return(1);
222 }
223
224 void
225 iteattach(struct device *pdp, struct device *dp, void *auxp)
226 {
227 struct grf_softc *gp;
228 struct ite_softc *ip;
229 int s;
230
231 gp = (struct grf_softc *)auxp;
232 if (dp) {
233 ip = (struct ite_softc *)dp;
234
235 s = spltty();
236 if (con_itesoftc.grf != NULL &&
237 con_itesoftc.grf->g_unit == gp->g_unit) {
238 /*
239 * console reinit copy params over.
240 * and console always gets keyboard
241 */
242 bcopy(&con_itesoftc.grf, &ip->grf,
243 (char *)&ip[1] - (char *)&ip->grf);
244 con_itesoftc.grf = NULL;
245 kbd_ite = ip;
246 }
247 ip->grf = gp;
248 splx(s);
249
250 alloc_sicallback();
251 iteinit(gp->g_itedev);
252 printf(": rows %d cols %d", ip->rows, ip->cols);
253 printf(" repeat at (%d/100)s next at (%d/100)s",
254 start_repeat_timeo, next_repeat_timeo);
255
256 if (kbd_ite == NULL)
257 kbd_ite = ip;
258 if (kbd_ite == ip)
259 printf(" has keyboard");
260 printf("\n");
261 ip->flags |= ITE_ATTACHED;
262 } else {
263 if (con_itesoftc.grf != NULL &&
264 con_itesoftc.grf->g_conpri > gp->g_conpri)
265 return;
266 con_itesoftc.grf = gp;
267 con_itesoftc.tabs = cons_tabs;
268 }
269 }
270
271 struct ite_softc *
272 getitesp(dev_t dev)
273 {
274 if (amiga_realconfig && con_itesoftc.grf == NULL)
275 return(ite_cd.cd_devs[ITEUNIT(dev)]);
276
277 if (con_itesoftc.grf == NULL)
278 panic("no ite_softc for console");
279 return(&con_itesoftc);
280 }
281
282 /*
283 * cons.c entry points into ite device.
284 */
285
286 /*
287 * Return a priority in consdev->cn_pri field highest wins. This function
288 * is called before any devices have been probed.
289 */
290 void
291 itecnprobe(struct consdev *cd)
292 {
293 /*
294 * bring graphics layer up.
295 */
296 config_console();
297
298 /*
299 * return priority of the best ite (already picked from attach)
300 * or CN_DEAD.
301 */
302 if (con_itesoftc.grf == NULL)
303 cd->cn_pri = CN_DEAD;
304 else {
305 cd->cn_pri = con_itesoftc.grf->g_conpri;
306 cd->cn_dev = con_itesoftc.grf->g_itedev;
307 }
308 }
309
310 /* audio bell stuff */
311 void
312 init_bell(void)
313 {
314 if (bsamplep != NULL)
315 return;
316 bsamplep = alloc_chipmem(20);
317 if (bsamplep == NULL)
318 panic("no chipmem for ite_bell");
319
320 bcopy(sample, bsamplep, 20);
321 }
322
323 void
324 ite_bell(void)
325 {
326 u_int clock;
327 u_int period;
328 u_int count;
329
330 clock = 3579545; /* PAL 3546895 */
331
332 /*
333 * the number of clock ticks per sample byte must be > 124
334 * ergo bpitch must be < clock / 124*20
335 * i.e. ~1443, 1300 to be safe (PAL etc.). also not zero obviously
336 */
337 period = clock / (bpitch * 20);
338 count = bmsec * bpitch / 1000;
339
340 play_sample(10, PREP_DMA_MEM(bsamplep), period, bvolume, 0x3, count);
341 }
342
343 void
344 itecninit(struct consdev *cd)
345 {
346 struct ite_softc *ip;
347
348 ip = getitesp(cd->cn_dev);
349 iteinit(cd->cn_dev);
350 ip->flags |= ITE_ACTIVE | ITE_ISCONS;
351
352 #ifdef DRACO
353 if (!is_draco())
354 #endif
355 init_bell();
356 }
357
358 /*
359 * ite_cnfinish() is called in ite_init() when the device is
360 * being probed in the normal fasion, thus we can finish setting
361 * up this ite now that the system is more functional.
362 */
363 void
364 ite_cnfinish(struct ite_softc *ip)
365 {
366 static int done;
367
368 if (done)
369 return;
370 done = 1;
371 }
372
373 int
374 itecngetc(dev_t dev)
375 {
376 int c;
377
378 /* XXX this should be moved */
379 kbdenable();
380 do {
381 c = kbdgetcn();
382 c = ite_cnfilter(c, ITEFILT_CONSOLE);
383 } while (c == -1);
384 return (c);
385 }
386
387 void
388 itecnputc(dev_t dev, int c)
389 {
390 static int paniced;
391 struct ite_softc *ip;
392 char ch;
393
394 ip = getitesp(dev);
395 ch = c;
396
397 if (panicstr && !paniced &&
398 (ip->flags & (ITE_ACTIVE | ITE_INGRF)) != ITE_ACTIVE) {
399 ite_on(dev, 3);
400 paniced = 1;
401 }
402 iteputchar(ch, ip);
403 }
404
405 void
406 itecnpollc(dev_t dev, int on)
407 {
408 }
409
410 /*
411 * standard entry points to the device.
412 */
413
414 /*
415 * iteinit() is the standard entry point for initialization of
416 * an ite device, it is also called from ite_cninit().
417 *
418 */
419 void
420 iteinit(dev_t dev)
421 {
422 struct ite_softc *ip;
423 static int kbdmap_loaded = 0;
424
425 ip = getitesp(dev);
426 if (ip->flags & ITE_INITED)
427 return;
428 if (kbdmap_loaded == 0) {
429 bcopy(&ascii_kbdmap, &kbdmap, sizeof(struct kbdmap));
430 kbdmap_loaded = 1;
431 }
432
433 ip->cursorx = 0;
434 ip->cursory = 0;
435 SUBR_INIT(ip);
436 SUBR_CURSOR(ip, DRAW_CURSOR);
437 if (ip->tabs == NULL)
438 ip->tabs = malloc(MAX_TABS * sizeof(u_char),M_DEVBUF,M_WAITOK);
439 ite_reset(ip);
440 ip->flags |= ITE_INITED;
441 }
442
443 int
444 iteopen(dev_t dev, int mode, int devtype, struct proc *p)
445 {
446 struct ite_softc *ip;
447 struct tty *tp;
448 int error, first, unit;
449
450 unit = ITEUNIT(dev);
451 first = 0;
452
453 if (unit >= ite_cd.cd_ndevs)
454 return ENXIO;
455 ip = getitesp(dev);
456 if ((ip->flags & ITE_ATTACHED) == 0)
457 return ENXIO;
458
459 if (ip->tp == NULL) {
460 tp = ip->tp = ttymalloc();
461 tty_attach(tp);
462 } else
463 tp = ip->tp;
464 if ((tp->t_state & (TS_ISOPEN | TS_XCLUDE)) == (TS_ISOPEN | TS_XCLUDE)
465 && p->p_ucred->cr_uid != 0)
466 return (EBUSY);
467 if ((ip->flags & ITE_ACTIVE) == 0) {
468 ite_on(dev, 0);
469 first = 1;
470 }
471 tp->t_oproc = itestart;
472 tp->t_param = ite_param;
473 tp->t_dev = dev;
474 if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
475 ttychars(tp);
476 tp->t_iflag = TTYDEF_IFLAG;
477 tp->t_oflag = TTYDEF_OFLAG;
478 tp->t_cflag = TTYDEF_CFLAG;
479 tp->t_lflag = TTYDEF_LFLAG;
480 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
481 tp->t_state = TS_CARR_ON;
482 ttsetwater(tp);
483 }
484 error = ttyopen(tp, 0, mode & O_NONBLOCK);
485 if (error)
486 goto bad;
487
488 error = tp->t_linesw->l_open(dev, tp);
489 if (error)
490 goto bad;
491
492 tp->t_winsize.ws_row = ip->rows;
493 tp->t_winsize.ws_col = ip->cols;
494 kbdenable();
495 return (0);
496 bad:
497 if (first)
498 ite_off(dev, 0);
499 return (error);
500 }
501
502 int
503 iteclose(dev_t dev, int flag, int mode, struct proc *p)
504 {
505 struct tty *tp;
506
507 tp = getitesp(dev)->tp;
508
509 KDASSERT(tp);
510 tp->t_linesw->l_close(tp, flag);
511 ttyclose(tp);
512 ite_off(dev, 0);
513 return (0);
514 }
515
516 int
517 iteread(dev_t dev, struct uio *uio, int flag)
518 {
519 struct tty *tp;
520
521 tp = getitesp(dev)->tp;
522
523 KDASSERT(tp);
524 return tp->t_linesw->l_read(tp, uio, flag);
525 }
526
527 int
528 itewrite(dev_t dev, struct uio *uio, int flag)
529 {
530 struct tty *tp;
531
532 tp = getitesp(dev)->tp;
533
534 KDASSERT(tp);
535 return tp->t_linesw->l_write(tp, uio, flag);
536 }
537
538 int
539 itepoll(dev_t dev, int events, struct proc *p)
540 {
541 struct tty *tp;
542
543 tp = getitesp(dev)->tp;
544
545 KDASSERT(tp);
546 return ((*tp->t_linesw->l_poll)(tp, events, p));
547 }
548
549 struct tty *
550 itetty(dev_t dev)
551 {
552 return (getitesp(dev)->tp);
553 }
554
555 int
556 iteioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
557 {
558 struct iterepeat *irp;
559 struct ite_softc *ip;
560 struct itebell *ib;
561 struct tty *tp;
562 int error;
563
564 ip = getitesp(dev);
565 tp = ip->tp;
566
567 KDASSERT(tp);
568
569 error = tp->t_linesw->l_ioctl(tp, cmd, addr, flag, p);
570 if (error != EPASSTHROUGH)
571 return (error);
572 error = ttioctl(tp, cmd, addr, flag, p);
573 if (error != EPASSTHROUGH)
574 return (error);
575
576 switch (cmd) {
577 case ITEIOCGBELL:
578 ib = (struct itebell *)addr;
579 ib->volume = bvolume;
580 ib->pitch = bpitch;
581 ib->msec = bmsec;
582 return (0);
583 case ITEIOCSBELL:
584 ib = (struct itebell *)addr;
585
586 if (ib->pitch > MAXBPITCH || ib->pitch < MINBPITCH ||
587 ib->volume > MAXBVOLUME || ib->msec > MAXBTIME)
588 return (EINVAL);
589 bvolume = ib->volume;
590 bpitch = ib->pitch;
591 bmsec = ib->msec;
592 return (0);
593 case ITEIOCSKMAP:
594 if (addr == 0)
595 return(EFAULT);
596 bcopy(addr, &kbdmap, sizeof(struct kbdmap));
597 return(0);
598 case ITEIOCGKMAP:
599 if (addr == NULL)
600 return(EFAULT);
601 bcopy(&kbdmap, addr, sizeof(struct kbdmap));
602 return(0);
603 case ITEIOCGREPT:
604 irp = (struct iterepeat *)addr;
605 irp->start = start_repeat_timeo;
606 irp->next = next_repeat_timeo;
607 return (0);
608 case ITEIOCSREPT:
609 irp = (struct iterepeat *)addr;
610 if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
611 return(EINVAL);
612 start_repeat_timeo = irp->start;
613 next_repeat_timeo = irp->next;
614 return(0);
615 }
616 #if NGRFCC > 0
617 /* XXX */
618 if (minor(dev) == 0) {
619 error = ite_grf_ioctl(ip, cmd, addr, flag, p);
620 if (error >= 0)
621 return (error);
622 }
623 #endif
624 return (EPASSTHROUGH);
625 }
626
627 void
628 itestart(struct tty *tp)
629 {
630 struct clist *rbp;
631 struct ite_softc *ip;
632 u_char buf[ITEBURST];
633 int s, len;
634
635 ip = getitesp(tp->t_dev);
636
637 KDASSERT(tp);
638
639 s = spltty(); {
640 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
641 goto out;
642
643 tp->t_state |= TS_BUSY;
644 rbp = &tp->t_outq;
645
646 len = q_to_b(rbp, buf, ITEBURST);
647 } splx(s);
648
649 /* Here is a really good place to implement pre/jumpscroll() */
650 ite_putstr(buf, len, tp->t_dev);
651
652 s = spltty(); {
653 tp->t_state &= ~TS_BUSY;
654 /* we have characters remaining. */
655 if (rbp->c_cc) {
656 tp->t_state |= TS_TIMEOUT;
657 callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp);
658 }
659 /* wakeup we are below */
660 if (rbp->c_cc <= tp->t_lowat) {
661 if (tp->t_state & TS_ASLEEP) {
662 tp->t_state &= ~TS_ASLEEP;
663 wakeup((caddr_t) rbp);
664 }
665 selwakeup(&tp->t_wsel);
666 }
667 }
668 out:
669 splx(s);
670 }
671
672 void
673 ite_on(dev_t dev, int flag)
674 {
675 struct ite_softc *ip;
676 int unit;
677
678 unit = ITEUNIT(dev);
679 ip = getitesp(dev);
680
681 /* force ite active, overriding graphics mode */
682 if (flag & 1) {
683 ip->flags |= ITE_ACTIVE;
684 ip->flags &= ~(ITE_INGRF | ITE_INITED);
685 }
686 /* leave graphics mode */
687 if (flag & 2) {
688 ip->flags &= ~ITE_INGRF;
689 if ((ip->flags & ITE_ACTIVE) == 0)
690 return;
691 }
692 ip->flags |= ITE_ACTIVE;
693 if (ip->flags & ITE_INGRF)
694 return;
695 iteinit(dev);
696 }
697
698 void
699 ite_off(dev_t dev, int flag)
700 {
701 struct ite_softc *ip;
702
703 ip = getitesp(dev);
704 if (flag & 2)
705 ip->flags |= ITE_INGRF;
706 if ((ip->flags & ITE_ACTIVE) == 0)
707 return;
708 if ((flag & 1) ||
709 (ip->flags & (ITE_INGRF | ITE_ISCONS | ITE_INITED)) == ITE_INITED)
710 SUBR_DEINIT(ip);
711 /* XXX hmm grfon() I think wants this to go inactive. */
712 if ((flag & 2) == 0)
713 ip->flags &= ~ITE_ACTIVE;
714 }
715
716 /* XXX called after changes made in underlying grf layer. */
717 /* I want to nuke this */
718 void
719 ite_reinit(dev_t dev)
720 {
721 struct ite_softc *ip;
722
723 ip = getitesp(dev);
724 ip->flags &= ~ITE_INITED;
725 iteinit(dev);
726 }
727
728 int
729 ite_param(struct tty *tp, struct termios *t)
730 {
731 tp->t_ispeed = t->c_ispeed;
732 tp->t_ospeed = t->c_ospeed;
733 tp->t_cflag = t->c_cflag;
734 return (0);
735 }
736
737 void
738 ite_reset(struct ite_softc *ip)
739 {
740 int i;
741
742 ip->curx = 0;
743 ip->cury = 0;
744 ip->attribute = ATTR_NOR;
745 ip->save_curx = 0;
746 ip->save_cury = 0;
747 ip->save_attribute = ATTR_NOR;
748 ip->ap = ip->argbuf;
749 ip->emul_level = 0;
750 ip->eightbit_C1 = 0;
751 ip->top_margin = 0;
752 ip->bottom_margin = ip->rows - 1;
753 ip->inside_margins = 0;
754 ip->linefeed_newline = 0;
755 ip->auto_wrap = ite_default_wrap;
756 ip->cursor_appmode = 0;
757 ip->keypad_appmode = 0;
758 ip->imode = 0;
759 ip->key_repeat = 1;
760 bzero(ip->tabs, ip->cols);
761 for (i = 0; i < ip->cols; i++)
762 ip->tabs[i] = ((i & 7) == 0);
763 }
764
765 /*
766 * has to be global because of the shared filters.
767 */
768 static u_char key_mod;
769 static u_char last_dead;
770
771 /* Used in console at startup only */
772 int
773 ite_cnfilter(u_char c, enum caller caller)
774 {
775 struct key key;
776 u_char code, up, mask;
777 int s, i;
778
779 up = c & 0x80 ? 1 : 0;
780 c &= 0x7f;
781 code = 0;
782
783 s = spltty();
784
785 i = (int)c - KBD_LEFT_SHIFT;
786 if (i >= 0 && i <= (KBD_RIGHT_META - KBD_LEFT_SHIFT)) {
787 mask = 1 << i;
788 if (up)
789 key_mod &= ~mask;
790 else
791 key_mod |= mask;
792 splx(s);
793 return -1;
794 }
795
796 if (up) {
797 splx(s);
798 return -1;
799 }
800
801 /* translate modifiers */
802 if (key_mod & KBD_MOD_SHIFT) {
803 if (key_mod & KBD_MOD_ALT)
804 key = kbdmap.alt_shift_keys[c];
805 else
806 key = kbdmap.shift_keys[c];
807 } else if (key_mod & KBD_MOD_ALT)
808 key = kbdmap.alt_keys[c];
809 else {
810 key = kbdmap.keys[c];
811 /* if CAPS and key is CAPable (no pun intended) */
812 if ((key_mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
813 key = kbdmap.shift_keys[c];
814 }
815 code = key.code;
816
817 /* if string return */
818 if (key.mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) {
819 splx(s);
820 return -1;
821 }
822 /* handle dead keys */
823 if (key.mode & KBD_MODE_DEAD) {
824 /* if entered twice, send accent itself */
825 if (last_dead == (key.mode & KBD_MODE_ACCMASK))
826 last_dead = 0;
827 else {
828 last_dead = key.mode & KBD_MODE_ACCMASK;
829 splx(s);
830 return -1;
831 }
832 }
833 if (last_dead) {
834 /* can't apply dead flag to string-keys */
835 if (code >= '@' && code < 0x7f)
836 code =
837 acctable[KBD_MODE_ACCENT(last_dead)][code - '@'];
838 last_dead = 0;
839 }
840 if (key_mod & KBD_MOD_CTRL)
841 code &= 0x1f;
842 if (key_mod & KBD_MOD_META)
843 code |= 0x80;
844
845 /* do console mapping. */
846 code = code == '\r' ? '\n' : code;
847
848 splx(s);
849 return (code);
850 }
851
852 /* And now the old stuff. */
853
854 /* these are used to implement repeating keys.. */
855 static u_char last_char;
856 static u_char tout_pending;
857
858 static struct callout repeat_ch = CALLOUT_INITIALIZER;
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 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(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