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