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