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