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