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

Defined functions

ANSInormal defined in line 54; used 8 times
ANSIparse defined in line 507; used 4 times
ANSIstring defined in line 458; used 4 times
ReverseVideo defined in line 1137; used 3 times
TekFlushBuf defined in line 425; used 1 times
  • in line 31
TekMode defined in line 340; used 1 times
  • in line 76
WriteText defined in line 299; used 1 times
bitclr defined in line 1131; used 3 times
bitset defined in line 1122; used 4 times
docontrol defined in line 938; used 3 times
doescape defined in line 632; used 1 times
dotext defined in line 234; used 3 times
dpmodes defined in line 1064; used 2 times
flushbuf defined in line 168; used 3 times
modes defined in line 1039; used 2 times
procseq defined in line 579; used 4 times

Defined variables

ctotal defined in line 46; used 2 times
nlf defined in line 45; used 5 times
nri defined in line 44; used 5 times
ntotal defined in line 47; used 2 times
rcsid_charproc_c defined in line 16; never used
text_buf defined in line 42; used 11 times

Defined macros

ANSIflush defined in line 26; used 6 times
DEFAULT defined in line 590; used 1 times
FIXEDLEN defined in line 591; used 1 times
INTERS defined in line 587; used 2 times
  • in line 607(2)
NDEFLT defined in line 589; used 4 times
SEQKEY defined in line 586; used 1 times
SEQTYPE defined in line 588; used 1 times
TEKflush defined in line 31; used 4 times
TEXT_BUF_SIZE defined in line 37; used 7 times
getb defined in line 21; used 5 times
peekb defined in line 24; used 1 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2672
Valid CSS Valid XHTML 1.0 Strict