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