ite.c revision 1.13 1 /* $NetBSD: ite.c,v 1.13 1998/08/06 14:08:54 minoura Exp $ */
2
3 /*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: Utah $Hdr: ite.c 1.1 90/07/09$
41 *
42 * @(#)ite.c 7.6 (Berkeley) 5/16/91
43 */
44
45 /*
46 * ite - bitmaped terminal.
47 * Supports VT200, a few terminal features will be unavailable until
48 * the system actually probes the device (i.e. not after consinit())
49 */
50
51 #include "ite.h"
52 #if NITE > 0
53
54 #include "bell.h"
55
56 #include <sys/param.h>
57 #include <sys/conf.h>
58 #include <sys/proc.h>
59 #include <sys/ioctl.h>
60 #include <sys/tty.h>
61 #include <sys/systm.h>
62 #include <sys/device.h>
63 #include <sys/malloc.h>
64 #include <machine/kbio.h>
65 #include <machine/iteioctl.h>
66 #include <machine/grfioctl.h>
67
68 #include <x68k/dev/grfvar.h>
69 #include <x68k/dev/itevar.h>
70 #include <x68k/dev/kbdmap.h>
71
72 #include <x68k/x68k/iodevice.h>
73
74 #define SUBR_CNPROBE(min) itesw[min].ite_cnprobe(min)
75 #define SUBR_INIT(ip) ip->isw->ite_init(ip)
76 #define SUBR_DEINIT(ip) ip->isw->ite_deinit(ip)
77 #define SUBR_PUTC(ip,c,dy,dx,m) ip->isw->ite_putc(ip,c,dy,dx,m)
78 #define SUBR_CURSOR(ip,flg) ip->isw->ite_cursor(ip,flg)
79 #define SUBR_CLEAR(ip,sy,sx,h,w) ip->isw->ite_clear(ip,sy,sx,h,w)
80 #define SUBR_SCROLL(ip,sy,sx,count,dir) \
81 ip->isw->ite_scroll(ip,sy,sx,count,dir)
82
83 struct consdev;
84
85 __inline static void itesendch __P((int));
86 __inline static void alignment_display __P((struct ite_softc *));
87 __inline static void snap_cury __P((struct ite_softc *));
88 __inline static void ite_dnchar __P((struct ite_softc *, int));
89 static void ite_inchar __P((struct ite_softc *, int));
90 __inline static void ite_clrtoeol __P((struct ite_softc *));
91 __inline static void ite_clrtobol __P((struct ite_softc *));
92 __inline static void ite_clrline __P((struct ite_softc *));
93 __inline static void ite_clrtoeos __P((struct ite_softc *));
94 __inline static void ite_clrtobos __P((struct ite_softc *));
95 __inline static void ite_clrscreen __P((struct ite_softc *));
96 __inline static void ite_dnline __P((struct ite_softc *, int));
97 __inline static void ite_inline __P((struct ite_softc *, int));
98 __inline static void ite_index __P((struct ite_softc *));
99 __inline static void ite_lf __P((struct ite_softc *));
100 __inline static void ite_crlf __P((struct ite_softc *));
101 __inline static void ite_cr __P((struct ite_softc *));
102 __inline static void ite_rlf __P((struct ite_softc *));
103 static void iteprecheckwrap __P((struct ite_softc *ip));
104 static void itecheckwrap __P((struct ite_softc *ip));
105 static void repeat_handler __P((void *arg));
106 static int ite_argnum __P((struct ite_softc *ip));
107 static int ite_zargnum __P((struct ite_softc *ip));
108 static void ite_sendstr __P((struct ite_softc *ip, char *str));
109 __inline static int atoi __P((const char *cp));
110 __inline static char *index __P((const char *cp, char ch));
111 void ite_reset __P((struct ite_softc *ip));
112 struct ite_softc *getitesp __P((dev_t));
113 int iteon __P((dev_t, int));
114 void iteoff __P((dev_t, int));
115
116 struct itesw itesw[] = {
117 0, tv_init, tv_deinit, 0,
118 0, 0, 0,
119 };
120 int nitesw = sizeof(itesw) / sizeof(itesw[0]);
121
122 /*
123 * # of chars are output in a single itestart() call.
124 * If this is too big, user processes will be blocked out for
125 * long periods of time while we are emptying the queue in itestart().
126 * If it is too small, console output will be very ragged.
127 */
128 #define ITEBURST 64
129
130 int nite = NITE;
131 struct tty *ite_tty[NITE];
132 struct ite_softc *kbd_ite = NULL;
133 struct ite_softc con_itesoftc;
134
135 struct tty *kbd_tty = NULL;
136
137 int start_repeat_timeo = 20; /* /100: initial timeout till pressed key repeats */
138 int next_repeat_timeo = 3; /* /100: timeout when repeating for next char */
139
140 u_char cons_tabs[MAX_TABS];
141
142 int kbd_init;
143
144 cdev_decl(ite);
145
146 void itestart __P((struct tty *tp));
147
148 void iteputchar __P((int c, struct ite_softc *ip));
149 void ite_putstr __P((const u_char * s, int len, dev_t dev));
150
151 void iteattach __P((struct device *, struct device *, void *));
152 int itematch __P((struct device *, struct cfdata *, void *));
153
154 struct cfattach ite_ca = {
155 sizeof(struct ite_softc), itematch, iteattach
156 };
157
158 extern struct cfdriver ite_cd;
159
160 int
161 itematch(pdp, cdp, auxp)
162 struct device *pdp;
163 struct cfdata *cdp;
164 void *auxp;
165 {
166 struct grf_softc *gp;
167 int maj;
168
169 gp = auxp;
170
171 /* ite0 should be at grf0 XXX */
172 if(cdp->cf_unit != gp->g_device.dv_unit)
173 return(0);
174
175 #if 0
176 /*
177 * all that our mask allows (more than enough no one
178 * has > 32 monitors for text consoles on one machine)
179 */
180 if (cdp->cf_unit >= sizeof(ite_confunits) * NBBY)
181 return(0);
182 /*
183 * XXX
184 * normally this would be done in attach, however
185 * during early init we do not have a device pointer
186 * and thus no unit number.
187 */
188 for(maj = 0; maj < nchrdev; maj++)
189 if (cdevsw[maj].d_open == iteopen)
190 break;
191 gp->g_itedev = makedev(maj, cdp->cf_unit);
192 #endif
193 return(1);
194 }
195
196 /*
197 * iteinit() is the standard entry point for initialization of
198 * an ite device, it is also called from ite_cninit().
199 */
200 void
201 iteattach(pdp, dp, auxp)
202 struct device *pdp, *dp;
203 void *auxp;
204 {
205 struct ite_softc *ip;
206 struct grf_softc *gp;
207
208 gp = (struct grf_softc *)auxp;
209 if (dp) {
210 ip = (struct ite_softc *)dp;
211 if(con_itesoftc.grf != NULL
212 /*&& con_itesoftc.grf->g_unit == gp->g_unit*/) {
213 /*
214 * console reinit copy params over.
215 * and console always gets keyboard
216 */
217 bcopy(&con_itesoftc.grf, &ip->grf,
218 (char *)&ip[1] - (char *)&ip->grf);
219 con_itesoftc.grf = NULL;
220 kbd_ite = ip;
221 }
222 ip->grf = gp;
223 iteinit(ip->device.dv_unit); /* XXX */
224 printf(": rows %d cols %d", ip->rows, ip->cols);
225 if (kbd_ite == NULL)
226 kbd_ite = ip;
227 printf("\n");
228 } else {
229 if (con_itesoftc.grf != NULL)
230 return;
231 con_itesoftc.grf = gp;
232 con_itesoftc.tabs = cons_tabs;
233 }
234 }
235
236 struct ite_softc *
237 getitesp(dev)
238 dev_t dev;
239 {
240 extern int x68k_realconfig;
241
242 if (x68k_realconfig && con_itesoftc.grf == NULL)
243 return(ite_cd.cd_devs[UNIT(dev)]);
244
245 if (con_itesoftc.grf == NULL)
246 panic("no ite_softc for console");
247 return(&con_itesoftc);
248 }
249
250 void
251 iteinit(dev)
252 dev_t dev;
253 {
254 struct ite_softc *ip;
255
256 ip = getitesp(dev);
257
258 if (ip->flags & ITE_INITED)
259 return;
260 bcopy(&ascii_kbdmap, &kbdmap, sizeof(struct kbdmap));
261
262 ip->curx = 0;
263 ip->cury = 0;
264 ip->cursorx = 0;
265 ip->cursory = 0;
266
267 ip->isw = &itesw[ip->device.dv_unit]; /* XXX */
268 SUBR_INIT(ip);
269 SUBR_CURSOR(ip, DRAW_CURSOR);
270 if (!ip->tabs)
271 ip->tabs = malloc(MAX_TABS*sizeof(u_char), M_DEVBUF, M_WAITOK);
272 ite_reset(ip);
273 ip->flags |= ITE_INITED;
274 }
275
276 /*
277 * Perform functions necessary to setup device as a terminal emulator.
278 */
279 int
280 iteon(dev, flag)
281 dev_t dev;
282 int flag;
283 {
284 int unit = UNIT(dev);
285 struct ite_softc *ip;
286
287 if (unit < 0 || unit >= ite_cd.cd_ndevs ||
288 (ip = getitesp(unit)) == NULL || (ip->flags&ITE_ALIVE) == 0)
289 return(ENXIO);
290 /* force ite active, overriding graphics mode */
291 if (flag & 1) {
292 ip->flags |= ITE_ACTIVE;
293 ip->flags &= ~(ITE_INGRF|ITE_INITED);
294 }
295 /* leave graphics mode */
296 if (flag & 2) {
297 ip->flags &= ~ITE_INGRF;
298 if ((ip->flags & ITE_ACTIVE) == 0)
299 return(0);
300 }
301 ip->flags |= ITE_ACTIVE;
302 if (ip->flags & ITE_INGRF)
303 return(0);
304 iteinit(dev);
305 return(0);
306 }
307
308 /*
309 * "Shut down" device as terminal emulator.
310 * Note that we do not deinit the console device unless forced.
311 * Deinit'ing the console every time leads to a very active
312 * screen when processing /etc/rc.
313 */
314 void
315 iteoff(dev, flag)
316 dev_t dev;
317 int flag;
318 {
319 int unit = UNIT(dev);
320 register struct ite_softc *ip;
321
322 /* XXX check whether when call from grf.c */
323 if (unit < 0 || unit >= ite_cd.cd_ndevs ||
324 (ip = getitesp(unit)) == NULL || (ip->flags&ITE_ALIVE) == 0)
325 return;
326 if (flag & 2)
327 ip->flags |= ITE_INGRF;
328
329 if ((ip->flags & ITE_ACTIVE) == 0)
330 return;
331 if ((flag & 1) ||
332 (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED)
333 SUBR_DEINIT(ip);
334
335 /*
336 * XXX When the system is rebooted with "reboot", init(8)
337 * kills the last process to have the console open.
338 * If we don't revent the the ITE_ACTIVE bit from being
339 * cleared, we will never see messages printed during
340 * the process of rebooting.
341 */
342 if ((flag & 2) == 0 && (ip->flags & ITE_ISCONS) == 0)
343 ip->flags &= ~ITE_ACTIVE;
344 }
345
346 /*
347 * standard entry points to the device.
348 */
349
350 /* ARGSUSED */
351 int
352 iteopen(dev, mode, devtype, p)
353 dev_t dev;
354 int mode, devtype;
355 struct proc *p;
356 {
357 int unit = UNIT(dev);
358 register struct tty *tp;
359 register struct ite_softc *ip;
360 register int error;
361 int first = 0;
362
363 ip = getitesp(dev);
364 if (!ite_tty[unit]) {
365 tp = ite_tty[unit] = ttymalloc();
366 tty_attach(tp);
367 } else
368 tp = ite_tty[unit];
369 if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE)
370 && p->p_ucred->cr_uid != 0)
371 return (EBUSY);
372 if ((ip->flags & ITE_ACTIVE) == 0) {
373 error = iteon(dev, 0);
374 if (error)
375 return (error);
376 first = 1;
377 }
378 tp->t_oproc = itestart;
379 tp->t_param = NULL;
380 tp->t_dev = dev;
381 if ((tp->t_state&TS_ISOPEN) == 0) {
382 ttychars(tp);
383 tp->t_iflag = TTYDEF_IFLAG;
384 tp->t_oflag = TTYDEF_OFLAG;
385 tp->t_cflag = TTYDEF_CFLAG;
386 tp->t_lflag = TTYDEF_LFLAG;
387 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
388 tp->t_state = TS_ISOPEN|TS_CARR_ON;
389 ttsetwater(tp);
390 }
391 error = (*linesw[tp->t_line].l_open)(dev, tp);
392 if (error == 0) {
393 tp->t_winsize.ws_row = ip->rows;
394 tp->t_winsize.ws_col = ip->cols;
395 if (!kbd_init) {
396 kbd_init = 1;
397 kbdenable();
398 }
399 } else if (first)
400 iteoff(dev, 0);
401 return (error);
402 }
403
404 /*ARGSUSED*/
405 int
406 iteclose(dev, flag, mode, p)
407 dev_t dev;
408 int flag, mode;
409 struct proc *p;
410 {
411 register struct tty *tp = ite_tty[UNIT(dev)];
412
413 (*linesw[tp->t_line].l_close)(tp, flag);
414 ttyclose(tp);
415 iteoff(dev, 0);
416 #if 0
417 ttyfree(tp);
418 ite_tty[UNIT(dev)] = (struct tty *)0;
419 #endif
420 return(0);
421 }
422
423 int
424 iteread(dev, uio, flag)
425 dev_t dev;
426 struct uio *uio;
427 int flag;
428 {
429 register struct tty *tp = ite_tty[UNIT(dev)];
430
431 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
432 }
433
434 int
435 itewrite(dev, uio, flag)
436 dev_t dev;
437 struct uio *uio;
438 int flag;
439 {
440 register struct tty *tp = ite_tty[UNIT(dev)];
441
442 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
443 }
444
445 struct tty *
446 itetty(dev)
447 dev_t dev;
448 {
449
450 return (ite_tty[UNIT(dev)]);
451 }
452
453 int
454 iteioctl(dev, cmd, addr, flag, p)
455 dev_t dev;
456 u_long cmd;
457 caddr_t addr;
458 int flag;
459 struct proc *p;
460 {
461 struct iterepeat *irp;
462 register struct tty *tp = ite_tty[UNIT(dev)];
463 int error;
464
465 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p);
466 if (error >= 0)
467 return (error);
468 error = ttioctl(tp, cmd, addr, flag, p);
469 if (error >= 0)
470 return (error);
471
472 switch (cmd) {
473 case ITEIOCSKMAP:
474 if (addr == 0)
475 return(EFAULT);
476 bcopy(addr, &kbdmap, sizeof(struct kbdmap));
477 return(0);
478
479 case ITEIOCGKMAP:
480 if (addr == NULL)
481 return(EFAULT);
482 bcopy(&kbdmap, addr, sizeof(struct kbdmap));
483 return(0);
484
485 case ITEIOCGREPT:
486 irp = (struct iterepeat *)addr;
487 irp->start = start_repeat_timeo;
488 irp->next = next_repeat_timeo;
489
490 case ITEIOCSREPT:
491 irp = (struct iterepeat *)addr;
492 if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
493 return(EINVAL);
494 start_repeat_timeo = irp->start;
495 next_repeat_timeo = irp->next;
496 #if x68k
497 case ITELOADFONT:
498 if (addr) {
499 bcopy(addr, kern_font, 4096 /*sizeof (kernel_font)*/);
500 return 0;
501 } else
502 return EFAULT;
503
504 case ITETVCTRL:
505 if (addr && *(u_char *)addr < 0x40) {
506 while(!(mfp.tsr & 0x80)) ;
507 mfp.udr = *(u_char *)addr;
508 return 0;
509 } else
510 return EFAULT;
511 #endif
512 }
513 return (ENOTTY);
514 }
515
516 void
517 itestart(tp)
518 register struct tty *tp;
519 {
520 struct clist *rbp;
521 struct ite_softc *ip;
522 u_char buf[ITEBURST];
523 int s, len, n;
524
525 ip = getitesp(tp->t_dev);
526 /*
527 * (Potentially) lower priority. We only need to protect ourselves
528 * from keyboard interrupts since that is all that can affect the
529 * state of our tty (kernel printf doesn't go through this routine).
530 */
531 s = spltty();
532 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
533 goto out;
534 tp->t_state |= TS_BUSY;
535 rbp = &tp->t_outq;
536 len = q_to_b(rbp, buf, ITEBURST);
537 /*splx(s);*/
538
539 /* Here is a really good place to implement pre/jumpscroll() */
540 ite_putstr(buf, len, tp->t_dev);
541
542 /*s = spltty();*/
543 tp->t_state &= ~TS_BUSY;
544 /* we have characters remaining. */
545 if (rbp->c_cc) {
546 tp->t_state |= TS_TIMEOUT;
547 timeout(ttrstrt, (caddr_t)tp, 1);
548 }
549 /* wakeup we are below */
550 if (rbp->c_cc <= tp->t_lowat) {
551 if (tp->t_state & TS_ASLEEP) {
552 tp->t_state &= ~TS_ASLEEP;
553 wakeup((caddr_t)rbp);
554 }
555 selwakeup(&tp->t_wsel);
556 }
557 out:
558 splx(s);
559 }
560
561 /* XXX called after changes made in underlying grf layer. */
562 /* I want to nuke this */
563 void
564 ite_reinit(dev)
565 dev_t dev;
566 {
567 struct ite_softc *ip;
568 int unit = UNIT(dev);
569
570 /* XXX check whether when call from grf.c */
571 if (unit < 0 || unit >= ite_cd.cd_ndevs ||
572 (ip = getitesp(unit)) == NULL)
573 return;
574
575 ip->flags &= ~ITE_INITED;
576 iteinit(dev);
577 }
578
579 void
580 ite_reset(ip)
581 struct ite_softc *ip;
582 {
583 int i;
584
585 ip->curx = 0;
586 ip->cury = 0;
587 ip->attribute = 0;
588 ip->save_curx = 0;
589 ip->save_cury = 0;
590 ip->save_attribute = 0;
591 ip->ap = ip->argbuf;
592 ip->emul_level = EMUL_VT300_8;
593 ip->eightbit_C1 = 0;
594 ip->top_margin = 0;
595 ip->bottom_margin = ip->rows - 1;
596 ip->inside_margins = 0; /* origin mode == absolute */
597 ip->linefeed_newline = 0;
598 ip->auto_wrap = 1;
599 ip->cursor_appmode = 0;
600 ip->keypad_appmode = 0;
601 ip->imode = 0;
602 ip->key_repeat = 1;
603 ip->G0 = CSET_ASCII;
604 ip->G1 = CSET_JIS1983;
605 ip->G2 = CSET_JISKANA;
606 ip->G3 = CSET_JIS1990;
607 ip->GL = &ip->G0;
608 ip->GR = &ip->G1;
609 ip->save_GL = 0;
610 ip->save_char = 0;
611 ip->fgcolor = 7;
612 ip->bgcolor = 0;
613 for (i = 0; i < ip->cols; i++)
614 ip->tabs[i] = ((i & 7) == 0);
615 /* XXX clear screen */
616 SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
617 attrclr(ip, 0, 0, ip->rows, ip->cols);
618 }
619
620 /* Used in console at startup only */
621 int
622 ite_cnfilter(c, caller)
623 u_char c;
624 enum caller caller;
625 {
626 struct tty *kbd_tty;
627 static u_char mod = 0;
628 struct key key;
629 u_char code, up, mask;
630 int s, i;
631
632 up = c & 0x80 ? 1 : 0;
633 c &= 0x7f;
634 code = 0;
635
636 s = spltty();
637
638 mask = 0;
639 if (c >= KBD_LEFT_ALT && !(c >= 0x63 && c <= 0x6c)) { /* 0x63: F1, 0x6c:F10 */
640 switch (c) {
641 case KBD_LEFT_SHIFT:
642 mask = KBD_MOD_SHIFT;
643 break;
644
645 case KBD_LEFT_ALT:
646 mask = KBD_MOD_LALT;
647 break;
648
649 case KBD_RIGHT_ALT:
650 mask = KBD_MOD_RALT;
651 break;
652
653 case KBD_LEFT_META:
654 mask = KBD_MOD_LMETA;
655 break;
656
657 case KBD_RIGHT_META:
658 mask = KBD_MOD_RMETA;
659 break;
660
661 case KBD_CAPS_LOCK:
662 /*
663 * capslock already behaves `right', don't need to
664 * keep track of the state in here.
665 */
666 mask = KBD_MOD_CAPS;
667 break;
668
669 case KBD_CTRL:
670 mask = KBD_MOD_CTRL;
671 break;
672
673 case KBD_RECONNECT:
674 /* ite got 0xff */
675 if (up)
676 kbd_setLED();
677 break;
678 }
679 if (mask & KBD_MOD_CAPS) {
680 if (!up) {
681 mod ^= KBD_MOD_CAPS;
682 kbdled ^= LED_CAPS_LOCK;
683 kbd_setLED();
684 }
685 } else if (up)
686 mod &= ~mask;
687 else mod |= mask;
688 splx (s);
689 return -1;
690 }
691
692 if (up) {
693 splx(s);
694 return -1;
695 }
696
697 /* translate modifiers */
698 if (mod & KBD_MOD_SHIFT) {
699 if (mod & KBD_MOD_ALT)
700 key = kbdmap.alt_shift_keys[c];
701 else
702 key = kbdmap.shift_keys[c];
703 } else if (mod & KBD_MOD_ALT)
704 key = kbdmap.alt_keys[c];
705 else {
706 key = kbdmap.keys[c];
707 /* if CAPS and key is CAPable (no pun intended) */
708 if ((mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
709 key = kbdmap.shift_keys[c];
710 }
711 code = key.code;
712
713 /* if string return */
714 if (key.mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) {
715 splx(s);
716 return -1;
717 }
718 /* handle dead keys */
719 if (key.mode & KBD_MODE_DEAD) {
720 splx(s);
721 return -1;
722 }
723 if (mod & KBD_MOD_CTRL)
724 code &= 0x1f;
725 if (mod & KBD_MOD_META)
726 code |= 0x80;
727
728 /* do console mapping. */
729 code = code == '\r' ? '\n' : code;
730
731 splx(s);
732 return (code);
733 }
734
735 /* And now the old stuff. */
736
737 /* these are used to implement repeating keys.. */
738 static u_char last_char = 0;
739 static u_char tout_pending = 0;
740
741 /*ARGSUSED*/
742 static void
743 repeat_handler (arg)
744 void *arg;
745 {
746 tout_pending = 0;
747 if (last_char)
748 add_sicallback(ite_filter, last_char, ITEFILT_REPEATER);
749 }
750
751 __inline static void
752 itesendch (ch)
753 int ch;
754 {
755 (*linesw[kbd_tty->t_line].l_rint)(ch, kbd_tty);
756 }
757
758
759 void
760 ite_filter(c, caller)
761 u_char c;
762 enum caller caller;
763 {
764 static u_short mod = 0;
765 register unsigned char code, *str;
766 u_short up, mask;
767 struct key key;
768 int s, i;
769
770 if (!kbd_ite)
771 return;
772 kbd_tty = ite_tty[kbd_ite->device.dv_unit];
773
774 /* have to make sure we're at spltty in here */
775 s = spltty ();
776
777 #if 0 /* XXX? x68k */
778 /* keyboard interrupts come at priority 2, while softint-
779 generated keyboard-repeat interrupts come at level 1.
780 So, to not allow a key-up event to get thru before
781 a repeat for the key-down, we remove any outstanding
782 callout requests.. */
783 rem_sicallback (ite_filter);
784 #endif
785
786 up = c & 0x80 ? 1 : 0;
787 c &= 0x7f;
788 code = 0;
789
790 mask = 0;
791 if (c >= KBD_LEFT_ALT &&
792 !(c >= 0x63 && c <= 0x6c)) { /* 0x63: F1, 0x6c:F10 */
793 switch (c) {
794 case KBD_LEFT_SHIFT:
795 mask = KBD_MOD_SHIFT;
796 break;
797
798 case KBD_LEFT_ALT:
799 mask = KBD_MOD_LALT;
800 break;
801
802 case KBD_RIGHT_ALT:
803 mask = KBD_MOD_RALT;
804 break;
805
806 case KBD_LEFT_META:
807 mask = KBD_MOD_LMETA;
808 break;
809
810 case KBD_RIGHT_META:
811 mask = KBD_MOD_RMETA;
812 break;
813
814 case KBD_CAPS_LOCK:
815 /*
816 * capslock already behaves `right', don't need to keep
817 * track of the state in here.
818 */
819 mask = KBD_MOD_CAPS;
820 break;
821
822 case KBD_CTRL:
823 mask = KBD_MOD_CTRL;
824 break;
825
826 case KBD_OPT1:
827 mask = KBD_MOD_OPT1;
828 break;
829
830 case KBD_OPT2:
831 mask = KBD_MOD_OPT2;
832 break;
833
834 case KBD_RECONNECT:
835 if (up) { /* ite got 0xff */
836 kbd_setLED();
837 }
838 break;
839 }
840
841 if (mask & KBD_MOD_CAPS) {
842 if (!up) {
843 mod ^= KBD_MOD_CAPS;
844 kbdled ^= LED_CAPS_LOCK;
845 kbd_setLED();
846 }
847 } else if (up) {
848 mod &= ~mask;
849 } else mod |= mask;
850
851 /*
852 * these keys should not repeat, so it's the Right Thing
853 * dealing with repeaters only after this block.
854 */
855
856 /*
857 * return even if it wasn't a modifier key, the other
858 * codes up here are either special (like reset warning),
859 * or not yet defined
860 */
861 splx (s);
862 return;
863 }
864
865 /*
866 * no matter which character we're repeating, stop it if we
867 * get a key-up event. I think this is the same thing amigados does.
868 */
869 if (up) {
870 if (tout_pending) {
871 untimeout (repeat_handler, 0);
872 tout_pending = 0;
873 last_char = 0;
874 }
875 splx (s);
876 return;
877 } else if (tout_pending && last_char != c) {
878 /*
879 * not the same character remove the repeater and continue
880 * to process this key. -ch
881 */
882 untimeout (repeat_handler, 0);
883 tout_pending = 0;
884 last_char = 0;
885 }
886
887 /*
888 * intercept LAlt-LMeta-F1 here to switch back to original ascii-keymap.
889 * this should probably be configurable..
890 */
891 if (mod == (KBD_MOD_LALT|KBD_MOD_LMETA) && c == 0x50) {
892 bcopy (&ascii_kbdmap, &kbdmap, sizeof (struct kbdmap));
893 splx (s);
894 return;
895 }
896
897 /* translate modifiers */
898 if (mod & KBD_MOD_SHIFT) {
899 if (mod & KBD_MOD_ALT)
900 key = kbdmap.alt_shift_keys[c];
901 else
902 key = kbdmap.shift_keys[c];
903 } else if (mod & KBD_MOD_ALT)
904 key = kbdmap.alt_keys[c];
905 else {
906 key = kbdmap.keys[c];
907 /* if CAPS and key is CAPable (no pun intended) */
908 if ((mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
909 key = kbdmap.shift_keys[c];
910 else if ((mod & KBD_MOD_OPT2) && (key.mode & KBD_MODE_KPAD))
911 key = kbdmap.shift_keys[c];
912 }
913 code = key.code;
914
915 /*
916 * arrange to repeat the keystroke. By doing this at the level of scan-codes,
917 * we can have function keys, and keys that send strings, repeat too. This
918 * also entitles an additional overhead, since we have to do the conversion
919 * each time, but I guess that's ok.
920 */
921 if (!tout_pending && caller == ITEFILT_TTY && kbd_ite->key_repeat) {
922 tout_pending = 1;
923 last_char = c;
924 timeout (repeat_handler, 0, start_repeat_timeo);
925 } else if (!tout_pending && caller == ITEFILT_REPEATER &&
926 kbd_ite->key_repeat) {
927 tout_pending = 1;
928 last_char = c;
929 timeout (repeat_handler, 0, next_repeat_timeo);
930 }
931
932 /* handle dead keys */
933 if (key.mode & KBD_MODE_DEAD) {
934 splx (s);
935 return;
936 }
937 /* if not string, apply META and CTRL modifiers */
938 if (! (key.mode & KBD_MODE_STRING)
939 && (!(key.mode & KBD_MODE_KPAD) ||
940 (kbd_ite && !kbd_ite->keypad_appmode))) {
941 if ((mod & KBD_MOD_CTRL) &&
942 (code == ' ' || (code >= '@' && code <= 'z')))
943 code &= 0x1f;
944 if (mod & KBD_MOD_META)
945 code |= 0x80;
946 } else if ((key.mode & KBD_MODE_KPAD) &&
947 (kbd_ite && kbd_ite->keypad_appmode)) {
948 static char *in = "0123456789-+.\r()/*";
949 static char *out = "pqrstuvwxymlnMPQRS";
950 char *cp = index (in, code);
951
952 /*
953 * keypad-appmode sends SS3 followed by the above
954 * translated character
955 */
956 (*linesw[kbd_tty->t_line].l_rint) (27, kbd_tty);
957 (*linesw[kbd_tty->t_line].l_rint) ('O', kbd_tty);
958 (*linesw[kbd_tty->t_line].l_rint) (out[cp - in], kbd_tty);
959 splx(s);
960 return;
961 } else {
962 /* *NO* I don't like this.... */
963 static u_char app_cursor[] =
964 {
965 3, 27, 'O', 'A',
966 3, 27, 'O', 'B',
967 3, 27, 'O', 'C',
968 3, 27, 'O', 'D'};
969
970 str = kbdmap.strings + code;
971 /*
972 * if this is a cursor key, AND it has the default
973 * keymap setting, AND we're in app-cursor mode, switch
974 * to the above table. This is *nasty* !
975 */
976 if (c >= 0x3b && c <= 0x3e && kbd_ite->cursor_appmode
977 && !bcmp(str, "\x03\x1b[", 3) &&
978 index("ABCD", str[3]))
979 str = app_cursor + 4 * (str[3] - 'A');
980
981 /*
982 * using a length-byte instead of 0-termination allows
983 * to embed \0 into strings, although this is not used
984 * in the default keymap
985 */
986 for (i = *str++; i; i--)
987 (*linesw[kbd_tty->t_line].l_rint) (*str++, kbd_tty);
988 splx(s);
989 return;
990 }
991 (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
992
993 splx(s);
994 return;
995 }
996
997 /* helper functions, makes the code below more readable */
998 __inline static void
999 ite_sendstr (ip, str)
1000 struct ite_softc *ip;
1001 char *str;
1002 {
1003 while (*str)
1004 itesendch (*str++);
1005 }
1006
1007 __inline static void
1008 alignment_display(ip)
1009 struct ite_softc *ip;
1010 {
1011 int i, j;
1012
1013 for (j = 0; j < ip->rows; j++)
1014 for (i = 0; i < ip->cols; i++)
1015 SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
1016 attrclr(ip, 0, 0, ip->rows, ip->cols);
1017 }
1018
1019 __inline static void
1020 snap_cury(ip)
1021 struct ite_softc *ip;
1022 {
1023 if (ip->inside_margins) {
1024 if (ip->cury < ip->top_margin)
1025 ip->cury = ip->top_margin;
1026 if (ip->cury > ip->bottom_margin)
1027 ip->cury = ip->bottom_margin;
1028 }
1029 }
1030
1031 __inline static void
1032 ite_dnchar(ip, n)
1033 struct ite_softc *ip;
1034 int n;
1035 {
1036 n = min(n, ip->cols - ip->curx);
1037 if (n < ip->cols - ip->curx) {
1038 SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
1039 attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
1040 1, ip->cols - ip->curx - n);
1041 attrclr(ip, ip->cury, ip->cols - n, 1, n);
1042 }
1043 while (n-- > 0)
1044 SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
1045 }
1046
1047 static void
1048 ite_inchar(ip, n)
1049 struct ite_softc *ip;
1050 int n;
1051 {
1052 int c = ip->save_char;
1053 ip->save_char = 0;
1054 n = min(n, ip->cols - ip->curx);
1055 if (n < ip->cols - ip->curx) {
1056 SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
1057 attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
1058 1, ip->cols - ip->curx - n);
1059 attrclr(ip, ip->cury, ip->curx, 1, n);
1060 }
1061 while (n--)
1062 SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1063 ip->save_char = c;
1064 }
1065
1066 __inline static void
1067 ite_clrtoeol(ip)
1068 struct ite_softc *ip;
1069 {
1070 int y = ip->cury, x = ip->curx;
1071 if (ip->cols - x > 0) {
1072 SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
1073 attrclr(ip, y, x, 1, ip->cols - x);
1074 }
1075 }
1076
1077 __inline static void
1078 ite_clrtobol(ip)
1079 struct ite_softc *ip;
1080 {
1081 int y = ip->cury, x = min(ip->curx + 1, ip->cols);
1082 SUBR_CLEAR(ip, y, 0, 1, x);
1083 attrclr(ip, y, 0, 1, x);
1084 }
1085
1086 __inline static void
1087 ite_clrline(ip)
1088 struct ite_softc *ip;
1089 {
1090 int y = ip->cury;
1091 SUBR_CLEAR(ip, y, 0, 1, ip->cols);
1092 attrclr(ip, y, 0, 1, ip->cols);
1093 }
1094
1095 __inline static void
1096 ite_clrtoeos(ip)
1097 struct ite_softc *ip;
1098 {
1099 ite_clrtoeol(ip);
1100 if (ip->cury < ip->rows - 1) {
1101 SUBR_CLEAR(ip, ip->cury + 1, 0, ip->rows - 1 - ip->cury, ip->cols);
1102 attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
1103 }
1104 }
1105
1106 __inline static void
1107 ite_clrtobos(ip)
1108 struct ite_softc *ip;
1109 {
1110 ite_clrtobol(ip);
1111 if (ip->cury > 0) {
1112 SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
1113 attrclr(ip, 0, 0, ip->cury, ip->cols);
1114 }
1115 }
1116
1117 __inline static void
1118 ite_clrscreen(ip)
1119 struct ite_softc *ip;
1120 {
1121 SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
1122 attrclr(ip, 0, 0, ip->rows, ip->cols);
1123 }
1124
1125
1126
1127 __inline static void
1128 ite_dnline(ip, n)
1129 struct ite_softc *ip;
1130 int n;
1131 {
1132 /*
1133 * interesting.. if the cursor is outside the scrolling
1134 * region, this command is simply ignored..
1135 */
1136 if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1137 return;
1138
1139 n = min(n, ip->bottom_margin + 1 - ip->cury);
1140 if (n <= ip->bottom_margin - ip->cury) {
1141 SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
1142 attrmov(ip, ip->cury + n, 0, ip->cury, 0,
1143 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1144 }
1145 SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1146 attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1147 }
1148
1149 __inline static void
1150 ite_inline(ip, n)
1151 struct ite_softc *ip;
1152 int n;
1153 {
1154 /*
1155 * interesting.. if the cursor is outside the scrolling
1156 * region, this command is simply ignored..
1157 */
1158 if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1159 return;
1160
1161 if (n <= 0)
1162 n = 1;
1163 else n = min(n, ip->bottom_margin + 1 - ip->cury);
1164 if (n <= ip->bottom_margin - ip->cury) {
1165 SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
1166 attrmov(ip, ip->cury, 0, ip->cury + n, 0,
1167 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1168 }
1169 SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
1170 attrclr(ip, ip->cury, 0, n, ip->cols);
1171 ip->curx = 0;
1172 }
1173
1174 __inline static void
1175 ite_index (ip)
1176 struct ite_softc *ip;
1177 {
1178 ++ip->cury;
1179 if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows)) {
1180 ip->cury--;
1181 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1182 ite_clrline(ip);
1183 }
1184 /*clr_attr(ip, ATTR_INV);*/
1185 }
1186
1187 __inline static void
1188 ite_lf (ip)
1189 struct ite_softc *ip;
1190 {
1191 ++ip->cury;
1192 if (ip->cury > ip->bottom_margin) {
1193 ip->cury--;
1194 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1195 ite_clrline(ip);
1196 }
1197 /* SUBR_CURSOR(ip, MOVE_CURSOR);*/
1198 /*clr_attr(ip, ATTR_INV);*/
1199 /* reset character set ... thanks for mohta. */
1200 ip->G0 = CSET_ASCII;
1201 ip->G1 = CSET_JIS1983;
1202 ip->G2 = CSET_JISKANA;
1203 ip->G3 = CSET_JIS1990;
1204 ip->GL = &ip->G0;
1205 ip->GR = &ip->G1;
1206 ip->save_GL = 0;
1207 ip->save_char = 0;
1208 }
1209
1210 __inline static void
1211 ite_crlf (ip)
1212 struct ite_softc *ip;
1213 {
1214 ip->curx = 0;
1215 ite_lf (ip);
1216 }
1217
1218 __inline static void
1219 ite_cr (ip)
1220 struct ite_softc *ip;
1221 {
1222 if (ip->curx) {
1223 ip->curx = 0;
1224 }
1225 }
1226
1227 __inline static void
1228 ite_rlf (ip)
1229 struct ite_softc *ip;
1230 {
1231 ip->cury--;
1232 if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1)) {
1233 ip->cury++;
1234 SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
1235 ite_clrline(ip);
1236 }
1237 clr_attr(ip, ATTR_INV);
1238 }
1239
1240 __inline static int
1241 atoi (cp)
1242 const char *cp;
1243 {
1244 int n;
1245
1246 for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
1247 n = n * 10 + *cp - '0';
1248 return n;
1249 }
1250
1251 __inline static char *
1252 index(cp, ch)
1253 const char *cp;
1254 char ch;
1255 {
1256 while (*cp && *cp != ch)
1257 cp++;
1258 return *cp ? (char *) cp : 0;
1259 }
1260
1261 __inline static int
1262 ite_argnum (ip)
1263 struct ite_softc *ip;
1264 {
1265 char ch;
1266 int n;
1267
1268 /* convert argument string into number */
1269 if (ip->ap == ip->argbuf)
1270 return 1;
1271 ch = *ip->ap;
1272 *ip->ap = 0;
1273 n = atoi (ip->argbuf);
1274 *ip->ap = ch;
1275
1276 return n;
1277 }
1278
1279 __inline static int
1280 ite_zargnum (ip)
1281 struct ite_softc *ip;
1282 {
1283 char ch;
1284 int n;
1285
1286 /* convert argument string into number */
1287 if (ip->ap == ip->argbuf)
1288 return 0;
1289 ch = *ip->ap;
1290 *ip->ap = 0; /* terminate string */
1291 n = atoi (ip->argbuf);
1292 *ip->ap = ch;
1293
1294 return n; /* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
1295 }
1296
1297 void
1298 ite_putstr(s, len, dev)
1299 const u_char *s;
1300 int len;
1301 dev_t dev;
1302 {
1303 struct ite_softc *ip;
1304 int i;
1305
1306 ip = getitesp(dev);
1307
1308 /* XXX avoid problems */
1309 if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
1310 return;
1311
1312 SUBR_CURSOR(ip, START_CURSOROPT);
1313 for (i = 0; i < len; i++)
1314 if (s[i])
1315 iteputchar(s[i], ip);
1316 SUBR_CURSOR(ip, END_CURSOROPT);
1317 }
1318
1319 void
1320 iteputchar(c, ip)
1321 register int c;
1322 struct ite_softc *ip;
1323 {
1324 int n, x, y;
1325 char *cp;
1326
1327 if (c >= 0x20 && ip->escape) {
1328 switch (ip->escape) {
1329
1330 case ESC:
1331 switch (c) {
1332 /* first 7bit equivalents for the 8bit control characters */
1333
1334 case 'D':
1335 c = IND;
1336 ip->escape = 0;
1337 break; /* and fall into the next switch below (same for all `break') */
1338
1339 case 'E':
1340 /* next line */
1341 c = NEL;
1342 ip->escape = 0;
1343 break;
1344
1345 case 'H':
1346 /* set TAB at current col */
1347 c = HTS;
1348 ip->escape = 0;
1349 break;
1350
1351 case 'M':
1352 /* reverse index */
1353 c = RI;
1354 ip->escape = 0;
1355 break;
1356
1357 case 'N':
1358 /* single shift G2 */
1359 c = SS2;
1360 ip->escape = 0;
1361 break;
1362
1363 case 'O':
1364 /* single shift G3 */
1365 c = SS3;
1366 ip->escape = 0;
1367 break;
1368
1369 case 'P':
1370 /* DCS detected */
1371 c = DCS;
1372 ip->escape = 0;
1373 break;
1374
1375 case '[':
1376 c = CSI;
1377 ip->escape = 0;
1378 break;
1379
1380 case '\\':
1381 /* String Terminator */
1382 c = ST;
1383 ip->escape = 0;
1384 break;
1385
1386 case ']':
1387 c = OSC;
1388 ip->escape = 0;
1389 break;
1390
1391 case '^':
1392 c = PM;
1393 ip->escape = 0;
1394 break;
1395
1396 case '_':
1397 c = APC;
1398 ip->escape = 0;
1399 break;
1400
1401
1402 /* introduces 7/8bit control */
1403 case ' ':
1404 /* can be followed by either F or G */
1405 ip->escape = ' ';
1406 break;
1407
1408
1409 /* a lot of character set selections, not yet used...
1410 94-character sets: */
1411 case '(': /* G0 */
1412 case ')': /* G1 */
1413 ip->escape = c;
1414 return;
1415
1416 case '*': /* G2 */
1417 case '+': /* G3 */
1418 case 'B': /* ASCII */
1419 case 'A': /* ISO latin 1 */
1420 case '<': /* user preferred suplemental */
1421 case '0': /* dec special graphics */
1422
1423 /* 96-character sets: */
1424 case '-': /* G1 */
1425 case '.': /* G2 */
1426 case '/': /* G3 */
1427
1428 /* national character sets: */
1429 case '4': /* dutch */
1430 case '5':
1431 case 'C': /* finnish */
1432 case 'R': /* french */
1433 case 'Q': /* french canadian */
1434 case 'K': /* german */
1435 case 'Y': /* italian */
1436 case '6': /* norwegian/danish */
1437 /* note: %5 and %6 are not supported (two chars..) */
1438
1439 ip->escape = 0;
1440 /* just ignore for now */
1441 return;
1442
1443 /* 94-multibyte character sets designate */
1444 case '$':
1445 ip->escape = '$';
1446 return;
1447
1448 /* locking shift modes */
1449 case '`':
1450 ip->GR = &ip->G1;
1451 ip->escape = 0;
1452 return;
1453
1454 case 'n':
1455 ip->GL = &ip->G2;
1456 ip->escape = 0;
1457 return;
1458
1459 case '}':
1460 ip->GR = &ip->G2;
1461 ip->escape = 0;
1462 return;
1463
1464 case 'o':
1465 ip->GL = &ip->G3;
1466 ip->escape = 0;
1467 return;
1468
1469 case '|':
1470 ip->GR = &ip->G3;
1471 ip->escape = 0;
1472 return;
1473
1474 case '~':
1475 ip->GR = &ip->G1;
1476 ip->escape = 0;
1477 return;
1478
1479 /* font width/height control */
1480 case '#':
1481 ip->escape = '#';
1482 return;
1483
1484 case 'c':
1485 /* hard terminal reset .. */
1486 ite_reset (ip);
1487 SUBR_CURSOR(ip, MOVE_CURSOR);
1488 ip->escape = 0;
1489 return;
1490
1491
1492 case '7':
1493 /* save cursor */
1494 ip->save_curx = ip->curx;
1495 ip->save_cury = ip->cury;
1496 ip->save_attribute = ip->attribute;
1497 ip->sc_om = ip->inside_margins;
1498 ip->sc_G0 = ip->G0;
1499 ip->sc_G1 = ip->G1;
1500 ip->sc_G2 = ip->G2;
1501 ip->sc_G3 = ip->G3;
1502 ip->sc_GL = ip->GL;
1503 ip->sc_GR = ip->GR;
1504 ip->escape = 0;
1505 return;
1506
1507 case '8':
1508 /* restore cursor */
1509 ip->curx = ip->save_curx;
1510 ip->cury = ip->save_cury;
1511 ip->attribute = ip->save_attribute;
1512 ip->inside_margins = ip->sc_om;
1513 ip->G0 = ip->sc_G0;
1514 ip->G1 = ip->sc_G1;
1515 ip->G2 = ip->sc_G2;
1516 ip->G3 = ip->sc_G3;
1517 ip->GL = ip->sc_GL;
1518 ip->GR = ip->sc_GR;
1519 SUBR_CURSOR(ip, MOVE_CURSOR);
1520 ip->escape = 0;
1521 return;
1522
1523 case '=':
1524 /* keypad application mode */
1525 ip->keypad_appmode = 1;
1526 ip->escape = 0;
1527 return;
1528
1529 case '>':
1530 /* keypad numeric mode */
1531 ip->keypad_appmode = 0;
1532 ip->escape = 0;
1533 return;
1534
1535 case 'Z': /* request ID */
1536 if (ip->emul_level == EMUL_VT100)
1537 ite_sendstr (ip, "\033[61;0c"); /* XXX not clean */
1538 else
1539 ite_sendstr (ip, "\033[63;0c"); /* XXX not clean */
1540 ip->escape = 0;
1541 return;
1542
1543 /* default catch all for not recognized ESC sequences */
1544 default:
1545 ip->escape = 0;
1546 return;
1547 }
1548 break;
1549
1550
1551 case '(': /* designate G0 */
1552 switch (c) {
1553 case 'B': /* USASCII */
1554 ip->G0 = CSET_ASCII;
1555 ip->escape = 0;
1556 return;
1557 case 'I':
1558 ip->G0 = CSET_JISKANA;
1559 ip->escape = 0;
1560 return;
1561 case 'J':
1562 ip->G0 = CSET_JISROMA;
1563 ip->escape = 0;
1564 return;
1565 case 'A': /* British or ISO-Latin-1 */
1566 case 'H': /* Swedish */
1567 case 'K': /* German */
1568 case 'R': /* French */
1569 case 'Y': /* Italian */
1570 case 'Z': /* Spanish */
1571 default:
1572 /* not supported */
1573 ip->escape = 0;
1574 return;
1575 }
1576
1577 case ')': /* designate G1 */
1578 ip->escape = 0;
1579 return;
1580
1581 case '$': /* 94-multibyte character set */
1582 switch (c) {
1583 case '@':
1584 ip->G0 = CSET_JIS1978;
1585 ip->escape = 0;
1586 return;
1587 case 'B':
1588 ip->G0 = CSET_JIS1983;
1589 ip->escape = 0;
1590 return;
1591 case 'D':
1592 ip->G0 = CSET_JIS1990;
1593 ip->escape = 0;
1594 return;
1595 default:
1596 /* not supported */
1597 ip->escape = 0;
1598 return;
1599 }
1600
1601 case ' ':
1602 switch (c) {
1603 case 'F':
1604 ip->eightbit_C1 = 0;
1605 ip->escape = 0;
1606 return;
1607
1608 case 'G':
1609 ip->eightbit_C1 = 1;
1610 ip->escape = 0;
1611 return;
1612
1613 default:
1614 /* not supported */
1615 ip->escape = 0;
1616 return;
1617 }
1618 break;
1619
1620 case '#':
1621 switch (c) {
1622 case '5':
1623 /* single height, single width */
1624 ip->escape = 0;
1625 return;
1626
1627 case '6':
1628 /* double width, single height */
1629 ip->escape = 0;
1630 return;
1631
1632 case '3':
1633 /* top half */
1634 ip->escape = 0;
1635 return;
1636
1637 case '4':
1638 /* bottom half */
1639 ip->escape = 0;
1640 return;
1641
1642 case '8':
1643 /* screen alignment pattern... */
1644 alignment_display (ip);
1645 ip->escape = 0;
1646 return;
1647
1648 default:
1649 ip->escape = 0;
1650 return;
1651 }
1652 break;
1653
1654
1655
1656 case CSI:
1657 /* the biggie... */
1658 switch (c) {
1659 case '0': case '1': case '2': case '3': case '4':
1660 case '5': case '6': case '7': case '8': case '9':
1661 case ';': case '\"': case '$': case '>':
1662 if (ip->ap < ip->argbuf + MAX_ARGSIZE)
1663 *ip->ap++ = c;
1664 return;
1665
1666 case 'p':
1667 *ip->ap = 0;
1668 if (!strncmp(ip->argbuf, "61\"", 3))
1669 ip->emul_level = EMUL_VT100;
1670 else if (!strncmp(ip->argbuf, "63;1\"", 5)
1671 || !strncmp(ip->argbuf, "62;1\"", 5))
1672 ip->emul_level = EMUL_VT300_7;
1673 else
1674 ip->emul_level = EMUL_VT300_8;
1675 ip->escape = 0;
1676 return;
1677
1678
1679 case '?':
1680 *ip->ap = 0;
1681 ip->escape = '?';
1682 ip->ap = ip->argbuf;
1683 return;
1684
1685
1686 case 'c':
1687 /* device attributes */
1688 *ip->ap = 0;
1689 if (ip->argbuf[0] == '>') {
1690 ite_sendstr (ip, "\033[>24;0;0;0c");
1691 } else
1692 switch (ite_zargnum(ip)) {
1693 case 0:
1694 /* primary DA request, send primary DA response */
1695 if (ip->emul_level == EMUL_VT100)
1696 ite_sendstr (ip, "\033[?1;1c");
1697 else
1698 ite_sendstr (ip, "\033[63;0c");
1699 break;
1700 }
1701 ip->escape = 0;
1702 return;
1703
1704 case 'n':
1705 switch (ite_zargnum(ip)) {
1706 case 5:
1707 ite_sendstr (ip, "\033[0n"); /* no malfunction */
1708 break;
1709 case 6:
1710 /* cursor position report */
1711 sprintf (ip->argbuf, "\033[%d;%dR",
1712 ip->cury + 1, ip->curx + 1);
1713 ite_sendstr (ip, ip->argbuf);
1714 break;
1715 }
1716 ip->escape = 0;
1717 return;
1718
1719
1720 case 'x':
1721 switch (ite_zargnum(ip)) {
1722 case 0:
1723 /* Fake some terminal parameters. */
1724 ite_sendstr (ip, "\033[2;1;1;112;112;1;0x");
1725 break;
1726 case 1:
1727 ite_sendstr (ip, "\033[3;1;1;112;112;1;0x");
1728 break;
1729 }
1730 ip->escape = 0;
1731 return;
1732
1733
1734 case 'g':
1735 /* clear tabs */
1736 switch (ite_zargnum(ip)) {
1737 case 0:
1738 if (ip->curx < ip->cols)
1739 ip->tabs[ip->curx] = 0;
1740 break;
1741 case 3:
1742 for (n = 0; n < ip->cols; n++)
1743 ip->tabs[n] = 0;
1744 break;
1745
1746 default:
1747 /* ignore */
1748 break;
1749 }
1750 ip->escape = 0;
1751 return;
1752
1753
1754 case 'h': /* set mode */
1755 case 'l': /* reset mode */
1756 n = ite_zargnum (ip);
1757 switch (n) {
1758 case 4:
1759 ip->imode = (c == 'h'); /* insert/replace mode */
1760 break;
1761 case 20:
1762 ip->linefeed_newline = (c == 'h');
1763 break;
1764 }
1765 ip->escape = 0;
1766 return;
1767
1768
1769 case 'M':
1770 /* delete line */
1771 ite_dnline (ip, ite_argnum (ip));
1772 ip->escape = 0;
1773 return;
1774
1775
1776 case 'L':
1777 /* insert line */
1778 ite_inline (ip, ite_argnum (ip));
1779 ip->escape = 0;
1780 return;
1781
1782
1783 case 'P':
1784 /* delete char */
1785 ite_dnchar (ip, ite_argnum (ip));
1786 ip->escape = 0;
1787 return;
1788
1789
1790 case '@':
1791 /* insert char(s) */
1792 ite_inchar (ip, ite_argnum (ip));
1793 ip->escape = 0;
1794 return;
1795
1796 case '!':
1797 /* soft terminal reset */
1798 ip->escape = 0; /* XXX */
1799 return;
1800
1801 case 'G':
1802 /* this one was *not* in my vt320 manual but in
1803 a vt320 termcap entry.. who is right?
1804 It's supposed to set the horizontal cursor position. */
1805 *ip->ap = 0;
1806 x = atoi (ip->argbuf);
1807 if (x) x--;
1808 ip->curx = min(x, ip->cols - 1);
1809 ip->escape = 0;
1810 SUBR_CURSOR(ip, MOVE_CURSOR);
1811 clr_attr (ip, ATTR_INV);
1812 return;
1813
1814
1815 case 'd':
1816 /* same thing here, this one's for setting the absolute
1817 vertical cursor position. Not documented... */
1818 *ip->ap = 0;
1819 y = atoi (ip->argbuf);
1820 if (y) y--;
1821 if (ip->inside_margins)
1822 y += ip->top_margin;
1823 ip->cury = min(y, ip->rows - 1);
1824 ip->escape = 0;
1825 snap_cury(ip);
1826 SUBR_CURSOR(ip, MOVE_CURSOR);
1827 clr_attr (ip, ATTR_INV);
1828 return;
1829
1830
1831 case 'H':
1832 case 'f':
1833 *ip->ap = 0;
1834 y = atoi (ip->argbuf);
1835 x = 0;
1836 cp = index (ip->argbuf, ';');
1837 if (cp)
1838 x = atoi (cp + 1);
1839 if (x) x--;
1840 if (y) y--;
1841 if (ip->inside_margins)
1842 y += ip->top_margin;
1843 ip->cury = min(y, ip->rows - 1);
1844 ip->curx = min(x, ip->cols - 1);
1845 ip->escape = 0;
1846 snap_cury(ip);
1847 SUBR_CURSOR(ip, MOVE_CURSOR);
1848 /*clr_attr (ip, ATTR_INV);*/
1849 return;
1850
1851 case 'A':
1852 /* cursor up */
1853 n = ite_argnum (ip);
1854 n = ip->cury - (n ? n : 1);
1855 if (n < 0) n = 0;
1856 if (ip->inside_margins)
1857 n = max(ip->top_margin, n);
1858 else if (n == ip->top_margin - 1)
1859 /* allow scrolling outside region, but don't scroll out
1860 of active region without explicit CUP */
1861 n = ip->top_margin;
1862 ip->cury = n;
1863 ip->escape = 0;
1864 SUBR_CURSOR(ip, MOVE_CURSOR);
1865 clr_attr (ip, ATTR_INV);
1866 return;
1867
1868 case 'B':
1869 /* cursor down */
1870 n = ite_argnum (ip);
1871 n = ip->cury + (n ? n : 1);
1872 n = min(ip->rows - 1, n);
1873 #if 0
1874 if (ip->inside_margins)
1875 #endif
1876 n = min(ip->bottom_margin, n);
1877 #if 0
1878 else if (n == ip->bottom_margin + 1)
1879 /* allow scrolling outside region, but don't scroll out
1880 of active region without explicit CUP */
1881 n = ip->bottom_margin;
1882 #endif
1883 ip->cury = n;
1884 ip->escape = 0;
1885 SUBR_CURSOR(ip, MOVE_CURSOR);
1886 clr_attr (ip, ATTR_INV);
1887 return;
1888
1889 case 'C':
1890 /* cursor forward */
1891 n = ite_argnum (ip);
1892 n = n ? n : 1;
1893 ip->curx = min(ip->curx + n, ip->cols - 1);
1894 ip->escape = 0;
1895 SUBR_CURSOR(ip, MOVE_CURSOR);
1896 clr_attr (ip, ATTR_INV);
1897 return;
1898
1899 case 'D':
1900 /* cursor backward */
1901 n = ite_argnum (ip);
1902 n = n ? n : 1;
1903 n = ip->curx - n;
1904 ip->curx = n >= 0 ? n : 0;
1905 ip->escape = 0;
1906 SUBR_CURSOR(ip, MOVE_CURSOR);
1907 clr_attr (ip, ATTR_INV);
1908 return;
1909
1910
1911 case 'J':
1912 /* erase screen */
1913 *ip->ap = 0;
1914 n = ite_zargnum (ip);
1915 if (n == 0)
1916 ite_clrtoeos(ip);
1917 else if (n == 1)
1918 ite_clrtobos(ip);
1919 else if (n == 2)
1920 ite_clrscreen(ip);
1921 ip->escape = 0;
1922 return;
1923
1924
1925 case 'K':
1926 /* erase line */
1927 n = ite_zargnum (ip);
1928 if (n == 0)
1929 ite_clrtoeol(ip);
1930 else if (n == 1)
1931 ite_clrtobol(ip);
1932 else if (n == 2)
1933 ite_clrline(ip);
1934 ip->escape = 0;
1935 return;
1936
1937 case 'S':
1938 /* scroll up */
1939 n = ite_zargnum (ip);
1940 if (n <= 0)
1941 n = 1;
1942 else if (n > ip->rows-1)
1943 n = ip->rows-1;
1944 SUBR_SCROLL(ip, ip->rows-1, 0, n, SCROLL_UP);
1945 ip->escape = 0;
1946 return;
1947
1948 case 'T':
1949 /* scroll down */
1950 n = ite_zargnum (ip);
1951 if (n <= 0)
1952 n = 1;
1953 else if (n > ip->rows-1)
1954 n = ip->rows-1;
1955 SUBR_SCROLL(ip, 0, 0, n, SCROLL_DOWN);
1956 ip->escape = 0;
1957 return;
1958
1959 case 'X':
1960 /* erase character */
1961 n = ite_argnum(ip) - 1;
1962 n = min(n, ip->cols - 1 - ip->curx);
1963 for (; n >= 0; n--) {
1964 attrclr(ip, ip->cury, ip->curx + n, 1, 1);
1965 SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1966 }
1967 ip->escape = 0;
1968 return;
1969
1970
1971 case '}': case '`':
1972 /* status line control */
1973 ip->escape = 0;
1974 return;
1975
1976 case 'r':
1977 /* set scrolling region */
1978 ip->escape = 0;
1979 *ip->ap = 0;
1980 x = atoi (ip->argbuf);
1981 x = x ? x : 1;
1982 y = ip->rows;
1983 cp = index (ip->argbuf, ';');
1984 if (cp) {
1985 y = atoi (cp + 1);
1986 y = y ? y : ip->rows;
1987 }
1988 if (y <= x)
1989 return;
1990 x--;
1991 y--;
1992 ip->top_margin = min(x, ip->rows - 2);
1993 ip->bottom_margin = min(y, ip->rows - 1);
1994 if (ip->inside_margins) {
1995 ip->cury = ip->top_margin;
1996 } else
1997 ip->cury = 0;
1998 ip->curx = 0;
1999 return;
2000
2001
2002 case 'm':
2003 /* big attribute setter/resetter */
2004 {
2005 char *cp;
2006 *ip->ap = 0;
2007 /* kludge to make CSIm work (== CSI0m) */
2008 if (ip->ap == ip->argbuf)
2009 ip->ap++;
2010 for (cp = ip->argbuf; cp < ip->ap; ) {
2011 switch (*cp) {
2012 case 0:
2013 case '0':
2014 clr_attr (ip, ATTR_ALL);
2015 ip->fgcolor = 7;
2016 ip->bgcolor = 0;
2017 cp++;
2018 break;
2019
2020 case '1':
2021 set_attr (ip, ATTR_BOLD);
2022 cp++;
2023 break;
2024
2025 case '2':
2026 switch (cp[1]) {
2027 case '2':
2028 clr_attr (ip, ATTR_BOLD);
2029 cp += 2;
2030 break;
2031
2032 case '4':
2033 clr_attr (ip, ATTR_UL);
2034 cp += 2;
2035 break;
2036
2037 case '5':
2038 clr_attr (ip, ATTR_BLINK);
2039 cp += 2;
2040 break;
2041
2042 case '7':
2043 clr_attr (ip, ATTR_INV);
2044 cp += 2;
2045 break;
2046
2047 default:
2048 cp++;
2049 break;
2050 }
2051 break;
2052
2053 case '3':
2054 switch (cp[1]) {
2055 case '0': case '1': case '2': case '3':
2056 case '4': case '5': case '6': case '7':
2057 /* foreground colors */
2058 ip->fgcolor = cp[1] - '0';
2059 cp += 2;
2060 break;
2061 default:
2062 cp++;
2063 break;
2064 }
2065 break;
2066
2067 case '4':
2068 switch (cp[1]) {
2069 case '0': case '1': case '2': case '3':
2070 case '4': case '5': case '6': case '7':
2071 /* background colors */
2072 ip->bgcolor = cp[1] - '0';
2073 cp += 2;
2074 break;
2075 default:
2076 set_attr (ip, ATTR_UL);
2077 cp++;
2078 break;
2079 }
2080 break;
2081
2082 case '5':
2083 set_attr (ip, ATTR_BLINK);
2084 cp++;
2085 break;
2086
2087 case '7':
2088 set_attr (ip, ATTR_INV);
2089 cp++;
2090 break;
2091
2092 default:
2093 cp++;
2094 break;
2095 }
2096 }
2097
2098 }
2099 ip->escape = 0;
2100 return;
2101
2102
2103 case 'u':
2104 /* DECRQTSR */
2105 ite_sendstr (ip, "\033P\033\\");
2106 ip->escape = 0;
2107 return;
2108
2109 default:
2110 ip->escape = 0;
2111 return;
2112 }
2113 break;
2114
2115
2116
2117 case '?': /* CSI ? */
2118 switch (c) {
2119 case '0': case '1': case '2': case '3': case '4':
2120 case '5': case '6': case '7': case '8': case '9':
2121 case ';': case '\"': case '$':
2122 /* Don't fill the last character; it's needed. */
2123 /* XXX yeah, where ?? */
2124 if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
2125 *ip->ap++ = c;
2126 return;
2127
2128
2129 case 'n':
2130 /* Terminal Reports */
2131 *ip->ap = 0;
2132 if (ip->ap == &ip->argbuf[2]) {
2133 if (!strncmp(ip->argbuf, "15", 2))
2134 /* printer status: no printer */
2135 ite_sendstr (ip, "\033[13n");
2136
2137 else if (!strncmp(ip->argbuf, "25", 2))
2138 /* udk status */
2139 ite_sendstr (ip, "\033[20n");
2140
2141 else if (!strncmp(ip->argbuf, "26", 2))
2142 /* keyboard dialect: US */
2143 ite_sendstr (ip, "\033[27;1n");
2144 }
2145 ip->escape = 0;
2146 return;
2147
2148
2149 case 'h': /* set dec private modes */
2150 case 'l': /* reset dec private modes */
2151 n = ite_zargnum (ip);
2152 switch (n) {
2153 case 1:
2154 /* CKM - cursor key mode */
2155 ip->cursor_appmode = (c == 'h');
2156 break;
2157
2158 case 3:
2159 /* 132/80 columns (132 == 'h') */
2160 break;
2161
2162 case 4: /* smooth scroll */
2163 break;
2164
2165 case 5:
2166 /* light background (=='h') /dark background(=='l') */
2167 break;
2168
2169 case 6: /* origin mode */
2170 ip->inside_margins = (c == 'h');
2171 #if 0
2172 ip->curx = 0;
2173 ip->cury = ip->inside_margins ? ip->top_margin : 0;
2174 SUBR_CURSOR(ip, MOVE_CURSOR);
2175 #endif
2176 break;
2177
2178 case 7: /* auto wraparound */
2179 ip->auto_wrap = (c == 'h');
2180 break;
2181
2182 case 8: /* keyboard repeat */
2183 ip->key_repeat = (c == 'h');
2184 break;
2185
2186 case 20: /* newline mode */
2187 ip->linefeed_newline = (c == 'h');
2188 break;
2189
2190 case 25: /* cursor on/off */
2191 SUBR_CURSOR(ip, (c == 'h') ? DRAW_CURSOR : ERASE_CURSOR);
2192 break;
2193 }
2194 ip->escape = 0;
2195 return;
2196
2197 case 'K':
2198 /* selective erase in line */
2199 case 'J':
2200 /* selective erase in display */
2201
2202 default:
2203 ip->escape = 0;
2204 return;
2205 }
2206 break;
2207
2208
2209 default:
2210 ip->escape = 0;
2211 return;
2212 }
2213 }
2214
2215 switch (c) {
2216 case 0x00: /* NUL */
2217 case 0x01: /* SOH */
2218 case 0x02: /* STX */
2219 case 0x03: /* ETX */
2220 case 0x04: /* EOT */
2221 case 0x05: /* ENQ */
2222 case 0x06: /* ACK */
2223 break;
2224
2225 case BEL:
2226 #if NBELL > 0
2227 if (kbd_ite && ite_tty[kbd_ite->device.dv_unit])
2228 opm_bell();
2229 #endif
2230 break;
2231
2232 case BS:
2233 if (--ip->curx < 0)
2234 ip->curx = 0;
2235 else
2236 SUBR_CURSOR(ip, MOVE_CURSOR);
2237 break;
2238
2239 case HT:
2240 for (n = ip->curx + 1; n < ip->cols; n++) {
2241 if (ip->tabs[n]) {
2242 ip->curx = n;
2243 SUBR_CURSOR(ip, MOVE_CURSOR);
2244 break;
2245 }
2246 }
2247 break;
2248
2249 case VT: /* VT is treated like LF */
2250 case FF: /* so is FF */
2251 case LF:
2252 /* cr->crlf distinction is done here, on output,
2253 not on input! */
2254 if (ip->linefeed_newline)
2255 ite_crlf (ip);
2256 else
2257 ite_lf (ip);
2258 break;
2259
2260 case CR:
2261 ite_cr (ip);
2262 break;
2263
2264
2265 case SO:
2266 ip->GL = &ip->G1;
2267 break;
2268
2269 case SI:
2270 ip->GL = &ip->G0;
2271 break;
2272
2273 case 0x10: /* DLE */
2274 case 0x11: /* DC1/XON */
2275 case 0x12: /* DC2 */
2276 case 0x13: /* DC3/XOFF */
2277 case 0x14: /* DC4 */
2278 case 0x15: /* NAK */
2279 case 0x16: /* SYN */
2280 case 0x17: /* ETB */
2281 break;
2282
2283 case CAN:
2284 ip->escape = 0; /* cancel any escape sequence in progress */
2285 break;
2286
2287 case 0x19: /* EM */
2288 break;
2289
2290 case SUB:
2291 ip->escape = 0; /* dito, but see below */
2292 /* should also display a reverse question mark!! */
2293 break;
2294
2295 case ESC:
2296 ip->escape = ESC;
2297 break;
2298
2299 case 0x1c: /* FS */
2300 case 0x1d: /* GS */
2301 case 0x1e: /* RS */
2302 case 0x1f: /* US */
2303 break;
2304
2305 /* now it gets weird.. 8bit control sequences.. */
2306 case IND: /* index: move cursor down, scroll */
2307 ite_index (ip);
2308 break;
2309
2310 case NEL: /* next line. next line, first pos. */
2311 ite_crlf (ip);
2312 break;
2313
2314 case HTS: /* set horizontal tab */
2315 if (ip->curx < ip->cols)
2316 ip->tabs[ip->curx] = 1;
2317 break;
2318
2319 case RI: /* reverse index */
2320 ite_rlf (ip);
2321 break;
2322
2323 case SS2: /* go into G2 for one character */
2324 ip->save_GL = ip->GR; /* GL XXX EUC */
2325 ip->GR = &ip->G2; /* GL XXX */
2326 break;
2327
2328 case SS3: /* go into G3 for one character */
2329 ip->save_GL = ip->GR; /* GL XXX EUC */
2330 ip->GR = &ip->G3; /* GL XXX */
2331 break;
2332
2333 case DCS: /* device control string introducer */
2334 ip->escape = DCS;
2335 ip->ap = ip->argbuf;
2336 break;
2337
2338 case CSI: /* control sequence introducer */
2339 ip->escape = CSI;
2340 ip->ap = ip->argbuf;
2341 break;
2342
2343 case ST: /* string terminator */
2344 /* ignore, if not used as terminator */
2345 break;
2346
2347 case OSC: /* introduces OS command. Ignore everything upto ST */
2348 ip->escape = OSC;
2349 break;
2350
2351 case PM: /* privacy message, ignore everything upto ST */
2352 ip->escape = PM;
2353 break;
2354
2355 case APC: /* application program command, ignore everything upto ST */
2356 ip->escape = APC;
2357 break;
2358
2359 case DEL:
2360 break;
2361
2362 default:
2363 if (!ip->save_char && (*((c & 0x80) ? ip->GR : ip->GL) & CSET_MULTI)) {
2364 ip->save_char = c;
2365 break;
2366 }
2367 if (ip->imode)
2368 ite_inchar(ip, ip->save_char ? 2 : 1);
2369 iteprecheckwrap(ip);
2370 #ifdef DO_WEIRD_ATTRIBUTES
2371 if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
2372 attrset(ip, ATTR_INV);
2373 SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
2374 }
2375 else
2376 SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
2377 #else
2378 SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
2379 #endif
2380 /* SUBR_CURSOR(ip, DRAW_CURSOR);*/
2381 itecheckwrap(ip);
2382 if (ip->save_char) {
2383 itecheckwrap(ip);
2384 ip->save_char = 0;
2385 }
2386 if (ip->save_GL) {
2387 /*
2388 * reset single shift
2389 */
2390 ip->GR = ip->save_GL;
2391 ip->save_GL = 0;
2392 }
2393 break;
2394 }
2395 }
2396
2397 static void
2398 iteprecheckwrap(ip)
2399 struct ite_softc *ip;
2400 {
2401 if (ip->auto_wrap && ip->curx + (ip->save_char ? 1 : 0) == ip->cols) {
2402 ip->curx = 0;
2403 clr_attr(ip, ATTR_INV);
2404 if (++ip->cury >= ip->bottom_margin + 1) {
2405 ip->cury = ip->bottom_margin;
2406 /*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2407 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2408 ite_clrtoeol(ip);
2409 } /*else
2410 SUBR_CURSOR(ip, MOVE_CURSOR);*/
2411 }
2412 }
2413
2414 static void
2415 itecheckwrap(ip)
2416 struct ite_softc *ip;
2417 {
2418 #if 0
2419 if (++ip->curx == ip->cols) {
2420 if (ip->auto_wrap) {
2421 ip->curx = 0;
2422 clr_attr(ip, ATTR_INV);
2423 if (++ip->cury >= ip->bottom_margin + 1) {
2424 ip->cury = ip->bottom_margin;
2425 SUBR_CURSOR(ip, MOVE_CURSOR);
2426 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2427 ite_clrtoeol(ip);
2428 return;
2429 }
2430 } else
2431 /* stay there if no autowrap.. */
2432 ip->curx--;
2433 }
2434 #else
2435 if (ip->curx < ip->cols) {
2436 ip->curx++;
2437 /*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2438 }
2439 #endif
2440 }
2441
2442 #endif
2443
2444 /*
2445 * Console functions
2446 */
2447 #include <dev/cons.h>
2448
2449 /*
2450 * Return a priority in consdev->cn_pri field highest wins. This function
2451 * is called before any devices have been probed.
2452 */
2453 void
2454 itecnprobe(cd)
2455 struct consdev *cd;
2456 {
2457 int maj;
2458
2459 /*
2460 * bring graphics layer up.
2461 */
2462 config_console();
2463
2464 /* locate the major number */
2465 for (maj = 0; maj < nchrdev; maj++)
2466 if (cdevsw[maj].d_open == iteopen)
2467 break;
2468
2469 /*
2470 * return priority of the best ite (already picked from attach)
2471 * or CN_DEAD.
2472 */
2473 if (con_itesoftc.grf == NULL)
2474 cd->cn_pri = CN_DEAD;
2475 else {
2476 con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
2477 con_itesoftc.isw = &itesw[0]; /* XXX */
2478 cd->cn_pri = CN_INTERNAL;
2479 cd->cn_dev = makedev(maj, 0); /* XXX */
2480 }
2481
2482 }
2483
2484 void
2485 itecninit(cd)
2486 struct consdev *cd;
2487 {
2488 struct ite_softc *ip;
2489
2490 ip = getitesp(cd->cn_dev);
2491 iteinit(cd->cn_dev); /* init console unit */
2492 ip->flags |= ITE_ACTIVE | ITE_ISCONS;
2493 }
2494
2495 /*
2496 * itecnfinish() is called in ite_init() when the device is
2497 * being probed in the normal fasion, thus we can finish setting
2498 * up this ite now that the system is more functional.
2499 */
2500 void
2501 itecnfinish(ip)
2502 struct ite_softc *ip;
2503 {
2504 static int done;
2505
2506 if (done)
2507 return;
2508 done = 1;
2509 }
2510
2511 /*ARGSUSED*/
2512 int
2513 itecngetc(dev)
2514 dev_t dev;
2515 {
2516 register int c;
2517
2518 /* XXX this should be moved */
2519 if (!kbd_init) {
2520 kbd_init = 1;
2521 kbdenable();
2522 }
2523 do {
2524 c = kbdgetcn();
2525 c = ite_cnfilter(c, ITEFILT_CONSOLE);
2526 } while (c == -1);
2527 return (c);
2528 }
2529
2530 void
2531 itecnputc(dev, c)
2532 dev_t dev;
2533 int c;
2534 {
2535 static int paniced = 0;
2536 struct ite_softc *ip = getitesp(dev);
2537 char ch = c;
2538
2539 if (panicstr && !paniced &&
2540 (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
2541 (void) iteon(dev, 3);
2542 paniced = 1;
2543 }
2544 ite_putstr(&ch, 1, dev);
2545 }
2546