#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ite.c,v 1.73 2026/04/07 22:22:11 andvar Exp $");
#include "ite.h"
#if NITE > 0
#include "bell.h"
#include "kbd.h"
#include "opt_ite.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/kauth.h>
#include <sys/device_impl.h>
#include <machine/cpu.h>
#include <machine/kbio.h>
#include <machine/bus.h>
#include <machine/autoconf.h>
#include <machine/grfioctl.h>
#include <machine/iteioctl.h>
#include <arch/x68k/dev/grfvar.h>
#include <arch/x68k/dev/itevar.h>
#include <arch/x68k/dev/kbdmap.h>
#include <arch/x68k/dev/mfp.h>
#include "ioconf.h"
#if NBELL > 0
void opm_bell(void);
#endif
#define SUBR_INIT(ip) ip->isw->ite_init(ip)
#define SUBR_DEINIT(ip) ip->isw->ite_deinit(ip)
#define SUBR_PUTC(ip,c,dy,dx,m) ip->isw->ite_putc(ip,c,dy,dx,m)
#define SUBR_CURSOR(ip,flg) ip->isw->ite_cursor(ip,flg)
#define SUBR_CLEAR(ip,sy,sx,h,w) ip->isw->ite_clear(ip,sy,sx,h,w)
#define SUBR_SCROLL(ip,sy,sx,count,dir) \
ip->isw->ite_scroll(ip,sy,sx,count,dir)
#if defined(ITE_SIXEL)
#define SUBR_SIXEL(ip,sy,sx) ip->isw->ite_sixel(ip,sy,sx)
#endif
struct consdev;
static inline void itesendch(int);
static inline void alignment_display(struct ite_softc *);
static inline void snap_cury(struct ite_softc *);
static inline void ite_dnchar(struct ite_softc *, int);
static void ite_inchar(struct ite_softc *, int);
static inline void ite_clrtoeol(struct ite_softc *);
static inline void ite_clrtobol(struct ite_softc *);
static inline void ite_clrline(struct ite_softc *);
static inline void ite_clrtoeos(struct ite_softc *);
static inline void ite_clrtobos(struct ite_softc *);
static inline void ite_clrscreen(struct ite_softc *);
static inline void ite_dnline(struct ite_softc *, int);
static inline void ite_inline(struct ite_softc *, int);
static inline void ite_index(struct ite_softc *);
static inline void ite_lf(struct ite_softc *);
static inline void ite_crlf(struct ite_softc *);
static inline void ite_cr(struct ite_softc *);
static inline void ite_rlf(struct ite_softc *);
static void iteprecheckwrap(struct ite_softc *);
static void itecheckwrap(struct ite_softc *);
static int ite_argnum(struct ite_softc *);
static int ite_zargnum(struct ite_softc *);
static void ite_sendstr(struct ite_softc *, const char *);
static inline int atoi(const char *);
static struct ite_softc *getitesp(dev_t);
static struct itesw itesw[] = {
{0, tv_init, tv_deinit, 0,
0, 0, 0}
};
#define ITEBURST 64
struct tty *ite_tty[NITE];
static struct ite_softc *kbd_ite = NULL;
static struct ite_softc con_itesoftc;
static struct device con_itedev;
static struct tty *kbd_tty = NULL;
static int start_repeat_timeo = 20;
static int next_repeat_timeo = 3;
static u_char cons_tabs[MAX_TABS];
static void itestart(struct tty *);
static void iteputchar(int, struct ite_softc *);
#if defined(ITE_SIXEL)
static int ite_dcs(const int, struct ite_softc *);
#endif
static void ite_putstr(const u_char *, int, dev_t);
static int itematch(device_t, cfdata_t, void *);
static void iteattach(device_t, device_t, void *);
CFATTACH_DECL_NEW(ite, sizeof(struct ite_softc),
itematch, iteattach, NULL, NULL);
static dev_type_open(iteopen);
static dev_type_close(iteclose);
static dev_type_read(iteread);
static dev_type_write(itewrite);
static dev_type_ioctl(iteioctl);
static dev_type_tty(itetty);
static dev_type_poll(itepoll);
const struct cdevsw ite_cdevsw = {
.d_open = iteopen,
.d_close = iteclose,
.d_read = iteread,
.d_write = itewrite,
.d_ioctl = iteioctl,
.d_stop = nostop,
.d_tty = itetty,
.d_poll = itepoll,
.d_mmap = nommap,
.d_kqfilter = ttykqfilter,
.d_discard = nodiscard,
.d_flag = D_TTY
};
static int
itematch(device_t parent, cfdata_t cf, void *aux)
{
struct grf_softc *gp;
gp = aux;
if (cf->cf_loc[GRFCF_GRFADDR] != gp->g_cfaddr)
return 0;
return 1;
}
static void
iteattach(device_t parent, device_t self, void *aux)
{
struct ite_softc *ip;
struct grf_softc *gp;
gp = aux;
ip = device_private(self);
ip->device = self;
if(con_itesoftc.grf != NULL
) {
memcpy(&ip->grf, &con_itesoftc.grf,
(char *)&ip[1] - (char *)&ip->grf);
con_itesoftc.grf = NULL;
kbd_ite = ip;
}
ip->grf = gp;
iteinit(device_unit(self));
aprint_normal(": rows %d cols %d", ip->rows, ip->cols);
if (kbd_ite == NULL)
kbd_ite = ip;
aprint_normal("\n");
}
static struct ite_softc *
getitesp(dev_t dev)
{
if (x68k_realconfig && con_itesoftc.grf == NULL)
return device_lookup_private(&ite_cd, UNIT(dev));
if (con_itesoftc.grf == NULL)
panic("no ite_softc for console");
return &con_itesoftc;
}
void
iteinit(dev_t dev)
{
struct ite_softc *ip;
ip = getitesp(dev);
if (ip->flags & ITE_INITED)
return;
memcpy(&kbdmap, &ascii_kbdmap, sizeof(struct kbdmap));
ip->curx = 0;
ip->cury = 0;
ip->cursorx = 0;
ip->cursory = 0;
ip->isw = &itesw[device_unit(ip->device)];
SUBR_INIT(ip);
SUBR_CURSOR(ip, DRAW_CURSOR);
if (ip->tabs == NULL)
ip->tabs = malloc(MAX_TABS * sizeof(u_char),
M_DEVBUF, M_WAITOK);
ite_reset(ip);
ip->flags |= ITE_INITED;
}
void
ite_config_console(void)
{
struct grf_softc *gp = &congrf;
if (con_itesoftc.grf != NULL)
return;
con_itesoftc.grf = gp;
con_itesoftc.tabs = cons_tabs;
con_itesoftc.device = &con_itedev;
}
int
iteon(dev_t dev, int flag)
{
int unit = UNIT(dev);
struct ite_softc *ip;
if (unit < 0 || unit >= ite_cd.cd_ndevs ||
(ip = getitesp(dev)) == NULL || (ip->flags & ITE_ALIVE) == 0)
return ENXIO;
if ((flag & 1) != 0) {
ip->flags |= ITE_ACTIVE;
ip->flags &= ~(ITE_INGRF|ITE_INITED);
}
if ((flag & 2) != 0) {
ip->flags &= ~ITE_INGRF;
if ((ip->flags & ITE_ACTIVE) == 0)
return 0;
}
ip->flags |= ITE_ACTIVE;
if ((ip->flags & ITE_INGRF) != 0)
return 0;
iteinit(dev);
if ((flag & 2) != 0)
ite_reset(ip);
#if NKBD > 0
mfp_send_usart(0x49);
#endif
return 0;
}
void
iteoff(dev_t dev, int flag)
{
int unit = UNIT(dev);
struct ite_softc *ip;
if (unit < 0 || unit >= ite_cd.cd_ndevs ||
(ip = getitesp(dev)) == NULL || (ip->flags & ITE_ALIVE) == 0)
return;
if ((flag & 2) != 0)
ip->flags |= ITE_INGRF;
if ((ip->flags & ITE_ACTIVE) == 0)
return;
if ((flag & 1) != 0 ||
(ip->flags & (ITE_INGRF | ITE_ISCONS | ITE_INITED)) == ITE_INITED)
SUBR_DEINIT(ip);
if ((flag & 2) == 0 && (ip->flags & ITE_ISCONS) == 0) {
ip->flags &= ~ITE_ACTIVE;
#if NKBD > 0
mfp_send_usart(0x48);
#endif
}
}
static int
iteopen(dev_t dev, int mode, int devtype, struct lwp *l)
{
int unit = UNIT(dev);
struct tty *tp;
struct ite_softc *ip;
int error;
int first = 0;
if (unit >= ite_cd.cd_ndevs || (ip = getitesp(dev)) == NULL)
return ENXIO;
if (ite_tty[unit] == NULL) {
tp = ite_tty[unit] = tty_alloc();
tty_attach(tp);
} else
tp = ite_tty[unit];
if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
return EBUSY;
if ((ip->flags & ITE_ACTIVE) == 0) {
error = iteon(dev, 0);
if (error)
return error;
first = 1;
}
tp->t_oproc = itestart;
tp->t_param = NULL;
tp->t_dev = dev;
if ((tp->t_state&TS_ISOPEN) == 0) {
ttychars(tp);
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
tp->t_cflag = TTYDEF_CFLAG;
tp->t_lflag = TTYDEF_LFLAG;
tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
tp->t_state = TS_ISOPEN|TS_CARR_ON;
ttsetwater(tp);
}
error = (*tp->t_linesw->l_open)(dev, tp);
if (error == 0) {
tp->t_winsize.ws_row = ip->rows;
tp->t_winsize.ws_col = ip->cols;
} else if (first)
iteoff(dev, 0);
return error;
}
static int
iteclose(dev_t dev, int flag, int mode, struct lwp *l)
{
struct tty *tp = ite_tty[UNIT(dev)];
(*tp->t_linesw->l_close)(tp, flag);
ttyclose(tp);
iteoff(dev, 0);
#if 0
tty_free(tp);
ite_tty[UNIT(dev)] = NULL;
#endif
return 0;
}
static int
iteread(dev_t dev, struct uio *uio, int flag)
{
struct tty *tp = ite_tty[UNIT(dev)];
return (*tp->t_linesw->l_read)(tp, uio, flag);
}
static int
itewrite(dev_t dev, struct uio *uio, int flag)
{
struct tty *tp = ite_tty[UNIT(dev)];
return (*tp->t_linesw->l_write)(tp, uio, flag);
}
static int
itepoll(dev_t dev, int events, struct lwp *l)
{
struct tty *tp = ite_tty[UNIT(dev)];
return (*tp->t_linesw->l_poll)(tp, events, l);
}
static struct tty *
itetty(dev_t dev)
{
return ite_tty[UNIT(dev)];
}
static int
iteioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
struct iterepeat *irp;
struct tty *tp = ite_tty[UNIT(dev)];
int error;
error = (*tp->t_linesw->l_ioctl)(tp, cmd, addr, flag, l);
if (error != EPASSTHROUGH)
return error;
error = ttioctl(tp, cmd, addr, flag, l);
if (error != EPASSTHROUGH)
return error;
switch (cmd) {
case ITEIOCSKMAP:
if (addr == NULL)
return EFAULT;
memcpy(&kbdmap, addr, sizeof(struct kbdmap));
return 0;
case ITEIOCGKMAP:
if (addr == NULL)
return EFAULT;
memcpy(addr, &kbdmap, sizeof(struct kbdmap));
return 0;
case ITEIOCGREPT:
irp = (struct iterepeat *)addr;
irp->start = start_repeat_timeo;
irp->next = next_repeat_timeo;
case ITEIOCSREPT:
irp = (struct iterepeat *)addr;
if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
return(EINVAL);
start_repeat_timeo = irp->start;
next_repeat_timeo = irp->next;
#if x68k
case ITELOADFONT:
if (addr != NULL) {
memcpy(kern_font, addr, 4096 );
ite_set_glyph();
return 0;
} else
return EFAULT;
case ITETVCTRL:
if (addr != NULL && *(uint8_t *)addr < 0x40) {
return mfp_send_usart(*(uint8_t *)addr);
} else {
return EFAULT;
}
#endif
}
return EPASSTHROUGH;
}
static void
itestart(struct tty *tp)
{
struct clist *rbp;
uint8_t buf[ITEBURST];
int s, len;
getitesp(tp->t_dev);
s = spltty();
if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) != 0)
goto out;
tp->t_state |= TS_BUSY;
rbp = &tp->t_outq;
len = q_to_b(rbp, buf, ITEBURST);
ite_putstr(buf, len, tp->t_dev);
tp->t_state &= ~TS_BUSY;
if (ttypull(tp)) {
tp->t_state |= TS_TIMEOUT;
callout_schedule(&tp->t_rstrt_ch, 1);
}
out:
splx(s);
}
void
ite_reinit(dev_t dev)
{
struct ite_softc *ip;
int unit = UNIT(dev);
if (unit < 0 || unit >= ite_cd.cd_ndevs ||
(ip = getitesp(dev)) == NULL)
return;
ip->flags &= ~ITE_INITED;
iteinit(dev);
}
void
ite_reset(struct ite_softc *ip)
{
int i;
ip->curx = 0;
ip->cury = 0;
ip->attribute = 0;
ip->save_curx = 0;
ip->save_cury = 0;
ip->save_attribute = 0;
ip->ap = ip->argbuf;
ip->emul_level = EMUL_VT300_8;
ip->eightbit_C1 = 0;
ip->top_margin = 0;
ip->bottom_margin = ip->rows - 1;
ip->inside_margins = 0;
ip->linefeed_newline = 0;
ip->auto_wrap = 1;
ip->cursor_appmode = 0;
ip->keypad_appmode = 0;
ip->imode = 0;
ip->key_repeat = 1;
ip->G0 = CSET_ASCII;
ip->G1 = CSET_JIS1983;
ip->G2 = CSET_JISKANA;
ip->G3 = CSET_JIS1990;
ip->GL = &ip->G0;
ip->GR = &ip->G1;
ip->save_GL = 0;
ip->save_char = 0;
ip->fgcolor = 7;
ip->bgcolor = 0;
for (i = 0; i < ip->cols; i++)
ip->tabs[i] = ((i & 7) == 0);
SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
attrclr(ip, 0, 0, ip->rows, ip->cols);
}
int
ite_cnfilter(u_char c)
{
static u_char mod = 0;
struct key key;
uint8_t code, up, mask;
int s;
up = c & 0x80 ? 1 : 0;
c &= 0x7f;
code = 0;
s = spltty();
mask = 0;
if (c >= KBD_LEFT_ALT &&
!(c >= 0x63 && c <= 0x6c)) {
switch (c) {
case KBD_LEFT_SHIFT:
mask = KBD_MOD_SHIFT;
break;
case KBD_LEFT_ALT:
mask = KBD_MOD_LALT;
break;
case KBD_RIGHT_ALT:
mask = KBD_MOD_RALT;
break;
case KBD_LEFT_META:
mask = KBD_MOD_LMETA;
break;
case KBD_RIGHT_META:
mask = KBD_MOD_RMETA;
break;
case KBD_CAPS_LOCK:
mask = KBD_MOD_CAPS;
break;
case KBD_CTRL:
mask = KBD_MOD_CTRL;
break;
case KBD_RECONNECT:
if (up)
kbd_setLED();
break;
}
if (mask & KBD_MOD_CAPS) {
if (!up) {
mod ^= KBD_MOD_CAPS;
kbdled ^= LED_CAPS_LOCK;
kbd_setLED();
}
} else if (up)
mod &= ~mask;
else
mod |= mask;
splx(s);
return -1;
}
if (up) {
splx(s);
return -1;
}
if ((mod & KBD_MOD_SHIFT) != 0) {
if ((mod & KBD_MOD_ALT) != 0)
key = kbdmap.alt_shift_keys[c];
else
key = kbdmap.shift_keys[c];
} else if ((mod & KBD_MOD_ALT) != 0)
key = kbdmap.alt_keys[c];
else {
key = kbdmap.keys[c];
if ((mod & KBD_MOD_CAPS) != 0 &&
(key.mode & KBD_MODE_CAPS) != 0)
key = kbdmap.shift_keys[c];
}
code = key.code;
if ((key.mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) != 0) {
splx(s);
return -1;
}
if ((key.mode & KBD_MODE_DEAD) != 0) {
splx(s);
return -1;
}
if ((mod & KBD_MOD_CTRL) != 0)
code &= 0x1f;
if ((mod & KBD_MOD_META) != 0)
code |= 0x80;
code = code == '\r' ? '\n' : code;
splx(s);
return code;
}
static inline void
itesendch(int ch)
{
(*kbd_tty->t_linesw->l_rint)(ch, kbd_tty);
}
void
ite_filter(u_char c)
{
static uint16_t mod = 0;
uint8_t code, *str;
uint16_t up, mask;
struct key key;
int s, i;
if (kbd_ite == NULL ||
(kbd_tty = ite_tty[device_unit(kbd_ite->device)]) == NULL)
return;
s = spltty();
up = c & 0x80 ? 1 : 0;
c &= 0x7f;
code = 0;
mask = 0;
if (c >= KBD_LEFT_ALT &&
!(c >= 0x63 && c <= 0x6c)) {
switch (c) {
case KBD_LEFT_SHIFT:
mask = KBD_MOD_SHIFT;
break;
case KBD_LEFT_ALT:
mask = KBD_MOD_LALT;
break;
case KBD_RIGHT_ALT:
mask = KBD_MOD_RALT;
break;
case KBD_LEFT_META:
mask = KBD_MOD_LMETA;
break;
case KBD_RIGHT_META:
mask = KBD_MOD_RMETA;
break;
case KBD_CAPS_LOCK:
mask = KBD_MOD_CAPS;
break;
case KBD_CTRL:
mask = KBD_MOD_CTRL;
break;
case KBD_OPT1:
mask = KBD_MOD_OPT1;
break;
case KBD_OPT2:
mask = KBD_MOD_OPT2;
break;
case KBD_RECONNECT:
if (up) {
kbd_setLED();
}
break;
}
if ((mask & KBD_MOD_CAPS) != 0) {
if (!up) {
mod ^= KBD_MOD_CAPS;
kbdled ^= LED_CAPS_LOCK;
kbd_setLED();
}
} else if (up) {
mod &= ~mask;
} else
mod |= mask;
splx(s);
return;
}
if (up) {
splx(s);
return;
}
if (mod == (KBD_MOD_LALT|KBD_MOD_LMETA) && c == 0x63) {
memcpy(&kbdmap, &ascii_kbdmap, sizeof(struct kbdmap));
splx(s);
return;
}
if ((mod & KBD_MOD_SHIFT) != 0) {
if ((mod & KBD_MOD_ALT) != 0)
key = kbdmap.alt_shift_keys[c];
else
key = kbdmap.shift_keys[c];
} else if ((mod & KBD_MOD_ALT) != 0)
key = kbdmap.alt_keys[c];
else {
key = kbdmap.keys[c];
if ((mod & KBD_MOD_CAPS) != 0 &&
(key.mode & KBD_MODE_CAPS) != 0)
key = kbdmap.shift_keys[c];
else if ((mod & KBD_MOD_OPT2) != 0 &&
(key.mode & KBD_MODE_KPAD) != 0)
key = kbdmap.shift_keys[c];
}
code = key.code;
if ((key.mode & KBD_MODE_DEAD) != 0) {
splx(s);
return;
}
if ((key.mode & KBD_MODE_STRING) == 0 &&
((key.mode & KBD_MODE_KPAD) == 0 ||
(kbd_ite != NULL && kbd_ite->keypad_appmode == 0))) {
if ((mod & KBD_MOD_CTRL) != 0 &&
(code == ' ' || (code >= '@' && code <= 'z')))
code &= 0x1f;
if ((mod & KBD_MOD_META) != 0)
code |= 0x80;
} else if ((key.mode & KBD_MODE_KPAD) != 0 &&
(kbd_ite != NULL && kbd_ite->keypad_appmode != 0)) {
static const char * const in = "0123456789-+.\r()/*";
static const char * const out = "pqrstuvwxymlnMPQRS";
char *cp = strchr(in, code);
(*kbd_tty->t_linesw->l_rint)(27, kbd_tty);
(*kbd_tty->t_linesw->l_rint)('O', kbd_tty);
(*kbd_tty->t_linesw->l_rint)(out[cp - in], kbd_tty);
splx(s);
return;
} else {
static u_char app_cursor[] = {
3, 27, 'O', 'A',
3, 27, 'O', 'B',
3, 27, 'O', 'C',
3, 27, 'O', 'D'
};
str = kbdmap.strings + code;
if (c >= 0x3b && c <= 0x3e && kbd_ite->cursor_appmode != 0 &&
memcmp(str, "\x03\x1b[", 3) == 0 &&
strchr("ABCD", str[3]) != 0)
str = app_cursor + 4 * (str[3] - 'A');
for (i = *str++; i; i--)
(*kbd_tty->t_linesw->l_rint)(*str++, kbd_tty);
splx(s);
return;
}
(*kbd_tty->t_linesw->l_rint)(code, kbd_tty);
splx(s);
return;
}
static inline void
ite_sendstr(struct ite_softc *ip, const char *str)
{
while (*str != 0)
itesendch(*str++);
}
static inline void
alignment_display(struct ite_softc *ip)
{
int i, j;
for (j = 0; j < ip->rows; j++)
for (i = 0; i < ip->cols; i++)
SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
attrclr(ip, 0, 0, ip->rows, ip->cols);
}
static inline void
snap_cury(struct ite_softc *ip)
{
if (ip->inside_margins != 0) {
if (ip->cury < ip->top_margin)
ip->cury = ip->top_margin;
if (ip->cury > ip->bottom_margin)
ip->cury = ip->bottom_margin;
}
}
static inline void
ite_dnchar(struct ite_softc *ip, int n)
{
n = uimin(n, ip->cols - ip->curx);
if (n < ip->cols - ip->curx) {
SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
1, ip->cols - ip->curx - n);
attrclr(ip, ip->cury, ip->cols - n, 1, n);
}
while (n-- > 0)
SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
}
static void
ite_inchar(struct ite_softc *ip, int n)
{
int c = ip->save_char;
ip->save_char = 0;
n = uimin(n, ip->cols - ip->curx);
if (n < ip->cols - ip->curx) {
SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
1, ip->cols - ip->curx - n);
attrclr(ip, ip->cury, ip->curx, 1, n);
}
while (n-- != 0)
SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
ip->save_char = c;
}
static inline void
ite_clrtoeol(struct ite_softc *ip)
{
int y = ip->cury, x = ip->curx;
if (ip->cols - x > 0) {
SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
attrclr(ip, y, x, 1, ip->cols - x);
}
}
static inline void
ite_clrtobol(struct ite_softc *ip)
{
int y = ip->cury, x = uimin(ip->curx + 1, ip->cols);
SUBR_CLEAR(ip, y, 0, 1, x);
attrclr(ip, y, 0, 1, x);
}
static inline void
ite_clrline(struct ite_softc *ip)
{
int y = ip->cury;
SUBR_CLEAR(ip, y, 0, 1, ip->cols);
attrclr(ip, y, 0, 1, ip->cols);
}
static inline void
ite_clrtoeos(struct ite_softc *ip)
{
ite_clrtoeol(ip);
if (ip->cury < ip->rows - 1) {
SUBR_CLEAR(ip, ip->cury + 1, 0,
ip->rows - 1 - ip->cury, ip->cols);
attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
}
}
static inline void
ite_clrtobos(struct ite_softc *ip)
{
ite_clrtobol(ip);
if (ip->cury > 0) {
SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
attrclr(ip, 0, 0, ip->cury, ip->cols);
}
}
static inline void
ite_clrscreen(struct ite_softc *ip)
{
SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
attrclr(ip, 0, 0, ip->rows, ip->cols);
}
static inline void
ite_dnline(struct ite_softc *ip, int n)
{
if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
return;
n = uimin(n, ip->bottom_margin + 1 - ip->cury);
if (n <= ip->bottom_margin - ip->cury) {
SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
attrmov(ip, ip->cury + n, 0, ip->cury, 0,
ip->bottom_margin + 1 - ip->cury - n, ip->cols);
}
SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
}
static inline void
ite_inline(struct ite_softc *ip, int n)
{
if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
return;
if (n <= 0)
n = 1;
else
n = uimin(n, ip->bottom_margin + 1 - ip->cury);
if (n <= ip->bottom_margin - ip->cury) {
SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
attrmov(ip, ip->cury, 0, ip->cury + n, 0,
ip->bottom_margin + 1 - ip->cury - n, ip->cols);
}
SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
attrclr(ip, ip->cury, 0, n, ip->cols);
ip->curx = 0;
}
static inline void
ite_index(struct ite_softc *ip)
{
++ip->cury;
if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows)) {
ip->cury--;
SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
ite_clrline(ip);
}
}
static inline void
ite_lf(struct ite_softc *ip)
{
++ip->cury;
if (ip->cury > ip->bottom_margin) {
ip->cury--;
SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
ite_clrline(ip);
}
ip->G0 = CSET_ASCII;
ip->G1 = CSET_JIS1983;
ip->G2 = CSET_JISKANA;
ip->G3 = CSET_JIS1990;
ip->GL = &ip->G0;
ip->GR = &ip->G1;
ip->save_GL = 0;
ip->save_char = 0;
}
static inline void
ite_crlf(struct ite_softc *ip)
{
ip->curx = 0;
ite_lf(ip);
}
static inline void
ite_cr(struct ite_softc *ip)
{
if (ip->curx != 0) {
ip->curx = 0;
}
}
static inline void
ite_rlf(struct ite_softc *ip)
{
ip->cury--;
if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1)) {
ip->cury++;
SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
ite_clrline(ip);
}
clr_attr(ip, ATTR_INV);
}
static inline int
atoi(const char *cp)
{
int n;
for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
n = n * 10 + *cp - '0';
return n;
}
static inline int
ite_argnum(struct ite_softc *ip)
{
char ch;
int n;
if (ip->ap == ip->argbuf)
return 1;
ch = *ip->ap;
*ip->ap = 0;
n = atoi(ip->argbuf);
*ip->ap = ch;
return n;
}
static inline int
ite_zargnum(struct ite_softc *ip)
{
char ch;
int n;
if (ip->ap == ip->argbuf)
return 0;
ch = *ip->ap;
*ip->ap = 0;
n = atoi(ip->argbuf);
*ip->ap = ch;
return n;
}
static void
ite_putstr(const u_char *s, int len, dev_t dev)
{
struct ite_softc *ip;
int i;
ip = getitesp(dev);
if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
return;
#if defined(ITE_SIXEL)
if (ip->escape == 0)
#endif
SUBR_CURSOR(ip, START_CURSOROPT);
for (i = 0; i < len; i++)
if (s[i] != 0)
iteputchar(s[i], ip);
#if defined(ITE_SIXEL)
if (ip->escape == 0)
#endif
SUBR_CURSOR(ip, END_CURSOROPT);
}
static void
iteputchar(int c, struct ite_softc *ip)
{
int n, x, y;
char *cp;
#if defined(ITE_SIXEL)
if ((c >= 0x20 && ip->escape != 0) || ip->escape == DCS) {
#else
if (c >= 0x20 && ip->escape != 0) {
#endif
switch (ip->escape) {
case ESC:
switch (c) {
case 'D':
c = IND;
ip->escape = 0;
break;
case 'E':
c = NEL;
ip->escape = 0;
break;
case 'H':
c = HTS;
ip->escape = 0;
break;
case 'M':
c = RI;
ip->escape = 0;
break;
case 'N':
c = SS2;
ip->escape = 0;
break;
case 'O':
c = SS3;
ip->escape = 0;
break;
case 'P':
c = DCS;
ip->escape = 0;
break;
case '[':
c = CSI;
ip->escape = 0;
break;
case '\\':
c = ST;
ip->escape = 0;
#if defined(ITE_SIXEL)
if (ip->decsixel_y != 0) {
ite_lf(ip);
}
#endif
break;
case ']':
c = OSC;
ip->escape = 0;
break;
case '^':
c = PM;
ip->escape = 0;
break;
case '_':
c = APC;
ip->escape = 0;
break;
case ' ':
ip->escape = ' ';
break;
case '(':
case ')':
ip->escape = c;
return;
case '*':
case '+':
case 'B':
case 'A':
case '<':
case '0':
case '-':
case '.':
case '/':
case '4':
case '5':
case 'C':
case 'R':
case 'Q':
case 'K':
case 'Y':
case '6':
ip->escape = 0;
return;
case '$':
ip->escape = '$';
return;
case '`':
ip->GR = &ip->G1;
ip->escape = 0;
return;
case 'n':
ip->GL = &ip->G2;
ip->escape = 0;
return;
case '}':
ip->GR = &ip->G2;
ip->escape = 0;
return;
case 'o':
ip->GL = &ip->G3;
ip->escape = 0;
return;
case '|':
ip->GR = &ip->G3;
ip->escape = 0;
return;
case '~':
ip->GR = &ip->G1;
ip->escape = 0;
return;
case '#':
ip->escape = '#';
return;
case 'c':
ite_reset(ip);
SUBR_CURSOR(ip, MOVE_CURSOR);
ip->escape = 0;
return;
case '7':
ip->save_curx = ip->curx;
ip->save_cury = ip->cury;
ip->save_attribute = ip->attribute;
ip->sc_om = ip->inside_margins;
ip->sc_G0 = ip->G0;
ip->sc_G1 = ip->G1;
ip->sc_G2 = ip->G2;
ip->sc_G3 = ip->G3;
ip->sc_GL = ip->GL;
ip->sc_GR = ip->GR;
ip->escape = 0;
return;
case '8':
ip->curx = ip->save_curx;
ip->cury = ip->save_cury;
ip->attribute = ip->save_attribute;
ip->inside_margins = ip->sc_om;
ip->G0 = ip->sc_G0;
ip->G1 = ip->sc_G1;
ip->G2 = ip->sc_G2;
ip->G3 = ip->sc_G3;
ip->GL = ip->sc_GL;
ip->GR = ip->sc_GR;
SUBR_CURSOR(ip, MOVE_CURSOR);
ip->escape = 0;
return;
case '=':
ip->keypad_appmode = 1;
ip->escape = 0;
return;
case '>':
ip->keypad_appmode = 0;
ip->escape = 0;
return;
case 'Z':
if (ip->emul_level == EMUL_VT100) {
ite_sendstr(ip, "\033[61;0c");
} else {
ite_sendstr(ip, "\033[63;0c");
}
ip->escape = 0;
return;
default:
ip->escape = 0;
return;
}
break;
case '(':
switch (c) {
case 'B':
ip->G0 = CSET_ASCII;
ip->escape = 0;
return;
case 'I':
ip->G0 = CSET_JISKANA;
ip->escape = 0;
return;
case 'J':
ip->G0 = CSET_JISROMA;
ip->escape = 0;
return;
case '0':
ip->G0 = CSET_DECGRAPH;
ip->escape = 0;
return;
case 'A':
case 'H':
case 'K':
case 'R':
case 'Y':
case 'Z':
default:
ip->escape = 0;
return;
}
case ')':
ip->escape = 0;
return;
case '$':
switch (c) {
case '@':
ip->G0 = CSET_JIS1978;
ip->escape = 0;
return;
case 'B':
ip->G0 = CSET_JIS1983;
ip->escape = 0;
return;
case 'D':
ip->G0 = CSET_JIS1990;
ip->escape = 0;
return;
default:
ip->escape = 0;
return;
}
case ' ':
switch (c) {
case 'F':
ip->eightbit_C1 = 0;
ip->escape = 0;
return;
case 'G':
ip->eightbit_C1 = 1;
ip->escape = 0;
return;
default:
ip->escape = 0;
return;
}
break;
case '#':
switch (c) {
case '5':
ip->escape = 0;
return;
case '6':
ip->escape = 0;
return;
case '3':
ip->escape = 0;
return;
case '4':
ip->escape = 0;
return;
case '8':
alignment_display(ip);
ip->escape = 0;
return;
default:
ip->escape = 0;
return;
}
break;
case CSI:
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case ';':
case '\"':
case '$':
case '>':
if (ip->ap < ip->argbuf + MAX_ARGSIZE)
*ip->ap++ = c;
return;
case 'p':
*ip->ap = 0;
if (!strncmp(ip->argbuf, "61\"", 3))
ip->emul_level = EMUL_VT100;
else if (!strncmp(ip->argbuf, "63;1\"", 5) ||
!strncmp(ip->argbuf, "62;1\"", 5))
ip->emul_level = EMUL_VT300_7;
else
ip->emul_level = EMUL_VT300_8;
ip->escape = 0;
return;
case '?':
*ip->ap = 0;
ip->escape = '?';
ip->ap = ip->argbuf;
return;
case 'c':
*ip->ap = 0;
if (ip->argbuf[0] == '>') {
ite_sendstr(ip, "\033[>24;0;0;0c");
} else {
switch (ite_zargnum(ip)) {
case 0:
if (ip->emul_level ==
EMUL_VT100)
ite_sendstr(ip,
"\033[?1;1c");
else
#if defined(ITE_SIXEL)
ite_sendstr(ip,
"\033[63;4c");
#else
ite_sendstr(ip,
"\033[63;0c");
#endif
break;
}
}
ip->escape = 0;
return;
case 'n':
switch (ite_zargnum(ip)) {
case 5:
ite_sendstr(ip, "\033[0n");
break;
case 6:
snprintf(ip->argbuf, sizeof(ip->argbuf),
"\033[%d;%dR",
ip->cury + 1, ip->curx + 1);
ite_sendstr(ip, ip->argbuf);
break;
}
ip->escape = 0;
return;
case 'x':
switch (ite_zargnum(ip)) {
case 0:
ite_sendstr(ip,
"\033[2;1;1;112;112;1;0x");
break;
case 1:
ite_sendstr(ip,
"\033[3;1;1;112;112;1;0x");
break;
}
ip->escape = 0;
return;
case 'g':
switch (ite_zargnum(ip)) {
case 0:
if (ip->curx < ip->cols)
ip->tabs[ip->curx] = 0;
break;
case 3:
for (n = 0; n < ip->cols; n++)
ip->tabs[n] = 0;
break;
default:
break;
}
ip->escape = 0;
return;
case 'h':
case 'l':
n = ite_zargnum(ip);
switch (n) {
case 4:
ip->imode = (c == 'h');
break;
case 20:
ip->linefeed_newline = (c == 'h');
break;
}
ip->escape = 0;
return;
case 'M':
ite_dnline(ip, ite_argnum(ip));
ip->escape = 0;
return;
case 'L':
ite_inline(ip, ite_argnum(ip));
ip->escape = 0;
return;
case 'P':
ite_dnchar(ip, ite_argnum(ip));
ip->escape = 0;
return;
case '@':
ite_inchar(ip, ite_argnum(ip));
ip->escape = 0;
return;
case '!':
ip->escape = 0;
return;
case 'G':
*ip->ap = 0;
x = atoi(ip->argbuf);
if (x != 0)
x--;
ip->curx = uimin(x, ip->cols - 1);
ip->escape = 0;
SUBR_CURSOR(ip, MOVE_CURSOR);
clr_attr(ip, ATTR_INV);
return;
case 'd':
*ip->ap = 0;
y = atoi(ip->argbuf);
if (y)
y--;
if (ip->inside_margins)
y += ip->top_margin;
ip->cury = uimin(y, ip->rows - 1);
ip->escape = 0;
snap_cury(ip);
SUBR_CURSOR(ip, MOVE_CURSOR);
clr_attr(ip, ATTR_INV);
return;
case 'H':
case 'f':
*ip->ap = 0;
y = atoi(ip->argbuf);
x = 0;
cp = strchr(ip->argbuf, ';');
if (cp != NULL)
x = atoi(cp + 1);
if (x != 0)
x--;
if (y != 0)
y--;
if (ip->inside_margins != 0)
y += ip->top_margin;
ip->cury = uimin(y, ip->rows - 1);
ip->curx = uimin(x, ip->cols - 1);
ip->escape = 0;
snap_cury(ip);
SUBR_CURSOR(ip, MOVE_CURSOR);
return;
case 'A':
n = ite_argnum(ip);
n = ip->cury - (n ? n : 1);
if (n < 0)
n = 0;
if (ip->inside_margins)
n = uimax(ip->top_margin, n);
else if (n == ip->top_margin - 1)
n = ip->top_margin;
ip->cury = n;
ip->escape = 0;
SUBR_CURSOR(ip, MOVE_CURSOR);
clr_attr(ip, ATTR_INV);
return;
case 'B':
n = ite_argnum(ip);
n = ip->cury + (n ? n : 1);
n = uimin(ip->rows - 1, n);
#if 0
if (ip->inside_margins)
#endif
n = uimin(ip->bottom_margin, n);
#if 0
else if (n == ip->bottom_margin + 1)
n = ip->bottom_margin;
#endif
ip->cury = n;
ip->escape = 0;
SUBR_CURSOR(ip, MOVE_CURSOR);
clr_attr(ip, ATTR_INV);
return;
case 'C':
n = ite_argnum(ip);
n = n ? n : 1;
ip->curx = uimin(ip->curx + n, ip->cols - 1);
ip->escape = 0;
SUBR_CURSOR(ip, MOVE_CURSOR);
clr_attr(ip, ATTR_INV);
return;
case 'D':
n = ite_argnum(ip);
n = n ? n : 1;
n = ip->curx - n;
ip->curx = n >= 0 ? n : 0;
ip->escape = 0;
SUBR_CURSOR(ip, MOVE_CURSOR);
clr_attr(ip, ATTR_INV);
return;
case 'J':
*ip->ap = 0;
n = ite_zargnum(ip);
if (n == 0)
ite_clrtoeos(ip);
else if (n == 1)
ite_clrtobos(ip);
else if (n == 2)
ite_clrscreen(ip);
ip->escape = 0;
return;
case 'K':
n = ite_zargnum(ip);
if (n == 0)
ite_clrtoeol(ip);
else if (n == 1)
ite_clrtobol(ip);
else if (n == 2)
ite_clrline(ip);
ip->escape = 0;
return;
case 'S':
n = ite_zargnum(ip);
if (n <= 0)
n = 1;
else if (n > ip->rows-1)
n = ip->rows-1;
SUBR_SCROLL(ip, ip->rows-1, 0, n, SCROLL_UP);
ip->escape = 0;
return;
case 'T':
n = ite_zargnum(ip);
if (n <= 0)
n = 1;
else if (n > ip->rows-1)
n = ip->rows-1;
SUBR_SCROLL(ip, 0, 0, n, SCROLL_DOWN);
ip->escape = 0;
return;
case 'X':
n = ite_argnum(ip) - 1;
n = uimin(n, ip->cols - 1 - ip->curx);
for (; n >= 0; n--) {
attrclr(ip, ip->cury, ip->curx + n,
1, 1);
SUBR_PUTC(ip, ' ',
ip->cury, ip->curx + n, ATTR_NOR);
}
ip->escape = 0;
return;
case '}': case '`':
ip->escape = 0;
return;
case 'r':
ip->escape = 0;
*ip->ap = 0;
x = atoi(ip->argbuf);
x = x ? x : 1;
y = ip->rows;
cp = strchr(ip->argbuf, ';');
if (cp) {
y = atoi(cp + 1);
y = y ? y : ip->rows;
}
if (y <= x)
return;
x--;
y--;
ip->top_margin = uimin(x, ip->rows - 2);
ip->bottom_margin = uimin(y, ip->rows - 1);
if (ip->inside_margins) {
ip->cury = ip->top_margin;
} else
ip->cury = 0;
ip->curx = 0;
return;
case 'm':
{
char *c_p;
*ip->ap = 0;
if (ip->ap == ip->argbuf)
ip->ap++;
for (c_p = ip->argbuf; c_p < ip->ap; ) {
switch (*c_p) {
case 0:
case '0':
clr_attr(ip, ATTR_ALL);
ip->fgcolor = 7;
ip->bgcolor = 0;
c_p++;
break;
case '1':
set_attr(ip, ATTR_BOLD);
c_p++;
break;
case '2':
switch (c_p[1]) {
case '2':
clr_attr(ip, ATTR_BOLD);
c_p += 2;
break;
case '4':
clr_attr(ip, ATTR_UL);
c_p += 2;
break;
case '5':
clr_attr(ip,
ATTR_BLINK);
c_p += 2;
break;
case '7':
clr_attr(ip, ATTR_INV);
c_p += 2;
break;
default:
c_p++;
break;
}
break;
case '3':
switch (c_p[1]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
ip->fgcolor =
c_p[1] - '0';
c_p += 2;
break;
default:
c_p++;
break;
}
break;
case '4':
switch (c_p[1]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
ip->bgcolor =
c_p[1] - '0';
c_p += 2;
break;
default:
set_attr(ip, ATTR_UL);
c_p++;
break;
}
break;
case '5':
set_attr(ip, ATTR_BLINK);
c_p++;
break;
case '7':
set_attr(ip, ATTR_INV);
c_p++;
break;
default:
c_p++;
break;
}
}
}
ip->escape = 0;
return;
case 'u':
ite_sendstr(ip, "\033P\033\\");
ip->escape = 0;
return;
default:
ip->escape = 0;
return;
}
break;
case '?':
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case ';':
case '\"':
case '$':
if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
*ip->ap++ = c;
return;
case 'n':
*ip->ap = 0;
if (ip->ap == &ip->argbuf[2]) {
if (!strncmp(ip->argbuf, "15", 2))
ite_sendstr(ip, "\033[13n");
else if (!strncmp(ip->argbuf, "25", 2))
ite_sendstr(ip, "\033[20n");
else if (!strncmp(ip->argbuf, "26", 2))
ite_sendstr(ip, "\033[27;1n");
}
ip->escape = 0;
return;
case 'h':
case 'l':
n = ite_zargnum(ip);
switch (n) {
case 1:
ip->cursor_appmode = (c == 'h');
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
ip->inside_margins = (c == 'h');
#if 0
ip->curx = 0;
ip->cury = ip->inside_margins ?
ip->top_margin : 0;
SUBR_CURSOR(ip, MOVE_CURSOR);
#endif
break;
case 7:
ip->auto_wrap = (c == 'h');
break;
case 8:
ip->key_repeat = (c == 'h');
break;
case 20:
ip->linefeed_newline = (c == 'h');
break;
case 25:
SUBR_CURSOR(ip, (c == 'h') ?
DRAW_CURSOR : ERASE_CURSOR);
break;
}
ip->escape = 0;
return;
case 'K':
case 'J':
default:
ip->escape = 0;
return;
}
break;
#if defined(ITE_SIXEL)
case DCS:
if (ite_dcs(c, ip) == 0) {
return;
}
break;
#endif
default:
ip->escape = 0;
return;
}
}
switch (c) {
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
break;
case BEL:
#if NBELL > 0
if (kbd_ite && ite_tty[device_unit(kbd_ite->device)])
opm_bell();
#endif
break;
case BS:
if (--ip->curx < 0)
ip->curx = 0;
else
SUBR_CURSOR(ip, MOVE_CURSOR);
break;
case HT:
for (n = ip->curx + 1; n < ip->cols; n++) {
if (ip->tabs[n]) {
ip->curx = n;
SUBR_CURSOR(ip, MOVE_CURSOR);
break;
}
}
break;
case VT:
case FF:
case LF:
if (ip->linefeed_newline)
ite_crlf(ip);
else
ite_lf(ip);
break;
case CR:
ite_cr(ip);
break;
case SO:
ip->GL = &ip->G1;
break;
case SI:
ip->GL = &ip->G0;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
break;
case CAN:
ip->escape = 0;
break;
case 0x19:
break;
case SUB:
ip->escape = 0;
break;
case ESC:
ip->escape = ESC;
break;
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:
break;
case IND:
ite_index(ip);
break;
case NEL:
ite_crlf(ip);
break;
case HTS:
if (ip->curx < ip->cols)
ip->tabs[ip->curx] = 1;
break;
case RI:
ite_rlf(ip);
break;
case SS2:
ip->save_GL = ip->GR;
ip->GR = &ip->G2;
break;
case SS3:
ip->save_GL = ip->GR;
ip->GR = &ip->G3;
break;
case DCS:
ip->escape = DCS;
#if defined(ITE_SIXEL)
ip->dcs_cmd = DCS_START;
#endif
ip->ap = ip->argbuf;
break;
case CSI:
ip->escape = CSI;
ip->ap = ip->argbuf;
break;
case ST:
break;
case OSC:
ip->escape = OSC;
break;
case PM:
ip->escape = PM;
break;
case APC:
ip->escape = APC;
break;
case DEL:
break;
default:
if (ip->save_char == 0 &&
(*((c & 0x80) ? ip->GR : ip->GL) & CSET_MULTI) != 0) {
ip->save_char = c;
break;
}
if (ip->imode != 0)
ite_inchar(ip, ip->save_char ? 2 : 1);
iteprecheckwrap(ip);
#ifdef DO_WEIRD_ATTRIBUTES
if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
attrset(ip, ATTR_INV);
SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
}
else
SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
#else
SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
#endif
itecheckwrap(ip);
if (ip->save_char) {
itecheckwrap(ip);
ip->save_char = 0;
}
if (ip->save_GL) {
ip->GR = ip->save_GL;
ip->save_GL = 0;
}
break;
}
}
#if defined(ITE_SIXEL)
static int
ite_dcs(const int c, struct ite_softc *ip)
{
static const uint32_t table[64] = {
0x000000, 0x000001, 0x000010, 0x000011,
0x000100, 0x000101, 0x000110, 0x000111,
0x001000, 0x001001, 0x001010, 0x001011,
0x001100, 0x001101, 0x001110, 0x001111,
0x010000, 0x010001, 0x010010, 0x010011,
0x010100, 0x010101, 0x010110, 0x010111,
0x011000, 0x011001, 0x011010, 0x011011,
0x011100, 0x011101, 0x011110, 0x011111,
0x100000, 0x100001, 0x100010, 0x100011,
0x100100, 0x100101, 0x100110, 0x100111,
0x101000, 0x101001, 0x101010, 0x101011,
0x101100, 0x101101, 0x101110, 0x101111,
0x110000, 0x110001, 0x110010, 0x110011,
0x110100, 0x110101, 0x110110, 0x110111,
0x111000, 0x111001, 0x111010, 0x111011,
0x111100, 0x111101, 0x111110, 0x111111,
};
switch (ip->dcs_cmd) {
case DCS_DISCARD:
switch (c) {
case '-':
ite_lf(ip);
goto sixel_restart;
case CAN:
case SUB:
ip->escape = 0;
return 0;
case ESC:
ip->escape = ESC;
return 0;
default:
return 0;
}
break;
case DCS_START:
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case ';':
case '$':
if (ip->ap < ip->argbuf + MAX_ARGSIZE)
*ip->ap++ = c;
return 0;
case 'q':
{
char *cp;
ip->ap = ip->argbuf;
cp = strchr(ip->ap, ';');
if (cp != NULL) {
int mode;
mode = atoi(cp + 1) - '0';
ip->decsixel_ormode = (mode & 4);
} else {
ip->decsixel_ormode = 0;
}
sixel_restart:
ip->dcs_cmd = DCS_SIXEL;
ip->decsixel_state = DECSIXEL_INIT;
ip->decsixel_ph = MAX_SIXEL_WIDTH;
ip->decsixel_x = 0;
ip->decsixel_y = 0;
ip->decsixel_repcount = 0;
ip->decsixel_color = ip->fgcolor;
memset(ip->decsixel_buf, 0, sizeof(ip->decsixel_buf));
return 0;
}
case CAN:
case SUB:
ip->escape = 0;
return 0;
case ESC:
ip->escape = ESC;
return 0;
default:
return 0;
}
break;
case DCS_SIXEL:
sixel_loop:
switch (ip->decsixel_state) {
case DECSIXEL_INIT:
switch (c) {
case CAN:
case SUB:
ip->escape = 0;
return 0;
case ESC:
ip->escape = ESC;
return 0;
case DECSIXEL_REPEAT:
ip->decsixel_state = c;
ip->decsixel_repcount = 0;
return 0;
case DECSIXEL_RASTER:
case DECSIXEL_COLOR:
ip->decsixel_state = c;
ip->ap = ip->argbuf;
return 0;
case '$':
ip->decsixel_x = 0;
return 0;
case '-':
if (ip->decsixel_y + 6 > 15) {
ite_lf(ip);
ip->decsixel_y -= 16;
}
SUBR_SIXEL(ip, ip->cury, ip->curx);
memset(ip->decsixel_buf, 0,
sizeof(ip->decsixel_buf));
ip->decsixel_x = 0;
ip->decsixel_y += 6;
return 0;
default:
if ('?' <= c && c <= '~'
&& ip->decsixel_x < MAX_SIXEL_WIDTH) {
uint32_t d;
d = table[c - '?'] * ip->decsixel_color;
ip->decsixel_buf[ip->decsixel_x] |= d;
ip->decsixel_x++;
} else {
}
return 0;
}
break;
case DECSIXEL_REPEAT:
if ('0' <= c && c <= '9') {
ip->decsixel_repcount =
ip->decsixel_repcount * 10 + (c - '0');
} else if ('?' <= c && c <= '~') {
uint32_t d;
int i;
int cnt = MIN(ip->decsixel_repcount,
MAX_SIXEL_WIDTH - ip->decsixel_x);
d = table[c - '?'] * ip->decsixel_color;
for (i = 0; i < cnt; i++) {
ip->decsixel_buf[ip->decsixel_x + i] |=
d;
}
ip->decsixel_x += cnt;
ip->decsixel_state = DECSIXEL_INIT;
} else {
ip->decsixel_state = DECSIXEL_INIT;
}
return 0;
case DECSIXEL_RASTER:
case DECSIXEL_RASTER_PAD:
case DECSIXEL_RASTER_PH:
case DECSIXEL_RASTER_PV:
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (ip->ap < ip->argbuf + MAX_ARGSIZE)
*ip->ap++ = c;
return 0;
case ';':
default:
switch (ip->decsixel_state) {
case DECSIXEL_RASTER:
ip->ap = ip->argbuf;
ip->decsixel_state =
DECSIXEL_RASTER_PAD;
return 0;
case DECSIXEL_RASTER_PAD:
ip->ap = ip->argbuf;
ip->decsixel_state = DECSIXEL_RASTER_PH;
return 0;
case DECSIXEL_RASTER_PH:
ip->decsixel_ph = ite_zargnum(ip);
ip->ap = ip->argbuf;
ip->decsixel_state = DECSIXEL_RASTER_PV;
return 0;
case DECSIXEL_RASTER_PV:
ip->decsixel_state = DECSIXEL_INIT;
goto sixel_loop;
default:
return 0;
}
}
return 0;
case DECSIXEL_COLOR:
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case ';':
if (ip->ap < ip->argbuf + MAX_ARGSIZE)
*ip->ap++ = c;
return 0;
default:
*ip->ap = '\0';
if (strchr(ip->argbuf, ';')) {
} else {
ip->decsixel_color =
ite_zargnum(ip) & 7;
}
ip->decsixel_state = DECSIXEL_INIT;
ip->ap = ip->argbuf;
goto sixel_loop;
}
return 0;
}
break;
}
return 1;
}
#endif
static void
iteprecheckwrap(struct ite_softc *ip)
{
if (ip->auto_wrap && ip->curx + (ip->save_char ? 1 : 0) == ip->cols) {
ip->curx = 0;
clr_attr(ip, ATTR_INV);
if (++ip->cury >= ip->bottom_margin + 1) {
ip->cury = ip->bottom_margin;
SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
ite_clrtoeol(ip);
}
}
}
static void
itecheckwrap(struct ite_softc *ip)
{
#if 0
if (++ip->curx == ip->cols) {
if (ip->auto_wrap) {
ip->curx = 0;
clr_attr(ip, ATTR_INV);
if (++ip->cury >= ip->bottom_margin + 1) {
ip->cury = ip->bottom_margin;
SUBR_CURSOR(ip, MOVE_CURSOR);
SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1,
SCROLL_UP);
ite_clrtoeol(ip);
return;
}
} else
ip->curx--;
}
#else
if (ip->curx < ip->cols) {
ip->curx++;
}
#endif
}
const uint8_t ite_decgraph2ascii[128] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
' ',
'*',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
'+',
'+',
'+',
'+',
'+',
'~',
'-',
'-',
'-',
'_',
'+',
'+',
'+',
'+',
'|',
'<',
'>',
' ',
' ',
' ',
'.',
0x7f
};
#endif
#if NITE > 0 && NKBD > 0
#include <dev/cons.h>
extern void kbdenable(int);
extern int kbdcngetc(void);
void
itecnprobe(struct consdev *cd)
{
int maj;
maj = cdevsw_lookup_major(&ite_cdevsw);
if (con_itesoftc.grf == NULL)
cd->cn_pri = CN_DEAD;
else {
con_itesoftc.flags = (ITE_ALIVE|ITE_CONSOLE);
con_itesoftc.isw = &itesw[0];
cd->cn_pri = CN_INTERNAL;
cd->cn_dev = makedev(maj, 0);
}
}
void
itecninit(struct consdev *cd)
{
struct ite_softc *ip;
ip = getitesp(cd->cn_dev);
iteinit(cd->cn_dev);
ip->flags |= ITE_ACTIVE | ITE_ISCONS;
kbdenable(0);
mfp_send_usart(0x49);
}
void
itecnfinish(struct ite_softc *ip)
{
static int done;
if (done)
return;
done = 1;
}
int
itecngetc(dev_t dev)
{
int c;
do {
c = kbdcngetc();
c = ite_cnfilter(c);
} while (c == -1);
return (c);
}
void
itecnputc(dev_t dev, int c)
{
static int paniced = 0;
struct ite_softc *ip = getitesp(dev);
char ch = c;
#ifdef ITE_KERNEL_ATTR
short save_attribute;
#endif
#if defined(ITE_SIXEL)
int save_escape;
#endif
if (panicstr && !paniced &&
(ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) {
(void) iteon(dev, 3);
paniced = 1;
}
#if defined(ITE_SIXEL)
save_escape = ip->escape;
if (ip->escape == DCS) {
ip->escape = 0;
ip->dcs_cmd = DCS_DISCARD;
}
#endif
#ifdef ITE_KERNEL_ATTR
save_attribute = ip->attribute;
ip->attribute = ITE_KERNEL_ATTR;
#endif
ite_putstr(&ch, 1, dev);
#ifdef ITE_KERNEL_ATTR
ip->attribute = save_attribute;
#endif
#if defined(ITE_SIXEL)
if (ip->escape == 0) {
ip->escape = save_escape;
}
#endif
}
#endif