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