|
|
1.1 ! root 1: #include <X/mit-copyright.h> ! 2: ! 3: /* Copyright (c) 1985 Massachusetts Institute of Technology */ ! 4: /* Copyright (c) 1985 Digital Equipment Corporation */ ! 5: ! 6: /* charproc.c */ ! 7: ! 8: #include <X/Xlib.h> ! 9: #include "ptyx.h" ! 10: #include <stdio.h> ! 11: #include <sgtty.h> ! 12: #include "chartable.h" ! 13: #include "esctable.h" ! 14: ! 15: #ifndef lint ! 16: static char *rcsid_charproc_c = "$Header: charproc.c,v 10.10 86/02/01 16:05:52 tony Rel $"; ! 17: #endif lint ! 18: ! 19: /* CAUTION: getb "knows" that the variable "c" is receiving the result */ ! 20: ! 21: #define getb(buf) (--buf_cnt >= 0 ? *buf_ptr++: \ ! 22: ((c=fill(buf)), buf_cnt=buf->cnt, buf_ptr=buf->ptr, c)) ! 23: ! 24: #define peekb(buf) (buf_cnt > 0 ? *buf_ptr : -1) ! 25: ! 26: #define ANSIflush() { arg = flushbuf(screen, term->flags, text_ptr); \ ! 27: buffermode = 0; \ ! 28: text_ptr = text_buf; \ ! 29: text_cnt = TEXT_BUF_SIZE; } ! 30: ! 31: #define TEKflush() { arg = TekFlushBuf(term, text_ptr); \ ! 32: buffermode = 0; \ ! 33: text_ptr = text_buf; \ ! 34: text_cnt = TEXT_BUF_SIZE; \ ! 35: } ! 36: ! 37: #define TEXT_BUF_SIZE 256 ! 38: ! 39: extern TekLink *tb_end_link; ! 40: extern int tb_end; ! 41: ! 42: unsigned char text_buf[TEXT_BUF_SIZE]; ! 43: ! 44: unsigned nri = 0; ! 45: unsigned nlf = 0; ! 46: unsigned ctotal = 0; ! 47: unsigned ntotal = 0; ! 48: ! 49: /* ! 50: * in normal mode, buffer up as large a string of printing characters ! 51: * as possible before flushing the buffer. buffer up LF's and RI's ! 52: * so these can be processed as a block. ! 53: */ ! 54: ANSInormal(term) ! 55: Terminal *term; ! 56: { ! 57: register int c; ! 58: register unsigned char *text_ptr; ! 59: register int text_cnt; ! 60: register unsigned char *buf_ptr; ! 61: register int buf_cnt; ! 62: register unsigned buffermode; ! 63: register Screen *screen = &term->screen; ! 64: register Buffer *trmbuf = &term->buf; ! 65: int arg; ! 66: ! 67: buffermode = 0; ! 68: arg = 0; ! 69: c = 0; ! 70: text_ptr = text_buf; ! 71: text_cnt = TEXT_BUF_SIZE; ! 72: buf_cnt = trmbuf->cnt; ! 73: buf_ptr = trmbuf->ptr; ! 74: ! 75: if (screen->TekGMode || screen->TekAMode) ! 76: return (TekMode(term)); ! 77: ! 78: for (;;) { ! 79: /* ! 80: * if special condition has occurred, c will already ! 81: * be set to EOF. otherwise, pick up a new char. ! 82: */ ! 83: if (c >= 0) ! 84: c = getb(trmbuf); ! 85: ! 86: if (ctable[c] == CPRINTING) { ! 87: buffermode = BUFFER_MODE; ! 88: if (--text_cnt >= 0) ! 89: *text_ptr++ = c; ! 90: else { ! 91: ANSIflush(); ! 92: --text_cnt, *text_ptr++ = c; ! 93: if (arg) ! 94: c = EOF; ! 95: } ! 96: continue; ! 97: ! 98: } ! 99: ! 100: switch (ctable[c]) { ! 101: case CIGNORE: ! 102: break; ! 103: ! 104: ! 105: case CLINEFEED: ! 106: if (buffermode || nri) { ! 107: ANSIflush(); ! 108: if (arg) ! 109: c = EOF; ! 110: } ! 111: ++nlf; ! 112: break; ! 113: ! 114: case CRETURN: ! 115: if (buffermode) { ! 116: ANSIflush(); ! 117: if (arg) ! 118: c = EOF; ! 119: } ! 120: screen->cur_col = 0; ! 121: screen->do_wrap = 0; ! 122: break; ! 123: ! 124: case CRI: ! 125: RI_kluge: if (buffermode || nlf) { ! 126: ANSIflush(); ! 127: if (arg) ! 128: c = EOF; ! 129: } ! 130: ++nri; ! 131: break; ! 132: ! 133: case FLUSH: ! 134: ANSIflush(); ! 135: trmbuf->cnt = buf_cnt; ! 136: trmbuf->ptr = buf_ptr; ! 137: return (arg); ! 138: ! 139: case CESC: ! 140: /* try to intercept RI's so we can buffer them */ ! 141: if (peekb(trmbuf) == 'M') { ! 142: c = getb(trmbuf); ! 143: goto RI_kluge; ! 144: } ! 145: /* no RI detected; fall into default case */ ! 146: ! 147: default: ! 148: ANSIflush(); ! 149: docontrol(term, c); ! 150: ! 151: /* ! 152: * if mode changes or event occurs, force a ! 153: * cleanup and return by setting char to EOF ! 154: */ ! 155: if (arg ! 156: || screen->mode!=ANSInormal ! 157: || screen->TekGMode ! 158: || screen->TekAMode) ! 159: c = EOF; ! 160: } ! 161: } ! 162: } ! 163: ! 164: /* ! 165: * flush the buffer of printing characters. first, process any LF's or ! 166: * RI's that have been buffered. ! 167: */ ! 168: flushbuf(screen, flags, text_ptr) ! 169: register Screen *screen; ! 170: unsigned flags; ! 171: register unsigned char *text_ptr; ! 172: { ! 173: register unsigned char *s; ! 174: register unsigned char *p; ! 175: int arg = 0; ! 176: ! 177: if (nri != 0) { ! 178: ioctl(screen->display->fd, FIONREAD, &arg); ! 179: RevIndex(screen, nri); ! 180: nri = 0; ! 181: } ! 182: if (nlf != 0) { ! 183: ioctl(screen->display->fd, FIONREAD, &arg); ! 184: Index(screen, nlf); ! 185: if (flags & LINEFEED) { /* do a carriage return */ ! 186: screen->cur_col = 0; ! 187: screen->do_wrap = 0; ! 188: } ! 189: nlf = 0; ! 190: } ! 191: ! 192: s = text_buf; ! 193: /* ! 194: * if a single shift is in effect, process ! 195: * the one character it affects. ! 196: */ ! 197: if (screen->curss!=0 && s<text_ptr) { ! 198: dotext(screen, flags, screen->gsets[screen->curss], s, s+1); ! 199: ++s; ! 200: screen->curss = 0; ! 201: } ! 202: ! 203: /* ! 204: * characters with and without the high bit set must be processed ! 205: * separately (they select different character sets). collect them ! 206: * into groups before processing for as much efficiency as possible. ! 207: */ ! 208: while (s < text_ptr) { ! 209: p = s; ! 210: if (*s < 0x80) { ! 211: /* character doesn't have high bit set */ ! 212: while (*s<0x80 && s<text_ptr) ! 213: ++s; ! 214: dotext(screen, flags, ! 215: screen->gsets[screen->curgl], p, s); ! 216: } ! 217: else { /* character has high bit set */ ! 218: while (*s>=0x80 && s<text_ptr) { ! 219: *s &= 0x7f; ! 220: ++s; ! 221: } ! 222: dotext(screen, flags, ! 223: screen->gsets[screen->curgr], p, s); ! 224: } ! 225: } ! 226: ! 227: return (arg || screen->display->qlen!=0); ! 228: } ! 229: ! 230: /* ! 231: * process a string of characters according to the character set indicated ! 232: * by charset. worry about end of line conditions (wraparound if selected). ! 233: */ ! 234: dotext(screen, flags, charset, buf, ptr) ! 235: register Screen *screen; ! 236: unsigned flags; ! 237: char charset; ! 238: unsigned char *buf; ! 239: unsigned char *ptr; ! 240: { ! 241: register unsigned char *s; ! 242: register int len; ! 243: register int n; ! 244: register int next_col; ! 245: ! 246: switch (charset) { ! 247: case 'A': /* United Kingdom set */ ! 248: for (s=buf; s<ptr; ++s) ! 249: if (*s == '#') ! 250: *s = '\036'; /* UK pound sign */ ! 251: break; ! 252: ! 253: case 'B': /* ASCII set */ ! 254: break; ! 255: ! 256: case '0': /* special graphics (line drawing) */ ! 257: for (s=buf; s<ptr; ++s) ! 258: if (*s>=0x5f && *s<=0x7e) ! 259: *s = *s - 0x5f; ! 260: break; ! 261: ! 262: default: /* any character sets we don't recognize */ ! 263: return; ! 264: } ! 265: ! 266: len = ptr - buf; ! 267: ptr = buf; ! 268: while (len > 0) { ! 269: n = screen->max_col-screen->cur_col+1; ! 270: if (n <= 1) { ! 271: if (screen->do_wrap && (flags&WRAPAROUND)) { ! 272: Index(screen, 1); ! 273: screen->cur_col = 0; ! 274: screen->do_wrap = 0; ! 275: n = screen->max_col+1; ! 276: } ! 277: else ! 278: n = 1; ! 279: } ! 280: if (len < n) ! 281: n = len; ! 282: next_col = screen->cur_col + n; ! 283: WriteText(screen, ptr, n, flags); ! 284: /* ! 285: * the call to WriteText updates screen->cur_col. ! 286: * If screen->cur_col != next_col, we must have ! 287: * hit the right margin, so set the do_wrap flag. ! 288: */ ! 289: screen->do_wrap = (screen->cur_col < next_col); ! 290: len -= n; ! 291: ptr += n; ! 292: } ! 293: } ! 294: ! 295: /* ! 296: * write a string str of length len onto the screen at ! 297: * the current cursor position. update cursor position. ! 298: */ ! 299: WriteText(screen, str, len, flags) ! 300: register Screen *screen; ! 301: register unsigned char *str; ! 302: register int len; ! 303: unsigned flags; ! 304: { ! 305: Font fnt; ! 306: ! 307: fnt = (flags & BOLD ? screen->fnt_bold : screen->fnt_norm); ! 308: if (flags & INSERT) ! 309: InsertChar(screen, len); ! 310: #ifdef JUMPSCROLL ! 311: if (!(AddToRefresh(screen))) { ! 312: if(screen->scroll_amt) ! 313: FlushScroll(screen); ! 314: #endif JUMPSCROLL ! 315: if (flags & INVERSE) ! 316: XText(screen->window, CursorX(screen), CursorY(screen), ! 317: str, len, fnt, screen->background, screen->foreground); ! 318: else ! 319: XText(screen->window, CursorX(screen), CursorY(screen), ! 320: str, len, fnt, screen->foreground, screen->background); ! 321: /* ! 322: * the following statements compile data to compute the average ! 323: * number of characters written on each call to XText. The data ! 324: * may be examined via the use of a "hidden" escape sequence. ! 325: */ ! 326: ctotal += len; ! 327: ++ntotal; ! 328: #ifdef JUMPSCROLL ! 329: } ! 330: #endif JUMPSCROLL ! 331: ScreenWrite(screen, str, flags, len); ! 332: CursorForward(screen, len); ! 333: } ! 334: ! 335: /* ! 336: * in Tek mode (graphics or alpha), buffer up as large a string of printing ! 337: * characters as possible before flushing buffer. in graphics mode the ! 338: * characters are plotted, in alpha mode they are printed. ! 339: */ ! 340: TekMode(term) ! 341: Terminal *term; ! 342: { ! 343: register int c; ! 344: register unsigned char *text_ptr; ! 345: register int text_cnt; ! 346: register unsigned char *buf_ptr; ! 347: register int buf_cnt; ! 348: register unsigned buffermode; ! 349: register Screen *screen = &term->screen; ! 350: register Buffer *trmbuf = &term->buf; ! 351: int arg; ! 352: ! 353: c = 0; ! 354: buffermode = 0; ! 355: text_ptr = text_buf; ! 356: text_cnt = TEXT_BUF_SIZE; ! 357: buf_cnt = trmbuf->cnt; ! 358: buf_ptr = trmbuf->ptr; ! 359: ! 360: for (;;) { ! 361: /* ! 362: * if special condition has occurred, c will already ! 363: * be set to EOF. otherwise, pick up a new char. ! 364: */ ! 365: if (c >= 0) ! 366: c = getb(trmbuf); ! 367: ! 368: if (c > 0) ! 369: c &= 0x7f; ! 370: ! 371: if (ctable[c]==CPRINTING || (c==DEL && screen->TekGMode)) { ! 372: buffermode = BUFFER_MODE; ! 373: if (--text_cnt >= 0) ! 374: *text_ptr++ = c; ! 375: else { ! 376: TEKflush(); ! 377: --text_cnt, *text_ptr++ = c; ! 378: if (arg) ! 379: c = EOF; ! 380: } ! 381: continue; ! 382: ! 383: } ! 384: ! 385: switch (ctable[c]) { ! 386: case CIGNORE: ! 387: break; ! 388: ! 389: case CTEKINIT: ! 390: if (buffermode) ! 391: TEKflush(); ! 392: TekInit(term, c); ! 393: if (arg) ! 394: c = EOF; ! 395: break; ! 396: ! 397: case FLUSH: ! 398: TEKflush(); ! 399: trmbuf->cnt = buf_cnt; ! 400: trmbuf->ptr = buf_ptr; ! 401: return (arg); ! 402: ! 403: default: /* BEL, BS, HT, LF, VT, FF, CR, ESC, US */ ! 404: /* and also SI, SO, CAN, SUB */ ! 405: TEKflush(); ! 406: if (screen->TekGMode) ! 407: TekAlph(term, c); ! 408: docontrol(term, c); ! 409: ! 410: /* ! 411: * if mode changes or event occurs, force a ! 412: * cleanup and return by setting char to EOF ! 413: */ ! 414: if (arg || screen->mode!=ANSInormal ! 415: || (screen->TekGMode==0 && screen->TekAMode==0)) ! 416: c = EOF; ! 417: } ! 418: } ! 419: } ! 420: ! 421: /* ! 422: * flush the buffer of printing characters. ! 423: * use TekString, TekPoint, or TekPlot according to current mode. ! 424: */ ! 425: TekFlushBuf(term, text_ptr) ! 426: Terminal *term; ! 427: register unsigned char *text_ptr; ! 428: { ! 429: register Screen *screen = &term->screen; ! 430: register unsigned char *s; ! 431: ! 432: s = text_buf; ! 433: if (text_ptr != text_buf) { ! 434: if (screen->TekGMode) { ! 435: if (screen->TekIMode) ! 436: while (s < text_ptr) { ! 437: TekBufPut(*s); ! 438: TekPoint(term, *s++); ! 439: } ! 440: else ! 441: while (s < text_ptr) { ! 442: TekBufPut(*s); ! 443: TekPlot(term, *s++); ! 444: } ! 445: } ! 446: else ! 447: TekString(term, text_buf, text_ptr-text_buf); ! 448: } ! 449: ! 450: return (screen->display->qlen != 0); ! 451: } ! 452: ! 453: /* ! 454: * a string (DCS, OSC, PM, APC) has been encountered in ANSI mode. ! 455: * all printing characters are ignored until a string terminator ! 456: * is seen (other possible exits are CAN, SUB, ESC, and C1 controls). ! 457: */ ! 458: ANSIstring(term) ! 459: Terminal *term; ! 460: { ! 461: register int c; ! 462: register Screen *screen = &term->screen; ! 463: register Buffer *trmbuf = &term->buf; ! 464: register unsigned char *buf_ptr; ! 465: register int buf_cnt; ! 466: ! 467: buf_cnt = trmbuf->cnt; ! 468: buf_ptr = trmbuf->ptr; ! 469: while (screen->mode==ANSIstring && screen->display->qlen==0) { ! 470: if ((c=getb(trmbuf)) == -1) ! 471: break; ! 472: if ((c=parseseq(c, &screen->ansi, screen->TekEmu)) != -1) { ! 473: switch (ctable[c]) { ! 474: case CIGNORE: ! 475: case CPRINTING: ! 476: break; ! 477: case CESC: ! 478: case CCSI: ! 479: screen->mode = ANSInormal; ! 480: procseq(term); ! 481: break; ! 482: case CDCS: ! 483: screen->mode = ANSIstring; ! 484: procseq(term); ! 485: break; ! 486: case CCANCEL: ! 487: screen->mode = ANSInormal; ! 488: break; ! 489: default: ! 490: break; ! 491: } ! 492: } ! 493: } ! 494: trmbuf->cnt = buf_cnt; ! 495: trmbuf->ptr = buf_ptr; ! 496: return (screen->display->qlen != 0); ! 497: } ! 498: ! 499: /* ! 500: * call parseseq with each new character until the sequence has been ! 501: * parsed. once parsed, call procseq to process the sequence. DEC ! 502: * standard says C0 controls in the middle of a sequence are acted ! 503: * on just as if they weren't in the middle of a sequence (ANSI says ! 504: * this is an error condition, but as always doesn't specify how to ! 505: * handle the error). ! 506: */ ! 507: ANSIparse(term) ! 508: Terminal *term; ! 509: { ! 510: register int c, ch; ! 511: register Screen *screen = &term->screen; ! 512: register Buffer *trmbuf = &term->buf; ! 513: register unsigned char *buf_ptr; ! 514: register int buf_cnt; ! 515: ! 516: c = 0; ! 517: buf_cnt = trmbuf->cnt; ! 518: buf_ptr = trmbuf->ptr; ! 519: ! 520: for (;;) { ! 521: /* ! 522: * if special condition has occurred, c will already ! 523: * be set to EOF. otherwise, pick up a new char. ! 524: */ ! 525: if (c >= 0) ! 526: c = getb(trmbuf); ! 527: ! 528: if (c == EOF) { ! 529: trmbuf->cnt = buf_cnt; ! 530: trmbuf->ptr = buf_ptr; ! 531: return (screen->display->qlen != 0); ! 532: } ! 533: ! 534: if ((ch=parseseq(c, &screen->ansi, screen->TekEmu)) != -1) { ! 535: switch (ctable[ch]) { ! 536: case CIGNORE: ! 537: break; ! 538: ! 539: case CESC: ! 540: case CCSI: ! 541: screen->mode = ANSInormal; ! 542: procseq(term); ! 543: break; ! 544: ! 545: case CDCS: ! 546: screen->mode = ANSIstring; ! 547: procseq(term); ! 548: break; ! 549: ! 550: default: ! 551: docontrol(term, ch); ! 552: break; ! 553: } ! 554: ! 555: /* ! 556: * if mode changes or event occurs, force a ! 557: * cleanup and return by setting char to EOF ! 558: */ ! 559: if (screen->mode!=ANSIparse || screen->ansi.a_type==0) { ! 560: c = EOF; ! 561: if (screen->mode==ANSIparse) ! 562: screen->mode = ANSInormal; ! 563: screen->ansi.a_type = 0; ! 564: screen->ansi.a_pintro = 0; ! 565: screen->ansi.a_final = 0; ! 566: } ! 567: if (screen->display->qlen != 0); ! 568: c = EOF; ! 569: ! 570: } ! 571: } ! 572: } ! 573: ! 574: /* ! 575: * some sort of ANSI sequence has been parsed. look through the ! 576: * esctable to look for a match. if found, apply default parameters ! 577: * and dispatch. ! 578: */ ! 579: procseq(term) ! 580: Terminal *term; ! 581: { ! 582: register ANSI *ap = &term->screen.ansi; ! 583: register int i; ! 584: register long *p; ! 585: register long a_funct; ! 586: #define SEQKEY p[0] /* type, private, & final in a long */ ! 587: #define INTERS p[1] /* intermediate(s) in a long */ ! 588: #define SEQTYPE p[2] /* sequence type (dispatch value) */ ! 589: #define NDEFLT p[3] /* number of default parameters */ ! 590: #define DEFAULT(n) p[4+n] /* the n'th default parameter (0 origin)*/ ! 591: #define FIXEDLEN 4 /* fixed (min) length of table entries */ ! 592: ! 593: /* ! 594: * just return if any error encountered ! 595: */ ! 596: if (ap->a_nastyf != 0) ! 597: return; ! 598: ! 599: a_funct = (ap->a_final << 16) | (ap->a_pintro << 8) | ap->a_type; ! 600: ! 601: /* ! 602: * step through table, looking for an ! 603: * entry which matches the current sequence. ! 604: */ ! 605: for (p=esctable; *p!=0; p+=NDEFLT+FIXEDLEN) { ! 606: if (SEQKEY==a_funct ! 607: && (INTERS==ap->a_inters || INTERS==WILD)) { ! 608: /* ! 609: * we have a match. ! 610: * get default values from table. ! 611: */ ! 612: for (i=0; i<NDEFLT; ++i) { ! 613: if (ap->a_dflt[i] || i>=ap->a_nparam) ! 614: ap->a_param[i] = DEFAULT(i); ! 615: } ! 616: if (ap->a_nparam < NDEFLT) ! 617: ap->a_nparam = NDEFLT; ! 618: /* ! 619: * ready to process the sequence. ! 620: */ ! 621: doescape(term, SEQTYPE, ap); ! 622: break; ! 623: } ! 624: } ! 625: } ! 626: ! 627: /* ! 628: * this is a big switch of all the ANSI (and other) sequences ! 629: * we know how to handle. the cases of the switch must ! 630: * have a corresponding entry in the esctable. ! 631: */ ! 632: doescape(term, kind, ap) ! 633: Terminal *term; ! 634: long kind; ! 635: ANSI *ap; ! 636: { ! 637: register Screen *screen = &term->screen; ! 638: register row, col; ! 639: register i, top, bot; ! 640: ANSI reply; ! 641: int bitset(), bitclr(); ! 642: register unsigned char *text_ptr; ! 643: register int text_cnt; ! 644: ! 645: switch (kind) { ! 646: case DECKPAM: ! 647: term->keyboard.flags |= KYPD_APL; ! 648: break; ! 649: ! 650: case DECKPNM: ! 651: term->keyboard.flags &= ~KYPD_APL; ! 652: break; ! 653: ! 654: case DECTC1: ! 655: screen->rx8bit = 0; ! 656: break; ! 657: ! 658: case DECSC: ! 659: screen->sc.row = screen->cur_row; ! 660: screen->sc.col = screen->cur_col; ! 661: screen->sc.flags = term->flags; ! 662: break; ! 663: ! 664: case DECAC1: ! 665: screen->rx8bit = 1; ! 666: break; ! 667: ! 668: case S7C1T: ! 669: screen->tx8bit = 0; ! 670: break; ! 671: ! 672: case S8C1T: ! 673: screen->tx8bit = 1; ! 674: break; ! 675: ! 676: case DECRC: ! 677: term->flags &= ~(BOLD|INVERSE); ! 678: term->flags |= screen->sc.flags&(BOLD|INVERSE); ! 679: CursorSet(screen, screen->sc.row, ! 680: screen->sc.col, term->flags); ! 681: break; ! 682: ! 683: case LS2: ! 684: screen->curgl = 2; ! 685: break; ! 686: ! 687: case LS3: ! 688: screen->curgl = 3; ! 689: break; ! 690: ! 691: case LS3R: ! 692: screen->curgr = 3; ! 693: break; ! 694: ! 695: case LS2R: ! 696: screen->curgr = 2; ! 697: break; ! 698: ! 699: case LS1R: ! 700: screen->curgr = 1; ! 701: break; ! 702: ! 703: case DESIGNATE: ! 704: switch (ap->a_inters) { ! 705: case '(': ! 706: screen->gsets[0] = ap->a_final; ! 707: break; ! 708: ! 709: case ')': ! 710: screen->gsets[1] = ap->a_final; ! 711: break; ! 712: ! 713: case '*': ! 714: screen->gsets[2] = ap->a_final; ! 715: break; ! 716: ! 717: case '+': ! 718: screen->gsets[3] = ap->a_final; ! 719: break; ! 720: ! 721: case '#': /* special "hidden" sequence */ ! 722: if (ap->a_final == '1') ! 723: fprintf(stderr, "avg call = %d char\n", ! 724: ctotal/ntotal); ! 725: ! 726: default: ! 727: break; ! 728: } ! 729: break; ! 730: ! 731: case DA1: ! 732: if (ap->a_param[0]==0) { ! 733: reply.a_type = CSI; ! 734: reply.a_pintro = '?'; ! 735: reply.a_nparam = 1; ! 736: reply.a_param[0] = 6; /* VT102 */ ! 737: reply.a_inters = 0; ! 738: reply.a_final = 'c'; ! 739: unparseseq(&reply, screen->tx8bit, screen->respond); ! 740: } ! 741: break; ! 742: ! 743: case TBC: ! 744: if (ap->a_param[0]==0) ! 745: TabClear(term->tabs, screen->cur_col); ! 746: else if (ap->a_param[0] == 3) ! 747: TabZonk(term->tabs); ! 748: break; ! 749: ! 750: case SET: ! 751: modes(term, bitset); ! 752: break; ! 753: ! 754: case DECSET: ! 755: dpmodes(term, bitset); ! 756: break; ! 757: ! 758: case RST: ! 759: modes(term, bitclr); ! 760: break; ! 761: ! 762: case DECRST: ! 763: dpmodes(term, bitclr); ! 764: break; ! 765: ! 766: case SGR: ! 767: for (i=0; i<ap->a_nparam; ++i) { ! 768: switch (ap->a_param[i]) { ! 769: case 0: ! 770: term->flags &= ~(INVERSE|BOLD); ! 771: break; ! 772: ! 773: case 1: ! 774: case 4: /* Underscore, really */ ! 775: case 5: /* Blink, really. */ ! 776: term->flags |= BOLD; ! 777: break; ! 778: ! 779: case 7: ! 780: term->flags |= INVERSE; ! 781: } ! 782: } ! 783: break; ! 784: ! 785: case CPR: ! 786: if (ap->a_param[0]==5) { ! 787: reply.a_type = CSI; ! 788: reply.a_pintro = 0; ! 789: reply.a_nparam = 1; ! 790: reply.a_param[0] = 0; ! 791: reply.a_inters = 0; ! 792: reply.a_final = 'n'; ! 793: unparseseq(&reply, screen->tx8bit, screen->respond); ! 794: break; ! 795: } ! 796: if (ap->a_param[0]==6) { ! 797: reply.a_type = CSI; ! 798: reply.a_pintro = 0; ! 799: reply.a_nparam = 2; ! 800: reply.a_param[0] = screen->cur_row+1; ! 801: reply.a_param[1] = screen->cur_col+1; ! 802: reply.a_inters = 0; ! 803: reply.a_final = 'R'; ! 804: unparseseq(&reply, screen->tx8bit, screen->respond); ! 805: break; ! 806: } ! 807: break; ! 808: ! 809: case DECSTBM: ! 810: top = ap->a_param[0]; ! 811: bot = ap->a_param[1]; ! 812: if (top < 1) ! 813: top = 1; ! 814: if (bot > screen->max_row+1) ! 815: bot = screen->max_row+1; ! 816: if (bot > top) { ! 817: #ifdef JUMPSCROLL ! 818: if(screen->scroll_amt) ! 819: FlushScroll(screen); ! 820: #endif JUMPSCROLL ! 821: screen->top_marg = top-1; ! 822: screen->bot_marg = bot-1; ! 823: CursorSet(screen, 0, 0, term->flags); ! 824: } ! 825: break; ! 826: ! 827: case ICH: ! 828: InsertChar(screen, ap->a_param[0]); ! 829: break; ! 830: ! 831: case CUU: ! 832: CursorUp(screen, ap->a_param[0]); ! 833: break; ! 834: ! 835: case CUD: ! 836: CursorDown(screen, ap->a_param[0]); ! 837: break; ! 838: ! 839: case CUF: ! 840: CursorForward(screen, ap->a_param[0]); ! 841: break; ! 842: ! 843: case CUB: ! 844: CursorBack(screen, ap->a_param[0]); ! 845: break; ! 846: ! 847: case HVP: ! 848: case CUP: ! 849: row = ap->a_param[0]; ! 850: col = ap->a_param[1]; ! 851: ! 852: screen->cur_x = screen->cur_y = 0; ! 853: screen->TekAMode = 0; ! 854: CursorSet(screen, row-1, col-1, term->flags); ! 855: break; ! 856: ! 857: case ED: ! 858: switch (ap->a_param[0]) { ! 859: case 0: ClearBelow(screen); ! 860: break; ! 861: ! 862: case 1: ClearAbove(screen); ! 863: break; ! 864: ! 865: case 2: ClearScreen(screen); ! 866: if (screen->TekEmu) ! 867: TekErase(term); ! 868: break; ! 869: } ! 870: break; ! 871: ! 872: case EL: ! 873: switch (ap->a_param[0]) { ! 874: case 0: ClearRight(screen); ! 875: break; ! 876: ! 877: case 1: ClearLeft(screen); ! 878: break; ! 879: ! 880: case 2: ClearLine(screen); ! 881: break; ! 882: } ! 883: break; ! 884: ! 885: case IL: ! 886: InsertLine(screen, ap->a_param[0]); ! 887: break; ! 888: ! 889: case DL: ! 890: DeleteLine(screen, ap->a_param[0]); ! 891: break; ! 892: ! 893: case DCH: ! 894: DeleteChar(screen, ap->a_param[0]); ! 895: break; ! 896: ! 897: case DECALN: ! 898: text_ptr = text_buf; ! 899: text_cnt = TEXT_BUF_SIZE; ! 900: for (i=0; i<256; ++i) { ! 901: if (--text_cnt >= 0) ! 902: *text_ptr++ = i; ! 903: else { ! 904: flushbuf(screen, term->flags, text_ptr); ! 905: text_ptr = text_buf; ! 906: text_cnt = TEXT_BUF_SIZE-1; ! 907: *text_ptr++ = i; ! 908: } ! 909: } ! 910: flushbuf(screen, term->flags, text_ptr); ! 911: break; ! 912: ! 913: case TEKESCFF: ! 914: case TEKCSIUS: ! 915: CursorSet(screen, 0, 0, term->flags); ! 916: ClearScreen(screen); ! 917: TekErase(term); ! 918: break; ! 919: ! 920: case TEKESCSUB: ! 921: TekCursor(term); ! 922: break; ! 923: ! 924: case TEKESCINQ: ! 925: TekInq(term); ! 926: break; ! 927: ! 928: default: ! 929: Panic("unexpected dispatch (%d) encountered in doescape", kind); ! 930: break; ! 931: } ! 932: } ! 933: ! 934: /* ! 935: * this is a big switch of all the control characters we know how to handle. ! 936: * the cases of the switch have a corresponding entry in the ctable. ! 937: */ ! 938: docontrol(term, c) ! 939: Terminal *term; ! 940: { ! 941: register Screen *screen = &term->screen; ! 942: ! 943: switch (ctable[c]) { ! 944: case CIGNORE: ! 945: break; ! 946: ! 947: case CBELL: ! 948: XFeep(0); ! 949: break; ! 950: ! 951: case CBACKSPACE: ! 952: CursorBack(screen, 1); ! 953: break; ! 954: ! 955: case CTAB: ! 956: screen->cur_col = TabNext(term->tabs, screen->cur_col); ! 957: if (screen->cur_col > screen->max_col) ! 958: screen->cur_col = screen->max_col; ! 959: break; ! 960: ! 961: case CLINEFEED: /* actually both VT and LF map here */ ! 962: case CFORMFEED: ! 963: if (screen->TekAMode) ! 964: TekReset(term); ! 965: Index(screen, 1); ! 966: if (term->flags & LINEFEED) ! 967: CarriageReturn(screen); ! 968: break; ! 969: ! 970: case CRETURN: ! 971: if (screen->TekAMode) ! 972: TekReset(term); ! 973: CarriageReturn(screen); ! 974: break; ! 975: ! 976: case CLS1: ! 977: screen->curgl = 1; ! 978: break; ! 979: ! 980: case CLS0: ! 981: screen->curgl = 0; ! 982: break; ! 983: ! 984: case CCANCEL: ! 985: screen->mode = ANSInormal; ! 986: break; ! 987: ! 988: case CESC: ! 989: case CDCS: ! 990: case CCSI: ! 991: screen->ansi.a_type = c; ! 992: screen->ansi.a_pintro = 0; ! 993: screen->ansi.a_final = 0; ! 994: screen->ansi.a_inters = 0; ! 995: screen->ansi.a_nparam = 0; ! 996: screen->ansi.a_nastyf = 0; ! 997: screen->mode = ANSIparse; ! 998: break; ! 999: ! 1000: case CTEKINIT: /* come here from FS, GS, or RS */ ! 1001: if (screen->TekEmu) ! 1002: TekInit(term, c); ! 1003: break; ! 1004: ! 1005: case CTEKALPH: /* US */ ! 1006: break; /* just ignore; can only get to alpha */ ! 1007: /* mode from Tek graphics mode */ ! 1008: ! 1009: case CIND: ! 1010: Index(screen, 1); ! 1011: break; ! 1012: ! 1013: case CNEL: ! 1014: Index(screen, 1); ! 1015: CarriageReturn(screen); ! 1016: break; ! 1017: ! 1018: case CRI: ! 1019: RevIndex(screen, 1); ! 1020: break; ! 1021: ! 1022: case CSS2: ! 1023: screen->curss = 2; ! 1024: break; ! 1025: ! 1026: case CSS3: ! 1027: screen->curss = 3; ! 1028: break; ! 1029: ! 1030: default: ! 1031: Panic("unexpected char (0x%x) encountered in docontrol", c); ! 1032: break; ! 1033: } ! 1034: } ! 1035: ! 1036: /* ! 1037: * process ANSI modes set, reset ! 1038: */ ! 1039: modes(term, func) ! 1040: Terminal *term; ! 1041: int (*func)(); ! 1042: { ! 1043: register Screen *screen = &term->screen; ! 1044: register ANSI *ansi; ! 1045: register int i; ! 1046: ! 1047: ansi = &screen->ansi; ! 1048: for (i=0; i<ansi->a_nparam; ++i) { ! 1049: switch (ansi->a_param[i]) { ! 1050: case 4: /* IRM */ ! 1051: (*func)(&term->flags, INSERT); ! 1052: break; ! 1053: ! 1054: case 20: /* LNM */ ! 1055: (*func)(&term->flags, LINEFEED); ! 1056: break; ! 1057: } ! 1058: } ! 1059: } ! 1060: ! 1061: /* ! 1062: * process DEC private modes set, reset ! 1063: */ ! 1064: dpmodes(term, func) ! 1065: Terminal *term; ! 1066: int (*func)(); ! 1067: { ! 1068: register Screen *screen = &term->screen; ! 1069: register ANSI *ap; ! 1070: register int i; ! 1071: ! 1072: ap = &screen->ansi; ! 1073: for (i=0; i<ap->a_nparam; ++i) { ! 1074: switch (ap->a_param[i]) { ! 1075: case 1: /* DECCKM */ ! 1076: (*func)(&term->keyboard.flags, CURSOR_APL); ! 1077: break; ! 1078: ! 1079: #ifdef JUMPSCROLL ! 1080: case 4: /* DECSCLM (slow scroll) */ ! 1081: if (func == bitset) { ! 1082: screen->jumpscroll = 0; ! 1083: if (screen->scroll_amt) ! 1084: FlushScroll(screen); ! 1085: } else if (!screen->TekEmu) ! 1086: screen->jumpscroll = 1; ! 1087: (*func)(&term->flags, SMOOTHSCROLL); ! 1088: break; ! 1089: #endif JUMPSCROLL ! 1090: case 5: /* DECSCNM */ ! 1091: i = term->flags; ! 1092: (*func)(&term->flags, REVERSE_VIDEO); ! 1093: if ((term->flags ^ i) & REVERSE_VIDEO) ! 1094: ReverseVideo(term); ! 1095: break; ! 1096: ! 1097: case 6: /* DECOM */ ! 1098: (*func)(&term->flags, ORIGIN); ! 1099: CursorSet(screen, 0, 0, term->flags); ! 1100: break; ! 1101: ! 1102: case 7: /* DECAWM */ ! 1103: (*func)(&term->flags, WRAPAROUND); ! 1104: break; ! 1105: case 9: /* MIT bogus sequence */ ! 1106: (*func)(&screen->send_mouse_pos, 1); ! 1107: break; ! 1108: case 38: /* DECTEK */ ! 1109: (*func)(&screen->TekEmu, 1); ! 1110: /* ! 1111: * probably need to do some work here to get ! 1112: * into or out of Tek emulation cleanly ! 1113: */ ! 1114: break; ! 1115: } ! 1116: } ! 1117: } ! 1118: ! 1119: /* ! 1120: * set a bit in a word given a pointer to the word and a mask. ! 1121: */ ! 1122: bitset(p, mask) ! 1123: int *p; ! 1124: { ! 1125: *p |= mask; ! 1126: } ! 1127: ! 1128: /* ! 1129: * clear a bit in a word given a pointer to the word and a mask. ! 1130: */ ! 1131: bitclr(p, mask) ! 1132: int *p; ! 1133: { ! 1134: *p &= ~mask; ! 1135: } ! 1136: ! 1137: ReverseVideo (term) ! 1138: Terminal *term; ! 1139: { ! 1140: register Screen *screen = &term->screen; ! 1141: int tmp; ! 1142: ! 1143: XDefineCursor(screen->window, ! 1144: (term->flags & REVERSE_VIDEO) ? screen->rcurs : screen->curs); ! 1145: tmp = screen->background; ! 1146: if (screen->cursorcolor == screen->foreground) ! 1147: screen->cursorcolor = tmp; ! 1148: screen->background = screen->foreground; ! 1149: screen->foreground = tmp; ! 1150: XFreePixmap(screen->bgndtile); ! 1151: screen->bgndtile = XMakeTile(screen->background); ! 1152: if (screen->borderwidth && ! 1153: screen->background < 2 && ! 1154: screen->foreground < 2) { ! 1155: if (screen->bgndtile == BlackPixmap) ! 1156: screen->bordertile = WhitePixmap; ! 1157: else if (screen->bgndtile == WhitePixmap) ! 1158: screen->bordertile = BlackPixmap; ! 1159: XChangeBorder (screen->window, screen->bordertile); ! 1160: } ! 1161: XChangeBackground (screen->window, screen->bgndtile); ! 1162: XClear (screen->window); ! 1163: ScrnRefresh (screen, 0, 0, screen->max_row +1, screen->max_col + 1); ! 1164: if (screen->TekEmu) TekRefresh (term); ! 1165: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.