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