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