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