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