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