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