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