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