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