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