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