ite.c revision 1.8 1 /* $NetBSD: ite.c,v 1.8 1997/10/12 18:06:24 oki 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
66 #include <x68k/dev/grfioctl.h>
67 #include <x68k/dev/grfvar.h>
68 #include <x68k/dev/itevar.h>
69 #include <x68k/dev/kbdmap.h>
70
71 #include <x68k/x68k/iodevice.h>
72 #include <x68k/dev/iteioctl.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 *, void *, void *));
153
154 struct cfattach ite_ca = {
155 sizeof(struct ite_softc), itematch, iteattach
156 };
157
158 struct cfdriver ite_cd = {
159 NULL, "ite", DV_DULL, NULL, 0
160 };
161
162 int
163 itematch(pdp, match, auxp)
164 struct device *pdp;
165 void *match, *auxp;
166 {
167 struct cfdata *cdp = match;
168 struct grf_softc *gp;
169 int maj;
170
171 gp = auxp;
172
173 /* ite0 should be at grf0 XXX */
174 if(cdp->cf_unit != gp->g_device.dv_unit)
175 return(0);
176
177 #if 0
178 /*
179 * all that our mask allows (more than enough no one
180 * has > 32 monitors for text consoles on one machine)
181 */
182 if (cdp->cf_unit >= sizeof(ite_confunits) * NBBY)
183 return(0);
184 /*
185 * XXX
186 * normally this would be done in attach, however
187 * during early init we do not have a device pointer
188 * and thus no unit number.
189 */
190 for(maj = 0; maj < nchrdev; maj++)
191 if (cdevsw[maj].d_open == iteopen)
192 break;
193 gp->g_itedev = makedev(maj, cdp->cf_unit);
194 #endif
195 return(1);
196 }
197
198 /*
199 * iteinit() is the standard entry point for initialization of
200 * an ite device, it is also called from ite_cninit().
201 */
202 void
203 iteattach(pdp, dp, auxp)
204 struct device *pdp, *dp;
205 void *auxp;
206 {
207 struct ite_softc *ip;
208 struct grf_softc *gp;
209
210 gp = (struct grf_softc *)auxp;
211 if (dp) {
212 ip = (struct ite_softc *)dp;
213 if(con_itesoftc.grf != NULL
214 /*&& con_itesoftc.grf->g_unit == gp->g_unit*/) {
215 /*
216 * console reinit copy params over.
217 * and console always gets keyboard
218 */
219 bcopy(&con_itesoftc.grf, &ip->grf,
220 (char *)&ip[1] - (char *)&ip->grf);
221 con_itesoftc.grf = NULL;
222 kbd_ite = ip;
223 }
224 ip->grf = gp;
225 iteinit(ip->device.dv_unit); /* XXX */
226 printf(": rows %d cols %d", ip->rows, ip->cols);
227 if (kbd_ite == NULL)
228 kbd_ite = ip;
229 printf("\n");
230 } else {
231 if (con_itesoftc.grf != NULL)
232 return;
233 con_itesoftc.grf = gp;
234 con_itesoftc.tabs = cons_tabs;
235 }
236 }
237
238 struct ite_softc *
239 getitesp(dev)
240 dev_t dev;
241 {
242 extern int x68k_realconfig;
243
244 if (x68k_realconfig && con_itesoftc.grf == NULL)
245 return(ite_cd.cd_devs[UNIT(dev)]);
246
247 if (con_itesoftc.grf == NULL)
248 panic("no ite_softc for console");
249 return(&con_itesoftc);
250 }
251
252 void
253 iteinit(dev)
254 dev_t dev;
255 {
256 struct ite_softc *ip;
257
258 ip = getitesp(dev);
259
260 if (ip->flags & ITE_INITED)
261 return;
262 bcopy(&ascii_kbdmap, &kbdmap, sizeof(struct kbdmap));
263
264 ip->curx = 0;
265 ip->cury = 0;
266 ip->cursorx = 0;
267 ip->cursory = 0;
268
269 ip->isw = &itesw[ip->device.dv_unit]; /* XXX */
270 SUBR_INIT(ip);
271 SUBR_CURSOR(ip, DRAW_CURSOR);
272 if (!ip->tabs)
273 ip->tabs = malloc(MAX_TABS*sizeof(u_char), M_DEVBUF, M_WAITOK);
274 ite_reset(ip);
275 ip->flags |= ITE_INITED;
276 }
277
278 /*
279 * Perform functions necessary to setup device as a terminal emulator.
280 */
281 int
282 iteon(dev, flag)
283 dev_t dev;
284 int flag;
285 {
286 int unit = UNIT(dev);
287 struct ite_softc *ip = getitesp(unit);
288
289 if (unit < 0 || unit >= ite_cd.cd_ndevs || (ip->flags&ITE_ALIVE) == 0)
290 return(ENXIO);
291 /* force ite active, overriding graphics mode */
292 if (flag & 1) {
293 ip->flags |= ITE_ACTIVE;
294 ip->flags &= ~(ITE_INGRF|ITE_INITED);
295 }
296 /* leave graphics mode */
297 if (flag & 2) {
298 ip->flags &= ~ITE_INGRF;
299 if ((ip->flags & ITE_ACTIVE) == 0)
300 return(0);
301 }
302 ip->flags |= ITE_ACTIVE;
303 if (ip->flags & ITE_INGRF)
304 return(0);
305 iteinit(dev);
306 return(0);
307 }
308
309 /*
310 * "Shut down" device as terminal emulator.
311 * Note that we do not deinit the console device unless forced.
312 * Deinit'ing the console every time leads to a very active
313 * screen when processing /etc/rc.
314 */
315 void
316 iteoff(dev, flag)
317 dev_t dev;
318 int flag;
319 {
320 int unit = UNIT(dev);
321 register struct ite_softc *ip = getitesp(unit);
322
323 /* XXX check whether when call from grf.c */
324 if (unit < 0 || unit >= ite_cd.cd_ndevs || (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 return;
573
574 ip = getitesp(dev);
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 struct tty *kbd_tty;
1325 int n, x, y;
1326 char *cp;
1327
1328 kbd_tty = ite_tty[kbd_ite->device.dv_unit];
1329
1330 if (c >= 0x20 && ip->escape) {
1331 switch (ip->escape) {
1332
1333 case ESC:
1334 switch (c) {
1335 /* first 7bit equivalents for the 8bit control characters */
1336
1337 case 'D':
1338 c = IND;
1339 ip->escape = 0;
1340 break; /* and fall into the next switch below (same for all `break') */
1341
1342 case 'E':
1343 /* next line */
1344 c = NEL;
1345 ip->escape = 0;
1346 break;
1347
1348 case 'H':
1349 /* set TAB at current col */
1350 c = HTS;
1351 ip->escape = 0;
1352 break;
1353
1354 case 'M':
1355 /* reverse index */
1356 c = RI;
1357 ip->escape = 0;
1358 break;
1359
1360 case 'N':
1361 /* single shift G2 */
1362 c = SS2;
1363 ip->escape = 0;
1364 break;
1365
1366 case 'O':
1367 /* single shift G3 */
1368 c = SS3;
1369 ip->escape = 0;
1370 break;
1371
1372 case 'P':
1373 /* DCS detected */
1374 c = DCS;
1375 ip->escape = 0;
1376 break;
1377
1378 case '[':
1379 c = CSI;
1380 ip->escape = 0;
1381 break;
1382
1383 case '\\':
1384 /* String Terminator */
1385 c = ST;
1386 ip->escape = 0;
1387 break;
1388
1389 case ']':
1390 c = OSC;
1391 ip->escape = 0;
1392 break;
1393
1394 case '^':
1395 c = PM;
1396 ip->escape = 0;
1397 break;
1398
1399 case '_':
1400 c = APC;
1401 ip->escape = 0;
1402 break;
1403
1404
1405 /* introduces 7/8bit control */
1406 case ' ':
1407 /* can be followed by either F or G */
1408 ip->escape = ' ';
1409 break;
1410
1411
1412 /* a lot of character set selections, not yet used...
1413 94-character sets: */
1414 case '(': /* G0 */
1415 case ')': /* G1 */
1416 ip->escape = c;
1417 return;
1418
1419 case '*': /* G2 */
1420 case '+': /* G3 */
1421 case 'B': /* ASCII */
1422 case 'A': /* ISO latin 1 */
1423 case '<': /* user preferred suplemental */
1424 case '0': /* dec special graphics */
1425
1426 /* 96-character sets: */
1427 case '-': /* G1 */
1428 case '.': /* G2 */
1429 case '/': /* G3 */
1430
1431 /* national character sets: */
1432 case '4': /* dutch */
1433 case '5':
1434 case 'C': /* finnish */
1435 case 'R': /* french */
1436 case 'Q': /* french canadian */
1437 case 'K': /* german */
1438 case 'Y': /* italian */
1439 case '6': /* norwegian/danish */
1440 /* note: %5 and %6 are not supported (two chars..) */
1441
1442 ip->escape = 0;
1443 /* just ignore for now */
1444 return;
1445
1446 /* 94-multibyte character sets designate */
1447 case '$':
1448 ip->escape = '$';
1449 return;
1450
1451 /* locking shift modes */
1452 case '`':
1453 ip->GR = &ip->G1;
1454 ip->escape = 0;
1455 return;
1456
1457 case 'n':
1458 ip->GL = &ip->G2;
1459 ip->escape = 0;
1460 return;
1461
1462 case '}':
1463 ip->GR = &ip->G2;
1464 ip->escape = 0;
1465 return;
1466
1467 case 'o':
1468 ip->GL = &ip->G3;
1469 ip->escape = 0;
1470 return;
1471
1472 case '|':
1473 ip->GR = &ip->G3;
1474 ip->escape = 0;
1475 return;
1476
1477 case '~':
1478 ip->GR = &ip->G1;
1479 ip->escape = 0;
1480 return;
1481
1482 /* font width/height control */
1483 case '#':
1484 ip->escape = '#';
1485 return;
1486
1487 case 'c':
1488 /* hard terminal reset .. */
1489 ite_reset (ip);
1490 SUBR_CURSOR(ip, MOVE_CURSOR);
1491 ip->escape = 0;
1492 return;
1493
1494
1495 case '7':
1496 /* save cursor */
1497 ip->save_curx = ip->curx;
1498 ip->save_cury = ip->cury;
1499 ip->save_attribute = ip->attribute;
1500 ip->sc_om = ip->inside_margins;
1501 ip->sc_G0 = ip->G0;
1502 ip->sc_G1 = ip->G1;
1503 ip->sc_G2 = ip->G2;
1504 ip->sc_G3 = ip->G3;
1505 ip->sc_GL = ip->GL;
1506 ip->sc_GR = ip->GR;
1507 ip->escape = 0;
1508 return;
1509
1510 case '8':
1511 /* restore cursor */
1512 ip->curx = ip->save_curx;
1513 ip->cury = ip->save_cury;
1514 ip->attribute = ip->save_attribute;
1515 ip->inside_margins = ip->sc_om;
1516 ip->G0 = ip->sc_G0;
1517 ip->G1 = ip->sc_G1;
1518 ip->G2 = ip->sc_G2;
1519 ip->G3 = ip->sc_G3;
1520 ip->GL = ip->sc_GL;
1521 ip->GR = ip->sc_GR;
1522 SUBR_CURSOR(ip, MOVE_CURSOR);
1523 ip->escape = 0;
1524 return;
1525
1526 case '=':
1527 /* keypad application mode */
1528 ip->keypad_appmode = 1;
1529 ip->escape = 0;
1530 return;
1531
1532 case '>':
1533 /* keypad numeric mode */
1534 ip->keypad_appmode = 0;
1535 ip->escape = 0;
1536 return;
1537
1538 case 'Z': /* request ID */
1539 if (ip->emul_level == EMUL_VT100)
1540 ite_sendstr (ip, "\033[61;0c"); /* XXX not clean */
1541 else
1542 ite_sendstr (ip, "\033[63;0c"); /* XXX not clean */
1543 ip->escape = 0;
1544 return;
1545
1546 /* default catch all for not recognized ESC sequences */
1547 default:
1548 ip->escape = 0;
1549 return;
1550 }
1551 break;
1552
1553
1554 case '(': /* designate G0 */
1555 switch (c) {
1556 case 'B': /* USASCII */
1557 ip->G0 = CSET_ASCII;
1558 ip->escape = 0;
1559 return;
1560 case 'I':
1561 ip->G0 = CSET_JISKANA;
1562 ip->escape = 0;
1563 return;
1564 case 'J':
1565 ip->G0 = CSET_JISROMA;
1566 ip->escape = 0;
1567 return;
1568 case 'A': /* British or ISO-Latin-1 */
1569 case 'H': /* Swedish */
1570 case 'K': /* German */
1571 case 'R': /* French */
1572 case 'Y': /* Italian */
1573 case 'Z': /* Spanish */
1574 default:
1575 /* not supported */
1576 ip->escape = 0;
1577 return;
1578 }
1579
1580 case ')': /* designate G1 */
1581 ip->escape = 0;
1582 return;
1583
1584 case '$': /* 94-multibyte character set */
1585 switch (c) {
1586 case '@':
1587 ip->G0 = CSET_JIS1978;
1588 ip->escape = 0;
1589 return;
1590 case 'B':
1591 ip->G0 = CSET_JIS1983;
1592 ip->escape = 0;
1593 return;
1594 case 'D':
1595 ip->G0 = CSET_JIS1990;
1596 ip->escape = 0;
1597 return;
1598 default:
1599 /* not supported */
1600 ip->escape = 0;
1601 return;
1602 }
1603
1604 case ' ':
1605 switch (c) {
1606 case 'F':
1607 ip->eightbit_C1 = 0;
1608 ip->escape = 0;
1609 return;
1610
1611 case 'G':
1612 ip->eightbit_C1 = 1;
1613 ip->escape = 0;
1614 return;
1615
1616 default:
1617 /* not supported */
1618 ip->escape = 0;
1619 return;
1620 }
1621 break;
1622
1623 case '#':
1624 switch (c) {
1625 case '5':
1626 /* single height, single width */
1627 ip->escape = 0;
1628 return;
1629
1630 case '6':
1631 /* double width, single height */
1632 ip->escape = 0;
1633 return;
1634
1635 case '3':
1636 /* top half */
1637 ip->escape = 0;
1638 return;
1639
1640 case '4':
1641 /* bottom half */
1642 ip->escape = 0;
1643 return;
1644
1645 case '8':
1646 /* screen alignment pattern... */
1647 alignment_display (ip);
1648 ip->escape = 0;
1649 return;
1650
1651 default:
1652 ip->escape = 0;
1653 return;
1654 }
1655 break;
1656
1657
1658
1659 case CSI:
1660 /* the biggie... */
1661 switch (c) {
1662 case '0': case '1': case '2': case '3': case '4':
1663 case '5': case '6': case '7': case '8': case '9':
1664 case ';': case '\"': case '$': case '>':
1665 if (ip->ap < ip->argbuf + MAX_ARGSIZE)
1666 *ip->ap++ = c;
1667 return;
1668
1669 case 'p':
1670 *ip->ap = 0;
1671 if (!strncmp(ip->argbuf, "61\"", 3))
1672 ip->emul_level = EMUL_VT100;
1673 else if (!strncmp(ip->argbuf, "63;1\"", 5)
1674 || !strncmp(ip->argbuf, "62;1\"", 5))
1675 ip->emul_level = EMUL_VT300_7;
1676 else
1677 ip->emul_level = EMUL_VT300_8;
1678 ip->escape = 0;
1679 return;
1680
1681
1682 case '?':
1683 *ip->ap = 0;
1684 ip->escape = '?';
1685 ip->ap = ip->argbuf;
1686 return;
1687
1688
1689 case 'c':
1690 /* device attributes */
1691 *ip->ap = 0;
1692 if (ip->argbuf[0] == '>') {
1693 ite_sendstr (ip, "\033[>24;0;0;0c");
1694 } else
1695 switch (ite_zargnum(ip)) {
1696 case 0:
1697 /* primary DA request, send primary DA response */
1698 if (ip->emul_level == EMUL_VT100)
1699 ite_sendstr (ip, "\033[?1;1c");
1700 else
1701 ite_sendstr (ip, "\033[63;0c");
1702 break;
1703 }
1704 ip->escape = 0;
1705 return;
1706
1707 case 'n':
1708 switch (ite_zargnum(ip)) {
1709 case 5:
1710 ite_sendstr (ip, "\033[0n"); /* no malfunction */
1711 break;
1712 case 6:
1713 /* cursor position report */
1714 sprintf (ip->argbuf, "\033[%d;%dR",
1715 ip->cury + 1, ip->curx + 1);
1716 ite_sendstr (ip, ip->argbuf);
1717 break;
1718 }
1719 ip->escape = 0;
1720 return;
1721
1722
1723 case 'x':
1724 switch (ite_zargnum(ip)) {
1725 case 0:
1726 /* Fake some terminal parameters. */
1727 ite_sendstr (ip, "\033[2;1;1;112;112;1;0x");
1728 break;
1729 case 1:
1730 ite_sendstr (ip, "\033[3;1;1;112;112;1;0x");
1731 break;
1732 }
1733 ip->escape = 0;
1734 return;
1735
1736
1737 case 'g':
1738 /* clear tabs */
1739 switch (ite_zargnum(ip)) {
1740 case 0:
1741 if (ip->curx < ip->cols)
1742 ip->tabs[ip->curx] = 0;
1743 break;
1744 case 3:
1745 for (n = 0; n < ip->cols; n++)
1746 ip->tabs[n] = 0;
1747 break;
1748
1749 default:
1750 /* ignore */
1751 break;
1752 }
1753 ip->escape = 0;
1754 return;
1755
1756
1757 case 'h': /* set mode */
1758 case 'l': /* reset mode */
1759 n = ite_zargnum (ip);
1760 switch (n) {
1761 case 4:
1762 ip->imode = (c == 'h'); /* insert/replace mode */
1763 break;
1764 case 20:
1765 ip->linefeed_newline = (c == 'h');
1766 break;
1767 }
1768 ip->escape = 0;
1769 return;
1770
1771
1772 case 'M':
1773 /* delete line */
1774 ite_dnline (ip, ite_argnum (ip));
1775 ip->escape = 0;
1776 return;
1777
1778
1779 case 'L':
1780 /* insert line */
1781 ite_inline (ip, ite_argnum (ip));
1782 ip->escape = 0;
1783 return;
1784
1785
1786 case 'P':
1787 /* delete char */
1788 ite_dnchar (ip, ite_argnum (ip));
1789 ip->escape = 0;
1790 return;
1791
1792
1793 case '@':
1794 /* insert char(s) */
1795 ite_inchar (ip, ite_argnum (ip));
1796 ip->escape = 0;
1797 return;
1798
1799 case '!':
1800 /* soft terminal reset */
1801 ip->escape = 0; /* XXX */
1802 return;
1803
1804 case 'G':
1805 /* this one was *not* in my vt320 manual but in
1806 a vt320 termcap entry.. who is right?
1807 It's supposed to set the horizontal cursor position. */
1808 *ip->ap = 0;
1809 x = atoi (ip->argbuf);
1810 if (x) x--;
1811 ip->curx = min(x, ip->cols - 1);
1812 ip->escape = 0;
1813 SUBR_CURSOR(ip, MOVE_CURSOR);
1814 clr_attr (ip, ATTR_INV);
1815 return;
1816
1817
1818 case 'd':
1819 /* same thing here, this one's for setting the absolute
1820 vertical cursor position. Not documented... */
1821 *ip->ap = 0;
1822 y = atoi (ip->argbuf);
1823 if (y) y--;
1824 if (ip->inside_margins)
1825 y += ip->top_margin;
1826 ip->cury = min(y, ip->rows - 1);
1827 ip->escape = 0;
1828 snap_cury(ip);
1829 SUBR_CURSOR(ip, MOVE_CURSOR);
1830 clr_attr (ip, ATTR_INV);
1831 return;
1832
1833
1834 case 'H':
1835 case 'f':
1836 *ip->ap = 0;
1837 y = atoi (ip->argbuf);
1838 x = 0;
1839 cp = index (ip->argbuf, ';');
1840 if (cp)
1841 x = atoi (cp + 1);
1842 if (x) x--;
1843 if (y) y--;
1844 if (ip->inside_margins)
1845 y += ip->top_margin;
1846 ip->cury = min(y, ip->rows - 1);
1847 ip->curx = min(x, ip->cols - 1);
1848 ip->escape = 0;
1849 snap_cury(ip);
1850 SUBR_CURSOR(ip, MOVE_CURSOR);
1851 /*clr_attr (ip, ATTR_INV);*/
1852 return;
1853
1854 case 'A':
1855 /* cursor up */
1856 n = ite_argnum (ip);
1857 n = ip->cury - (n ? n : 1);
1858 if (n < 0) n = 0;
1859 if (ip->inside_margins)
1860 n = max(ip->top_margin, n);
1861 else if (n == ip->top_margin - 1)
1862 /* allow scrolling outside region, but don't scroll out
1863 of active region without explicit CUP */
1864 n = ip->top_margin;
1865 ip->cury = n;
1866 ip->escape = 0;
1867 SUBR_CURSOR(ip, MOVE_CURSOR);
1868 clr_attr (ip, ATTR_INV);
1869 return;
1870
1871 case 'B':
1872 /* cursor down */
1873 n = ite_argnum (ip);
1874 n = ip->cury + (n ? n : 1);
1875 n = min(ip->rows - 1, n);
1876 #if 0
1877 if (ip->inside_margins)
1878 #endif
1879 n = min(ip->bottom_margin, n);
1880 #if 0
1881 else if (n == ip->bottom_margin + 1)
1882 /* allow scrolling outside region, but don't scroll out
1883 of active region without explicit CUP */
1884 n = ip->bottom_margin;
1885 #endif
1886 ip->cury = n;
1887 ip->escape = 0;
1888 SUBR_CURSOR(ip, MOVE_CURSOR);
1889 clr_attr (ip, ATTR_INV);
1890 return;
1891
1892 case 'C':
1893 /* cursor forward */
1894 n = ite_argnum (ip);
1895 n = n ? n : 1;
1896 ip->curx = min(ip->curx + n, ip->cols - 1);
1897 ip->escape = 0;
1898 SUBR_CURSOR(ip, MOVE_CURSOR);
1899 clr_attr (ip, ATTR_INV);
1900 return;
1901
1902 case 'D':
1903 /* cursor backward */
1904 n = ite_argnum (ip);
1905 n = n ? n : 1;
1906 n = ip->curx - n;
1907 ip->curx = n >= 0 ? n : 0;
1908 ip->escape = 0;
1909 SUBR_CURSOR(ip, MOVE_CURSOR);
1910 clr_attr (ip, ATTR_INV);
1911 return;
1912
1913
1914 case 'J':
1915 /* erase screen */
1916 *ip->ap = 0;
1917 n = ite_zargnum (ip);
1918 if (n == 0)
1919 ite_clrtoeos(ip);
1920 else if (n == 1)
1921 ite_clrtobos(ip);
1922 else if (n == 2)
1923 ite_clrscreen(ip);
1924 ip->escape = 0;
1925 return;
1926
1927
1928 case 'K':
1929 /* erase line */
1930 n = ite_zargnum (ip);
1931 if (n == 0)
1932 ite_clrtoeol(ip);
1933 else if (n == 1)
1934 ite_clrtobol(ip);
1935 else if (n == 2)
1936 ite_clrline(ip);
1937 ip->escape = 0;
1938 return;
1939
1940 case 'S':
1941 /* scroll up */
1942 n = ite_zargnum (ip);
1943 if (n <= 0)
1944 n = 1;
1945 else if (n > ip->rows-1)
1946 n = ip->rows-1;
1947 SUBR_SCROLL(ip, ip->rows-1, 0, n, SCROLL_UP);
1948 ip->escape = 0;
1949 return;
1950
1951 case 'T':
1952 /* scroll down */
1953 n = ite_zargnum (ip);
1954 if (n <= 0)
1955 n = 1;
1956 else if (n > ip->rows-1)
1957 n = ip->rows-1;
1958 SUBR_SCROLL(ip, 0, 0, n, SCROLL_DOWN);
1959 ip->escape = 0;
1960 return;
1961
1962 case 'X':
1963 /* erase character */
1964 n = ite_argnum(ip) - 1;
1965 n = min(n, ip->cols - 1 - ip->curx);
1966 for (; n >= 0; n--) {
1967 attrclr(ip, ip->cury, ip->curx + n, 1, 1);
1968 SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1969 }
1970 ip->escape = 0;
1971 return;
1972
1973
1974 case '}': case '`':
1975 /* status line control */
1976 ip->escape = 0;
1977 return;
1978
1979 case 'r':
1980 /* set scrolling region */
1981 ip->escape = 0;
1982 *ip->ap = 0;
1983 x = atoi (ip->argbuf);
1984 x = x ? x : 1;
1985 y = ip->rows;
1986 cp = index (ip->argbuf, ';');
1987 if (cp) {
1988 y = atoi (cp + 1);
1989 y = y ? y : ip->rows;
1990 }
1991 if (y <= x)
1992 return;
1993 x--;
1994 y--;
1995 ip->top_margin = min(x, ip->rows - 2);
1996 ip->bottom_margin = min(y, ip->rows - 1);
1997 if (ip->inside_margins) {
1998 ip->cury = ip->top_margin;
1999 } else
2000 ip->cury = 0;
2001 ip->curx = 0;
2002 return;
2003
2004
2005 case 'm':
2006 /* big attribute setter/resetter */
2007 {
2008 char *cp;
2009 *ip->ap = 0;
2010 /* kludge to make CSIm work (== CSI0m) */
2011 if (ip->ap == ip->argbuf)
2012 ip->ap++;
2013 for (cp = ip->argbuf; cp < ip->ap; ) {
2014 switch (*cp) {
2015 case 0:
2016 case '0':
2017 clr_attr (ip, ATTR_ALL);
2018 ip->fgcolor = 7;
2019 ip->bgcolor = 0;
2020 cp++;
2021 break;
2022
2023 case '1':
2024 set_attr (ip, ATTR_BOLD);
2025 cp++;
2026 break;
2027
2028 case '2':
2029 switch (cp[1]) {
2030 case '2':
2031 clr_attr (ip, ATTR_BOLD);
2032 cp += 2;
2033 break;
2034
2035 case '4':
2036 clr_attr (ip, ATTR_UL);
2037 cp += 2;
2038 break;
2039
2040 case '5':
2041 clr_attr (ip, ATTR_BLINK);
2042 cp += 2;
2043 break;
2044
2045 case '7':
2046 clr_attr (ip, ATTR_INV);
2047 cp += 2;
2048 break;
2049
2050 default:
2051 cp++;
2052 break;
2053 }
2054 break;
2055
2056 case '3':
2057 switch (cp[1]) {
2058 case '0': case '1': case '2': case '3':
2059 case '4': case '5': case '6': case '7':
2060 /* foreground colors */
2061 ip->fgcolor = cp[1] - '0';
2062 cp += 2;
2063 break;
2064 default:
2065 cp++;
2066 break;
2067 }
2068 break;
2069
2070 case '4':
2071 switch (cp[1]) {
2072 case '0': case '1': case '2': case '3':
2073 case '4': case '5': case '6': case '7':
2074 /* background colors */
2075 ip->bgcolor = cp[1] - '0';
2076 cp += 2;
2077 break;
2078 default:
2079 set_attr (ip, ATTR_UL);
2080 cp++;
2081 break;
2082 }
2083 break;
2084
2085 case '5':
2086 set_attr (ip, ATTR_BLINK);
2087 cp++;
2088 break;
2089
2090 case '7':
2091 set_attr (ip, ATTR_INV);
2092 cp++;
2093 break;
2094
2095 default:
2096 cp++;
2097 break;
2098 }
2099 }
2100
2101 }
2102 ip->escape = 0;
2103 return;
2104
2105
2106 case 'u':
2107 /* DECRQTSR */
2108 ite_sendstr (ip, "\033P\033\\");
2109 ip->escape = 0;
2110 return;
2111
2112 default:
2113 ip->escape = 0;
2114 return;
2115 }
2116 break;
2117
2118
2119
2120 case '?': /* CSI ? */
2121 switch (c) {
2122 case '0': case '1': case '2': case '3': case '4':
2123 case '5': case '6': case '7': case '8': case '9':
2124 case ';': case '\"': case '$':
2125 /* Don't fill the last character; it's needed. */
2126 /* XXX yeah, where ?? */
2127 if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
2128 *ip->ap++ = c;
2129 return;
2130
2131
2132 case 'n':
2133 /* Terminal Reports */
2134 *ip->ap = 0;
2135 if (ip->ap == &ip->argbuf[2]) {
2136 if (!strncmp(ip->argbuf, "15", 2))
2137 /* printer status: no printer */
2138 ite_sendstr (ip, "\033[13n");
2139
2140 else if (!strncmp(ip->argbuf, "25", 2))
2141 /* udk status */
2142 ite_sendstr (ip, "\033[20n");
2143
2144 else if (!strncmp(ip->argbuf, "26", 2))
2145 /* keyboard dialect: US */
2146 ite_sendstr (ip, "\033[27;1n");
2147 }
2148 ip->escape = 0;
2149 return;
2150
2151
2152 case 'h': /* set dec private modes */
2153 case 'l': /* reset dec private modes */
2154 n = ite_zargnum (ip);
2155 switch (n) {
2156 case 1:
2157 /* CKM - cursor key mode */
2158 ip->cursor_appmode = (c == 'h');
2159 break;
2160
2161 case 3:
2162 /* 132/80 columns (132 == 'h') */
2163 break;
2164
2165 case 4: /* smooth scroll */
2166 break;
2167
2168 case 5:
2169 /* light background (=='h') /dark background(=='l') */
2170 break;
2171
2172 case 6: /* origin mode */
2173 ip->inside_margins = (c == 'h');
2174 #if 0
2175 ip->curx = 0;
2176 ip->cury = ip->inside_margins ? ip->top_margin : 0;
2177 SUBR_CURSOR(ip, MOVE_CURSOR);
2178 #endif
2179 break;
2180
2181 case 7: /* auto wraparound */
2182 ip->auto_wrap = (c == 'h');
2183 break;
2184
2185 case 8: /* keyboard repeat */
2186 ip->key_repeat = (c == 'h');
2187 break;
2188
2189 case 20: /* newline mode */
2190 ip->linefeed_newline = (c == 'h');
2191 break;
2192
2193 case 25: /* cursor on/off */
2194 SUBR_CURSOR(ip, (c == 'h') ? DRAW_CURSOR : ERASE_CURSOR);
2195 break;
2196 }
2197 ip->escape = 0;
2198 return;
2199
2200 case 'K':
2201 /* selective erase in line */
2202 case 'J':
2203 /* selective erase in display */
2204
2205 default:
2206 ip->escape = 0;
2207 return;
2208 }
2209 break;
2210
2211
2212 default:
2213 ip->escape = 0;
2214 return;
2215 }
2216 }
2217
2218 switch (c) {
2219 case 0x00: /* NUL */
2220 case 0x01: /* SOH */
2221 case 0x02: /* STX */
2222 case 0x03: /* ETX */
2223 case 0x04: /* EOT */
2224 case 0x05: /* ENQ */
2225 case 0x06: /* ACK */
2226 break;
2227
2228 case BEL:
2229 #if NBELL > 0
2230 if (kbd_tty && ite_tty[kbd_ite->device.dv_unit] == kbd_tty)
2231 opm_bell();
2232 #endif
2233 break;
2234
2235 case BS:
2236 if (--ip->curx < 0)
2237 ip->curx = 0;
2238 else
2239 SUBR_CURSOR(ip, MOVE_CURSOR);
2240 break;
2241
2242 case HT:
2243 for (n = ip->curx + 1; n < ip->cols; n++) {
2244 if (ip->tabs[n]) {
2245 ip->curx = n;
2246 SUBR_CURSOR(ip, MOVE_CURSOR);
2247 break;
2248 }
2249 }
2250 break;
2251
2252 case VT: /* VT is treated like LF */
2253 case FF: /* so is FF */
2254 case LF:
2255 /* cr->crlf distinction is done here, on output,
2256 not on input! */
2257 if (ip->linefeed_newline)
2258 ite_crlf (ip);
2259 else
2260 ite_lf (ip);
2261 break;
2262
2263 case CR:
2264 ite_cr (ip);
2265 break;
2266
2267
2268 case SO:
2269 ip->GL = &ip->G1;
2270 break;
2271
2272 case SI:
2273 ip->GL = &ip->G0;
2274 break;
2275
2276 case 0x10: /* DLE */
2277 case 0x11: /* DC1/XON */
2278 case 0x12: /* DC2 */
2279 case 0x13: /* DC3/XOFF */
2280 case 0x14: /* DC4 */
2281 case 0x15: /* NAK */
2282 case 0x16: /* SYN */
2283 case 0x17: /* ETB */
2284 break;
2285
2286 case CAN:
2287 ip->escape = 0; /* cancel any escape sequence in progress */
2288 break;
2289
2290 case 0x19: /* EM */
2291 break;
2292
2293 case SUB:
2294 ip->escape = 0; /* dito, but see below */
2295 /* should also display a reverse question mark!! */
2296 break;
2297
2298 case ESC:
2299 ip->escape = ESC;
2300 break;
2301
2302 case 0x1c: /* FS */
2303 case 0x1d: /* GS */
2304 case 0x1e: /* RS */
2305 case 0x1f: /* US */
2306 break;
2307
2308 /* now it gets weird.. 8bit control sequences.. */
2309 case IND: /* index: move cursor down, scroll */
2310 ite_index (ip);
2311 break;
2312
2313 case NEL: /* next line. next line, first pos. */
2314 ite_crlf (ip);
2315 break;
2316
2317 case HTS: /* set horizontal tab */
2318 if (ip->curx < ip->cols)
2319 ip->tabs[ip->curx] = 1;
2320 break;
2321
2322 case RI: /* reverse index */
2323 ite_rlf (ip);
2324 break;
2325
2326 case SS2: /* go into G2 for one character */
2327 ip->save_GL = ip->GR; /* GL XXX EUC */
2328 ip->GR = &ip->G2; /* GL XXX */
2329 break;
2330
2331 case SS3: /* go into G3 for one character */
2332 ip->save_GL = ip->GR; /* GL XXX EUC */
2333 ip->GR = &ip->G3; /* GL XXX */
2334 break;
2335
2336 case DCS: /* device control string introducer */
2337 ip->escape = DCS;
2338 ip->ap = ip->argbuf;
2339 break;
2340
2341 case CSI: /* control sequence introducer */
2342 ip->escape = CSI;
2343 ip->ap = ip->argbuf;
2344 break;
2345
2346 case ST: /* string terminator */
2347 /* ignore, if not used as terminator */
2348 break;
2349
2350 case OSC: /* introduces OS command. Ignore everything upto ST */
2351 ip->escape = OSC;
2352 break;
2353
2354 case PM: /* privacy message, ignore everything upto ST */
2355 ip->escape = PM;
2356 break;
2357
2358 case APC: /* application program command, ignore everything upto ST */
2359 ip->escape = APC;
2360 break;
2361
2362 case DEL:
2363 break;
2364
2365 default:
2366 if (!ip->save_char && (*((c & 0x80) ? ip->GR : ip->GL) & CSET_MULTI)) {
2367 ip->save_char = c;
2368 break;
2369 }
2370 if (ip->imode)
2371 ite_inchar(ip, ip->save_char ? 2 : 1);
2372 iteprecheckwrap(ip);
2373 #ifdef DO_WEIRD_ATTRIBUTES
2374 if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
2375 attrset(ip, ATTR_INV);
2376 SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
2377 }
2378 else
2379 SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
2380 #else
2381 SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
2382 #endif
2383 /* SUBR_CURSOR(ip, DRAW_CURSOR);*/
2384 itecheckwrap(ip);
2385 if (ip->save_char) {
2386 itecheckwrap(ip);
2387 ip->save_char = 0;
2388 }
2389 if (ip->save_GL) {
2390 /*
2391 * reset single shift
2392 */
2393 ip->GR = ip->save_GL;
2394 ip->save_GL = 0;
2395 }
2396 break;
2397 }
2398 }
2399
2400 static void
2401 iteprecheckwrap(ip)
2402 struct ite_softc *ip;
2403 {
2404 if (ip->auto_wrap && ip->curx + (ip->save_char ? 1 : 0) == ip->cols) {
2405 ip->curx = 0;
2406 clr_attr(ip, ATTR_INV);
2407 if (++ip->cury >= ip->bottom_margin + 1) {
2408 ip->cury = ip->bottom_margin;
2409 /*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2410 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2411 ite_clrtoeol(ip);
2412 } /*else
2413 SUBR_CURSOR(ip, MOVE_CURSOR);*/
2414 }
2415 }
2416
2417 static void
2418 itecheckwrap(ip)
2419 struct ite_softc *ip;
2420 {
2421 #if 0
2422 if (++ip->curx == ip->cols) {
2423 if (ip->auto_wrap) {
2424 ip->curx = 0;
2425 clr_attr(ip, ATTR_INV);
2426 if (++ip->cury >= ip->bottom_margin + 1) {
2427 ip->cury = ip->bottom_margin;
2428 SUBR_CURSOR(ip, MOVE_CURSOR);
2429 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2430 ite_clrtoeol(ip);
2431 return;
2432 }
2433 } else
2434 /* stay there if no autowrap.. */
2435 ip->curx--;
2436 }
2437 #else
2438 if (ip->curx < ip->cols) {
2439 ip->curx++;
2440 /*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2441 }
2442 #endif
2443 }
2444
2445 #endif
2446
2447 /*
2448 * Console functions
2449 */
2450 #include <dev/cons.h>
2451
2452 /*
2453 * Return a priority in consdev->cn_pri field highest wins. This function
2454 * is called before any devices have been probed.
2455 */
2456 void
2457 itecnprobe(cd)
2458 struct consdev *cd;
2459 {
2460 int maj;
2461
2462 /*
2463 * bring graphics layer up.
2464 */
2465 config_console();
2466
2467 /* locate the major number */
2468 for (maj = 0; maj < nchrdev; maj++)
2469 if (cdevsw[maj].d_open == iteopen)
2470 break;
2471
2472 /*
2473 * return priority of the best ite (already picked from attach)
2474 * or CN_DEAD.
2475 */
2476 if (con_itesoftc.grf == NULL)
2477 cd->cn_pri = CN_DEAD;
2478 else {
2479 con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
2480 con_itesoftc.isw = &itesw[0]; /* XXX */
2481 cd->cn_pri = CN_INTERNAL;
2482 cd->cn_dev = makedev(maj, 0); /* XXX */
2483 }
2484
2485 }
2486
2487 void
2488 itecninit(cd)
2489 struct consdev *cd;
2490 {
2491 struct ite_softc *ip;
2492
2493 ip = getitesp(cd->cn_dev);
2494 iteinit(cd->cn_dev); /* init console unit */
2495 ip->flags |= ITE_ACTIVE | ITE_ISCONS;
2496 }
2497
2498 /*
2499 * itecnfinish() is called in ite_init() when the device is
2500 * being probed in the normal fasion, thus we can finish setting
2501 * up this ite now that the system is more functional.
2502 */
2503 void
2504 itecnfinish(ip)
2505 struct ite_softc *ip;
2506 {
2507 static int done;
2508
2509 if (done)
2510 return;
2511 done = 1;
2512 }
2513
2514 /*ARGSUSED*/
2515 int
2516 itecngetc(dev)
2517 dev_t dev;
2518 {
2519 register int c;
2520
2521 /* XXX this should be moved */
2522 if (!kbd_init) {
2523 kbd_init = 1;
2524 kbdenable();
2525 }
2526 do {
2527 c = kbdgetcn();
2528 c = ite_cnfilter(c, ITEFILT_CONSOLE);
2529 } while (c == -1);
2530 return (c);
2531 }
2532
2533 void
2534 itecnputc(dev, c)
2535 dev_t dev;
2536 int c;
2537 {
2538 static int paniced = 0;
2539 struct ite_softc *ip = getitesp(dev);
2540 char ch = c;
2541
2542 if (panicstr && !paniced &&
2543 (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
2544 (void) iteon(dev, 3);
2545 paniced = 1;
2546 }
2547 ite_putstr(&ch, 1, dev);
2548 }
2549