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
itematch(device_t parent,cfdata_t cf,void * aux)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
iteattach(device_t parent,device_t self,void * aux)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 *
getitesp(dev_t dev)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
iteinit(dev_t dev)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
ite_config_console(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
iteon(dev_t dev,int flag)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
iteoff(dev_t dev,int flag)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
iteopen(dev_t dev,int mode,int devtype,struct lwp * l)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
iteclose(dev_t dev,int flag,int mode,struct lwp * l)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
iteread(dev_t dev,struct uio * uio,int flag)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
itewrite(dev_t dev,struct uio * uio,int flag)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
itepoll(dev_t dev,int events,struct lwp * l)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 *
itetty(dev_t dev)452 itetty(dev_t dev)
453 {
454 
455           return ite_tty[UNIT(dev)];
456 }
457 
458 static int
iteioctl(dev_t dev,u_long cmd,void * addr,int flag,struct lwp * l)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
itestart(struct tty * tp)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
ite_reinit(dev_t dev)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
ite_reset(struct ite_softc * ip)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
ite_cnfilter(u_char c)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
itesendch(int ch)726 itesendch(int ch)
727 {
728 
729           (*kbd_tty->t_linesw->l_rint)(ch, kbd_tty);
730 }
731 
732 void
ite_filter(u_char c)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
ite_sendstr(struct ite_softc * ip,const char * str)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
alignment_display(struct ite_softc * ip)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
snap_cury(struct ite_softc * ip)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
ite_dnchar(struct ite_softc * ip,int n)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
ite_inchar(struct ite_softc * ip,int n)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
ite_clrtoeol(struct ite_softc * ip)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
ite_clrtobol(struct ite_softc * ip)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
ite_clrline(struct ite_softc * ip)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
ite_clrtoeos(struct ite_softc * ip)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
ite_clrtobos(struct ite_softc * ip)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
ite_clrscreen(struct ite_softc * ip)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
ite_dnline(struct ite_softc * ip,int n)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
ite_inline(struct ite_softc * ip,int n)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
ite_index(struct ite_softc * ip)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
ite_lf(struct ite_softc * ip)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
ite_crlf(struct ite_softc * ip)1131 ite_crlf(struct ite_softc *ip)
1132 {
1133 
1134           ip->curx = 0;
1135           ite_lf(ip);
1136 }
1137 
1138 static inline void
ite_cr(struct ite_softc * ip)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
ite_rlf(struct ite_softc * ip)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
atoi(const char * cp)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
ite_argnum(struct ite_softc * ip)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
ite_zargnum(struct ite_softc * ip)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
ite_putstr(const u_char * s,int len,dev_t dev)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
iteputchar(int c,struct ite_softc * ip)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