ite.c revision 1.69 1 /* $NetBSD: ite.c,v 1.69 2022/06/25 03:18:38 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.69 2022/06/25 03:18:38 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 switch (c) {
1485 case 'B': /* USASCII */
1486 ip->G1 = CSET_ASCII;
1487 ip->escape = 0;
1488 return;
1489 case 'I':
1490 ip->G1 = CSET_JISKANA;
1491 ip->escape = 0;
1492 return;
1493 case 'J':
1494 ip->G1 = CSET_JISROMA;
1495 ip->escape = 0;
1496 return;
1497 case '0': /* dec special graphics */
1498 ip->G1 = CSET_DECGRAPH;
1499 ip->escape = 0;
1500 return;
1501 case 'A': /* British or ISO-Latin-1 */
1502 case 'H': /* Swedish */
1503 case 'K': /* German */
1504 case 'R': /* French */
1505 case 'Y': /* Italian */
1506 case 'Z': /* Spanish */
1507 default:
1508 /* not supported */
1509 ip->escape = 0;
1510 return;
1511 }
1512 return;
1513
1514 case '$': /* 94-multibyte character set */
1515 switch (c) {
1516 case '@':
1517 ip->G0 = CSET_JIS1978;
1518 ip->escape = 0;
1519 return;
1520 case 'B':
1521 ip->G0 = CSET_JIS1983;
1522 ip->escape = 0;
1523 return;
1524 case 'D':
1525 ip->G0 = CSET_JIS1990;
1526 ip->escape = 0;
1527 return;
1528 default:
1529 /* not supported */
1530 ip->escape = 0;
1531 return;
1532 }
1533
1534 case ' ':
1535 switch (c) {
1536 case 'F':
1537 ip->eightbit_C1 = 0;
1538 ip->escape = 0;
1539 return;
1540
1541 case 'G':
1542 ip->eightbit_C1 = 1;
1543 ip->escape = 0;
1544 return;
1545
1546 default:
1547 /* not supported */
1548 ip->escape = 0;
1549 return;
1550 }
1551 break;
1552
1553 case '#':
1554 switch (c) {
1555 case '5':
1556 /* single height, single width */
1557 ip->escape = 0;
1558 return;
1559
1560 case '6':
1561 /* double width, single height */
1562 ip->escape = 0;
1563 return;
1564
1565 case '3':
1566 /* top half */
1567 ip->escape = 0;
1568 return;
1569
1570 case '4':
1571 /* bottom half */
1572 ip->escape = 0;
1573 return;
1574
1575 case '8':
1576 /* screen alignment pattern... */
1577 alignment_display(ip);
1578 ip->escape = 0;
1579 return;
1580
1581 default:
1582 ip->escape = 0;
1583 return;
1584 }
1585 break;
1586
1587 case CSI:
1588 /* the biggie... */
1589 switch (c) {
1590 case '0':
1591 case '1':
1592 case '2':
1593 case '3':
1594 case '4':
1595 case '5':
1596 case '6':
1597 case '7':
1598 case '8':
1599 case '9':
1600 case ';':
1601 case '\"':
1602 case '$':
1603 case '>':
1604 if (ip->ap < ip->argbuf + MAX_ARGSIZE)
1605 *ip->ap++ = c;
1606 return;
1607
1608 case 'p':
1609 *ip->ap = 0;
1610 if (!strncmp(ip->argbuf, "61\"", 3))
1611 ip->emul_level = EMUL_VT100;
1612 else if (!strncmp(ip->argbuf, "63;1\"", 5) ||
1613 !strncmp(ip->argbuf, "62;1\"", 5))
1614 ip->emul_level = EMUL_VT300_7;
1615 else
1616 ip->emul_level = EMUL_VT300_8;
1617 ip->escape = 0;
1618 return;
1619
1620 case '?':
1621 *ip->ap = 0;
1622 ip->escape = '?';
1623 ip->ap = ip->argbuf;
1624 return;
1625
1626 case 'c':
1627 /* device attributes */
1628 *ip->ap = 0;
1629 if (ip->argbuf[0] == '>') {
1630 ite_sendstr(ip, "\033[>24;0;0;0c");
1631 } else {
1632 switch (ite_zargnum(ip)) {
1633 case 0:
1634 /*
1635 * primary DA request, send
1636 * primary DA response
1637 */
1638 if (ip->emul_level ==
1639 EMUL_VT100)
1640 ite_sendstr(ip,
1641 "\033[?1;1c");
1642 else
1643 ite_sendstr(ip,
1644 "\033[63;0c");
1645 break;
1646 }
1647 }
1648 ip->escape = 0;
1649 return;
1650
1651 case 'n':
1652 switch (ite_zargnum(ip)) {
1653 case 5:
1654 /* no malfunction */
1655 ite_sendstr(ip, "\033[0n");
1656 break;
1657 case 6:
1658 /* cursor position report */
1659 snprintf(ip->argbuf, sizeof(ip->argbuf),
1660 "\033[%d;%dR",
1661 ip->cury + 1, ip->curx + 1);
1662 ite_sendstr(ip, ip->argbuf);
1663 break;
1664 }
1665 ip->escape = 0;
1666 return;
1667
1668 case 'x':
1669 switch (ite_zargnum(ip)) {
1670 case 0:
1671 /* Fake some terminal parameters. */
1672 ite_sendstr(ip,
1673 "\033[2;1;1;112;112;1;0x");
1674 break;
1675 case 1:
1676 ite_sendstr(ip,
1677 "\033[3;1;1;112;112;1;0x");
1678 break;
1679 }
1680 ip->escape = 0;
1681 return;
1682
1683 case 'g':
1684 /* clear tabs */
1685 switch (ite_zargnum(ip)) {
1686 case 0:
1687 if (ip->curx < ip->cols)
1688 ip->tabs[ip->curx] = 0;
1689 break;
1690 case 3:
1691 for (n = 0; n < ip->cols; n++)
1692 ip->tabs[n] = 0;
1693 break;
1694
1695 default:
1696 /* ignore */
1697 break;
1698 }
1699 ip->escape = 0;
1700 return;
1701
1702 case 'h': /* set mode */
1703 case 'l': /* reset mode */
1704 n = ite_zargnum(ip);
1705 switch (n) {
1706 case 4:
1707 /* insert/replace mode */
1708 ip->imode = (c == 'h');
1709 break;
1710 case 20:
1711 ip->linefeed_newline = (c == 'h');
1712 break;
1713 }
1714 ip->escape = 0;
1715 return;
1716
1717 case 'M':
1718 /* delete line */
1719 ite_dnline(ip, ite_argnum(ip));
1720 ip->escape = 0;
1721 return;
1722
1723 case 'L':
1724 /* insert line */
1725 ite_inline(ip, ite_argnum(ip));
1726 ip->escape = 0;
1727 return;
1728
1729 case 'P':
1730 /* delete char */
1731 ite_dnchar(ip, ite_argnum(ip));
1732 ip->escape = 0;
1733 return;
1734
1735 case '@':
1736 /* insert char(s) */
1737 ite_inchar(ip, ite_argnum(ip));
1738 ip->escape = 0;
1739 return;
1740
1741 case '!':
1742 /* soft terminal reset */
1743 ip->escape = 0; /* XXX */
1744 return;
1745
1746 case 'G':
1747 /*
1748 * this one was *not* in my vt320 manual but
1749 * in a vt320 termcap entry.. who is right?
1750 * It's supposed to set the horizontal cursor
1751 * position.
1752 */
1753 *ip->ap = 0;
1754 x = atoi(ip->argbuf);
1755 if (x != 0)
1756 x--;
1757 ip->curx = uimin(x, ip->cols - 1);
1758 ip->escape = 0;
1759 SUBR_CURSOR(ip, MOVE_CURSOR);
1760 clr_attr(ip, ATTR_INV);
1761 return;
1762
1763 case 'd':
1764 /*
1765 * same thing here, this one's for setting
1766 * the absolute vertical cursor position.
1767 * Not documented...
1768 */
1769 *ip->ap = 0;
1770 y = atoi(ip->argbuf);
1771 if (y)
1772 y--;
1773 if (ip->inside_margins)
1774 y += ip->top_margin;
1775 ip->cury = uimin(y, ip->rows - 1);
1776 ip->escape = 0;
1777 snap_cury(ip);
1778 SUBR_CURSOR(ip, MOVE_CURSOR);
1779 clr_attr(ip, ATTR_INV);
1780 return;
1781
1782 case 'H':
1783 case 'f':
1784 *ip->ap = 0;
1785 y = atoi(ip->argbuf);
1786 x = 0;
1787 cp = strchr(ip->argbuf, ';');
1788 if (cp != NULL)
1789 x = atoi(cp + 1);
1790 if (x != 0)
1791 x--;
1792 if (y != 0)
1793 y--;
1794 if (ip->inside_margins != 0)
1795 y += ip->top_margin;
1796 ip->cury = uimin(y, ip->rows - 1);
1797 ip->curx = uimin(x, ip->cols - 1);
1798 ip->escape = 0;
1799 snap_cury(ip);
1800 SUBR_CURSOR(ip, MOVE_CURSOR);
1801 /*clr_attr(ip, ATTR_INV);*/
1802 return;
1803
1804 case 'A':
1805 /* cursor up */
1806 n = ite_argnum(ip);
1807 n = ip->cury - (n ? n : 1);
1808 if (n < 0)
1809 n = 0;
1810 if (ip->inside_margins)
1811 n = uimax(ip->top_margin, n);
1812 else if (n == ip->top_margin - 1)
1813 /*
1814 * allow scrolling outside region,
1815 * but don't scroll out of active
1816 * region without explicit CUP
1817 */
1818 n = ip->top_margin;
1819 ip->cury = n;
1820 ip->escape = 0;
1821 SUBR_CURSOR(ip, MOVE_CURSOR);
1822 clr_attr(ip, ATTR_INV);
1823 return;
1824
1825 case 'B':
1826 /* cursor down */
1827 n = ite_argnum(ip);
1828 n = ip->cury + (n ? n : 1);
1829 n = uimin(ip->rows - 1, n);
1830 #if 0
1831 if (ip->inside_margins)
1832 #endif
1833 n = uimin(ip->bottom_margin, n);
1834 #if 0
1835 else if (n == ip->bottom_margin + 1)
1836 /*
1837 * allow scrolling outside region,
1838 * but don't scroll out of active
1839 * region without explicit CUP
1840 */
1841 n = ip->bottom_margin;
1842 #endif
1843 ip->cury = n;
1844 ip->escape = 0;
1845 SUBR_CURSOR(ip, MOVE_CURSOR);
1846 clr_attr(ip, ATTR_INV);
1847 return;
1848
1849 case 'C':
1850 /* cursor forward */
1851 n = ite_argnum(ip);
1852 n = n ? n : 1;
1853 ip->curx = uimin(ip->curx + n, ip->cols - 1);
1854 ip->escape = 0;
1855 SUBR_CURSOR(ip, MOVE_CURSOR);
1856 clr_attr(ip, ATTR_INV);
1857 return;
1858
1859 case 'D':
1860 /* cursor backward */
1861 n = ite_argnum(ip);
1862 n = n ? n : 1;
1863 n = ip->curx - n;
1864 ip->curx = n >= 0 ? n : 0;
1865 ip->escape = 0;
1866 SUBR_CURSOR(ip, MOVE_CURSOR);
1867 clr_attr(ip, ATTR_INV);
1868 return;
1869
1870 case 'J':
1871 /* erase screen */
1872 *ip->ap = 0;
1873 n = ite_zargnum(ip);
1874 if (n == 0)
1875 ite_clrtoeos(ip);
1876 else if (n == 1)
1877 ite_clrtobos(ip);
1878 else if (n == 2)
1879 ite_clrscreen(ip);
1880 ip->escape = 0;
1881 return;
1882
1883 case 'K':
1884 /* erase line */
1885 n = ite_zargnum(ip);
1886 if (n == 0)
1887 ite_clrtoeol(ip);
1888 else if (n == 1)
1889 ite_clrtobol(ip);
1890 else if (n == 2)
1891 ite_clrline(ip);
1892 ip->escape = 0;
1893 return;
1894
1895 case 'S':
1896 /* scroll up */
1897 n = ite_zargnum(ip);
1898 if (n <= 0)
1899 n = 1;
1900 else if (n > ip->rows-1)
1901 n = ip->rows-1;
1902 SUBR_SCROLL(ip, ip->rows-1, 0, n, SCROLL_UP);
1903 ip->escape = 0;
1904 return;
1905
1906 case 'T':
1907 /* scroll down */
1908 n = ite_zargnum(ip);
1909 if (n <= 0)
1910 n = 1;
1911 else if (n > ip->rows-1)
1912 n = ip->rows-1;
1913 SUBR_SCROLL(ip, 0, 0, n, SCROLL_DOWN);
1914 ip->escape = 0;
1915 return;
1916
1917 case 'X':
1918 /* erase character */
1919 n = ite_argnum(ip) - 1;
1920 n = uimin(n, ip->cols - 1 - ip->curx);
1921 for (; n >= 0; n--) {
1922 attrclr(ip, ip->cury, ip->curx + n,
1923 1, 1);
1924 SUBR_PUTC(ip, ' ',
1925 ip->cury, ip->curx + n, ATTR_NOR);
1926 }
1927 ip->escape = 0;
1928 return;
1929
1930 case '}': case '`':
1931 /* status line control */
1932 ip->escape = 0;
1933 return;
1934
1935 case 'r':
1936 /* set scrolling region */
1937 ip->escape = 0;
1938 *ip->ap = 0;
1939 x = atoi(ip->argbuf);
1940 x = x ? x : 1;
1941 y = ip->rows;
1942 cp = strchr(ip->argbuf, ';');
1943 if (cp) {
1944 y = atoi(cp + 1);
1945 y = y ? y : ip->rows;
1946 }
1947 if (y <= x)
1948 return;
1949 x--;
1950 y--;
1951 ip->top_margin = uimin(x, ip->rows - 2);
1952 ip->bottom_margin = uimin(y, ip->rows - 1);
1953 if (ip->inside_margins) {
1954 ip->cury = ip->top_margin;
1955 } else
1956 ip->cury = 0;
1957 ip->curx = 0;
1958 return;
1959
1960 case 'm':
1961 /* big attribute setter/resetter */
1962 {
1963 char *c_p;
1964
1965 *ip->ap = 0;
1966 /* kludge to make CSIm work (== CSI0m) */
1967 if (ip->ap == ip->argbuf)
1968 ip->ap++;
1969 for (c_p = ip->argbuf; c_p < ip->ap; ) {
1970 switch (*c_p) {
1971 case 0:
1972 case '0':
1973 clr_attr(ip, ATTR_ALL);
1974 ip->fgcolor = 7;
1975 ip->bgcolor = 0;
1976 c_p++;
1977 break;
1978
1979 case '1':
1980 set_attr(ip, ATTR_BOLD);
1981 c_p++;
1982 break;
1983
1984 case '2':
1985 switch (c_p[1]) {
1986 case '2':
1987 clr_attr(ip, ATTR_BOLD);
1988 c_p += 2;
1989 break;
1990
1991 case '4':
1992 clr_attr(ip, ATTR_UL);
1993 c_p += 2;
1994 break;
1995
1996 case '5':
1997 clr_attr(ip,
1998 ATTR_BLINK);
1999 c_p += 2;
2000 break;
2001
2002 case '7':
2003 clr_attr(ip, ATTR_INV);
2004 c_p += 2;
2005 break;
2006
2007 default:
2008 c_p++;
2009 break;
2010 }
2011 break;
2012
2013 case '3':
2014 switch (c_p[1]) {
2015 case '0':
2016 case '1':
2017 case '2':
2018 case '3':
2019 case '4':
2020 case '5':
2021 case '6':
2022 case '7':
2023 /* foreground colors */
2024 ip->fgcolor =
2025 c_p[1] - '0';
2026 c_p += 2;
2027 break;
2028 default:
2029 c_p++;
2030 break;
2031 }
2032 break;
2033
2034 case '4':
2035 switch (c_p[1]) {
2036 case '0':
2037 case '1':
2038 case '2':
2039 case '3':
2040 case '4':
2041 case '5':
2042 case '6':
2043 case '7':
2044 /* background colors */
2045 ip->bgcolor =
2046 c_p[1] - '0';
2047 c_p += 2;
2048 break;
2049 default:
2050 set_attr(ip, ATTR_UL);
2051 c_p++;
2052 break;
2053 }
2054 break;
2055
2056 case '5':
2057 set_attr(ip, ATTR_BLINK);
2058 c_p++;
2059 break;
2060
2061 case '7':
2062 set_attr(ip, ATTR_INV);
2063 c_p++;
2064 break;
2065
2066 default:
2067 c_p++;
2068 break;
2069 }
2070 }
2071
2072 }
2073 ip->escape = 0;
2074 return;
2075
2076 case 'u':
2077 /* DECRQTSR */
2078 ite_sendstr(ip, "\033P\033\\");
2079 ip->escape = 0;
2080 return;
2081
2082 default:
2083 ip->escape = 0;
2084 return;
2085 }
2086 break;
2087
2088 case '?': /* CSI ? */
2089 switch (c) {
2090 case '0':
2091 case '1':
2092 case '2':
2093 case '3':
2094 case '4':
2095 case '5':
2096 case '6':
2097 case '7':
2098 case '8':
2099 case '9':
2100 case ';':
2101 case '\"':
2102 case '$':
2103 /*
2104 * Don't fill the last character; it's needed.
2105 */
2106 /* XXX yeah, where ?? */
2107 if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
2108 *ip->ap++ = c;
2109 return;
2110
2111 case 'n':
2112 /* Terminal Reports */
2113 *ip->ap = 0;
2114 if (ip->ap == &ip->argbuf[2]) {
2115 if (!strncmp(ip->argbuf, "15", 2))
2116 /* printer status: no printer */
2117 ite_sendstr(ip, "\033[13n");
2118 else if (!strncmp(ip->argbuf, "25", 2))
2119 /* udk status */
2120 ite_sendstr(ip, "\033[20n");
2121 else if (!strncmp(ip->argbuf, "26", 2))
2122 /* keyboard dialect: US */
2123 ite_sendstr(ip, "\033[27;1n");
2124 }
2125 ip->escape = 0;
2126 return;
2127
2128 case 'h': /* set dec private modes */
2129 case 'l': /* reset dec private modes */
2130 n = ite_zargnum(ip);
2131 switch (n) {
2132 case 1:
2133 /* CKM - cursor key mode */
2134 ip->cursor_appmode = (c == 'h');
2135 break;
2136
2137 case 3:
2138 /* 132/80 columns (132 == 'h') */
2139 break;
2140
2141 case 4: /* smooth scroll */
2142 break;
2143
2144 case 5:
2145 /*
2146 * light background (=='h') /
2147 * dark background (=='l')
2148 */
2149 break;
2150
2151 case 6: /* origin mode */
2152 ip->inside_margins = (c == 'h');
2153 #if 0
2154 ip->curx = 0;
2155 ip->cury = ip->inside_margins ?
2156 ip->top_margin : 0;
2157 SUBR_CURSOR(ip, MOVE_CURSOR);
2158 #endif
2159 break;
2160
2161 case 7: /* auto wraparound */
2162 ip->auto_wrap = (c == 'h');
2163 break;
2164
2165 case 8: /* keyboard repeat */
2166 ip->key_repeat = (c == 'h');
2167 break;
2168
2169 case 20: /* newline mode */
2170 ip->linefeed_newline = (c == 'h');
2171 break;
2172
2173 case 25: /* cursor on/off */
2174 SUBR_CURSOR(ip, (c == 'h') ?
2175 DRAW_CURSOR : ERASE_CURSOR);
2176 break;
2177 }
2178 ip->escape = 0;
2179 return;
2180
2181 case 'K':
2182 /* selective erase in line */
2183 case 'J':
2184 /* selective erase in display */
2185
2186 default:
2187 ip->escape = 0;
2188 return;
2189 }
2190 break;
2191
2192 default:
2193 ip->escape = 0;
2194 return;
2195 }
2196 }
2197
2198 switch (c) {
2199 case 0x00: /* NUL */
2200 case 0x01: /* SOH */
2201 case 0x02: /* STX */
2202 case 0x03: /* ETX */
2203 case 0x04: /* EOT */
2204 case 0x05: /* ENQ */
2205 case 0x06: /* ACK */
2206 break;
2207
2208 case BEL:
2209 #if NBELL > 0
2210 if (kbd_ite && ite_tty[device_unit(kbd_ite->device)])
2211 opm_bell();
2212 #endif
2213 break;
2214
2215 case BS:
2216 if (--ip->curx < 0)
2217 ip->curx = 0;
2218 else
2219 SUBR_CURSOR(ip, MOVE_CURSOR);
2220 break;
2221
2222 case HT:
2223 for (n = ip->curx + 1; n < ip->cols; n++) {
2224 if (ip->tabs[n]) {
2225 ip->curx = n;
2226 SUBR_CURSOR(ip, MOVE_CURSOR);
2227 break;
2228 }
2229 }
2230 break;
2231
2232 case VT: /* VT is treated like LF */
2233 case FF: /* so is FF */
2234 case LF:
2235 /*
2236 * cr->crlf distinction is done here, on output,
2237 * not on input!
2238 */
2239 if (ip->linefeed_newline)
2240 ite_crlf(ip);
2241 else
2242 ite_lf(ip);
2243 break;
2244
2245 case CR:
2246 ite_cr(ip);
2247 break;
2248
2249 case SO:
2250 ip->GL = &ip->G1;
2251 break;
2252
2253 case SI:
2254 ip->GL = &ip->G0;
2255 break;
2256
2257 case 0x10: /* DLE */
2258 case 0x11: /* DC1/XON */
2259 case 0x12: /* DC2 */
2260 case 0x13: /* DC3/XOFF */
2261 case 0x14: /* DC4 */
2262 case 0x15: /* NAK */
2263 case 0x16: /* SYN */
2264 case 0x17: /* ETB */
2265 break;
2266
2267 case CAN:
2268 ip->escape = 0; /* cancel any escape sequence in progress */
2269 break;
2270
2271 case 0x19: /* EM */
2272 break;
2273
2274 case SUB:
2275 ip->escape = 0; /* dito, but see below */
2276 /* should also display a reverse question mark!! */
2277 break;
2278
2279 case ESC:
2280 ip->escape = ESC;
2281 break;
2282
2283 case 0x1c: /* FS */
2284 case 0x1d: /* GS */
2285 case 0x1e: /* RS */
2286 case 0x1f: /* US */
2287 break;
2288
2289 /* now it gets weird.. 8bit control sequences.. */
2290 case IND: /* index: move cursor down, scroll */
2291 ite_index(ip);
2292 break;
2293
2294 case NEL: /* next line. next line, first pos. */
2295 ite_crlf(ip);
2296 break;
2297
2298 case HTS: /* set horizontal tab */
2299 if (ip->curx < ip->cols)
2300 ip->tabs[ip->curx] = 1;
2301 break;
2302
2303 case RI: /* reverse index */
2304 ite_rlf(ip);
2305 break;
2306
2307 case SS2: /* go into G2 for one character */
2308 ip->save_GL = ip->GR; /* GL XXX EUC */
2309 ip->GR = &ip->G2; /* GL XXX */
2310 break;
2311
2312 case SS3: /* go into G3 for one character */
2313 ip->save_GL = ip->GR; /* GL XXX EUC */
2314 ip->GR = &ip->G3; /* GL XXX */
2315 break;
2316
2317 case DCS: /* device control string introducer */
2318 ip->escape = DCS;
2319 ip->ap = ip->argbuf;
2320 break;
2321
2322 case CSI: /* control sequence introducer */
2323 ip->escape = CSI;
2324 ip->ap = ip->argbuf;
2325 break;
2326
2327 case ST: /* string terminator */
2328 /* ignore, if not used as terminator */
2329 break;
2330
2331 case OSC: /* introduces OS command. */
2332 /* Ignore everything upto ST */
2333 ip->escape = OSC;
2334 break;
2335
2336 case PM: /* privacy message */
2337 /* ignore everything upto ST */
2338 ip->escape = PM;
2339 break;
2340
2341 case APC: /* application program command */
2342 /* ignore everything upto ST */
2343 ip->escape = APC;
2344 break;
2345
2346 case DEL:
2347 break;
2348
2349 default:
2350 if (ip->save_char == 0 &&
2351 (*((c & 0x80) ? ip->GR : ip->GL) & CSET_MULTI) != 0) {
2352 ip->save_char = c;
2353 break;
2354 }
2355 if (ip->imode != 0)
2356 ite_inchar(ip, ip->save_char ? 2 : 1);
2357 iteprecheckwrap(ip);
2358 #ifdef DO_WEIRD_ATTRIBUTES
2359 if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
2360 attrset(ip, ATTR_INV);
2361 SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
2362 }
2363 else
2364 SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
2365 #else
2366 SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
2367 #endif
2368 /*SUBR_CURSOR(ip, DRAW_CURSOR);*/
2369 itecheckwrap(ip);
2370 if (ip->save_char) {
2371 itecheckwrap(ip);
2372 ip->save_char = 0;
2373 }
2374 if (ip->save_GL) {
2375 /*
2376 * reset single shift
2377 */
2378 ip->GR = ip->save_GL;
2379 ip->save_GL = 0;
2380 }
2381 break;
2382 }
2383 }
2384
2385 static void
2386 iteprecheckwrap(struct ite_softc *ip)
2387 {
2388
2389 if (ip->auto_wrap && ip->curx + (ip->save_char ? 1 : 0) == ip->cols) {
2390 ip->curx = 0;
2391 clr_attr(ip, ATTR_INV);
2392 if (++ip->cury >= ip->bottom_margin + 1) {
2393 ip->cury = ip->bottom_margin;
2394 /*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2395 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
2396 ite_clrtoeol(ip);
2397 } /*else
2398 SUBR_CURSOR(ip, MOVE_CURSOR);*/
2399 }
2400 }
2401
2402 static void
2403 itecheckwrap(struct ite_softc *ip)
2404 {
2405
2406 #if 0
2407 if (++ip->curx == ip->cols) {
2408 if (ip->auto_wrap) {
2409 ip->curx = 0;
2410 clr_attr(ip, ATTR_INV);
2411 if (++ip->cury >= ip->bottom_margin + 1) {
2412 ip->cury = ip->bottom_margin;
2413 SUBR_CURSOR(ip, MOVE_CURSOR);
2414 SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1,
2415 SCROLL_UP);
2416 ite_clrtoeol(ip);
2417 return;
2418 }
2419 } else
2420 /* stay there if no autowrap.. */
2421 ip->curx--;
2422 }
2423 #else
2424 if (ip->curx < ip->cols) {
2425 ip->curx++;
2426 /*SUBR_CURSOR(ip, MOVE_CURSOR);*/
2427 }
2428 #endif
2429 }
2430
2431 /*
2432 * A convertion table from DEC special graphics characters to ASCII characters.
2433 * Mostly for box drawing on sysinst(8).
2434 */
2435 const uint8_t ite_decgraph2ascii[128] = {
2436 /* same as ASCII from 0x00 to 0x5e */
2437 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
2438 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
2439 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
2440 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
2441 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
2442 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
2443 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
2444 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
2445 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
2446 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
2447 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
2448 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
2449
2450 /* special graphics characters from 0x5f to 0x7e */
2451 ' ', /* 0x5f NBSP */
2452 '*', /* 0x60 diamond */
2453 ' ', /* 0x61 medium shade */
2454 ' ', /* 0x62 HT */
2455 ' ', /* 0x63 FF */
2456 ' ', /* 0x64 CR */
2457 ' ', /* 0x65 LF */
2458 ' ', /* 0x66 degree symbol */
2459 ' ', /* 0x67 plus-minus sign */
2460 ' ', /* 0x68 NL */
2461 ' ', /* 0x69 VT */
2462 '+', /* 0x6a box drawings up left */
2463 '+', /* 0x6b box drawings down left */
2464 '+', /* 0x6c box drawings down right */
2465 '+', /* 0x6d box drawings up right */
2466 '+', /* 0x6e box drawings vertical horizontal */
2467 '~', /* 0x6f scan line 1 */
2468 '-', /* 0x70 scan line 3 */
2469 '-', /* 0x71 scan line 5 */
2470 '-', /* 0x72 scan line 7 */
2471 '_', /* 0x73 scan line 9 */
2472 '+', /* 0x74 box drawings vertical right */
2473 '+', /* 0x75 box drawings vertical left */
2474 '+', /* 0x76 box drawings horizontal up */
2475 '+', /* 0x77 box drawings horizontal down */
2476 '|', /* 0x78 box drawings vertical */
2477 '<', /* 0x79 less than or equal to */
2478 '>', /* 0x7a greater than or equal to */
2479 ' ', /* 0x7b pi */
2480 ' ', /* 0x7c not equal */
2481 ' ', /* 0x7d pound sign */
2482 '.', /* 0x7e middle dot */
2483 /* end of special graphics characters */
2484 0x7f
2485 };
2486
2487 #endif
2488
2489 #if NITE > 0 && NKBD > 0
2490
2491 /*
2492 * Console functions
2493 */
2494 #include <dev/cons.h>
2495 extern void kbdenable(int);
2496 extern int kbdcngetc(void);
2497
2498 /*
2499 * Return a priority in consdev->cn_pri field highest wins. This function
2500 * is called before any devices have been probed.
2501 */
2502 void
2503 itecnprobe(struct consdev *cd)
2504 {
2505 int maj;
2506
2507 /* locate the major number */
2508 maj = cdevsw_lookup_major(&ite_cdevsw);
2509
2510 /*
2511 * return priority of the best ite (already picked from attach)
2512 * or CN_DEAD.
2513 */
2514 if (con_itesoftc.grf == NULL)
2515 cd->cn_pri = CN_DEAD;
2516 else {
2517 con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
2518 /*
2519 * hardcode the minor number.
2520 * currently we support only one ITE, it is enough for now.
2521 */
2522 con_itesoftc.isw = &itesw[0];
2523 cd->cn_pri = CN_INTERNAL;
2524 cd->cn_dev = makedev(maj, 0);
2525 }
2526 }
2527
2528 void
2529 itecninit(struct consdev *cd)
2530 {
2531 struct ite_softc *ip;
2532
2533 ip = getitesp(cd->cn_dev);
2534 iteinit(cd->cn_dev); /* init console unit */
2535 ip->flags |= ITE_ACTIVE | ITE_ISCONS;
2536 kbdenable(0);
2537 mfp_send_usart(0x49);
2538 }
2539
2540 /*
2541 * itecnfinish() is called in ite_init() when the device is
2542 * being probed in the normal fashion, thus we can finish setting
2543 * up this ite now that the system is more functional.
2544 */
2545 void
2546 itecnfinish(struct ite_softc *ip)
2547 {
2548 static int done;
2549
2550 if (done)
2551 return;
2552 done = 1;
2553 }
2554
2555 /*ARGSUSED*/
2556 int
2557 itecngetc(dev_t dev)
2558 {
2559 int c;
2560
2561 do {
2562 c = kbdcngetc();
2563 c = ite_cnfilter(c);
2564 } while (c == -1);
2565 return (c);
2566 }
2567
2568 void
2569 itecnputc(dev_t dev, int c)
2570 {
2571 static int paniced = 0;
2572 struct ite_softc *ip = getitesp(dev);
2573 char ch = c;
2574 #ifdef ITE_KERNEL_ATTR
2575 short save_attribute;
2576 #endif
2577
2578 if (panicstr && !paniced &&
2579 (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
2580 (void) iteon(dev, 3);
2581 paniced = 1;
2582 }
2583 #ifdef ITE_KERNEL_ATTR
2584 save_attribute = ip->attribute;
2585 ip->attribute = ITE_KERNEL_ATTR;
2586 #endif
2587 ite_putstr(&ch, 1, dev);
2588 #ifdef ITE_KERNEL_ATTR
2589 ip->attribute = save_attribute;
2590 #endif
2591 }
2592 #endif
2593