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