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