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