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