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: }