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