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