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