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