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