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