ite.c revision 1.15 1 /* $NetBSD: ite.c,v 1.15 1999/03/22 03:20:51 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 if (unit >= ite_cd.cd_ndevs || (ip = getitesp(dev)) == NULL)
371 return (ENXIO);
372 if (!ite_tty[unit]) {
373 tp = ite_tty[unit] = ttymalloc();
374 tty_attach(tp);
375 } else
376 tp = ite_tty[unit];
377 if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE)
378 && p->p_ucred->cr_uid != 0)
379 return (EBUSY);
380 if ((ip->flags & ITE_ACTIVE) == 0) {
381 error = iteon(dev, 0);
382 if (error)
383 return (error);
384 first = 1;
385 }
386 tp->t_oproc = itestart;
387 tp->t_param = NULL;
388 tp->t_dev = dev;
389 if ((tp->t_state&TS_ISOPEN) == 0) {
390 ttychars(tp);
391 tp->t_iflag = TTYDEF_IFLAG;
392 tp->t_oflag = TTYDEF_OFLAG;
393 tp->t_cflag = TTYDEF_CFLAG;
394 tp->t_lflag = TTYDEF_LFLAG;
395 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
396 tp->t_state = TS_ISOPEN|TS_CARR_ON;
397 ttsetwater(tp);
398 }
399 error = (*linesw[tp->t_line].l_open)(dev, tp);
400 if (error == 0) {
401 tp->t_winsize.ws_row = ip->rows;
402 tp->t_winsize.ws_col = ip->cols;
403 } else if (first)
404 iteoff(dev, 0);
405 return (error);
406 }
407
408 /*ARGSUSED*/
409 int
410 iteclose(dev, flag, mode, p)
411 dev_t dev;
412 int flag, mode;
413 struct proc *p;
414 {
415 register struct tty *tp = ite_tty[UNIT(dev)];
416
417 (*linesw[tp->t_line].l_close)(tp, flag);
418 ttyclose(tp);
419 iteoff(dev, 0);
420 #if 0
421 ttyfree(tp);
422 ite_tty[UNIT(dev)] = (struct tty *)0;
423 #endif
424 return(0);
425 }
426
427 int
428 iteread(dev, uio, flag)
429 dev_t dev;
430 struct uio *uio;
431 int flag;
432 {
433 register struct tty *tp = ite_tty[UNIT(dev)];
434
435 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
436 }
437
438 int
439 itewrite(dev, uio, flag)
440 dev_t dev;
441 struct uio *uio;
442 int flag;
443 {
444 register struct tty *tp = ite_tty[UNIT(dev)];
445
446 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
447 }
448
449 struct tty *
450 itetty(dev)
451 dev_t dev;
452 {
453
454 return (ite_tty[UNIT(dev)]);
455 }
456
457 int
458 iteioctl(dev, cmd, addr, flag, p)
459 dev_t dev;
460 u_long cmd;
461 caddr_t addr;
462 int flag;
463 struct proc *p;
464 {
465 struct iterepeat *irp;
466 register struct tty *tp = ite_tty[UNIT(dev)];
467 int error;
468
469 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p);
470 if (error >= 0)
471 return (error);
472 error = ttioctl(tp, cmd, addr, flag, p);
473 if (error >= 0)
474 return (error);
475
476 switch (cmd) {
477 case ITEIOCSKMAP:
478 if (addr == 0)
479 return(EFAULT);
480 bcopy(addr, &kbdmap, sizeof(struct kbdmap));
481 return(0);
482
483 case ITEIOCGKMAP:
484 if (addr == NULL)
485 return(EFAULT);
486 bcopy(&kbdmap, addr, sizeof(struct kbdmap));
487 return(0);
488
489 case ITEIOCGREPT:
490 irp = (struct iterepeat *)addr;
491 irp->start = start_repeat_timeo;
492 irp->next = next_repeat_timeo;
493
494 case ITEIOCSREPT:
495 irp = (struct iterepeat *)addr;
496 if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
497 return(EINVAL);
498 start_repeat_timeo = irp->start;
499 next_repeat_timeo = irp->next;
500 #if x68k
501 case ITELOADFONT:
502 if (addr) {
503 bcopy(addr, kern_font, 4096 /*sizeof (kernel_font)*/);
504 return 0;
505 } else
506 return EFAULT;
507
508 case ITETVCTRL:
509 if (addr && *(u_int8_t *)addr < 0x40) {
510 return mfp_send_usart (* (u_int8_t *)addr);
511 } else {
512 return EFAULT;
513 }
514 #endif
515 }
516 return (ENOTTY);
517 }
518
519 void
520 itestart(tp)
521 register struct tty *tp;
522 {
523 struct clist *rbp;
524 struct ite_softc *ip;
525 u_char buf[ITEBURST];
526 int s, len, n;
527
528 ip = getitesp(tp->t_dev);
529 /*
530 * (Potentially) lower priority. We only need to protect ourselves
531 * from keyboard interrupts since that is all that can affect the
532 * state of our tty (kernel printf doesn't go through this routine).
533 */
534 s = spltty();
535 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
536 goto out;
537 tp->t_state |= TS_BUSY;
538 rbp = &tp->t_outq;
539 len = q_to_b(rbp, buf, ITEBURST);
540 /*splx(s);*/
541
542 /* Here is a really good place to implement pre/jumpscroll() */
543 ite_putstr(buf, len, tp->t_dev);
544
545 /*s = spltty();*/
546 tp->t_state &= ~TS_BUSY;
547 /* we have characters remaining. */
548 if (rbp->c_cc) {
549 tp->t_state |= TS_TIMEOUT;
550 timeout(ttrstrt, (caddr_t)tp, 1);
551 }
552 /* wakeup we are below */
553 if (rbp->c_cc <= tp->t_lowat) {
554 if (tp->t_state & TS_ASLEEP) {
555 tp->t_state &= ~TS_ASLEEP;
556 wakeup((caddr_t)rbp);
557 }
558 selwakeup(&tp->t_wsel);
559 }
560 out:
561 splx(s);
562 }
563
564 /* XXX called after changes made in underlying grf layer. */
565 /* I want to nuke this */
566 void
567 ite_reinit(dev)
568 dev_t dev;
569 {
570 struct ite_softc *ip;
571 int unit = UNIT(dev);
572
573 /* XXX check whether when call from grf.c */
574 if (unit < 0 || unit >= ite_cd.cd_ndevs ||
575 (ip = getitesp(unit)) == NULL)
576 return;
577
578 ip->flags &= ~ITE_INITED;
579 iteinit(dev);
580 }
581
582 void
583 ite_reset(ip)
584 struct ite_softc *ip;
585 {
586 int i;
587
588 ip->curx = 0;
589 ip->cury = 0;
590 ip->attribute = 0;
591 ip->save_curx = 0;
592 ip->save_cury = 0;
593 ip->save_attribute = 0;
594 ip->ap = ip->argbuf;
595 ip->emul_level = EMUL_VT300_8;
596 ip->eightbit_C1 = 0;
597 ip->top_margin = 0;
598 ip->bottom_margin = ip->rows - 1;
599 ip->inside_margins = 0; /* origin mode == absolute */
600 ip->linefeed_newline = 0;
601 ip->auto_wrap = 1;
602 ip->cursor_appmode = 0;
603 ip->keypad_appmode = 0;
604 ip->imode = 0;
605 ip->key_repeat = 1;
606 ip->G0 = CSET_ASCII;
607 ip->G1 = CSET_JIS1983;
608 ip->G2 = CSET_JISKANA;
609 ip->G3 = CSET_JIS1990;
610 ip->GL = &ip->G0;
611 ip->GR = &ip->G1;
612 ip->save_GL = 0;
613 ip->save_char = 0;
614 ip->fgcolor = 7;
615 ip->bgcolor = 0;
616 for (i = 0; i < ip->cols; i++)
617 ip->tabs[i] = ((i & 7) == 0);
618 /* XXX clear screen */
619 SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
620 attrclr(ip, 0, 0, ip->rows, ip->cols);
621 }
622
623 /* Used in console at startup only */
624 int
625 ite_cnfilter(c, caller)
626 u_char c;
627 enum caller caller;
628 {
629 struct tty *kbd_tty;
630 static u_char mod = 0;
631 struct key key;
632 u_char code, up, mask;
633 int s, i;
634
635 up = c & 0x80 ? 1 : 0;
636 c &= 0x7f;
637 code = 0;
638
639 s = spltty();
640
641 mask = 0;
642 if (c >= KBD_LEFT_ALT && !(c >= 0x63 && c <= 0x6c)) { /* 0x63: F1, 0x6c:F10 */
643 switch (c) {
644 case KBD_LEFT_SHIFT:
645 mask = KBD_MOD_SHIFT;
646 break;
647
648 case KBD_LEFT_ALT:
649 mask = KBD_MOD_LALT;
650 break;
651
652 case KBD_RIGHT_ALT:
653 mask = KBD_MOD_RALT;
654 break;
655
656 case KBD_LEFT_META:
657 mask = KBD_MOD_LMETA;
658 break;
659
660 case KBD_RIGHT_META:
661 mask = KBD_MOD_RMETA;
662 break;
663
664 case KBD_CAPS_LOCK:
665 /*
666 * capslock already behaves `right', don't need to
667 * keep track of the state in here.
668 */
669 mask = KBD_MOD_CAPS;
670 break;
671
672 case KBD_CTRL:
673 mask = KBD_MOD_CTRL;
674 break;
675
676 case KBD_RECONNECT:
677 /* ite got 0xff */
678 if (up)
679 kbd_setLED();
680 break;
681 }
682 if (mask & KBD_MOD_CAPS) {
683 if (!up) {
684 mod ^= KBD_MOD_CAPS;
685 kbdled ^= LED_CAPS_LOCK;
686 kbd_setLED();
687 }
688 } else if (up)
689 mod &= ~mask;
690 else mod |= mask;
691 splx (s);
692 return -1;
693 }
694
695 if (up) {
696 splx(s);
697 return -1;
698 }
699
700 /* translate modifiers */
701 if (mod & KBD_MOD_SHIFT) {
702 if (mod & KBD_MOD_ALT)
703 key = kbdmap.alt_shift_keys[c];
704 else
705 key = kbdmap.shift_keys[c];
706 } else if (mod & KBD_MOD_ALT)
707 key = kbdmap.alt_keys[c];
708 else {
709 key = kbdmap.keys[c];
710 /* if CAPS and key is CAPable (no pun intended) */
711 if ((mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
712 key = kbdmap.shift_keys[c];
713 }
714 code = key.code;
715
716 /* if string return */
717 if (key.mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) {
718 splx(s);
719 return -1;
720 }
721 /* handle dead keys */
722 if (key.mode & KBD_MODE_DEAD) {
723 splx(s);
724 return -1;
725 }
726 if (mod & KBD_MOD_CTRL)
727 code &= 0x1f;
728 if (mod & KBD_MOD_META)
729 code |= 0x80;
730
731 /* do console mapping. */
732 code = code == '\r' ? '\n' : code;
733
734 splx(s);
735 return (code);
736 }
737
738 /* And now the old stuff. */
739
740 /* these are used to implement repeating keys.. */
741 static u_char last_char = 0;
742 static u_char tout_pending = 0;
743
744 /*ARGSUSED*/
745 static void
746 repeat_handler (arg)
747 void *arg;
748 {
749 tout_pending = 0;
750 if (last_char)
751 add_sicallback(ite_filter, last_char, ITEFILT_REPEATER);
752 }
753
754 __inline static void
755 itesendch (ch)
756 int ch;
757 {
758 (*linesw[kbd_tty->t_line].l_rint)(ch, kbd_tty);
759 }
760
761
762 void
763 ite_filter(c, caller)
764 u_char c;
765 enum caller caller;
766 {
767 static u_short mod = 0;
768 register unsigned char code, *str;
769 u_short up, mask;
770 struct key key;
771 int s, i;
772
773 if (!kbd_ite)
774 return;
775 kbd_tty = ite_tty[kbd_ite->device.dv_unit];
776
777 /* have to make sure we're at spltty in here */
778 s = spltty ();
779
780 #if 0 /* XXX? x68k */
781 /* keyboard interrupts come at priority 2, while softint-
782 generated keyboard-repeat interrupts come at level 1.
783 So, to not allow a key-up event to get thru before
784 a repeat for the key-down, we remove any outstanding
785 callout requests.. */
786 rem_sicallback (ite_filter);
787 #endif
788
789 up = c & 0x80 ? 1 : 0;
790 c &= 0x7f;
791 code = 0;
792
793 mask = 0;
794 if (c >= KBD_LEFT_ALT &&
795 !(c >= 0x63 && c <= 0x6c)) { /* 0x63: F1, 0x6c:F10 */
796 switch (c) {
797 case KBD_LEFT_SHIFT:
798 mask = KBD_MOD_SHIFT;
799 break;
800
801 case KBD_LEFT_ALT:
802 mask = KBD_MOD_LALT;
803 break;
804
805 case KBD_RIGHT_ALT:
806 mask = KBD_MOD_RALT;
807 break;
808
809 case KBD_LEFT_META:
810 mask = KBD_MOD_LMETA;
811 break;
812
813 case KBD_RIGHT_META:
814 mask = KBD_MOD_RMETA;
815 break;
816
817 case KBD_CAPS_LOCK:
818 /*
819 * capslock already behaves `right', don't need to keep
820 * track of the state in here.
821 */
822 mask = KBD_MOD_CAPS;
823 break;
824
825 case KBD_CTRL:
826 mask = KBD_MOD_CTRL;
827 break;
828
829 case KBD_OPT1:
830 mask = KBD_MOD_OPT1;
831 break;
832
833 case KBD_OPT2:
834 mask = KBD_MOD_OPT2;
835 break;
836
837 case KBD_RECONNECT:
838 if (up) { /* ite got 0xff */
839 kbd_setLED();
840 }
841 break;
842 }
843
844 if (mask & KBD_MOD_CAPS) {
845 if (!up) {
846 mod ^= KBD_MOD_CAPS;
847 kbdled ^= LED_CAPS_LOCK;
848 kbd_setLED();
849 }
850 } else if (up) {
851 mod &= ~mask;
852 } else mod |= mask;
853
854 /*
855 * these keys should not repeat, so it's the Right Thing
856 * dealing with repeaters only after this block.
857 */
858
859 /*
860 * return even if it wasn't a modifier key, the other
861 * codes up here are either special (like reset warning),
862 * or not yet defined
863 */
864 splx (s);
865 return;
866 }
867
868 /*
869 * no matter which character we're repeating, stop it if we
870 * get a key-up event. I think this is the same thing amigados does.
871 */
872 if (up) {
873 if (tout_pending) {
874 untimeout (repeat_handler, 0);
875 tout_pending = 0;
876 last_char = 0;
877 }
878 splx (s);
879 return;
880 } else if (tout_pending && last_char != c) {
881 /*
882 * not the same character remove the repeater and continue
883 * to process this key. -ch
884 */
885 untimeout (repeat_handler, 0);
886 tout_pending = 0;
887 last_char = 0;
888 }
889
890 /*
891 * intercept LAlt-LMeta-F1 here to switch back to original ascii-keymap.
892 * this should probably be configurable..
893 */
894 if (mod == (KBD_MOD_LALT|KBD_MOD_LMETA) && c == 0x50) {
895 bcopy (&ascii_kbdmap, &kbdmap, sizeof (struct kbdmap));
896 splx (s);
897 return;
898 }
899
900 /* translate modifiers */
901 if (mod & KBD_MOD_SHIFT) {
902 if (mod & KBD_MOD_ALT)
903 key = kbdmap.alt_shift_keys[c];
904 else
905 key = kbdmap.shift_keys[c];
906 } else if (mod & KBD_MOD_ALT)
907 key = kbdmap.alt_keys[c];
908 else {
909 key = kbdmap.keys[c];
910 /* if CAPS and key is CAPable (no pun intended) */
911 if ((mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
912 key = kbdmap.shift_keys[c];
913 else if ((mod & KBD_MOD_OPT2) && (key.mode & KBD_MODE_KPAD))
914 key = kbdmap.shift_keys[c];
915 }
916 code = key.code;
917
918 /*
919 * arrange to repeat the keystroke. By doing this at the level of scan-codes,
920 * we can have function keys, and keys that send strings, repeat too. This
921 * also entitles an additional overhead, since we have to do the conversion
922 * each time, but I guess that's ok.
923 */
924 if (!tout_pending && caller == ITEFILT_TTY && kbd_ite->key_repeat) {
925 tout_pending = 1;
926 last_char = c;
927 timeout (repeat_handler, 0, start_repeat_timeo);
928 } else if (!tout_pending && caller == ITEFILT_REPEATER &&
929 kbd_ite->key_repeat) {
930 tout_pending = 1;
931 last_char = c;
932 timeout (repeat_handler, 0, next_repeat_timeo);
933 }
934
935 /* handle dead keys */
936 if (key.mode & KBD_MODE_DEAD) {
937 splx (s);
938 return;
939 }
940 /* if not string, apply META and CTRL modifiers */
941 if (! (key.mode & KBD_MODE_STRING)
942 && (!(key.mode & KBD_MODE_KPAD) ||
943 (kbd_ite && !kbd_ite->keypad_appmode))) {
944 if ((mod & KBD_MOD_CTRL) &&
945 (code == ' ' || (code >= '@' && code <= 'z')))
946 code &= 0x1f;
947 if (mod & KBD_MOD_META)
948 code |= 0x80;
949 } else if ((key.mode & KBD_MODE_KPAD) &&
950 (kbd_ite && kbd_ite->keypad_appmode)) {
951 static char *in = "0123456789-+.\r()/*";
952 static char *out = "pqrstuvwxymlnMPQRS";
953 char *cp = index (in, code);
954
955 /*
956 * keypad-appmode sends SS3 followed by the above
957 * translated character
958 */
959 (*linesw[kbd_tty->t_line].l_rint) (27, kbd_tty);
960 (*linesw[kbd_tty->t_line].l_rint) ('O', kbd_tty);
961 (*linesw[kbd_tty->t_line].l_rint) (out[cp - in], kbd_tty);
962 splx(s);
963 return;
964 } else {
965 /* *NO* I don't like this.... */
966 static u_char app_cursor[] =
967 {
968 3, 27, 'O', 'A',
969 3, 27, 'O', 'B',
970 3, 27, 'O', 'C',
971 3, 27, 'O', 'D'};
972
973 str = kbdmap.strings + code;
974 /*
975 * if this is a cursor key, AND it has the default
976 * keymap setting, AND we're in app-cursor mode, switch
977 * to the above table. This is *nasty* !
978 */
979 if (c >= 0x3b && c <= 0x3e && kbd_ite->cursor_appmode
980 && !bcmp(str, "\x03\x1b[", 3) &&
981 index("ABCD", str[3]))
982 str = app_cursor + 4 * (str[3] - 'A');
983
984 /*
985 * using a length-byte instead of 0-termination allows
986 * to embed \0 into strings, although this is not used
987 * in the default keymap
988 */
989 for (i = *str++; i; i--)
990 (*linesw[kbd_tty->t_line].l_rint) (*str++, kbd_tty);
991 splx(s);
992 return;
993 }
994 (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
995
996 splx(s);
997 return;
998 }
999
1000 /* helper functions, makes the code below more readable */
1001 __inline static void
1002 ite_sendstr (ip, str)
1003 struct ite_softc *ip;
1004 char *str;
1005 {
1006 while (*str)
1007 itesendch (*str++);
1008 }
1009
1010 __inline static void
1011 alignment_display(ip)
1012 struct ite_softc *ip;
1013 {
1014 int i, j;
1015
1016 for (j = 0; j < ip->rows; j++)
1017 for (i = 0; i < ip->cols; i++)
1018 SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
1019 attrclr(ip, 0, 0, ip->rows, ip->cols);
1020 }
1021
1022 __inline static void
1023 snap_cury(ip)
1024 struct ite_softc *ip;
1025 {
1026 if (ip->inside_margins) {
1027 if (ip->cury < ip->top_margin)
1028 ip->cury = ip->top_margin;
1029 if (ip->cury > ip->bottom_margin)
1030 ip->cury = ip->bottom_margin;
1031 }
1032 }
1033
1034 __inline static void
1035 ite_dnchar(ip, n)
1036 struct ite_softc *ip;
1037 int n;
1038 {
1039 n = min(n, ip->cols - ip->curx);
1040 if (n < ip->cols - ip->curx) {
1041 SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
1042 attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
1043 1, ip->cols - ip->curx - n);
1044 attrclr(ip, ip->cury, ip->cols - n, 1, n);
1045 }
1046 while (n-- > 0)
1047 SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
1048 }
1049
1050 static void
1051 ite_inchar(ip, n)
1052 struct ite_softc *ip;
1053 int n;
1054 {
1055 int c = ip->save_char;
1056 ip->save_char = 0;
1057 n = min(n, ip->cols - ip->curx);
1058 if (n < ip->cols - ip->curx) {
1059 SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
1060 attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
1061 1, ip->cols - ip->curx - n);
1062 attrclr(ip, ip->cury, ip->curx, 1, n);
1063 }
1064 while (n--)
1065 SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
1066 ip->save_char = c;
1067 }
1068
1069 __inline static void
1070 ite_clrtoeol(ip)
1071 struct ite_softc *ip;
1072 {
1073 int y = ip->cury, x = ip->curx;
1074 if (ip->cols - x > 0) {
1075 SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
1076 attrclr(ip, y, x, 1, ip->cols - x);
1077 }
1078 }
1079
1080 __inline static void
1081 ite_clrtobol(ip)
1082 struct ite_softc *ip;
1083 {
1084 int y = ip->cury, x = min(ip->curx + 1, ip->cols);
1085 SUBR_CLEAR(ip, y, 0, 1, x);
1086 attrclr(ip, y, 0, 1, x);
1087 }
1088
1089 __inline static void
1090 ite_clrline(ip)
1091 struct ite_softc *ip;
1092 {
1093 int y = ip->cury;
1094 SUBR_CLEAR(ip, y, 0, 1, ip->cols);
1095 attrclr(ip, y, 0, 1, ip->cols);
1096 }
1097
1098 __inline static void
1099 ite_clrtoeos(ip)
1100 struct ite_softc *ip;
1101 {
1102 ite_clrtoeol(ip);
1103 if (ip->cury < ip->rows - 1) {
1104 SUBR_CLEAR(ip, ip->cury + 1, 0, ip->rows - 1 - ip->cury, ip->cols);
1105 attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
1106 }
1107 }
1108
1109 __inline static void
1110 ite_clrtobos(ip)
1111 struct ite_softc *ip;
1112 {
1113 ite_clrtobol(ip);
1114 if (ip->cury > 0) {
1115 SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
1116 attrclr(ip, 0, 0, ip->cury, ip->cols);
1117 }
1118 }
1119
1120 __inline static void
1121 ite_clrscreen(ip)
1122 struct ite_softc *ip;
1123 {
1124 SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
1125 attrclr(ip, 0, 0, ip->rows, ip->cols);
1126 }
1127
1128
1129
1130 __inline static void
1131 ite_dnline(ip, n)
1132 struct ite_softc *ip;
1133 int n;
1134 {
1135 /*
1136 * interesting.. if the cursor is outside the scrolling
1137 * region, this command is simply ignored..
1138 */
1139 if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1140 return;
1141
1142 n = min(n, ip->bottom_margin + 1 - ip->cury);
1143 if (n <= ip->bottom_margin - ip->cury) {
1144 SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
1145 attrmov(ip, ip->cury + n, 0, ip->cury, 0,
1146 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1147 }
1148 SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1149 attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
1150 }
1151
1152 __inline static void
1153 ite_inline(ip, n)
1154 struct ite_softc *ip;
1155 int n;
1156 {
1157 /*
1158 * interesting.. if the cursor is outside the scrolling
1159 * region, this command is simply ignored..
1160 */
1161 if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
1162 return;
1163
1164 if (n <= 0)
1165 n = 1;
1166 else n = min(n, ip->bottom_margin + 1 - ip->cury);
1167 if (n <= ip->bottom_margin - ip->cury) {
1168 SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
1169 attrmov(ip, ip->cury, 0, ip->cury + n, 0,
1170 ip->bottom_margin + 1 - ip->cury - n, ip->cols);
1171 }
1172 SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
1173 attrclr(ip, ip->cury, 0, n, ip->cols);
1174 ip->curx = 0;
1175 }
1176
1177 __inline static void
1178 ite_index (ip)
1179 struct ite_softc *ip;
1180 {
1181 ++ip->cury;
1182 if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows)) {
1183 ip->cury--;
1184 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1185 ite_clrline(ip);
1186 }
1187 /*clr_attr(ip, ATTR_INV);*/
1188 }
1189
1190 __inline static void
1191 ite_lf (ip)
1192 struct ite_softc *ip;
1193 {
1194 ++ip->cury;
1195 if (ip->cury > ip->bottom_margin) {
1196 ip->cury--;
1197 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
1198 ite_clrline(ip);
1199 }
1200 /* SUBR_CURSOR(ip, MOVE_CURSOR);*/
1201 /*clr_attr(ip, ATTR_INV);*/
1202 /* reset character set ... thanks for mohta. */
1203 ip->G0 = CSET_ASCII;
1204 ip->G1 = CSET_JIS1983;
1205 ip->G2 = CSET_JISKANA;
1206 ip->G3 = CSET_JIS1990;
1207 ip->GL = &ip->G0;
1208 ip->GR = &ip->G1;
1209 ip->save_GL = 0;
1210 ip->save_char = 0;
1211 }
1212
1213 __inline static void
1214 ite_crlf (ip)
1215 struct ite_softc *ip;
1216 {
1217 ip->curx = 0;
1218 ite_lf (ip);
1219 }
1220
1221 __inline static void
1222 ite_cr (ip)
1223 struct ite_softc *ip;
1224 {
1225 if (ip->curx) {
1226 ip->curx = 0;
1227 }
1228 }
1229
1230 __inline static void
1231 ite_rlf (ip)
1232 struct ite_softc *ip;
1233 {
1234 ip->cury--;
1235 if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1)) {
1236 ip->cury++;
1237 SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
1238 ite_clrline(ip);
1239 }
1240 clr_attr(ip, ATTR_INV);
1241 }
1242
1243 __inline static int
1244 atoi (cp)
1245 const char *cp;
1246 {
1247 int n;
1248
1249 for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
1250 n = n * 10 + *cp - '0';
1251 return n;
1252 }
1253
1254 __inline static char *
1255 index(cp, ch)
1256 const char *cp;
1257 char ch;
1258 {
1259 while (*cp && *cp != ch)
1260 cp++;
1261 return *cp ? (char *) cp : 0;
1262 }
1263
1264 __inline static int
1265 ite_argnum (ip)
1266 struct ite_softc *ip;
1267 {
1268 char ch;
1269 int n;
1270
1271 /* convert argument string into number */
1272 if (ip->ap == ip->argbuf)
1273 return 1;
1274 ch = *ip->ap;
1275 *ip->ap = 0;
1276 n = atoi (ip->argbuf);
1277 *ip->ap = ch;
1278
1279 return n;
1280 }
1281
1282 __inline static int
1283 ite_zargnum (ip)
1284 struct ite_softc *ip;
1285 {
1286 char ch;
1287 int n;
1288
1289 /* convert argument string into number */
1290 if (ip->ap == ip->argbuf)
1291 return 0;
1292 ch = *ip->ap;
1293 *ip->ap = 0; /* terminate string */
1294 n = atoi (ip->argbuf);
1295 *ip->ap = ch;
1296
1297 return n; /* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
1298 }
1299
1300 void
1301 ite_putstr(s, len, dev)
1302 const u_char *s;
1303 int len;
1304 dev_t dev;
1305 {
1306 struct ite_softc *ip;
1307 int i;
1308
1309 ip = getitesp(dev);
1310
1311 /* XXX avoid problems */
1312 if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
1313 return;
1314
1315 SUBR_CURSOR(ip, START_CURSOROPT);
1316 for (i = 0; i < len; i++)
1317 if (s[i])
1318 iteputchar(s[i], ip);
1319 SUBR_CURSOR(ip, END_CURSOROPT);
1320 }
1321
1322 void
1323 iteputchar(c, ip)
1324 register int c;
1325 struct ite_softc *ip;
1326 {
1327 int n, x, y;
1328 char *cp;
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_ite && ite_tty[kbd_ite->device.dv_unit])
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 #if NITE > 0 && NKBD > 0
2448
2449 /*
2450 * Console functions
2451 */
2452 #include <dev/cons.h>
2453 extern void kbdenable __P((int));
2454 extern int kbdcngetc __P((void));
2455
2456 /*
2457 * Return a priority in consdev->cn_pri field highest wins. This function
2458 * is called before any devices have been probed.
2459 */
2460 void
2461 itecnprobe(cd)
2462 struct consdev *cd;
2463 {
2464 int maj;
2465
2466 /*
2467 * bring graphics layer up.
2468 */
2469 config_console();
2470
2471 /* locate the major number */
2472 for (maj = 0; maj < nchrdev; maj++)
2473 if (cdevsw[maj].d_open == iteopen)
2474 break;
2475
2476 /*
2477 * return priority of the best ite (already picked from attach)
2478 * or CN_DEAD.
2479 */
2480 if (con_itesoftc.grf == NULL)
2481 cd->cn_pri = CN_DEAD;
2482 else {
2483 con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
2484 /*
2485 * hardcode the minor number.
2486 * currently we support only one ITE, it is enough for now.
2487 */
2488 con_itesoftc.isw = &itesw[0];
2489 cd->cn_pri = CN_INTERNAL;
2490 cd->cn_dev = makedev(maj, 0);
2491 }
2492
2493 }
2494
2495 void
2496 itecninit(cd)
2497 struct consdev *cd;
2498 {
2499 struct ite_softc *ip;
2500
2501 ip = getitesp(cd->cn_dev);
2502 iteinit(cd->cn_dev); /* init console unit */
2503 ip->flags |= ITE_ACTIVE | ITE_ISCONS;
2504 kbdenable(0);
2505 mfp_send_usart(0x49);
2506 }
2507
2508 /*
2509 * itecnfinish() is called in ite_init() when the device is
2510 * being probed in the normal fasion, thus we can finish setting
2511 * up this ite now that the system is more functional.
2512 */
2513 void
2514 itecnfinish(ip)
2515 struct ite_softc *ip;
2516 {
2517 static int done;
2518
2519 if (done)
2520 return;
2521 done = 1;
2522 }
2523
2524 /*ARGSUSED*/
2525 int
2526 itecngetc(dev)
2527 dev_t dev;
2528 {
2529 register int c;
2530
2531 do {
2532 c = kbdcngetc();
2533 c = ite_cnfilter(c, ITEFILT_CONSOLE);
2534 } while (c == -1);
2535 return (c);
2536 }
2537
2538 void
2539 itecnputc(dev, c)
2540 dev_t dev;
2541 int c;
2542 {
2543 static int paniced = 0;
2544 struct ite_softc *ip = getitesp(dev);
2545 char ch = c;
2546 #ifdef ITE_KERNEL_ATTR
2547 short save_attribute;
2548 #endif
2549
2550 if (panicstr && !paniced &&
2551 (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
2552 (void) iteon(dev, 3);
2553 paniced = 1;
2554 }
2555 #ifdef ITE_KERNEL_ATTR
2556 save_attribute = ip->attribute;
2557 ip->attribute = ITE_KERNEL_ATTR;
2558 #endif
2559 ite_putstr(&ch, 1, dev);
2560 #ifdef ITE_KERNEL_ATTR
2561 ip->attribute = save_attribute;
2562 #endif
2563 }
2564 #endif
2565