ite.c revision 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 * from: @(#)ite.c 7.6 (Berkeley) 5/16/91
40 * $Id: ite.c,v 1.2 1993/08/01 19:23:09 mycroft Exp $
41 */
42
43 /*
44 * Bit-mapped display terminal emulator machine independent code.
45 * This is a very rudimentary. Much more can be abstracted out of
46 * the hardware dependent routines.
47 */
48 #include "ite.h"
49 #if NITE > 0
50
51 #include "grf.h"
52
53 #undef NITE
54 #define NITE NGRF
55
56 #include "param.h"
57 #include "conf.h"
58 #include "proc.h"
59 #include "ioctl.h"
60 #include "tty.h"
61 #include "systm.h"
62 #include "malloc.h"
63
64 #include "itevar.h"
65 #include "iteioctl.h"
66 #include "kbdmap.h"
67
68 #include "machine/cpu.h"
69
70 #ifdef __STDC__
71 /* automatically generated, as you might guess:-) */
72
73 struct consdev;
74 struct itesw;
75
76 extern int iteon (dev_t dev, int flag);
77 extern int iteinit (dev_t dev);
78 extern int iteoff (dev_t dev, int flag);
79 extern int iteopen (dev_t dev, int mode, int devtype, struct proc *p);
80 extern int iteclose (dev_t dev, int flag, int mode, struct proc *p);
81 extern int iteread (dev_t dev, struct uio *uio, int flag);
82 extern int itewrite (dev_t dev, struct uio *uio, int flag);
83 extern int iteioctl (dev_t dev, int cmd, caddr_t addr, int flag);
84 extern int itestart (register struct tty *tp);
85 extern int itefilter (register u_char c, enum caller caller);
86 extern int iteputchar (register int c, dev_t dev);
87 extern int itecheckwrap (register struct ite_softc *ip, register struct itesw *sp);
88 extern int itecnprobe (struct consdev *cp);
89 extern int itecninit (struct consdev *cp);
90 extern int itecngetc (dev_t dev);
91 extern int itecnputc (dev_t dev, int c);
92 static void repeat_handler (int a0, int a1);
93 static void ite_dnchar (struct ite_softc *ip, struct itesw *sp, int n);
94 static void ite_inchar (struct ite_softc *ip, struct itesw *sp, int n);
95 static void ite_clrtoeol (struct ite_softc *ip, struct itesw *sp, int y, int x);
96 static void ite_clrtobol (struct ite_softc *ip, struct itesw *sp, int y, int x);
97 static void ite_clrline (struct ite_softc *ip, struct itesw *sp, int y, int x);
98 static void ite_clrtoeos (struct ite_softc *ip, struct itesw *sp);
99 static void ite_clrtobos (struct ite_softc *ip, struct itesw *sp);
100 static void ite_clrscreen (struct ite_softc *ip, struct itesw *sp);
101 static void ite_dnline (struct ite_softc *ip, struct itesw *sp, int n);
102 static void ite_inline (struct ite_softc *ip, struct itesw *sp, int n);
103 static void ite_lf (struct ite_softc *ip, struct itesw *sp);
104 static void ite_crlf (struct ite_softc *ip, struct itesw *sp);
105 static void ite_cr (struct ite_softc *ip, struct itesw *sp);
106 static void ite_rlf (struct ite_softc *ip, struct itesw *sp);
107 static int atoi (const char *cp);
108 static char *index (const char *cp, char ch);
109 static int ite_argnum (struct ite_softc *ip);
110 static int ite_zargnum (struct ite_softc *ip);
111 static void ite_sendstr (struct ite_softc *ip, char *str);
112 static int strncmp (const char *a, const char *b, int l);
113 #endif
114
115
116 #define set_attr(ip, attr) ((ip)->attribute |= (attr))
117 #define clr_attr(ip, attr) ((ip)->attribute &= ~(attr))
118
119 extern int nodev();
120
121 int customc_scroll(), customc_init(), customc_deinit();
122 int customc_clear(), customc_putc(), customc_cursor();
123
124 int tiga_scroll(), tiga_init(), tiga_deinit();
125 int tiga_clear(), tiga_putc(), tiga_cursor();
126
127
128 struct itesw itesw[] =
129 {
130 customc_init, customc_deinit, customc_clear,
131 customc_putc, customc_cursor, customc_scroll,
132
133 tiga_init, tiga_deinit, tiga_clear,
134 tiga_putc, tiga_cursor, tiga_scroll,
135 };
136
137 /*
138 * # of chars are output in a single itestart() call.
139 * If this is too big, user processes will be blocked out for
140 * long periods of time while we are emptying the queue in itestart().
141 * If it is too small, console output will be very ragged.
142 */
143 int iteburst = 64;
144
145 int nite = NITE;
146 struct tty *kbd_tty = NULL;
147 struct tty ite_cons;
148 struct tty *ite_tty[NITE] = { &ite_cons };
149 struct ite_softc ite_softc[NITE];
150
151 int itestart();
152 extern int ttrstrt();
153 extern struct tty *constty;
154
155 /* These are (later..) settable via an ioctl */
156 int start_repeat_timo = 30; /* /100: initial timeout till pressed key repeats */
157 int next_repeat_timo = 5; /* /100: timeout when repeating for next char */
158
159 /*
160 * Primary attribute buffer to be used by the first bitmapped console
161 * found. Secondary displays alloc the attribute buffer as needed.
162 * Size is based on a 68x128 display, which is currently our largest.
163 */
164 u_char console_attributes[0x2200];
165
166 /*
167 * Perform functions necessary to setup device as a terminal emulator.
168 */
169 iteon(dev, flag)
170 dev_t dev;
171 {
172 int unit = UNIT(dev);
173 struct tty *tp = ite_tty[unit];
174 struct ite_softc *ip = &ite_softc[unit];
175
176 if (unit < 0 || unit >= NITE || (ip->flags&ITE_ALIVE) == 0)
177 return(ENXIO);
178 /* force ite active, overriding graphics mode */
179 if (flag & 1) {
180 ip->flags |= ITE_ACTIVE;
181 ip->flags &= ~(ITE_INGRF|ITE_INITED);
182 }
183 /* leave graphics mode */
184 if (flag & 2) {
185 ip->flags &= ~ITE_INGRF;
186 if ((ip->flags & ITE_ACTIVE) == 0)
187 return(0);
188 }
189 ip->flags |= ITE_ACTIVE;
190 if (ip->flags & ITE_INGRF)
191 return(0);
192 if (kbd_tty == NULL || kbd_tty == tp) {
193 kbd_tty = tp;
194 kbdenable();
195 }
196 iteinit(dev);
197 return(0);
198 }
199
200 /* used by the grf layer to reinitialize ite after changing fb parameters */
201 itereinit(dev)
202 dev_t dev;
203 {
204 int unit = UNIT(dev);
205 struct ite_softc *ip = &ite_softc[unit];
206
207 ip->flags &= ~ITE_INITED;
208 iteinit (dev);
209 }
210
211 iteinit(dev)
212 dev_t dev;
213 {
214 int unit = UNIT(dev);
215 struct ite_softc *ip = &ite_softc[unit];
216
217 if (ip->flags & ITE_INITED)
218 return;
219
220 ip->curx = 0;
221 ip->cury = 0;
222 ip->cursorx = 0;
223 ip->cursory = 0;
224 ip->save_curx = 0;
225 ip->save_cury = 0;
226 ip->ap = ip->argbuf;
227 ip->emul_level = EMUL_VT300_7;
228 ip->eightbit_C1 = 0;
229 ip->inside_margins = 0;
230 ip->linefeed_newline = 0;
231
232 (*itesw[ip->type].ite_init)(ip);
233 (*itesw[ip->type].ite_cursor)(ip, DRAW_CURSOR);
234
235 /* ip->rows initialized by ite_init above */
236 ip->top_margin = 0; ip->bottom_margin = ip->rows - 1;
237
238 ip->attribute = 0;
239 if (ip->attrbuf == NULL)
240 ip->attrbuf = (u_char *)
241 malloc(ip->rows * ip->cols, M_DEVBUF, M_WAITOK);
242 bzero(ip->attrbuf, (ip->rows * ip->cols));
243
244 ip->imode = 0;
245 ip->flags |= ITE_INITED;
246 }
247
248 /*
249 * "Shut down" device as terminal emulator.
250 * Note that we do not deinit the console device unless forced.
251 * Deinit'ing the console every time leads to a very active
252 * screen when processing /etc/rc.
253 */
254 iteoff(dev, flag)
255 dev_t dev;
256 {
257 register struct ite_softc *ip = &ite_softc[UNIT(dev)];
258
259 if (flag & 2)
260 ip->flags |= ITE_INGRF;
261 if ((ip->flags & ITE_ACTIVE) == 0)
262 return;
263 if ((flag & 1) ||
264 (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED)
265 (*itesw[ip->type].ite_deinit)(ip);
266 if ((flag & 2) == 0)
267 ip->flags &= ~ITE_ACTIVE;
268 }
269
270 /* ARGSUSED */
271 #ifdef __STDC__
272 iteopen(dev_t dev, int mode, int devtype, struct proc *p)
273 #else
274 iteopen(dev, mode, devtype, p)
275 dev_t dev;
276 int mode, devtype;
277 struct proc *p;
278 #endif
279 {
280 int unit = UNIT(dev);
281 register struct tty *tp;
282 register struct ite_softc *ip = &ite_softc[unit];
283 register int error;
284 int first = 0;
285
286 if(!ite_tty[unit]) {
287 MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK);
288 bzero(tp, sizeof(struct tty));
289 ite_tty[unit] = tp;
290 } else
291 tp = ite_tty[unit];
292
293 if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE)
294 && p->p_ucred->cr_uid != 0)
295 return (EBUSY);
296 if ((ip->flags & ITE_ACTIVE) == 0) {
297 error = iteon(dev, 0);
298 if (error)
299 return (error);
300 first = 1;
301 }
302 tp->t_oproc = itestart;
303 tp->t_param = NULL;
304 tp->t_dev = dev;
305 if ((tp->t_state&TS_ISOPEN) == 0) {
306 ttychars(tp);
307 tp->t_iflag = TTYDEF_IFLAG;
308 tp->t_oflag = TTYDEF_OFLAG;
309 tp->t_cflag = CS8|CREAD;
310 tp->t_lflag = TTYDEF_LFLAG;
311 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
312 /* don't set TS_ISOPEN here, or the tty queues won't
313 be initialized in ttyopen()! */
314 tp->t_state = TS_CARR_ON;
315 ttsetwater(tp);
316 }
317 error = (*linesw[tp->t_line].l_open)(dev, tp);
318 if (error == 0) {
319 tp->t_winsize.ws_row = ip->rows;
320 tp->t_winsize.ws_col = ip->cols;
321 } else if (first)
322 iteoff(dev, 0);
323 return (error);
324 }
325
326 /*ARGSUSED*/
327 iteclose(dev, flag, mode, p)
328 dev_t dev;
329 int flag, mode;
330 struct proc *p;
331 {
332 register struct tty *tp = ite_tty[UNIT(dev)];
333
334 (*linesw[tp->t_line].l_close)(tp, flag);
335 ttyclose(tp);
336 iteoff(dev, 0);
337 if (tp != &ite_cons)
338 {
339 FREE(tp, M_TTYS);
340 ite_tty[UNIT(dev)] = (struct tty *)NULL;
341 }
342 return(0);
343 }
344
345 iteread(dev, uio, flag)
346 dev_t dev;
347 struct uio *uio;
348 {
349 register struct tty *tp = ite_tty[UNIT(dev)];
350 int rc;
351
352 rc = ((*linesw[tp->t_line].l_read)(tp, uio, flag));
353 return rc;
354 }
355
356 itewrite(dev, uio, flag)
357 dev_t dev;
358 struct uio *uio;
359 {
360 int unit = UNIT(dev);
361 register struct tty *tp = ite_tty[unit];
362
363 if ((ite_softc[unit].flags & ITE_ISCONS) && constty &&
364 (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
365 tp = constty;
366 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
367 }
368
369 iteioctl(dev, cmd, addr, flag)
370 dev_t dev;
371 caddr_t addr;
372 {
373 register struct tty *tp = ite_tty[UNIT(dev)];
374 int error;
375
376 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag);
377 if (error >= 0)
378 return (error);
379 error = ttioctl(tp, cmd, addr, flag);
380 if (error >= 0)
381 return (error);
382 return (ENOTTY);
383 }
384
385 itestart(tp)
386 register struct tty *tp;
387 {
388 register int cc, s;
389 int hiwat = 0;
390
391 s = spltty();
392 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
393 splx(s);
394 return;
395 }
396 tp->t_state |= TS_BUSY;
397 cc = RB_LEN (&tp->t_out);
398 if (cc <= tp->t_lowat) {
399 if (tp->t_state & TS_ASLEEP) {
400 tp->t_state &= ~TS_ASLEEP;
401 wakeup(&tp->t_out);
402 }
403 selwakeup(&tp->t_wsel);
404 }
405 /*
406 * Limit the amount of output we do in one burst
407 * to prevent hogging the CPU.
408 */
409 if (cc > iteburst) {
410 hiwat++;
411 cc = iteburst;
412 }
413 while (--cc >= 0) {
414 register int c;
415
416 c = rbgetc(&tp->t_out);
417 /*
418 * iteputchar() may take a long time and we don't want to
419 * block all interrupts for long periods of time. Since
420 * there is no need to stay at high priority while outputing
421 * the character (since we don't have to worry about
422 * interrupts), we don't. We just need to make sure that
423 * we don't reenter iteputchar, which is guarenteed by the
424 * earlier setting of TS_BUSY.
425 */
426 splx(s);
427 iteputchar(c, tp->t_dev);
428 spltty();
429 }
430 if (hiwat) {
431 tp->t_state |= TS_TIMEOUT;
432 timeout(ttrstrt, tp, 1);
433 }
434 tp->t_state &= ~TS_BUSY;
435 splx(s);
436 }
437
438 /* these are used to implement repeating keys.. */
439 static u_char last_char = 0;
440 static u_char tout_pending = 0;
441
442 static void
443 repeat_handler (a0, a1)
444 int a0, a1;
445 {
446 tout_pending = 0;
447 /* leave it up to itefilter() to possible install a new callout entry
448 to reinvoke repeat_handler() */
449 itefilter (last_char, ITEFILT_REPEATER);
450 }
451
452
453 int
454 itefilter(c, caller)
455 register u_char c;
456 enum caller caller;
457 {
458 static u_char mod = 0;
459 static u_char last_dead = 0;
460 register char code, *str;
461 u_char up, mask, i;
462 struct key key;
463
464 if (caller != ITEFILT_CONSOLE && kbd_tty == NULL)
465 return;
466
467 up = c & 0x80 ? 1 : 0;
468 c &= 0x7f;
469 code = 0;
470
471 mask = 0;
472 if (c >= KBD_LEFT_SHIFT)
473 {
474 switch (c)
475 {
476 case KBD_LEFT_SHIFT:
477 mask = KBD_MOD_LSHIFT;
478 break;
479
480 case KBD_RIGHT_SHIFT:
481 mask = KBD_MOD_RSHIFT;
482 break;
483
484 case KBD_LEFT_ALT:
485 mask = KBD_MOD_LALT;
486 break;
487
488 case KBD_RIGHT_ALT:
489 mask = KBD_MOD_RALT;
490 break;
491
492 case KBD_LEFT_META:
493 mask = KBD_MOD_LMETA;
494 break;
495
496 case KBD_RIGHT_META:
497 mask = KBD_MOD_RMETA;
498 break;
499
500 case KBD_CAPS_LOCK:
501 /* capslock already behaves `right', don't need to keep track of the
502 state in here. */
503 mask = KBD_MOD_CAPS;
504 break;
505
506 case KBD_CTRL:
507 mask = KBD_MOD_CTRL;
508 break;
509 }
510
511 if (mask)
512 {
513 if (up)
514 mod &= ~mask;
515 else
516 mod |= mask;
517 }
518
519 /* these keys should not repeat, so it's the Right Thing dealing with
520 repeaters only after this block. */
521
522 /* return even if it wasn't a modifier key, the other codes up here
523 are either special (like reset warning), or not yet defined */
524 return -1;
525 }
526
527 /* no matter which character we're repeating, stop it if we get a key-up
528 event. I think this is the same thing amigados does. */
529 if (up)
530 {
531 if (tout_pending)
532 {
533 untimeout (repeat_handler, 0);
534 tout_pending = 0;
535 }
536 return -1;
537 }
538
539
540 switch (mod & (KBD_MOD_ALT | KBD_MOD_SHIFT))
541 {
542 case 0:
543 key = kbdmap.keys[c];
544 if (!(mod & KBD_MOD_CAPS) || !(key.mode & KBD_MODE_CAPS))
545 break;
546 /* FALL INTO */
547
548 case KBD_MOD_LSHIFT:
549 case KBD_MOD_RSHIFT:
550 case KBD_MOD_SHIFT:
551 key = kbdmap.shift_keys[c];
552 break;
553
554 case KBD_MOD_LALT:
555 case KBD_MOD_RALT:
556 case KBD_MOD_ALT:
557 key = kbdmap.alt_keys[c];
558 if (!(mod & KBD_MOD_CAPS) || !(key.mode & KBD_MODE_CAPS))
559 break;
560 /* FALL INTO */
561
562 case KBD_MOD_LALT|KBD_MOD_LSHIFT:
563 case KBD_MOD_LALT|KBD_MOD_RSHIFT:
564 case KBD_MOD_LALT|KBD_MOD_SHIFT:
565 case KBD_MOD_RALT|KBD_MOD_RSHIFT:
566 case KBD_MOD_RALT|KBD_MOD_SHIFT:
567 case KBD_MOD_ALT|KBD_MOD_RSHIFT:
568 key = kbdmap.alt_shift_keys[c];
569 break;
570 }
571
572 code = key.code;
573
574 /* arrange to repeat the keystroke. By doing this at the level of scan-codes,
575 we can have function keys, and keys that send strings, repeat too. This
576 also entitles an additional overhead, since we have to do the conversion
577 each time, but I guess that's ok. */
578 if (!tout_pending && caller == ITEFILT_TTY)
579 {
580 tout_pending = 1;
581 last_char = c;
582 timeout (repeat_handler, 0, start_repeat_timo);
583 }
584 else if (!tout_pending && caller == ITEFILT_REPEATER)
585 {
586 tout_pending = 1;
587 last_char = c;
588 timeout (repeat_handler, 0, next_repeat_timo);
589 }
590
591 /* handle dead keys */
592 if (key.mode & KBD_MODE_DEAD)
593 {
594 /* if entered twice, send accent itself */
595 if (last_dead == key.mode & KBD_MODE_ACCMASK)
596 last_dead = 0;
597 else
598 {
599 last_dead = key.mode & KBD_MODE_ACCMASK;
600 return -1;
601 }
602 }
603 if (last_dead)
604 {
605 /* can't apply dead flag to string-keys */
606 if (! (key.mode & KBD_MODE_STRING) && code >= '@' && code < 0x7f)
607 code = acctable[KBD_MODE_ACCENT (last_dead)][code - '@'];
608
609 last_dead = 0;
610 }
611
612 /* if not string, apply META and CTRL modifiers */
613 if (! (key.mode & KBD_MODE_STRING))
614 {
615 if (mod & KBD_MOD_CTRL)
616 code &= 0x1f;
617
618 if (mod & KBD_MOD_META)
619 code |= 0x80;
620 }
621 else
622 {
623 /* strings are only supported in normal tty mode, not in console mode */
624 if (caller != ITEFILT_CONSOLE)
625 {
626 str = kbdmap.strings + code;
627 /* using a length-byte instead of 0-termination allows to embed \0 into
628 strings, although this is not used in the default keymap */
629 for (i = *str++; i; i--)
630 (*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
631 }
632 return -1;
633 }
634
635 if (caller == ITEFILT_CONSOLE)
636 return code;
637 else
638 (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
639
640 return -1;
641 }
642
643
644 /* helper functions, makes the code below more readable */
645 static void inline
646 ite_dnchar(ip, sp, n)
647 struct ite_softc *ip;
648 struct itesw *sp;
649 int n;
650 {
651 (*sp->ite_scroll)(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
652 attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
653 1, ip->cols - ip->curx - n);
654 attrclr(ip, ip->cury, ip->cols - n, 1, n);
655 while (n--)
656 (*sp->ite_putc)(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
657 (*sp->ite_cursor)(ip, DRAW_CURSOR);
658 }
659
660 static void inline
661 ite_inchar(ip, sp, n)
662 struct ite_softc *ip;
663 struct itesw *sp;
664 int n;
665 {
666 (*sp->ite_scroll)(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
667 attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
668 1, ip->cols - ip->curx - n);
669 attrclr(ip, ip->cury, ip->curx, 1, n);
670 while (n--)
671 (*sp->ite_putc)(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
672 (*sp->ite_cursor)(ip, DRAW_CURSOR);
673 }
674
675 static void inline
676 ite_clrtoeol(ip, sp, y, x)
677 struct ite_softc *ip;
678 struct itesw *sp;
679 int y, x;
680 {
681 (*sp->ite_clear)(ip, y, x, 1, ip->cols - x);
682 attrclr(ip, y, x, 1, ip->cols - x);
683 (*sp->ite_cursor)(ip, DRAW_CURSOR);
684 }
685
686 static void inline
687 ite_clrtobol(ip, sp, y, x)
688 struct ite_softc *ip;
689 struct itesw *sp;
690 int y, x;
691 {
692 (*sp->ite_clear)(ip, y, 0, 1, x);
693 attrclr(ip, y, 0, 1, x);
694 (*sp->ite_cursor)(ip, DRAW_CURSOR);
695 }
696
697 static void inline
698 ite_clrline(ip, sp, y, x)
699 struct ite_softc *ip;
700 struct itesw *sp;
701 int y, x;
702 {
703 (*sp->ite_clear)(ip, y, 0, 1, ip->cols);
704 attrclr(ip, y, 0, 1, ip->cols);
705 (*sp->ite_cursor)(ip, DRAW_CURSOR);
706 }
707
708
709
710 static void inline
711 ite_clrtoeos(ip, sp)
712 struct ite_softc *ip;
713 struct itesw *sp;
714 {
715 (*sp->ite_clear)(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
716 attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
717 (*sp->ite_cursor)(ip, DRAW_CURSOR);
718 }
719
720 static void inline
721 ite_clrtobos(ip, sp)
722 struct ite_softc *ip;
723 struct itesw *sp;
724 {
725 (*sp->ite_clear)(ip, 0, 0, ip->cury, ip->cols);
726 attrclr(ip, 0, 0, ip->cury, ip->cols);
727 (*sp->ite_cursor)(ip, DRAW_CURSOR);
728 }
729
730 static void inline
731 ite_clrscreen(ip, sp)
732 struct ite_softc *ip;
733 struct itesw *sp;
734 {
735 (*sp->ite_clear)(ip, 0, 0, ip->rows, ip->cols);
736 attrclr(ip, 0, 0, ip->rows, ip->cols);
737 (*sp->ite_cursor)(ip, DRAW_CURSOR);
738 }
739
740
741
742 static void inline
743 ite_dnline(ip, sp, n)
744 struct ite_softc *ip;
745 struct itesw *sp;
746 int n;
747 {
748 (*sp->ite_scroll)(ip, ip->cury + n, 0, n, SCROLL_UP);
749 attrmov(ip, ip->cury + n, 0, ip->cury, 0,
750 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
751 (*sp->ite_clear)(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
752 attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
753 (*sp->ite_cursor)(ip, DRAW_CURSOR);
754 }
755
756 static void inline
757 ite_inline(ip, sp, n)
758 struct ite_softc *ip;
759 struct itesw *sp;
760 int n;
761 {
762 (*sp->ite_scroll)(ip, ip->cury, 0, n, SCROLL_DOWN);
763 attrmov(ip, ip->cury, 0, ip->cury + n, 0,
764 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
765 (*sp->ite_clear)(ip, ip->cury, 0, n, ip->cols);
766 attrclr(ip, ip->cury, 0, n, ip->cols);
767 (*sp->ite_cursor)(ip, DRAW_CURSOR);
768 }
769
770 static void inline
771 ite_lf (ip, sp)
772 struct ite_softc *ip;
773 struct itesw *sp;
774 {
775 #if 0
776 if (ip->inside_margins)
777 {
778 #endif
779 if (++ip->cury >= ip->bottom_margin + 1)
780 {
781 ip->cury = ip->bottom_margin;
782 (*sp->ite_scroll)(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
783 ite_clrtoeol(ip, sp, ip->cury, 0);
784 }
785 else
786 (*sp->ite_cursor)(ip, MOVE_CURSOR);
787 #if 0
788 }
789 else
790 {
791 if (++ip->cury == ip->rows)
792 {
793 --ip->cury;
794 (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP);
795 ite_clrtoeol(ip, sp, ip->cury, 0);
796 }
797 else
798 (*sp->ite_cursor)(ip, MOVE_CURSOR);
799 }
800 #endif
801 clr_attr(ip, ATTR_INV);
802 }
803
804 static void inline
805 ite_crlf (ip, sp)
806 struct ite_softc *ip;
807 struct itesw *sp;
808 {
809 ip->curx = 0;
810 ite_lf (ip, sp);
811 }
812
813 static void inline
814 ite_cr (ip, sp)
815 struct ite_softc *ip;
816 struct itesw *sp;
817 {
818 if (ip->curx)
819 {
820 ip->curx = 0;
821 (*sp->ite_cursor)(ip, MOVE_CURSOR);
822 }
823 }
824
825 static void inline
826 ite_rlf (ip, sp)
827 struct ite_softc *ip;
828 struct itesw *sp;
829 {
830 if (ip->cury > 0)
831 {
832 ip->cury--;
833 (*sp->ite_cursor)(ip, MOVE_CURSOR);
834 }
835 else
836 ite_inline (ip, sp, 1);
837 clr_attr(ip, ATTR_INV);
838 }
839
840 static int inline
841 atoi (cp)
842 const char *cp;
843 {
844 int n;
845
846 for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
847 n = n * 10 + *cp - '0';
848
849 return n;
850 }
851
852 static char *
853 index (cp, ch)
854 const char *cp;
855 char ch;
856 {
857 while (*cp && *cp != ch) cp++;
858 return *cp ? cp : 0;
859 }
860
861
862
863 static int inline
864 ite_argnum (ip)
865 struct ite_softc *ip;
866 {
867 char ch;
868 int n;
869
870 /* convert argument string into number */
871 if (ip->ap == ip->argbuf)
872 return 1;
873 ch = *ip->ap;
874 *ip->ap = 0;
875 n = atoi (ip->argbuf);
876 *ip->ap = ch;
877
878 return n;
879 }
880
881 static int inline
882 ite_zargnum (ip)
883 struct ite_softc *ip;
884 {
885 char ch, *cp;
886 int n;
887
888 /* convert argument string into number */
889 if (ip->ap == ip->argbuf)
890 return 0;
891 ch = *ip->ap;
892 *ip->ap = 0;
893 n = atoi (ip->argbuf);
894 *ip->ap = ch;
895
896 return n;
897 }
898
899 static void inline
900 ite_sendstr (ip, str)
901 struct ite_softc *ip;
902 char *str;
903 {
904 while (*str)
905 (*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
906 }
907
908 static int inline
909 strncmp (a, b, l)
910 const char *a, *b;
911 int l;
912 {
913 for (;l--; a++, b++)
914 if (*a != *b)
915 return *a - *b;
916 return 0;
917 }
918
919 static void inline
920 ite_reinit(ip)
921 struct ite_softc *ip;
922 {
923 ip->curx = 0;
924 ip->cury = 0;
925 ip->cursorx = 0;
926 ip->cursory = 0;
927 ip->save_curx = 0;
928 ip->save_cury = 0;
929 ip->ap = ip->argbuf;
930 ip->emul_level = EMUL_VT300_7;
931 ip->eightbit_C1 = 0;
932 ip->top_margin = 0; ip->bottom_margin = 23;
933 ip->inside_margins = 0;
934 ip->linefeed_newline = 0;
935
936 (*itesw[ip->type].ite_cursor)(ip, DRAW_CURSOR);
937
938 ip->attribute = 0;
939 bzero(ip->attrbuf, (ip->rows * ip->cols));
940
941 ip->imode = 0;
942 }
943
944
945
946 iteputchar(c, dev)
947 register int c;
948 dev_t dev;
949 {
950 int unit = UNIT(dev);
951 register struct ite_softc *ip = &ite_softc[unit];
952 register struct itesw *sp = &itesw[ip->type];
953 register int n;
954 int x, y;
955 char *cp;
956
957 if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
958 return;
959
960 if ((ite_tty[unit]->t_cflag & CSIZE) == CS7
961 || (ite_tty[unit]->t_cflag & PARENB))
962 c &= 0x7f;
963
964 if (ip->escape)
965 {
966 doesc:
967 switch (ip->escape)
968 {
969 case ESC:
970 switch (c)
971 {
972 /* first 7bit equivalents for the 8bit control characters */
973
974 case 'D':
975 c = IND;
976 ip->escape = 0;
977 break;
978
979 case 'E':
980 c = NEL;
981 ip->escape = 0;
982 break;
983
984 case 'H':
985 c = HTS;
986 ip->escape = 0;
987 break;
988
989 case 'M':
990 c = RI;
991 ip->escape = 0;
992 break;
993
994 case 'N':
995 c = SS2;
996 ip->escape = 0;
997 break;
998
999 case 'O':
1000 c = SS3;
1001 ip->escape = 0;
1002 break;
1003
1004 case 'P':
1005 c = DCS;
1006 ip->escape = 0;
1007 break;
1008
1009 case '[':
1010 c = CSI;
1011 ip->escape = 0;
1012 break;
1013
1014 case '\\':
1015 c = ST;
1016 ip->escape = 0;
1017 break;
1018
1019 case ']':
1020 c = OSC;
1021 ip->escape = 0;
1022 break;
1023
1024 case '^':
1025 c = PM;
1026 ip->escape = 0;
1027 break;
1028
1029 case '_':
1030 c = APC;
1031 ip->escape = 0;
1032 break;
1033
1034
1035 /* introduces 7/8bit control */
1036 case ' ':
1037 /* can be followed by either F or G */
1038 ip->escape = ' ';
1039 break;
1040
1041
1042 /* a lot of character set selections, not yet used...
1043 94-character sets: */
1044 case '(': /* G0 */
1045 case ')': /* G1 */
1046 case '*': /* G2 */
1047 case '+': /* G3 */
1048 case 'B': /* ASCII */
1049 case 'A': /* ISO latin 1 */
1050 case '<': /* user preferred suplemental */
1051 case '0': /* dec special graphics */
1052
1053 /* 96-character sets: */
1054 case '-': /* G1 */
1055 case '.': /* G2 */
1056 case '/': /* G3 */
1057
1058 /* national character sets: */
1059 case '4': /* dutch */
1060 case '5':
1061 case 'C': /* finnish */
1062 case 'R': /* french */
1063 case 'Q': /* french canadian */
1064 case 'K': /* german */
1065 case 'Y': /* italian */
1066 case '6': /* norwegian/danish */
1067 case 'Z': /* spanish */
1068 case '=': /* swiss */
1069 /* note: %5 and %6 are not supported (two chars..) */
1070
1071 ip->escape = 0;
1072 /* just ignore for now */
1073 return -1;
1074
1075
1076 /* locking shift modes (as you might guess, not yet supported..) */
1077 case '`':
1078 ip->GR = ip->G1;
1079 ip->escape = 0;
1080 return -1;
1081
1082 case 'n':
1083 ip->GL = ip->G2;
1084 ip->escape = 0;
1085 return -1;
1086
1087 case '}':
1088 ip->GR = ip->G2;
1089 ip->escape = 0;
1090 return -1;
1091
1092 case 'o':
1093 ip->GL = ip->G3;
1094 ip->escape = 0;
1095 return -1;
1096
1097 case '|':
1098 ip->GR = ip->G3;
1099 ip->escape = 0;
1100 return -1;
1101
1102
1103 /* font width/height control */
1104 case '#':
1105 ip->escape = '#';
1106 return -1;
1107
1108
1109 /* hard terminal reset .. */
1110 case 'c':
1111 ite_reinit (ip);
1112 ip->escape = 0;
1113 return -1;
1114
1115
1116 case '7':
1117 ip->save_curx = ip->curx;
1118 ip->save_cury = ip->cury;
1119 ip->escape = 0;
1120 return -1;
1121
1122 case '8':
1123 ip->curx = ip->save_curx;
1124 ip->cury = ip->save_cury;
1125 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1126 ip->escape = 0;
1127 return -1;
1128
1129
1130 /* default catch all for not recognized ESC sequences */
1131 default:
1132 ip->escape = 0;
1133 return -1;
1134 }
1135 break;
1136
1137
1138 case ' ':
1139 switch (c)
1140 {
1141 case 'F':
1142 ip->eightbit_C1 = 0;
1143 ip->escape = 0;
1144 return -1;
1145
1146 case 'G':
1147 ip->eightbit_C1 = 1;
1148 ip->escape = 0;
1149 return -1;
1150
1151 default:
1152 /* not supported */
1153 ip->escape = 0;
1154 return -1;
1155 }
1156 break;
1157
1158
1159 case '#':
1160 switch (c)
1161 {
1162 case '5':
1163 /* single height, single width */
1164 ip->escape = 0;
1165 return -1;
1166
1167 case '6':
1168 /* double width, single height */
1169 ip->escape = 0;
1170 return -1;
1171
1172 case '3':
1173 /* top half */
1174 ip->escape = 0;
1175 return -1;
1176
1177 case '4':
1178 /* bottom half */
1179 ip->escape = 0;
1180 return -1;
1181
1182 case '8':
1183 /* screen alignment pattern... */
1184 ip->escape = 0;
1185 return -1;
1186
1187 default:
1188 ip->escape = 0;
1189 return -1;
1190 }
1191 break;
1192
1193
1194
1195 #if 0
1196 case DCS:
1197 case PM:
1198 case APC:
1199 case OSC:
1200 switch (c)
1201 {
1202 case ST:
1203 ip->escape = 0;
1204 return -1;
1205
1206 default:
1207 return -1;
1208 }
1209 break;
1210 #endif
1211
1212
1213 case CSI:
1214 /* the biggie... */
1215 switch (c)
1216 {
1217 case '0': case '1': case '2': case '3': case '4':
1218 case '5': case '6': case '7': case '8': case '9':
1219 case ';': case '\"': case '$': case '>':
1220 if (ip->ap < ip->argbuf + ARGBUF_SIZE)
1221 *ip->ap++ = c;
1222 return -1;
1223
1224 case CAN:
1225 ip->escape = 0;
1226 return -1;
1227
1228
1229 case 'p':
1230 *ip->ap = 0;
1231 if (! strncmp (ip->argbuf, "61\"", 3))
1232 ip->emul_level = EMUL_VT100;
1233 else if (! strncmp (ip->argbuf, "63;1\"", 5)
1234 || ! strncmp (ip->argbuf, "62;1\"", 5))
1235 ip->emul_level = EMUL_VT300_7;
1236 else
1237 ip->emul_level = EMUL_VT300_8;
1238 ip->escape = 0;
1239 return -1;
1240
1241
1242 case '?':
1243 *ip->ap = 0;
1244 ip->escape = '?';
1245 ip->ap = ip->argbuf;
1246 return -1;
1247
1248
1249 case 'c':
1250 *ip->ap = 0;
1251 if (ip->ap == ip->argbuf
1252 || (ip->ap == &ip->argbuf[1] && ip->argbuf[0] == '0'))
1253 {
1254 /* primary DA request, send primary DA response */
1255 if (ip->emul_level == EMUL_VT100)
1256 ite_sendstr (ip, "\033[61;0c");
1257 else
1258 ite_sendstr (ip, "\033[63;0c");
1259 }
1260
1261 else if ((ip->ap == &ip->argbuf[1] && ip->argbuf[0] == '>')
1262 || (ip->ap == &ip->argbuf[2]
1263 && !strncmp (ip->argbuf, ">0", 2)))
1264 {
1265 ite_sendstr (ip, "\033[>24;0;0;0c");
1266 }
1267
1268 ip->escape = 0;
1269 return -1;
1270
1271
1272 case 'n':
1273 *ip->ap = 0;
1274 if (ip->ap == &ip->argbuf[1])
1275 {
1276 if (ip->argbuf[0] == '5')
1277 ite_sendstr (ip, "\033[0n"); /* no malfunction */
1278
1279 else if (ip->argbuf[0] == '6')
1280 {
1281 sprintf (ip->argbuf, "\033[%d;%dR",
1282 ip->cury + 1, ip->curx + 1);
1283 /* cursor position report */
1284 ite_sendstr (ip, ip->argbuf);
1285 }
1286
1287 }
1288 ip->escape = 0;
1289 return -1;
1290
1291
1292 case 'h': case 'l':
1293 *ip->ap = 0;
1294 if (ip->ap == &ip->argbuf[1] && ip->argbuf[0] == '4')
1295 ip->imode = (c == 'h'); /* insert/replace mode */
1296
1297 else if (ip->ap == &ip->argbuf[2]
1298 && !strncmp (ip->argbuf, "20", 2))
1299 ip->linefeed_newline = (c == 'h');
1300
1301
1302 /* various not supported commands */
1303 ip->escape = 0;
1304 return -1;
1305
1306
1307 case 'M':
1308 *ip->ap = 0;
1309 ite_dnline (ip, sp, ite_argnum (ip));
1310 ip->escape = 0;
1311 return -1;
1312
1313
1314 case 'L':
1315 *ip->ap = 0;
1316 ite_inline (ip, sp, ite_argnum (ip));
1317 ip->escape = 0;
1318 return -1;
1319
1320
1321 case 'P':
1322 *ip->ap = 0;
1323 ite_dnchar (ip, sp, ite_argnum (ip));
1324 ip->escape = 0;
1325 return -1;
1326
1327
1328 case '@':
1329 *ip->ap = 0;
1330 ite_inchar (ip, sp, ite_argnum (ip));
1331 ip->escape = 0;
1332 return -1;
1333
1334
1335 case 'H':
1336 case 'f':
1337 *ip->ap = 0;
1338 y = atoi (ip->argbuf);
1339 x = 0;
1340 cp = index (ip->argbuf, ';');
1341 if (cp)
1342 x = atoi (cp + 1);
1343 if (x) x--;
1344 if (y) y--;
1345 if (ip->inside_margins)
1346 {
1347 y += ip->top_margin;
1348 ip->cury = MIN(y, ip->bottom_margin);
1349 }
1350 else
1351 {
1352 ip->cury = MIN(y, ip->rows - 1);
1353 }
1354 ip->curx = MIN(x, ip->cols - 1);
1355 ip->escape = 0;
1356 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1357 clr_attr (ip, ATTR_INV);
1358 return -1;
1359
1360 case 'A':
1361 *ip->ap = 0;
1362 n = ip->cury - ite_argnum (ip);
1363 ip->cury = n >= 0 ? n : 0;
1364 ip->escape = 0;
1365 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1366 clr_attr (ip, ATTR_INV);
1367 return -1;
1368
1369 case 'B':
1370 *ip->ap = 0;
1371 n = ite_argnum (ip) + ip->cury;
1372 ip->cury = MIN(n, ip->rows - 1);
1373 ip->escape = 0;
1374 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1375 clr_attr (ip, ATTR_INV);
1376 return -1;
1377
1378 case 'C':
1379 *ip->ap = 0;
1380 n = ite_argnum (ip) + ip->curx;
1381 ip->curx = MIN(n, ip->cols - 1);
1382 ip->escape = 0;
1383 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1384 clr_attr (ip, ATTR_INV);
1385 return -1;
1386
1387 case 'D':
1388 *ip->ap = 0;
1389 n = ip->curx - ite_argnum (ip);
1390 ip->curx = n >= 0 ? n : 0;
1391 ip->escape = 0;
1392 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1393 clr_attr (ip, ATTR_INV);
1394 return -1;
1395
1396
1397
1398
1399 case 'J':
1400 *ip->ap = 0;
1401 n = ite_zargnum (ip);
1402 if (n == 0)
1403 ite_clrtoeos(ip, sp);
1404 else if (n == 1)
1405 ite_clrtobos(ip, sp);
1406 else if (n == 2)
1407 ite_clrscreen(ip, sp);
1408 ip->escape = 0;
1409 return -1;
1410
1411
1412 case 'K':
1413 *ip->ap = 0;
1414 n = ite_zargnum (ip);
1415 if (n == 0)
1416 ite_clrtoeol(ip, sp, ip->cury, ip->curx);
1417 else if (n == 1)
1418 ite_clrtobol(ip, sp, ip->cury, ip->curx);
1419 else if (n == 2)
1420 ite_clrline(ip, sp, ip->cury, ip->curx);
1421 ip->escape = 0;
1422 return -1;
1423
1424
1425 case 'X':
1426 *ip->ap = 0;
1427 for (n = ite_argnum (ip); n > 0; n--)
1428 {
1429 attrclr(ip, ip->cury, ip->curx + n - 1, 1, 1);
1430 (*sp->ite_putc)(ip, ' ', ip->cury, ip->curx + n - 1, ATTR_NOR);
1431 }
1432 ip->escape = 0;
1433 return -1;
1434
1435
1436 case '}': case '`':
1437 /* status line control */
1438 ip->escape = 0;
1439 return -1;
1440
1441
1442 case 'r':
1443 *ip->ap = 0;
1444 x = atoi (ip->argbuf);
1445 y = 0;
1446 cp = index (ip->argbuf, ';');
1447 if (cp)
1448 y = atoi (cp + 1);
1449 if (x) x--;
1450 if (y) y--;
1451 ip->top_margin = MIN(x, ip->rows - 1);
1452 ip->bottom_margin = MIN(y, ip->rows - 1);
1453 ip->escape = 0;
1454 return -1;
1455
1456
1457 case 'm':
1458 /* big attribute setter/resetter */
1459 {
1460 char *cp;
1461 *ip->ap = 0;
1462 for (cp = ip->argbuf; cp < ip->ap; )
1463 {
1464 switch (*cp)
1465 {
1466 case '0':
1467 clr_attr (ip, ATTR_ALL);
1468 cp++;
1469 break;
1470
1471 case '1':
1472 set_attr (ip, ATTR_BOLD);
1473 cp++;
1474 break;
1475
1476 case '2':
1477 switch (cp[1])
1478 {
1479 case '2':
1480 clr_attr (ip, ATTR_BOLD);
1481 cp += 2;
1482 break;
1483
1484 case '4':
1485 clr_attr (ip, ATTR_UL);
1486 cp += 2;
1487 break;
1488
1489 case '5':
1490 clr_attr (ip, ATTR_BLINK);
1491 cp += 2;
1492 break;
1493
1494 case '7':
1495 clr_attr (ip, ATTR_INV);
1496 cp += 2;
1497 break;
1498
1499 default:
1500 cp++;
1501 break;
1502 }
1503 break;
1504
1505 case '4':
1506 set_attr (ip, ATTR_UL);
1507 cp++;
1508 break;
1509
1510 case '5':
1511 set_attr (ip, ATTR_BLINK);
1512 cp++;
1513 break;
1514
1515 case '7':
1516 set_attr (ip, ATTR_INV);
1517 cp++;
1518 break;
1519
1520 default:
1521 cp++;
1522 break;
1523 }
1524 }
1525
1526 }
1527 ip->escape = 0;
1528 return -1;
1529
1530
1531 case 'u':
1532 /* DECRQTSR */
1533 ite_sendstr (ip, "\033P\033\\");
1534 ip->escape = 0;
1535 return -1;
1536
1537
1538
1539 default:
1540 ip->escape = 0;
1541 return -1;
1542 }
1543 break;
1544
1545
1546
1547 case '?': /* CSI ? */
1548 switch (c)
1549 {
1550 case '0': case '1': case '2': case '3': case '4':
1551 case '5': case '6': case '7': case '8': case '9':
1552 case ';': case '\"': case '$':
1553 if (ip->ap < ip->argbuf + ARGBUF_SIZE)
1554 *ip->ap++ = c;
1555 return -1;
1556
1557
1558 case CAN:
1559 ip->escape = 0;
1560 return -1;
1561
1562
1563 case 'n':
1564 *ip->ap = 0;
1565 if (ip->ap == &ip->argbuf[2])
1566 {
1567 if (! strncmp (ip->argbuf, "15", 2))
1568 /* printer status: no printer */
1569 ite_sendstr (ip, "\033[13n");
1570
1571 else if (! strncmp (ip->argbuf, "25", 2))
1572 /* udk status */
1573 ite_sendstr (ip, "\033[20n");
1574
1575 else if (! strncmp (ip->argbuf, "26", 2))
1576 /* keyboard dialect: US */
1577 ite_sendstr (ip, "\033[27;1n");
1578 }
1579 ip->escape = 0;
1580 return -1;
1581
1582
1583 case 'h': case 'l':
1584 *ip->ap = 0;
1585 if (ip->ap[0] == '6')
1586 ip->inside_margins = (c == 'h');
1587
1588 else if (! strncmp (ip->ap, "25", 2))
1589 (*itesw[ip->type].ite_cursor)(ip,
1590 (c == 'h') ? DRAW_CURSOR : ERASE_CURSOR);
1591
1592 /* others.. */
1593
1594 default:
1595 ip->escape = 0;
1596 return -1;
1597 }
1598 break;
1599
1600
1601 default:
1602 ip->escape = 0;
1603 return -1;
1604 }
1605 }
1606
1607
1608 switch (c) {
1609
1610 case VT: /* VT is treated like LF */
1611 case FF: /* so is FF */
1612 case LF:
1613 if (ip->linefeed_newline)
1614 ite_crlf (ip, sp);
1615 else
1616 ite_lf (ip, sp);
1617 break;
1618
1619 case CR:
1620 ite_cr (ip, sp);
1621 break;
1622
1623 case BS:
1624 if (--ip->curx < 0)
1625 ip->curx = 0;
1626 else
1627 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1628 break;
1629
1630 case HT:
1631 if (ip->curx < TABEND(unit)) {
1632 n = TABSIZE - (ip->curx & (TABSIZE - 1));
1633 ip->curx += n;
1634 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1635 } else
1636 itecheckwrap(ip, sp);
1637 break;
1638
1639 case BEL:
1640 if (ite_tty[unit] == kbd_tty)
1641 kbdbell();
1642 break;
1643
1644 case SO:
1645 ip->GL = ip->G1;
1646 break;
1647
1648 case SI:
1649 ip->GL = ip->G0;
1650 break;
1651
1652 case ENQ:
1653 /* send answer-back message !! */
1654 break;
1655
1656 case CAN:
1657 ip->escape = 0; /* cancel any escape sequence in progress */
1658 break;
1659
1660 case SUB:
1661 ip->escape = 0; /* dito, but see below */
1662 /* should also display a reverse question mark!! */
1663 break;
1664
1665 case ESC:
1666 ip->escape = ESC;
1667 break;
1668
1669
1670 /* now it gets weird.. 8bit control sequences.. */
1671 case IND: /* index: move cursor down, scroll */
1672 ite_lf (ip, sp);
1673 break;
1674
1675 case NEL: /* next line. next line, first pos. */
1676 ite_crlf (ip, sp);
1677 break;
1678
1679 case HTS: /* set horizontal tab */
1680 /* not yet supported */
1681 break;
1682
1683 case RI: /* reverse index */
1684 ite_rlf (ip, sp);
1685 break;
1686
1687 case SS2: /* go into G2 for one character */
1688 /* not yet supported */
1689 break;
1690
1691 case SS3: /* go into G3 for one character */
1692 break;
1693
1694 case DCS: /* device control string introducer */
1695 ip->escape = DCS;
1696 ip->ap = ip->argbuf;
1697 break;
1698
1699 case CSI: /* control sequence introducer */
1700 ip->escape = CSI;
1701 ip->ap = ip->argbuf;
1702 break;
1703
1704 case ST: /* string terminator */
1705 /* ignore, if not used as terminator */
1706 break;
1707
1708 case OSC: /* introduces OS command. Ignore everything upto ST */
1709 ip->escape = OSC;
1710 break;
1711
1712 case PM: /* privacy message, ignore everything upto ST */
1713 ip->escape = PM;
1714 break;
1715
1716 case APC: /* application program command, ignore everything upto ST */
1717 ip->escape = APC;
1718 break;
1719
1720 default:
1721 if (c < ' ' || c == DEL)
1722 break;
1723 if (ip->imode)
1724 ite_inchar(ip, sp, 1);
1725 if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
1726 attrset(ip, ATTR_INV);
1727 (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_INV);
1728 }
1729 else
1730 (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_NOR);
1731 (*sp->ite_cursor)(ip, DRAW_CURSOR);
1732 itecheckwrap(ip, sp);
1733 break;
1734 }
1735 }
1736
1737 itecheckwrap(ip, sp)
1738 register struct ite_softc *ip;
1739 register struct itesw *sp;
1740 {
1741 if (++ip->curx == ip->cols) {
1742 ip->curx = 0;
1743 clr_attr(ip, ATTR_INV);
1744 if (++ip->cury >= ip->bottom_margin + 1) {
1745 ip->cury = ip->bottom_margin;
1746 (*sp->ite_scroll)(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1747 ite_clrtoeol(ip, sp, ip->cury, 0);
1748 return;
1749 }
1750 }
1751 (*sp->ite_cursor)(ip, MOVE_CURSOR);
1752 }
1753
1754 /*
1755 * Console functions
1756 */
1757 #include "../amiga/cons.h"
1758 #include "grfioctl.h"
1759 #include "grfvar.h"
1760
1761 #ifdef DEBUG
1762 /*
1763 * Minimum ITE number at which to start looking for a console.
1764 * Setting to 0 will do normal search, 1 will skip first ITE device,
1765 * NITE will skip ITEs and use serial port.
1766 */
1767 int whichconsole = 0;
1768 #endif
1769
1770 itecnprobe(cp)
1771 struct consdev *cp;
1772 {
1773 register struct ite_softc *ip;
1774 int i, maj, unit, pri;
1775
1776 /* locate the major number */
1777 for (maj = 0; maj < nchrdev; maj++)
1778 if (cdevsw[maj].d_open == iteopen)
1779 break;
1780
1781 /* urk! */
1782 grfconfig();
1783
1784 /* check all the individual displays and find the best */
1785 unit = -1;
1786 pri = CN_DEAD;
1787 for (i = 0; i < NITE; i++) {
1788 struct grf_softc *gp = &grf_softc[i];
1789
1790 ip = &ite_softc[i];
1791 if ((gp->g_flags & GF_ALIVE) == 0)
1792 continue;
1793 ip->flags = (ITE_ALIVE|ITE_CONSOLE);
1794
1795 /* XXX - we need to do something about mapping these */
1796 switch (gp->g_type) {
1797 case GT_CUSTOMCHIPS:
1798 ip->type = ITE_CUSTOMCHIPS;
1799 break;
1800
1801 case GT_TIGA_A2410:
1802 ip->type = ITE_TIGA_A2410;
1803 break;
1804 }
1805 #ifdef DEBUG
1806 if (i < whichconsole)
1807 continue;
1808 #endif
1809 if ((int)gp->g_type == GT_CUSTOMCHIPS) {
1810 pri = CN_INTERNAL;
1811 unit = i;
1812 } else if (unit < 0) {
1813 pri = CN_NORMAL;
1814 unit = i;
1815 }
1816 }
1817
1818 /* initialize required fields */
1819 cp->cn_dev = makedev(maj, unit);
1820 cp->cn_tp = ite_tty[unit];
1821 cp->cn_pri = pri;
1822 }
1823
1824 itecninit(cp)
1825 struct consdev *cp;
1826 {
1827 int unit = UNIT(cp->cn_dev);
1828 struct ite_softc *ip = &ite_softc[unit];
1829 ip->attrbuf = console_attributes;
1830 iteinit(cp->cn_dev);
1831 ip->flags |= (ITE_ACTIVE|ITE_ISCONS);
1832 kbd_tty = ite_tty[unit];
1833 kbdenable();
1834 }
1835
1836 /*ARGSUSED*/
1837 itecngetc(dev)
1838 dev_t dev;
1839 {
1840 register int c;
1841
1842 do
1843 {
1844 c = kbdgetcn ();
1845 c = itefilter (c, ITEFILT_CONSOLE);
1846 }
1847 while (c == -1);
1848
1849 return(c);
1850 }
1851
1852 itecnputc(dev, c)
1853 dev_t dev;
1854 int c;
1855 {
1856 static int paniced = 0;
1857 struct ite_softc *ip = &ite_softc[UNIT(dev)];
1858 extern char *panicstr;
1859
1860 if (panicstr && !paniced &&
1861 (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
1862 (void) iteon(dev, 3);
1863 paniced = 1;
1864 }
1865 iteputchar(c, dev);
1866 }
1867 #endif
1868