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