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