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