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