ite.c revision 1.1.1.2 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.1.1.2 1993/09/02 16:53:36 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 Ctrl-LAlt-F1 here to switch back to original ascii-keymap.
667 this should probably be configurable.. */
668 if (mod == (KBD_MOD_LALT|KBD_MOD_SHIFT) && code == 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 {
752 if (mod & KBD_MOD_CTRL)
753 code &= 0x1f;
754
755 if (mod & KBD_MOD_META)
756 code |= 0x80;
757 }
758 else
759 {
760 /* strings are only supported in normal tty mode, not in console mode */
761 if (caller != ITEFILT_CONSOLE)
762 {
763 str = kbdmap.strings + code;
764 /* using a length-byte instead of 0-termination allows to embed \0 into
765 strings, although this is not used in the default keymap */
766 for (i = *str++; i; i--)
767 itesendch(*str++);
768 }
769 splx (s);
770 return -1;
771 }
772
773 if (caller == ITEFILT_CONSOLE)
774 {
775 /* do the conversion here because raw console input doesn't go thru
776 tty conversions */
777 code = code == '\r' ? '\n' : code;
778 splx (s);
779 return code;
780 }
781 else
782 /* NOTE: *don't* do any cr->crlf conversion here, this is input
783 processing, the mentioned conversion should only be
784 done for output processing (for input, it is not
785 terminal-specific but depends on tty-settings!) */
786 (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
787
788 splx (s);
789 return -1;
790 }
791
792
793 /* helper functions, makes the code below more readable */
794 static void inline
795 ite_sendstr (ip, str)
796 struct ite_softc *ip;
797 char *str;
798 {
799 while (*str)
800 itesendch (*str++);
801 }
802
803 static void
804 alignment_display(struct ite_softc *ip, struct itesw *sp)
805 {
806 int i, j;
807
808 for (j = 0; j < ip->rows; j++)
809 for (i = 0; i < ip->cols; i++)
810 (*sp->ite_putc)(ip, 'E', j, i, ATTR_NOR);
811 attrclr(ip, 0, 0, ip->rows, ip->cols);
812 (*sp->ite_cursor)(ip, DRAW_CURSOR);
813 }
814
815 static void inline
816 snap_cury(struct ite_softc *ip, struct itesw *sp)
817 {
818 if (ip->inside_margins)
819 {
820 if (ip->cury < ip->top_margin)
821 ip->cury = ip->top_margin;
822 if (ip->cury > ip->bottom_margin)
823 ip->cury = ip->bottom_margin;
824 }
825 }
826
827 static void inline
828 ite_dnchar(ip, sp, n)
829 struct ite_softc *ip;
830 struct itesw *sp;
831 int n;
832 {
833 n = MIN(n, ip->cols - ip->curx);
834 if (n < ip->cols - ip->curx)
835 {
836 (*sp->ite_scroll)(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
837 attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
838 1, ip->cols - ip->curx - n);
839 attrclr(ip, ip->cury, ip->cols - n, 1, n);
840 }
841 while (n-- > 0)
842 (*sp->ite_putc)(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
843 (*sp->ite_cursor)(ip, DRAW_CURSOR);
844 }
845
846 static void inline
847 ite_inchar(ip, sp, n)
848 struct ite_softc *ip;
849 struct itesw *sp;
850 int n;
851 {
852 n = MIN(n, ip->cols - ip->curx);
853 if (n < ip->cols - ip->curx)
854 {
855 (*sp->ite_scroll)(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
856 attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
857 1, ip->cols - ip->curx - n);
858 attrclr(ip, ip->cury, ip->curx, 1, n);
859 }
860 while (n--)
861 (*sp->ite_putc)(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
862 (*sp->ite_cursor)(ip, DRAW_CURSOR);
863 }
864
865 static void inline
866 ite_clrtoeol(ip, sp)
867 struct ite_softc *ip;
868 struct itesw *sp;
869 {
870 int y = ip->cury, x = ip->curx;
871 if (ip->cols - x > 0)
872 {
873 (*sp->ite_clear)(ip, y, x, 1, ip->cols - x);
874 attrclr(ip, y, x, 1, ip->cols - x);
875 (*sp->ite_cursor)(ip, DRAW_CURSOR);
876 }
877 }
878
879 static void inline
880 ite_clrtobol(ip, sp)
881 struct ite_softc *ip;
882 struct itesw *sp;
883 {
884 int y = ip->cury, x = MIN(ip->curx + 1, ip->cols);
885 (*sp->ite_clear)(ip, y, 0, 1, x);
886 attrclr(ip, y, 0, 1, x);
887 (*sp->ite_cursor)(ip, DRAW_CURSOR);
888 }
889
890 static void inline
891 ite_clrline(ip, sp)
892 struct ite_softc *ip;
893 struct itesw *sp;
894 {
895 int y = ip->cury;
896 (*sp->ite_clear)(ip, y, 0, 1, ip->cols);
897 attrclr(ip, y, 0, 1, ip->cols);
898 (*sp->ite_cursor)(ip, DRAW_CURSOR);
899 }
900
901
902
903 static void inline
904 ite_clrtoeos(ip, sp)
905 struct ite_softc *ip;
906 struct itesw *sp;
907 {
908 ite_clrtoeol(ip, sp);
909 if (ip->cury < ip->rows - 1)
910 {
911 (*sp->ite_clear)(ip, ip->cury + 1, 0, ip->rows - 1 - ip->cury, ip->cols);
912 attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
913 (*sp->ite_cursor)(ip, DRAW_CURSOR);
914 }
915 }
916
917 static void inline
918 ite_clrtobos(ip, sp)
919 struct ite_softc *ip;
920 struct itesw *sp;
921 {
922 ite_clrtobol(ip, sp);
923 if (ip->cury > 0)
924 {
925 (*sp->ite_clear)(ip, 0, 0, ip->cury, ip->cols);
926 attrclr(ip, 0, 0, ip->cury, ip->cols);
927 (*sp->ite_cursor)(ip, DRAW_CURSOR);
928 }
929 }
930
931 static void inline
932 ite_clrscreen(ip, sp)
933 struct ite_softc *ip;
934 struct itesw *sp;
935 {
936 (*sp->ite_clear)(ip, 0, 0, ip->rows, ip->cols);
937 attrclr(ip, 0, 0, ip->rows, ip->cols);
938 (*sp->ite_cursor)(ip, DRAW_CURSOR);
939 }
940
941
942
943 static void inline
944 ite_dnline(ip, sp, n)
945 struct ite_softc *ip;
946 struct itesw *sp;
947 int n;
948 {
949 n = MIN(n, ip->bottom_margin + 1 - ip->cury);
950 if (n <= ip->bottom_margin - ip->cury)
951 {
952 (*sp->ite_scroll)(ip, ip->cury + n, 0, n, SCROLL_UP);
953 attrmov(ip, ip->cury + n, 0, ip->cury, 0,
954 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
955 }
956 (*sp->ite_clear)(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
957 attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
958 (*sp->ite_cursor)(ip, DRAW_CURSOR);
959 }
960
961 static void inline
962 ite_inline(ip, sp, n)
963 struct ite_softc *ip;
964 struct itesw *sp;
965 int n;
966 {
967 if ((ip->cury >= ip->top_margin) && (ip->cury <= ip->bottom_margin))
968 {
969 n = MIN(n, ip->bottom_margin + 1 - ip->cury);
970 if (n <= ip->bottom_margin - ip->cury)
971 {
972 (*sp->ite_scroll)(ip, ip->cury, 0, n, SCROLL_DOWN);
973 attrmov(ip, ip->cury, 0, ip->cury + n, 0,
974 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
975 }
976 (*sp->ite_clear)(ip, ip->cury, 0, n, ip->cols);
977 attrclr(ip, ip->cury, 0, n, ip->cols);
978 (*sp->ite_cursor)(ip, DRAW_CURSOR);
979 }
980 }
981
982 static void inline
983 ite_lf (ip, sp)
984 struct ite_softc *ip;
985 struct itesw *sp;
986 {
987 if (ip->inside_margins)
988 {
989 ++ip->cury;
990 if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows))
991 {
992 ip->cury--;
993 (*sp->ite_scroll)(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
994 ite_clrline(ip, sp);
995 }
996 (*sp->ite_cursor)(ip, MOVE_CURSOR);
997 }
998 else
999 {
1000 if (++ip->cury >= ip->rows)
1001 {
1002 ip->cury = ip->rows - 1;
1003 (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
1004 ite_clrline(ip, sp);
1005 }
1006 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1007 }
1008 clr_attr(ip, ATTR_INV);
1009 }
1010
1011 static void inline
1012 ite_crlf (ip, sp)
1013 struct ite_softc *ip;
1014 struct itesw *sp;
1015 {
1016 ip->curx = 0;
1017 ite_lf (ip, sp);
1018 }
1019
1020 static void inline
1021 ite_cr (ip, sp)
1022 struct ite_softc *ip;
1023 struct itesw *sp;
1024 {
1025 if (ip->curx)
1026 {
1027 ip->curx = 0;
1028 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1029 }
1030 }
1031
1032 static void inline
1033 ite_rlf (ip, sp)
1034 struct ite_softc *ip;
1035 struct itesw *sp;
1036 {
1037 int top = ip->inside_margins ? ip->top_margin : 0;
1038
1039 ip->cury--;
1040 if ((ip->cury < 0) || (ip->cury == top-1))
1041 {
1042 ip->cury++;
1043 (*sp->ite_scroll)(ip, top, 0, 1, SCROLL_DOWN);
1044 ite_clrline(ip, sp);
1045 }
1046 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1047 clr_attr(ip, ATTR_INV);
1048 }
1049
1050 static int inline
1051 atoi (cp)
1052 const char *cp;
1053 {
1054 int n;
1055
1056 for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
1057 n = n * 10 + *cp - '0';
1058
1059 return n;
1060 }
1061
1062 static char *
1063 index (cp, ch)
1064 const char *cp;
1065 char ch;
1066 {
1067 while (*cp && *cp != ch) cp++;
1068 return *cp ? (char *) cp : 0;
1069 }
1070
1071
1072
1073 static int inline
1074 ite_argnum (ip)
1075 struct ite_softc *ip;
1076 {
1077 char ch;
1078 int n;
1079
1080 /* convert argument string into number */
1081 if (ip->ap == ip->argbuf)
1082 return 1;
1083 ch = *ip->ap;
1084 *ip->ap = 0;
1085 n = atoi (ip->argbuf);
1086 *ip->ap = ch;
1087
1088 return n;
1089 }
1090
1091 static int inline
1092 ite_zargnum (ip)
1093 struct ite_softc *ip;
1094 {
1095 char ch, *cp;
1096 int n;
1097
1098 /* convert argument string into number */
1099 if (ip->ap == ip->argbuf)
1100 return 0;
1101 ch = *ip->ap;
1102 *ip->ap = 0;
1103 n = atoi (ip->argbuf);
1104 *ip->ap = ch;
1105
1106 return n; /* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
1107 }
1108
1109 static int inline
1110 strncmp (a, b, l)
1111 const char *a, *b;
1112 int l;
1113 {
1114 for (;l--; a++, b++)
1115 if (*a != *b)
1116 return *a - *b;
1117 return 0;
1118 }
1119
1120 static void inline
1121 ite_reset(ip)
1122 struct ite_softc *ip;
1123 {
1124 int i;
1125
1126 ip->curx = 0;
1127 ip->cury = 0;
1128 ip->attribute = 0;
1129 ip->save_curx = 0;
1130 ip->save_cury = 0;
1131 ip->save_attribute = 0;
1132 ip->ap = ip->argbuf;
1133 ip->emul_level = EMUL_VT300_7;
1134 ip->eightbit_C1 = 0;
1135 ip->top_margin = 0; ip->bottom_margin = ip->rows - 1;
1136 ip->inside_margins = 1;
1137 ip->linefeed_newline = 0;
1138 ip->auto_wrap = 0;
1139 ip->cursor_appmode = 0;
1140 ip->keypad_appmode = 0;
1141 ip->imode = 0;
1142 ip->key_repeat = 1;
1143
1144 #ifdef DO_WEIRD_ATTRIBUTES
1145 bzero(ip->attrbuf, (ip->rows * ip->cols));
1146 #endif
1147 bzero (ip->tabs, ip->cols);
1148 for (i = 0; i < ip->cols; i++)
1149 ip->tabs[i] = (i & 7) == 0;
1150 }
1151
1152
1153 void
1154 iteputchar(c, dev)
1155 register int c;
1156 dev_t dev;
1157 {
1158 int unit = UNIT(dev);
1159 register struct ite_softc *ip = &ite_softc[unit];
1160 register struct itesw *sp = &itesw[ip->type];
1161 register int n;
1162 int x, y;
1163 char *cp;
1164
1165 if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
1166 return;
1167
1168 #if 0
1169 if (ite_tty[unit])
1170 if ((ite_tty[unit]->t_cflag & CSIZE) == CS7
1171 || (ite_tty[unit]->t_cflag & PARENB))
1172 c &= 0x7f;
1173 #endif
1174
1175 if (ip->escape)
1176 {
1177 doesc:
1178 switch (ip->escape)
1179 {
1180 case ESC:
1181 switch (c)
1182 {
1183 /* first 7bit equivalents for the 8bit control characters */
1184
1185 case 'D':
1186 c = IND;
1187 ip->escape = 0;
1188 break; /* and fall into the next switch below (same for all `break') */
1189
1190 case 'E':
1191 c = NEL;
1192 ip->escape = 0;
1193 break;
1194
1195 case 'H':
1196 c = HTS;
1197 ip->escape = 0;
1198 break;
1199
1200 case 'M':
1201 c = RI;
1202 ip->escape = 0;
1203 break;
1204
1205 case 'N':
1206 c = SS2;
1207 ip->escape = 0;
1208 break;
1209
1210 case 'O':
1211 c = SS3;
1212 ip->escape = 0;
1213 break;
1214
1215 case 'P':
1216 c = DCS;
1217 ip->escape = 0;
1218 break;
1219
1220 case '[':
1221 c = CSI;
1222 ip->escape = 0;
1223 break;
1224
1225 case '\\':
1226 c = ST;
1227 ip->escape = 0;
1228 break;
1229
1230 case ']':
1231 c = OSC;
1232 ip->escape = 0;
1233 break;
1234
1235 case '^':
1236 c = PM;
1237 ip->escape = 0;
1238 break;
1239
1240 case '_':
1241 c = APC;
1242 ip->escape = 0;
1243 break;
1244
1245
1246 /* introduces 7/8bit control */
1247 case ' ':
1248 /* can be followed by either F or G */
1249 ip->escape = ' ';
1250 break;
1251
1252
1253 /* a lot of character set selections, not yet used...
1254 94-character sets: */
1255 case '(': /* G0 */
1256 case ')': /* G1 */
1257 ip->escape = c;
1258 return;
1259
1260 case '*': /* G2 */
1261 case '+': /* G3 */
1262 case 'B': /* ASCII */
1263 case 'A': /* ISO latin 1 */
1264 case '<': /* user preferred suplemental */
1265 case '0': /* dec special graphics */
1266
1267 /* 96-character sets: */
1268 case '-': /* G1 */
1269 case '.': /* G2 */
1270 case '/': /* G3 */
1271
1272 /* national character sets: */
1273 case '4': /* dutch */
1274 case '5':
1275 case 'C': /* finnish */
1276 case 'R': /* french */
1277 case 'Q': /* french canadian */
1278 case 'K': /* german */
1279 case 'Y': /* italian */
1280 case '6': /* norwegian/danish */
1281 /* note: %5 and %6 are not supported (two chars..) */
1282
1283 ip->escape = 0;
1284 /* just ignore for now */
1285 return;
1286
1287
1288 /* locking shift modes (as you might guess, not yet supported..) */
1289 case '`':
1290 ip->GR = ip->G1;
1291 ip->escape = 0;
1292 return;
1293
1294 case 'n':
1295 ip->GL = ip->G2;
1296 ip->escape = 0;
1297 return;
1298
1299 case '}':
1300 ip->GR = ip->G2;
1301 ip->escape = 0;
1302 return;
1303
1304 case 'o':
1305 ip->GL = ip->G3;
1306 ip->escape = 0;
1307 return;
1308
1309 case '|':
1310 ip->GR = ip->G3;
1311 ip->escape = 0;
1312 return;
1313
1314
1315 /* font width/height control */
1316 case '#':
1317 ip->escape = '#';
1318 return;
1319
1320
1321 /* hard terminal reset .. */
1322 case 'c':
1323 ite_reset (ip);
1324 (*itesw[ip->type].ite_cursor)(ip, MOVE_CURSOR);
1325 ip->escape = 0;
1326 return;
1327
1328
1329 case '7':
1330 ip->save_curx = ip->curx;
1331 ip->save_cury = ip->cury;
1332 ip->save_attribute = ip->attribute;
1333 ip->escape = 0;
1334 return;
1335
1336 case '8':
1337 ip->curx = ip->save_curx;
1338 ip->cury = ip->save_cury;
1339 ip->attribute = ip->save_attribute;
1340 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1341 ip->escape = 0;
1342 return;
1343
1344 case '=':
1345 ip->keypad_appmode = 1;
1346 ip->escape = 0;
1347 return;
1348
1349 case '>':
1350 ip->keypad_appmode = 0;
1351 ip->escape = 0;
1352 return;
1353
1354 case 'Z': /* request ID */
1355 if (ip->emul_level == EMUL_VT100)
1356 ite_sendstr (ip, "\033[61;0c");
1357 else
1358 ite_sendstr (ip, "\033[63;0c");
1359 ip->escape = 0;
1360 return;
1361
1362 /* default catch all for not recognized ESC sequences */
1363 default:
1364 ip->escape = 0;
1365 return;
1366 }
1367 break;
1368
1369
1370 case '(':
1371 case ')':
1372 ip->escape = 0;
1373 return;
1374
1375
1376 case ' ':
1377 switch (c)
1378 {
1379 case 'F':
1380 ip->eightbit_C1 = 0;
1381 ip->escape = 0;
1382 return;
1383
1384 case 'G':
1385 ip->eightbit_C1 = 1;
1386 ip->escape = 0;
1387 return;
1388
1389 default:
1390 /* not supported */
1391 ip->escape = 0;
1392 return;
1393 }
1394 break;
1395
1396
1397 case '#':
1398 switch (c)
1399 {
1400 case '5':
1401 /* single height, single width */
1402 ip->escape = 0;
1403 return;
1404
1405 case '6':
1406 /* double width, single height */
1407 ip->escape = 0;
1408 return;
1409
1410 case '3':
1411 /* top half */
1412 ip->escape = 0;
1413 return;
1414
1415 case '4':
1416 /* bottom half */
1417 ip->escape = 0;
1418 return;
1419
1420 case '8':
1421 /* screen alignment pattern... */
1422 ip->escape = 0;
1423 return;
1424
1425 default:
1426 ip->escape = 0;
1427 return;
1428 }
1429 break;
1430
1431
1432
1433 case CSI:
1434 /* the biggie... */
1435 switch (c)
1436 {
1437 case '0': case '1': case '2': case '3': case '4':
1438 case '5': case '6': case '7': case '8': case '9':
1439 case ';': case '\"': case '$': case '>':
1440 if (ip->ap < ip->argbuf + ARGBUF_SIZE)
1441 *ip->ap++ = c;
1442 return;
1443
1444 case 'p':
1445 *ip->ap = 0;
1446 if (! strncmp (ip->argbuf, "61\"", 3))
1447 ip->emul_level = EMUL_VT100;
1448 else if (! strncmp (ip->argbuf, "63;1\"", 5)
1449 || ! strncmp (ip->argbuf, "62;1\"", 5))
1450 ip->emul_level = EMUL_VT300_7;
1451 else
1452 ip->emul_level = EMUL_VT300_8;
1453 ip->escape = 0;
1454 return;
1455
1456
1457 case '?':
1458 *ip->ap = 0;
1459 ip->escape = '?';
1460 ip->ap = ip->argbuf;
1461 return;
1462
1463
1464 case 'c':
1465 *ip->ap = 0;
1466 if (ip->argbuf[0] == '>')
1467 {
1468 ite_sendstr (ip, "\033[>24;0;0;0c");
1469 }
1470 else switch (ite_zargnum(ip))
1471 {
1472 case 0:
1473 /* primary DA request, send primary DA response */
1474 if (ip->emul_level == EMUL_VT100)
1475 ite_sendstr (ip, "\033[?1;1c");
1476 else
1477 ite_sendstr (ip, "\033[63;0c");
1478 break;
1479 }
1480 ip->escape = 0;
1481 return;
1482
1483 case 'n':
1484 switch (ite_zargnum(ip))
1485 {
1486 case 5:
1487 ite_sendstr (ip, "\033[0n"); /* no malfunction */
1488 break;
1489 case 6:
1490 /* cursor position report */
1491 sprintf (ip->argbuf, "\033[%d;%dR",
1492 ip->cury + 1, ip->curx + 1);
1493 ite_sendstr (ip, ip->argbuf);
1494 break;
1495 }
1496 ip->escape = 0;
1497 return;
1498
1499
1500 case 'x':
1501 switch (ite_zargnum(ip))
1502 {
1503 case 0:
1504 /* Fake some terminal parameters. */
1505 ite_sendstr (ip, "\033[2;1;1;112;112;1;0x");
1506 break;
1507 case 1:
1508 ite_sendstr (ip, "\033[3;1;1;112;112;1;0x");
1509 break;
1510 }
1511 ip->escape = 0;
1512 return;
1513
1514
1515 case 'g':
1516 switch (ite_zargnum(ip))
1517 {
1518 case 0:
1519 if (ip->curx < ip->cols)
1520 ip->tabs[ip->curx] = 0;
1521 break;
1522 case 3:
1523 for (n = 0; n < ip->cols; n++)
1524 ip->tabs[n] = 0;
1525 break;
1526 }
1527 ip->escape = 0;
1528 return;
1529
1530
1531 case 'h': case 'l':
1532 n = ite_zargnum (ip);
1533 switch (n)
1534 {
1535 case 4:
1536 ip->imode = (c == 'h'); /* insert/replace mode */
1537 break;
1538 case 20:
1539 ip->linefeed_newline = (c == 'h');
1540 break;
1541 }
1542 ip->escape = 0;
1543 return;
1544
1545
1546 case 'M':
1547 ite_dnline (ip, sp, ite_argnum (ip));
1548 ip->escape = 0;
1549 return;
1550
1551
1552 case 'L':
1553 ite_inline (ip, sp, ite_argnum (ip));
1554 ip->escape = 0;
1555 return;
1556
1557
1558 case 'P':
1559 ite_dnchar (ip, sp, ite_argnum (ip));
1560 ip->escape = 0;
1561 return;
1562
1563
1564 case '@':
1565 ite_inchar (ip, sp, ite_argnum (ip));
1566 ip->escape = 0;
1567 return;
1568
1569
1570 case 'H':
1571 case 'f':
1572 *ip->ap = 0;
1573 y = atoi (ip->argbuf);
1574 x = 0;
1575 cp = index (ip->argbuf, ';');
1576 if (cp)
1577 x = atoi (cp + 1);
1578 if (x) x--;
1579 if (y) y--;
1580 ip->cury = MIN(y, ip->rows - 1);
1581 ip->curx = MIN(x, ip->cols - 1);
1582 ip->escape = 0;
1583 snap_cury(ip, sp);
1584 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1585 clr_attr (ip, ATTR_INV);
1586 return;
1587
1588 case 'A':
1589 n = ip->cury - ite_argnum (ip);
1590 if (n < 0) n = 0;
1591 ip->cury = MAX(n, ip->inside_margins ? ip->top_margin : 0);
1592 ip->escape = 0;
1593 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1594 clr_attr (ip, ATTR_INV);
1595 return;
1596
1597 case 'B':
1598 n = ite_argnum (ip) + ip->cury;
1599 ip->cury = MIN(n, ip->inside_margins ? ip->bottom_margin : ip->rows - 1);
1600 ip->escape = 0;
1601 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1602 clr_attr (ip, ATTR_INV);
1603 return;
1604
1605 case 'C':
1606 n = ite_argnum (ip);
1607 ip->curx = MIN(ip->curx + n, ip->cols - 1);
1608 ip->escape = 0;
1609 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1610 clr_attr (ip, ATTR_INV);
1611 return;
1612
1613 case 'D':
1614 n = ite_argnum (ip);
1615 n = ip->curx - n;
1616 ip->curx = n >= 0 ? n : 0;
1617 ip->escape = 0;
1618 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1619 clr_attr (ip, ATTR_INV);
1620 return;
1621
1622
1623
1624
1625 case 'J':
1626 *ip->ap = 0;
1627 n = ite_zargnum (ip);
1628 if (n == 0)
1629 ite_clrtoeos(ip, sp);
1630 else if (n == 1)
1631 ite_clrtobos(ip, sp);
1632 else if (n == 2)
1633 ite_clrscreen(ip, sp);
1634 ip->escape = 0;
1635 return;
1636
1637
1638 case 'K':
1639 n = ite_zargnum (ip);
1640 if (n == 0)
1641 ite_clrtoeol(ip, sp);
1642 else if (n == 1)
1643 ite_clrtobol(ip, sp);
1644 else if (n == 2)
1645 ite_clrline(ip, sp);
1646 ip->escape = 0;
1647 return;
1648
1649
1650 case 'X':
1651 n = ite_argnum(ip) - 1;
1652 n = MIN(n, ip->cols - 1 - ip->curx);
1653 for (; n >= 0; n--)
1654 {
1655 attrclr(ip, ip->cury, ip->curx + n, 1, 1);
1656 (*sp->ite_putc)(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1657 }
1658 ip->escape = 0;
1659 return;
1660
1661
1662 case '}': case '`':
1663 /* status line control */
1664 ip->escape = 0;
1665 return;
1666
1667
1668 case 'r':
1669 *ip->ap = 0;
1670 x = atoi (ip->argbuf);
1671 y = 0;
1672 cp = index (ip->argbuf, ';');
1673 if (cp)
1674 y = atoi (cp + 1);
1675 if ((x > 0) || (y > 1))
1676 {
1677 if (x) x--;
1678 if (y) y--;
1679 ip->top_margin = MIN(x, ip->rows - 1);
1680 ip->bottom_margin = MIN(y, ip->rows - 1);
1681 if (ip->bottom_margin < ip->top_margin)
1682 ip->bottom_margin = ip->top_margin;
1683 }
1684 else
1685 {
1686 ip->top_margin = 0;
1687 ip->bottom_margin = ip->rows - 1;
1688 }
1689 ip->cury = ip->top_margin;
1690 ip->curx = 0;
1691 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1692 ip->escape = 0;
1693 return;
1694
1695
1696 case 'm':
1697 /* big attribute setter/resetter */
1698 {
1699 char *cp;
1700 *ip->ap = 0;
1701 /* kludge to make CSIm work (== CSI0m) */
1702 if (ip->ap == ip->argbuf)
1703 ip->ap++;
1704 for (cp = ip->argbuf; cp < ip->ap; )
1705 {
1706 switch (*cp)
1707 {
1708 case 0:
1709 case '0':
1710 clr_attr (ip, ATTR_ALL);
1711 cp++;
1712 break;
1713
1714 case '1':
1715 set_attr (ip, ATTR_BOLD);
1716 cp++;
1717 break;
1718
1719 case '2':
1720 switch (cp[1])
1721 {
1722 case '2':
1723 clr_attr (ip, ATTR_BOLD);
1724 cp += 2;
1725 break;
1726
1727 case '4':
1728 clr_attr (ip, ATTR_UL);
1729 cp += 2;
1730 break;
1731
1732 case '5':
1733 clr_attr (ip, ATTR_BLINK);
1734 cp += 2;
1735 break;
1736
1737 case '7':
1738 clr_attr (ip, ATTR_INV);
1739 cp += 2;
1740 break;
1741
1742 default:
1743 cp++;
1744 break;
1745 }
1746 break;
1747
1748 case '4':
1749 set_attr (ip, ATTR_UL);
1750 cp++;
1751 break;
1752
1753 case '5':
1754 set_attr (ip, ATTR_BLINK);
1755 cp++;
1756 break;
1757
1758 case '7':
1759 set_attr (ip, ATTR_INV);
1760 cp++;
1761 break;
1762
1763 default:
1764 cp++;
1765 break;
1766 }
1767 }
1768
1769 }
1770 ip->escape = 0;
1771 return;
1772
1773
1774 case 'u':
1775 /* DECRQTSR */
1776 ite_sendstr (ip, "\033P\033\\");
1777 ip->escape = 0;
1778 return;
1779
1780
1781
1782 default:
1783 ip->escape = 0;
1784 return;
1785 }
1786 break;
1787
1788
1789
1790 case '?': /* CSI ? */
1791 switch (c)
1792 {
1793 case '0': case '1': case '2': case '3': case '4':
1794 case '5': case '6': case '7': case '8': case '9':
1795 case ';': case '\"': case '$':
1796 /* Don't fill the last character; it's needed. */
1797 /* XXX yeah, where ?? */
1798 if (ip->ap < ip->argbuf + ARGBUF_SIZE - 1)
1799 *ip->ap++ = c;
1800 return;
1801
1802
1803 case 'n':
1804 *ip->ap = 0;
1805 if (ip->ap == &ip->argbuf[2])
1806 {
1807 if (! strncmp (ip->argbuf, "15", 2))
1808 /* printer status: no printer */
1809 ite_sendstr (ip, "\033[13n");
1810
1811 else if (! strncmp (ip->argbuf, "25", 2))
1812 /* udk status */
1813 ite_sendstr (ip, "\033[20n");
1814
1815 else if (! strncmp (ip->argbuf, "26", 2))
1816 /* keyboard dialect: US */
1817 ite_sendstr (ip, "\033[27;1n");
1818 }
1819 ip->escape = 0;
1820 return;
1821
1822
1823 case 'h': case 'l':
1824 n = ite_zargnum (ip);
1825 switch (n)
1826 {
1827 case 1:
1828 ip->cursor_appmode = (c == 'h');
1829 break;
1830
1831 case 3:
1832 /* 132/80 columns (132 == 'h') */
1833 break;
1834
1835 case 4: /* smooth scroll */
1836 break;
1837
1838 case 5:
1839 /* light background (=='h') /dark background(=='l') */
1840 break;
1841
1842 case 6: /* origin mode */
1843 ip->inside_margins = (c == 'h');
1844 break;
1845
1846 case 7: /* auto wraparound */
1847 ip->auto_wrap = (c == 'h');
1848 break;
1849
1850 case 8: /* keyboard repeat */
1851 ip->key_repeat = (c == 'h');
1852 break;
1853
1854 case 20: /* newline mode */
1855 ip->linefeed_newline = (c == 'h');
1856 break;
1857
1858 case 25: /* cursor on/off */
1859 (*itesw[ip->type].ite_cursor)(ip, (c == 'h') ? DRAW_CURSOR : ERASE_CURSOR);
1860 break;
1861 }
1862 ip->escape = 0;
1863 return;
1864
1865 default:
1866 ip->escape = 0;
1867 return;
1868 }
1869 break;
1870
1871
1872 default:
1873 ip->escape = 0;
1874 return;
1875 }
1876 }
1877
1878
1879 switch (c) {
1880
1881 case VT: /* VT is treated like LF */
1882 case FF: /* so is FF */
1883 case LF:
1884 /* cr->crlf distinction is done here, on output,
1885 not on input! */
1886 if (ip->linefeed_newline)
1887 ite_crlf (ip, sp);
1888 else
1889 ite_lf (ip, sp);
1890 break;
1891
1892 case CR:
1893 ite_cr (ip, sp);
1894 break;
1895
1896 case BS:
1897 if (--ip->curx < 0)
1898 ip->curx = 0;
1899 else
1900 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1901 break;
1902
1903 case HT:
1904 for (n = ip->curx + 1; n < ip->cols; n++) {
1905 if (ip->tabs[n]) {
1906 ip->curx = n;
1907 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1908 break;
1909 }
1910 }
1911 break;
1912
1913 case BEL:
1914 if (kbd_tty && ite_tty[unit] == kbd_tty)
1915 kbdbell();
1916 break;
1917
1918 case SO:
1919 ip->GL = ip->G1;
1920 break;
1921
1922 case SI:
1923 ip->GL = ip->G0;
1924 break;
1925
1926 case ENQ:
1927 /* send answer-back message !! */
1928 break;
1929
1930 case CAN:
1931 ip->escape = 0; /* cancel any escape sequence in progress */
1932 break;
1933
1934 case SUB:
1935 ip->escape = 0; /* dito, but see below */
1936 /* should also display a reverse question mark!! */
1937 break;
1938
1939 case ESC:
1940 ip->escape = ESC;
1941 break;
1942
1943
1944 /* now it gets weird.. 8bit control sequences.. */
1945 case IND: /* index: move cursor down, scroll */
1946 ite_lf (ip, sp);
1947 break;
1948
1949 case NEL: /* next line. next line, first pos. */
1950 ite_crlf (ip, sp);
1951 break;
1952
1953 case HTS: /* set horizontal tab */
1954 if (ip->curx < ip->cols)
1955 ip->tabs[ip->curx] = 1;
1956 break;
1957
1958 case RI: /* reverse index */
1959 ite_rlf (ip, sp);
1960 break;
1961
1962 case SS2: /* go into G2 for one character */
1963 /* not yet supported */
1964 break;
1965
1966 case SS3: /* go into G3 for one character */
1967 break;
1968
1969 case DCS: /* device control string introducer */
1970 ip->escape = DCS;
1971 ip->ap = ip->argbuf;
1972 break;
1973
1974 case CSI: /* control sequence introducer */
1975 ip->escape = CSI;
1976 ip->ap = ip->argbuf;
1977 break;
1978
1979 case ST: /* string terminator */
1980 /* ignore, if not used as terminator */
1981 break;
1982
1983 case OSC: /* introduces OS command. Ignore everything upto ST */
1984 ip->escape = OSC;
1985 break;
1986
1987 case PM: /* privacy message, ignore everything upto ST */
1988 ip->escape = PM;
1989 break;
1990
1991 case APC: /* application program command, ignore everything upto ST */
1992 ip->escape = APC;
1993 break;
1994
1995 default:
1996 if (c < ' ' || c == DEL)
1997 break;
1998 if (ip->imode)
1999 ite_inchar(ip, sp, 1);
2000 iteprecheckwrap(ip, sp);
2001 #ifdef DO_WEIRD_ATTRIBUTES
2002 if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
2003 attrset(ip, ATTR_INV);
2004 (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_INV);
2005 }
2006 else
2007 (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_NOR);
2008 #else
2009 (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ip->attribute);
2010 #endif
2011 (*sp->ite_cursor)(ip, DRAW_CURSOR);
2012 itecheckwrap(ip, sp);
2013 break;
2014 }
2015 }
2016
2017 iteprecheckwrap(ip, sp)
2018 register struct ite_softc *ip;
2019 register struct itesw *sp;
2020 {
2021 if (ip->auto_wrap && ip->curx == ip->cols) {
2022 ip->curx = 0;
2023 clr_attr(ip, ATTR_INV);
2024 if (++ip->cury >= ip->bottom_margin + 1) {
2025 ip->cury = ip->bottom_margin;
2026 (*sp->ite_cursor)(ip, MOVE_CURSOR);
2027 (*sp->ite_scroll)(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2028 ite_clrtoeol(ip, sp);
2029 } else
2030 (*sp->ite_cursor)(ip, MOVE_CURSOR);
2031 }
2032 }
2033
2034 itecheckwrap(ip, sp)
2035 register struct ite_softc *ip;
2036 register struct itesw *sp;
2037 {
2038 #if 0
2039 if (++ip->curx == ip->cols) {
2040 if (ip->auto_wrap) {
2041 ip->curx = 0;
2042 clr_attr(ip, ATTR_INV);
2043 if (++ip->cury >= ip->bottom_margin + 1) {
2044 ip->cury = ip->bottom_margin;
2045 (*sp->ite_cursor)(ip, MOVE_CURSOR);
2046 (*sp->ite_scroll)(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2047 ite_clrtoeol(ip, sp);
2048 return;
2049 }
2050 } else
2051 /* stay there if no autowrap.. */
2052 ip->curx--;
2053 }
2054 #else
2055 if (ip->curx < ip->cols) {
2056 ip->curx++;
2057 (*sp->ite_cursor)(ip, MOVE_CURSOR);
2058 }
2059 #endif
2060 }
2061
2062 /*
2063 * Console functions
2064 */
2065 #include "grfioctl.h"
2066 #include "grfvar.h"
2067
2068 #ifdef DEBUG
2069 /*
2070 * Minimum ITE number at which to start looking for a console.
2071 * Setting to 0 will do normal search, 1 will skip first ITE device,
2072 * NITE will skip ITEs and use serial port.
2073 */
2074 int whichconsole = 0;
2075 #endif
2076
2077 itecnprobe(cp)
2078 struct consdev *cp;
2079 {
2080 register struct ite_softc *ip;
2081 int i, maj, unit, pri;
2082
2083 /* locate the major number */
2084 for (maj = 0; maj < nchrdev; maj++)
2085 if (cdevsw[maj].d_open == iteopen)
2086 break;
2087
2088 /* urk! */
2089 grfconfig();
2090
2091 /* check all the individual displays and find the best */
2092 unit = -1;
2093 pri = CN_DEAD;
2094 for (i = 0; i < NITE; i++) {
2095 struct grf_softc *gp = &grf_softc[i];
2096
2097 ip = &ite_softc[i];
2098 if ((gp->g_flags & GF_ALIVE) == 0)
2099 continue;
2100 ip->flags = (ITE_ALIVE|ITE_CONSOLE);
2101
2102 /* XXX - we need to do something about mapping these */
2103 switch (gp->g_type) {
2104 case GT_CUSTOMCHIPS:
2105 ip->type = ITE_CUSTOMCHIPS;
2106 break;
2107
2108 case GT_TIGA_A2410:
2109 ip->type = ITE_TIGA_A2410;
2110 break;
2111
2112 case GT_RETINA:
2113 ip->type = ITE_RETINA;
2114 break;
2115 }
2116 #ifdef DEBUG
2117 if (i < whichconsole)
2118 continue;
2119 #endif
2120 if ((int)gp->g_type == GT_CUSTOMCHIPS) {
2121 pri = CN_INTERNAL;
2122 unit = i;
2123 } else /* if (unit < 0) */ {
2124 pri = CN_NORMAL;
2125 unit = i;
2126 }
2127
2128 }
2129
2130 /* initialize required fields */
2131 cp->cn_dev = makedev(maj, unit);
2132 #if 0
2133 cp->cn_tp = ite_tty[unit];
2134 #else
2135 delayed_con_tty = unit;
2136 #endif
2137 cp->cn_pri = pri;
2138 }
2139
2140 itecninit(cp)
2141 struct consdev *cp;
2142 {
2143 int unit;
2144 struct ite_softc *ip;
2145
2146 iteinit(cp->cn_dev);
2147 unit = UNIT(cp->cn_dev);
2148 ip = &ite_softc[unit];
2149
2150 #ifdef DO_WEIRD_ATTRIBUTES
2151 ip->attrbuf = console_attributes;
2152 #endif
2153 ip->flags |= (ITE_ACTIVE|ITE_ISCONS);
2154 /* if this is the console, NEVER close the device! */
2155 ip->open_cnt++;
2156 #if 0
2157 /* have to delay this too.. sigh.. */
2158 kbd_tty = ite_tty[unit];
2159 kbd_ip = ip;
2160 kbdenable();
2161 #endif
2162 }
2163
2164 /*ARGSUSED*/
2165 itecngetc(dev)
2166 dev_t dev;
2167 {
2168 register int c;
2169
2170 do
2171 {
2172 c = kbdgetcn ();
2173 c = itefilter (c, ITEFILT_CONSOLE);
2174 }
2175 while (c == -1);
2176
2177 return(c);
2178 }
2179
2180 itecnputc(dev, c)
2181 dev_t dev;
2182 int c;
2183 {
2184 static int paniced = 0;
2185 struct ite_softc *ip = &ite_softc[UNIT(dev)];
2186
2187 if (panicstr && !paniced &&
2188 (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
2189 (void) iteon(dev, 3);
2190 paniced = 1;
2191 }
2192 iteputchar(c, dev);
2193 }
2194 #endif
2195