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