home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume9 / xterm / part04 / charproc.c next >
Encoding:
C/C++ Source or Header  |  1987-04-20  |  56.9 KB  |  2,429 lines

  1. /*
  2.  *    $Source: /u1/X/xterm/RCS/charproc.c,v $
  3.  *    $Header: charproc.c,v 10.102 86/12/02 11:37:25 swick Exp $
  4.  */
  5.  
  6. #include <X/mit-copyright.h>
  7.  
  8. /* Copyright (c) 1985 Massachusetts Institute of Technology        */
  9. /* Copyright (c) 1985    Digital Equipment Corporation            */
  10.  
  11. /* charproc.c */
  12.  
  13. #include <stdio.h>
  14. #include <sgtty.h>
  15. #include <ctype.h>
  16. #include <errno.h>
  17. #include <setjmp.h>
  18. #include <sys/ioctl.h>
  19. #include <sys/time.h>
  20. #include <X/Xlib.h>
  21. #include "scrollbar.h"
  22. #include "ptyx.h"
  23. #include "VTparse.h"
  24. #include "data.h"
  25. #include "error.h"
  26. #ifdef MODEMENU
  27. #include "menu.h"
  28. #endif MODEMENU
  29.  
  30. #define    DEFAULT        -1
  31. #define    TEXT_BUF_SIZE    256
  32.  
  33. #define    input()        (bcnt-- > 0 ? *bptr++ : in_put())
  34.  
  35. #ifndef lint
  36. static char sccs_id[] = "@(#)charproc.c\tX10/6.6B\t1/9/87";
  37. #endif lint
  38.  
  39. static long arg;
  40. static int ch;
  41. static int nparam;
  42. static ANSI reply;
  43. static int param[NPARAM];
  44.  
  45. static unsigned long ctotal;
  46. static unsigned long ntotal;
  47. static jmp_buf vtjmpbuf;
  48.  
  49. extern int groundtable[];
  50. extern int csitable[];
  51. extern int dectable[];
  52. extern int eigtable[];
  53. extern int esctable[];
  54. extern int iestable[];
  55. extern int igntable[];
  56. extern int scrtable[];
  57. extern int scstable[];
  58.  
  59. VTparse()
  60. {
  61.     register Screen *screen = &term.screen;
  62.     register int *parsestate = groundtable;
  63.     register int c;
  64.     register char *cp;
  65.     register int row, col, top, bot, scstype;
  66.     WindowInfo wininfo;
  67.     extern int bitset(), bitclr(), finput();
  68.  
  69.     if(setjmp(vtjmpbuf))
  70.         parsestate = groundtable;
  71.     for( ; ; )
  72.         switch(parsestate[c = input()]) {
  73.          case CASE_GROUND_STATE:
  74.             /* exit ignore mode */
  75.             parsestate = groundtable;
  76.             break;
  77.  
  78.          case CASE_IGNORE_STATE:
  79.             /* Ies: ignore anything else */
  80.             parsestate = igntable;
  81.             break;
  82.  
  83.          case CASE_IGNORE_ESC:
  84.             /* Ign: escape */
  85.             parsestate = iestable;
  86.             break;
  87.  
  88.          case CASE_IGNORE:
  89.             /* Ignore character */
  90.             break;
  91.  
  92.          case CASE_BELL:
  93.             /* bell */
  94.             Bell();
  95.             break;
  96.  
  97.          case CASE_BS:
  98.             /* backspace */
  99.             CursorBack(screen, 1);
  100.             break;
  101.  
  102.          case CASE_CR:
  103.             /* carriage return */
  104.             CarriageReturn(screen);
  105.             break;
  106.  
  107.          case CASE_ESC:
  108.             /* escape */
  109.             parsestate = esctable;
  110.             break;
  111.  
  112.          case CASE_VMOT:
  113.             /*
  114.              * form feed, line feed, vertical tab, but not in
  115.              * status line
  116.              */
  117.             if(!screen->instatus)
  118.                 Index(screen, 1);
  119.             if (term.flags & LINEFEED)
  120.                 CarriageReturn(screen);
  121.             if(screen->display->qlen > 0 ||
  122.              (ioctl(screen->display->fd, FIONREAD, &arg), arg) > 0)
  123.                 xevents();
  124.             break;
  125.  
  126.          case CASE_TAB:
  127.             /* tab */
  128.             screen->cur_col = TabNext(term.tabs, screen->cur_col);
  129.             if (screen->cur_col > screen->max_col)
  130.                 screen->cur_col = screen->max_col;
  131.             break;
  132.  
  133.          case CASE_SI:
  134.             screen->curgl = 0;
  135.             break;
  136.  
  137.          case CASE_SO:
  138.             screen->curgl = 1;
  139.             break;
  140.  
  141.          case CASE_SCR_STATE:
  142.             /* enter scr state */
  143.             parsestate = scrtable;
  144.             break;
  145.  
  146.          case CASE_SCS0_STATE:
  147.             /* enter scs state 0 */
  148.             scstype = 0;
  149.             parsestate = scstable;
  150.             break;
  151.  
  152.          case CASE_SCS1_STATE:
  153.             /* enter scs state 1 */
  154.             scstype = 1;
  155.             parsestate = scstable;
  156.             break;
  157.  
  158.          case CASE_SCS2_STATE:
  159.             /* enter scs state 2 */
  160.             scstype = 2;
  161.             parsestate = scstable;
  162.             break;
  163.  
  164.          case CASE_SCS3_STATE:
  165.             /* enter scs state 3 */
  166.             scstype = 3;
  167.             parsestate = scstable;
  168.             break;
  169.  
  170.          case CASE_ESC_IGNORE:
  171.             /* unknown escape sequence */
  172.             parsestate = eigtable;
  173.             break;
  174.  
  175.          case CASE_ESC_DIGIT:
  176.             /* digit in csi or dec mode */
  177.             if((row = param[nparam - 1]) == DEFAULT)
  178.                 row = 0;
  179.             param[nparam - 1] = 10 * row + (c - '0');
  180.             break;
  181.  
  182.          case CASE_ESC_SEMI:
  183.             /* semicolon in csi or dec mode */
  184.             param[nparam++] = DEFAULT;
  185.             break;
  186.  
  187.          case CASE_DEC_STATE:
  188.             /* enter dec mode */
  189.             parsestate = dectable;
  190.             break;
  191.  
  192.          case CASE_ICH:
  193.             /* ICH */
  194.             if((c = param[0]) < 1)
  195.                 c = 1;
  196.             InsertChar(screen, c);
  197.             parsestate = groundtable;
  198.             break;
  199.  
  200.          case CASE_CUU:
  201.             /* CUU */
  202.             /* only if not in status line */
  203.             if(!screen->instatus) {
  204.                 if((c = param[0]) < 1)
  205.                     c = 1;
  206.                 CursorUp(screen, c);
  207.             }
  208.             parsestate = groundtable;
  209.             break;
  210.  
  211.          case CASE_CUD:
  212.             /* CUD */
  213.             /* only if not in status line */
  214.             if(!screen->instatus) {
  215.                 if((c = param[0]) < 1)
  216.                     c = 1;
  217.                 CursorDown(screen, c);
  218.             }
  219.             parsestate = groundtable;
  220.             break;
  221.  
  222.          case CASE_CUF:
  223.             /* CUF */
  224.             if((c = param[0]) < 1)
  225.                 c = 1;
  226.             CursorForward(screen, c);
  227.             parsestate = groundtable;
  228.             break;
  229.  
  230.          case CASE_CUB:
  231.             /* CUB */
  232.             if((c = param[0]) < 1)
  233.                 c = 1;
  234.             CursorBack(screen, c);
  235.             parsestate = groundtable;
  236.             break;
  237.  
  238.          case CASE_CUP:
  239.             /* CUP | HVP */
  240.             /* only if not in status line */
  241.             if(!screen->instatus) {
  242.                 if((row = param[0]) < 1)
  243.                     row = 1;
  244.                 if(nparam < 2 || (col = param[1]) < 1)
  245.                     col = 1;
  246.                 CursorSet(screen, row-1, col-1, term.flags);
  247.             }
  248.             parsestate = groundtable;
  249.             break;
  250.  
  251.          case CASE_ED:
  252.             /* ED */
  253.             switch (param[0]) {
  254.              case DEFAULT:
  255.              case 0:
  256.                 if(screen->instatus)
  257.                     ClearRight(screen);
  258.                 else
  259.                     ClearBelow(screen);
  260.                 break;
  261.  
  262.              case 1:
  263.                 if(screen->instatus)
  264.                     ClearLeft(screen);
  265.                 else
  266.                     ClearAbove(screen);
  267.                 break;
  268.  
  269.              case 2:
  270.                 if(screen->instatus)
  271.                     ClearLine(screen);
  272.                 else
  273.                     ClearScreen(screen);
  274.                 break;
  275.             }
  276.             parsestate = groundtable;
  277.             break;
  278.  
  279.          case CASE_EL:
  280.             /* EL */
  281.             switch (param[0]) {
  282.              case DEFAULT:
  283.              case 0:
  284.                 ClearRight(screen);
  285.                 break;
  286.              case 1:
  287.                 ClearLeft(screen);
  288.                 break;
  289.              case 2:
  290.                 ClearLine(screen);
  291.                 break;
  292.             }
  293.             parsestate = groundtable;
  294.             break;
  295.  
  296.          case CASE_IL:
  297.             /* IL */
  298.             /* only if not in status line */
  299.             if(!screen->instatus) {
  300.                 if((c = param[0]) < 1)
  301.                     c = 1;
  302.                 InsertLine(screen, c);
  303.             }
  304.             parsestate = groundtable;
  305.             break;
  306.  
  307.          case CASE_DL:
  308.             /* DL */
  309.             /* only if not in status line */
  310.             if(!screen->instatus) {
  311.                 if((c = param[0]) < 1)
  312.                     c = 1;
  313.                 DeleteLine(screen, c);
  314.             }
  315.             parsestate = groundtable;
  316.             break;
  317.  
  318.          case CASE_DCH:
  319.             /* DCH */
  320.             if((c = param[0]) < 1)
  321.                 c = 1;
  322.             DeleteChar(screen, c);
  323.             parsestate = groundtable;
  324.             break;
  325.  
  326.          case CASE_DA1:
  327.             /* DA1 */
  328.             if (param[0] <= 0) {    /* less than means DEFAULT */
  329.                 reply.a_type   = CSI;
  330.                 reply.a_pintro = '?';
  331.                 reply.a_nparam = 2;
  332.                 reply.a_param[0] = 1;        /* VT102 */
  333.                 reply.a_param[1] = 2;        /* VT102 */
  334.                 reply.a_inters = 0;
  335.                 reply.a_final  = 'c';
  336.                 unparseseq(&reply, screen->respond);
  337.             }
  338.             parsestate = groundtable;
  339.             break;
  340.  
  341.          case CASE_TBC:
  342.             /* TBC */
  343.             if ((c = param[0]) <= 0) /* less than means default */
  344.                 TabClear(term.tabs, screen->cur_col);
  345.             else if (c == 3)
  346.                 TabZonk(term.tabs);
  347.             parsestate = groundtable;
  348.             break;
  349.  
  350.          case CASE_SET:
  351.             /* SET */
  352.             modes(&term, bitset);
  353.             parsestate = groundtable;
  354.             break;
  355.  
  356.          case CASE_RST:
  357.             /* RST */
  358.             modes(&term, bitclr);
  359.             parsestate = groundtable;
  360.             break;
  361.  
  362.          case CASE_SGR:
  363.             /* SGR */
  364.             for (c=0; c<nparam; ++c) {
  365.                 switch (param[c]) {
  366.                  case DEFAULT:
  367.                  case 0:
  368.                     term.flags &= ~(INVERSE|BOLD|UNDERLINE);
  369.                     break;
  370.                  case 1:
  371.                  case 5:    /* Blink, really.    */
  372.                     term.flags |= BOLD;
  373.                     break;
  374.                  case 4:    /* Underscore        */
  375.                     term.flags |= UNDERLINE;
  376.                     break;
  377.                  case 7:
  378.                     term.flags |= INVERSE;
  379.                 }
  380.             }
  381.             parsestate = groundtable;
  382.             break;
  383.  
  384.          case CASE_CPR:
  385.             /* CPR */
  386.             if ((c = param[0]) == 5) {
  387.                 reply.a_type = CSI;
  388.                 reply.a_pintro = 0;
  389.                 reply.a_nparam = 1;
  390.                 reply.a_param[0] = 0;
  391.                 reply.a_inters = 0;
  392.                 reply.a_final  = 'n';
  393.                 unparseseq(&reply, screen->respond);
  394.             } else if (c == 6) {
  395.                 reply.a_type = CSI;
  396.                 reply.a_pintro = 0;
  397.                 reply.a_nparam = 2;
  398.                 reply.a_param[0] = screen->cur_row+1;
  399.                 reply.a_param[1] = screen->cur_col+1;
  400.                 reply.a_inters = 0;
  401.                 reply.a_final  = 'R';
  402.                 unparseseq(&reply, screen->respond);
  403.             }
  404.             parsestate = groundtable;
  405.             break;
  406.  
  407.          case CASE_DECSTBM:
  408.             /* DECSTBM */
  409.             /* only if not in status line */
  410.             if(!screen->instatus) {
  411.                 if((top = param[0]) < 1)
  412.                     top = 1;
  413.                 if(nparam < 2 || (bot = param[1]) == DEFAULT
  414.                    || bot > screen->max_row + 1
  415.                    || bot == 0)
  416.                     bot = screen->max_row+1;
  417.                 if (bot > top) {
  418.                     if(screen->scroll_amt)
  419.                         FlushScroll(screen);
  420.                     screen->top_marg = top-1;
  421.                     screen->bot_marg = bot-1;
  422.                     CursorSet(screen, 0, 0, term.flags);
  423.                 }
  424.             }
  425.             parsestate = groundtable;
  426.             break;
  427.  
  428.          case CASE_SUN_EMU:
  429.             /* sub-set of sun tty emulation */
  430.             switch(param[0]) {
  431.              case 3:    /* move window */
  432.                 if(nparam == 3) {
  433.                     XMoveWindow(VWindow(screen), param[2],
  434.                      param[1]);
  435.                     XSync(FALSE);    /* synchronize */
  436.                     if(QLength() > 0)
  437.                         xevents();
  438.                 }
  439.                 break;
  440.              case 4:    /* resize window (pixels) */
  441.                 if(nparam == 3) {
  442.                     XChangeWindow (VWindow(screen), param[1],
  443.                      param[2]);
  444.                     XSync(FALSE);    /* synchronize */
  445.                     if(QLength() > 0)
  446.                         xevents();
  447.                 }
  448.                 break;
  449.              case 5:    /* raise window */
  450.                 XRaiseWindow(VWindow(screen));
  451.                 break;
  452.              case 6:    /* lower window */
  453.                 XLowerWindow(VWindow(screen));
  454.                 break;
  455.              case 7:    /* redisplay window */
  456.                 Redraw();
  457.                 break;
  458.              case 8:    /* resize window (rows and columns) */
  459.                 if(nparam == 3) {
  460.                     XChangeWindow (VWindow(screen),
  461.                      FontWidth(screen) * param[2] +
  462.                      2 * screen->border + screen->scrollbar,
  463.                      FontHeight(screen) * param[1] +
  464.                      screen->statusheight + Titlebar(screen)
  465.                      + 2 * screen->border);
  466.                     XSync(FALSE);    /* synchronize */
  467.                     if(QLength() > 0)
  468.                         xevents();
  469.                 }
  470.                 break;
  471.              case 13:    /* send window position */
  472.                 XQueryWindow(VWindow(screen), &wininfo);
  473.                 reply.a_type = CSI;
  474.                 reply.a_pintro = 0;
  475.                 reply.a_nparam = 3;
  476.                 reply.a_param[0] = 3;
  477.                 reply.a_param[1] = wininfo.y;
  478.                 reply.a_param[2] = wininfo.x;
  479.                 reply.a_inters = 0;
  480.                 reply.a_final  = 't';
  481.                 unparseseq(&reply, screen->respond);
  482.                 break;
  483.              case 14:    /* send window size (pixels) */
  484.                 reply.a_type = CSI;
  485.                 reply.a_pintro = 0;
  486.                 reply.a_nparam = 3;
  487.                 reply.a_param[0] = 4;
  488.                 reply.a_param[1] = (screen->max_col + 1) *
  489.                  FontWidth(screen) + 2 * screen->border +
  490.                  screen->scrollbar;
  491.                 reply.a_param[2] = (screen->max_row + 1) *
  492.                  FontHeight(screen) + screen->statusheight +
  493.                  Titlebar(screen) + 2 * screen->border;
  494.                 reply.a_inters = 0;
  495.                 reply.a_final  = 't';
  496.                 unparseseq(&reply, screen->respond);
  497.                 break;
  498.              case 18:    /* send window size (rows and cols) */
  499.                 reply.a_type = CSI;
  500.                 reply.a_pintro = 0;
  501.                 reply.a_nparam = 3;
  502.                 reply.a_param[0] = 8;
  503.                 reply.a_param[1] = screen->max_row + 1;
  504.                 reply.a_param[2] = screen->max_col + 1;
  505.                 reply.a_inters = 0;
  506.                 reply.a_final  = 't';
  507.                 unparseseq(&reply, screen->respond);
  508.                 break;
  509.             }
  510.             parsestate = groundtable;
  511.             break;
  512.  
  513.          case CASE_DECREQTPARM:
  514.             /* DECREQTPARM */
  515.             if ((c = param[0]) == DEFAULT)
  516.                 c = 0;
  517.             if (c == 0 || c == 1) {
  518.                 reply.a_type = CSI;
  519.                 reply.a_pintro = 0;
  520.                 reply.a_nparam = 7;
  521.                 reply.a_param[0] = c + 2;
  522.                 reply.a_param[1] = 1;    /* no parity */
  523.                 reply.a_param[2] = 1;    /* eight bits */
  524.                 reply.a_param[3] = 112;    /* transmit 9600 baud */
  525.                 reply.a_param[4] = 112;    /* receive 9600 baud */
  526.                 reply.a_param[5] = 1;    /* clock multiplier ? */
  527.                 reply.a_param[6] = 0;    /* STP flags ? */
  528.                 reply.a_inters = 0;
  529.                 reply.a_final  = 'x';
  530.                 unparseseq(&reply, screen->respond);
  531.             }
  532.             parsestate = groundtable;
  533.             break;
  534.  
  535.          case CASE_DECSET:
  536.             /* DECSET */
  537.             dpmodes(&term, bitset);
  538.             parsestate = groundtable;
  539.             if(screen->TekEmu)
  540.                 return;
  541.             break;
  542.  
  543.          case CASE_DECRST:
  544.             /* DECRST */
  545.             dpmodes(&term, bitclr);
  546.             parsestate = groundtable;
  547.             break;
  548.  
  549.          case CASE_HIDDEN:
  550.             /* special "hidden" sequence */
  551.             fprintf(stderr, "avg call = %ld char\n", ctotal/ntotal);
  552.             parsestate = groundtable;
  553.             break;
  554.  
  555.          case CASE_DECALN:
  556.             /* DECALN */
  557.             if(screen->cursor_state)
  558.                 HideCursor();
  559.             for(row = screen->max_row ; row >= 0 ; row--) {
  560.                 bzero(screen->buf[2 * row + 1],
  561.                  col = screen->max_col + 1);
  562.                 for(cp = screen->buf[2 * row] ; col > 0 ; col--)
  563.                     *cp++ = 'E';
  564.             }
  565.             ScrnRefresh(screen, 0, 0, screen->max_row + 1,
  566.              screen->max_col + 1);
  567.             parsestate = groundtable;
  568.             break;
  569.  
  570.          case CASE_GSETS:
  571.             screen->gsets[scstype] = c;
  572.             parsestate = groundtable;
  573.             break;
  574.  
  575.          case CASE_DECSC:
  576.             /* DECSC */
  577.             CursorSave(&term, &screen->sc);
  578.             parsestate = groundtable;
  579.             break;
  580.  
  581.          case CASE_DECRC:
  582.             /* DECRC */
  583.             CursorRestore(&term, &screen->sc);
  584.             parsestate = groundtable;
  585.             break;
  586.  
  587.          case CASE_DECKPAM:
  588.             /* DECKPAM */
  589.             term.keyboard.flags |= KYPD_APL;
  590.             parsestate = groundtable;
  591.             break;
  592.  
  593.          case CASE_DECKPNM:
  594.             /* DECKPNM */
  595.             term.keyboard.flags &= ~KYPD_APL;
  596.             parsestate = groundtable;
  597.             break;
  598.  
  599.          case CASE_IND:
  600.             /* IND */
  601.             /* only if not in status line */
  602.             if(!screen->instatus)
  603.                 Index(screen, 1);
  604.             if(screen->display->qlen > 0 ||
  605.              (ioctl(screen->display->fd, FIONREAD, &arg), arg) > 0)
  606.                 xevents();
  607.             parsestate = groundtable;
  608.             break;
  609.  
  610.          case CASE_NEL:
  611.             /* NEL */
  612.             /* only if not in status line */
  613.             if(!screen->instatus)
  614.                 Index(screen, 1);
  615.             CarriageReturn(screen);
  616.             if(screen->display->qlen > 0 ||
  617.              (ioctl(screen->display->fd, FIONREAD, &arg), arg) > 0)
  618.                 xevents();
  619.             parsestate = groundtable;
  620.             break;
  621.  
  622.          case CASE_HTS:
  623.             /* HTS */
  624.             TabSet(term.tabs, screen->cur_col);
  625.             parsestate = groundtable;
  626.             break;
  627.  
  628.          case CASE_RI:
  629.             /* RI */
  630.             /* only if not in status line */
  631.             if(!screen->instatus)
  632.                 RevIndex(screen, 1);
  633.             parsestate = groundtable;
  634.             break;
  635.  
  636.          case CASE_SS2:
  637.             /* SS2 */
  638.             screen->curss = 2;
  639.             parsestate = groundtable;
  640.             break;
  641.  
  642.          case CASE_SS3:
  643.             /* SS3 */
  644.             screen->curss = 3;
  645.             parsestate = groundtable;
  646.             break;
  647.  
  648.          case CASE_CSI_STATE:
  649.             /* enter csi state */
  650.             nparam = 1;
  651.             param[0] = DEFAULT;
  652.             parsestate = csitable;
  653.             break;
  654.  
  655.          case CASE_OSC:
  656.             /* do osc escapes */
  657.             do_osc(finput);
  658.             parsestate = groundtable;
  659.             break;
  660.  
  661.          case CASE_RIS:
  662.             /* RIS */
  663.             VTReset(TRUE);
  664.             parsestate = groundtable;
  665.             break;
  666.  
  667.          case CASE_LS2:
  668.             /* LS2 */
  669.             screen->curgl = 2;
  670.             parsestate = groundtable;
  671.             break;
  672.  
  673.          case CASE_LS3:
  674.             /* LS3 */
  675.             screen->curgl = 3;
  676.             parsestate = groundtable;
  677.             break;
  678.  
  679.          case CASE_LS3R:
  680.             /* LS3R */
  681.             screen->curgr = 3;
  682.             parsestate = groundtable;
  683.             break;
  684.  
  685.          case CASE_LS2R:
  686.             /* LS2R */
  687.             screen->curgr = 2;
  688.             parsestate = groundtable;
  689.             break;
  690.  
  691.          case CASE_LS1R:
  692.             /* LS1R */
  693.             screen->curgr = 1;
  694.             parsestate = groundtable;
  695.             break;
  696.  
  697.          case CASE_TO_STATUS:
  698.             if((c = param[0]) < 1)
  699.                 c = 1;
  700.             ToStatus(c - 1);
  701.             parsestate = groundtable;
  702.             break;
  703.  
  704.          case CASE_FROM_STATUS:
  705.             FromStatus();
  706.             parsestate = groundtable;
  707.             break;
  708.  
  709.          case CASE_SHOW_STATUS:
  710.             ShowStatus();
  711.             parsestate = groundtable;
  712.             break;
  713.  
  714.          case CASE_HIDE_STATUS:
  715.             HideStatus();
  716.             parsestate = groundtable;
  717.             break;
  718.  
  719.          case CASE_ERASE_STATUS:
  720.             EraseStatus();
  721.             parsestate = groundtable;
  722.             break;
  723.  
  724.          case CASE_XTERM_SAVE:
  725.             savemodes(&term);
  726.             parsestate = groundtable;
  727.             break;
  728.  
  729.          case CASE_XTERM_RESTORE:
  730.             restoremodes(&term);
  731.             parsestate = groundtable;
  732.             break;
  733.  
  734.          case CASE_PRINT:
  735.             /* printable characters */
  736.             top = bcnt > TEXT_BUF_SIZE ? TEXT_BUF_SIZE : bcnt;
  737.             cp = bptr;
  738.             *--bptr = c;
  739.             while(top > 0 && isprint(*cp)) {
  740.                 top--;
  741.                 bcnt--;
  742.                 cp++;
  743.             }
  744.             if(screen->curss) {
  745.                 dotext(screen, term.flags,
  746.                  screen->gsets[screen->curss], bptr, bptr + 1);
  747.                 screen->curss = 0;
  748.                 bptr++;
  749.             }
  750.             if(bptr < cp)
  751.                 dotext(screen, term.flags,
  752.                  screen->gsets[screen->curgl], bptr, cp);
  753.             bptr = cp;
  754.             break;
  755.         }
  756. }
  757.  
  758. finput()
  759. {
  760.     return(input());
  761. }
  762.  
  763. static int select_mask;
  764.  
  765. in_put()
  766. {
  767.     register Screen *screen = &term.screen;
  768.     register char *cp;
  769.     register int i;
  770.  
  771.     select_mask = pty_mask;    /* force initial read */
  772.     for( ; ; ) {
  773.         if(select_mask & pty_mask) {
  774.             if(screen->logging)
  775.                 FlushLog(screen);
  776.             if((bcnt = read(screen->respond, bptr = buffer,
  777.              BUF_SIZE)) < 0) {
  778.                 if(errno == EIO && am_slave)
  779.                     exit(0);
  780.                 else if(errno != EWOULDBLOCK)
  781.                     Panic(
  782.                  "input: read returned unexpected error (%d)\n",
  783.                      errno);
  784.             } else if(bcnt == 0)
  785.                 Panic("input: read returned zero\n");
  786.             else {
  787.                 /* strip parity bit */
  788.                 for(i = bcnt, cp = bptr ; i > 0 ; i--)
  789.                     *cp++ &= CHAR;
  790.                 if(screen->sb && screen->scrollinput &&
  791.                  screen->topline < 0)
  792.                     ScrollToBottom(screen->sb);
  793.                 if(screen->icon_show && !screen->iconinput) {
  794.                     screen->iconinput = TRUE;
  795.                     IconBox(screen);
  796.                 }
  797.                 break;
  798.             }
  799.         }
  800.         if(screen->scroll_amt)
  801.             FlushScroll(screen);
  802.         if(screen->cursor_set && (screen->cursor_col != screen->cur_col
  803.          || screen->cursor_row != screen->cur_row)) {
  804.             if(screen->cursor_state)
  805.                 HideCursor();
  806.             ShowCursor();
  807.         } else if(screen->cursor_set != screen->cursor_state) {
  808.             if(screen->cursor_set)
  809.                 ShowCursor();
  810.             else
  811.                 HideCursor();
  812.         }
  813.         if(QLength())
  814.             select_mask = X_mask;
  815.         else {
  816.             XFlush();
  817.             select_mask = Select_mask;
  818.             if((i = select(max_plus1, &select_mask, NULL, NULL,
  819.              screen->timeout)) < 0){
  820.                 if (errno != EINTR)
  821.                     SysError(ERROR_SELECT);
  822.                 continue;
  823.             } else if(i == 0) {
  824.                 if(GetButtonState(screen->sb) & HILITED)
  825.                     WindowScroll(screen,
  826.                      ButtonRegion(screen->sb));
  827.                 screen->timeout->tv_usec = STEPTIME;
  828.                 continue;
  829.             }
  830.         }
  831.         if(select_mask & X_mask)
  832.             xevents();
  833.     }
  834.     bcnt--;
  835.     return(*bptr++);
  836. }
  837.  
  838. /*
  839.  * process a string of characters according to the character set indicated
  840.  * by charset.  worry about end of line conditions (wraparound if selected).
  841.  */
  842. dotext(screen, flags, charset, buf, ptr)
  843. register Screen    *screen;
  844. unsigned    flags;
  845. char        charset;
  846. char    *buf;
  847. char    *ptr;
  848. {
  849.     register char    *s;
  850.     register int    len;
  851.     register int    n;
  852.     register int    next_col;
  853.  
  854.     switch (charset) {
  855.     case 'A':    /* United Kingdom set                */
  856.         for (s=buf; s<ptr; ++s)
  857.             if (*s == '#')
  858.                 *s = '\036';    /* UK pound sign    */
  859.         break;
  860.  
  861.     case 'B':    /* ASCII set                    */
  862.         break;
  863.  
  864.     case '0':    /* special graphics (line drawing)        */
  865.         for (s=buf; s<ptr; ++s)
  866.             if (*s>=0x5f && *s<=0x7e)
  867.                 *s = *s == 0x5f ? 0x7f : *s - 0x5f;
  868.         break;
  869.  
  870.     default:    /* any character sets we don't recognize    */
  871.         return;
  872.     }
  873.  
  874.     len = ptr - buf; 
  875.     ptr = buf;
  876.     while (len > 0) {
  877.         n = screen->max_col-screen->cur_col+1;
  878.         if (n <= 1) {
  879.             if (screen->do_wrap && (flags&WRAPAROUND) &&
  880.              !screen->instatus) {
  881.                 Index(screen, 1);
  882.                 screen->cur_col = 0;
  883.                 screen->do_wrap = 0;
  884.                 n = screen->max_col+1;
  885.             } else
  886.                 n = 1;
  887.         }
  888.         if (len < n)
  889.             n = len;
  890.         next_col = screen->cur_col + n;
  891.         WriteText(screen, ptr, n, flags);
  892.         /*
  893.          * the call to WriteText updates screen->cur_col.
  894.          * If screen->cur_col != next_col, we must have
  895.          * hit the right margin, so set the do_wrap flag.
  896.          */
  897.         screen->do_wrap = (screen->cur_col < next_col);
  898.         len -= n;
  899.         ptr += n;
  900.     }
  901. }
  902.  
  903. /*
  904.  * write a string str of length len onto the screen at
  905.  * the current cursor position.  update cursor position.
  906.  */
  907. WriteText(screen, str, len, flags)
  908. register Screen    *screen;
  909. register char    *str;
  910. register int    len;
  911. unsigned    flags;
  912. {
  913.     register int pix, cx, cy;
  914.     register unsigned fgs = flags;
  915.     Font    fnt;
  916.  
  917.    if(screen->instatus && screen->reversestatus)
  918.     fgs ^= INVERSE;
  919.    if(screen->cur_row - screen->topline <= screen->max_row ||
  920.      screen->instatus) {
  921.     /*
  922.     if(screen->cur_row == screen->cursor_row && screen->cur_col <=
  923.      screen->cursor_col && screen->cursor_col <= screen->cur_col + len - 1)
  924.         screen->cursor_state = OFF;
  925.      */
  926.     if(screen->cursor_state)
  927.         HideCursor();
  928.      fnt = ActiveIcon(screen) ? screen->fnt_icon
  929.           : (fgs & BOLD) ? screen->fnt_bold : screen->fnt_norm;
  930.     if (fgs & INSERT)
  931.         InsertChar(screen, len);
  932.       if (!(AddToRefresh(screen))) {
  933.         if(screen->scroll_amt)
  934.             FlushScroll(screen);
  935.     cx = CursorX(screen, screen->cur_col);
  936.     cy = CursorY(screen, screen->cur_row);
  937.     if (screen->show || ActiveIcon(screen)) {
  938.         if (fgs & INVERSE)
  939.         XText(VWindow(screen), cx, cy, str, len, fnt,
  940.          pix = screen->background, screen->foreground);
  941.         else
  942.          XText(VWindow(screen), cx, cy, str, len, fnt,
  943.          pix = screen->foreground, screen->background);
  944.         if((fgs & BOLD) && screen->enbolden)
  945.         XTextMask(VWindow(screen), cx + 1, cy, str, len, fnt, pix);
  946.         if(fgs & UNDERLINE) {
  947.         cy += FontHeight(screen) - 2;
  948.         XLine(VWindow(screen), cx, cy, cx + len * FontWidth(screen),
  949.          cy, 1, 1, pix, GXcopy, AllPlanes);
  950.         }
  951.     }
  952.     /*
  953.      * the following statements compile data to compute the average 
  954.      * number of characters written on each call to XText.  The data
  955.      * may be examined via the use of a "hidden" escape sequence.
  956.      */
  957.     ctotal += len;
  958.     ++ntotal;
  959.       }
  960.     }
  961.     ScreenWrite(screen, str, flags, len);
  962.     CursorForward(screen, len);
  963. }
  964.  
  965. /*
  966.  * process ANSI modes set, reset
  967.  */
  968. modes(term, func)
  969. Terminal    *term;
  970. int        (*func)();
  971. {
  972.     register Screen    *screen    = &term->screen;
  973.     register int    i;
  974.  
  975.     for (i=0; i<nparam; ++i) {
  976.         switch (param[i]) {
  977.         case 4:            /* IRM                */
  978.             (*func)(&term->flags, INSERT);
  979.             break;
  980.  
  981.         case 20:        /* LNM                */
  982.             (*func)(&term->flags, LINEFEED);
  983.             break;
  984.         }
  985.     }
  986. }
  987.  
  988. /*
  989.  * process DEC private modes set, reset
  990.  */
  991. dpmodes(term, func)
  992. Terminal    *term;
  993. int        (*func)();
  994. {
  995.     register Screen    *screen    = &term->screen;
  996.     register int    i, j;
  997.     extern int bitset();
  998.  
  999.     for (i=0; i<nparam; ++i) {
  1000.         switch (param[i]) {
  1001.         case 1:            /* DECCKM            */
  1002.             (*func)(&term->keyboard.flags, CURSOR_APL);
  1003.             break;
  1004.         case 3:            /* DECCOLM            */
  1005.             if(screen->c132) {
  1006.                 ClearScreen(screen);
  1007.                 CursorSet(screen, 0, 0, term->flags);
  1008.                 if((j = func == bitset ? 132 : 80) !=
  1009.                  ((term->flags & IN132COLUMNS) ? 132 : 80) ||
  1010.                  j != screen->max_col + 1) {
  1011.                     XChangeWindow (VWindow(screen),
  1012.                      FontWidth(screen) * j + 2*screen->border
  1013.                      + screen->scrollbar,
  1014.                      FontHeight(screen) * (screen->max_row
  1015.                      + 1) + screen->statusheight +
  1016.                      Titlebar(screen) + 2 * screen->border);
  1017.                     XSync(FALSE);    /* synchronize */
  1018.                     if(QLength() > 0)
  1019.                         xevents();
  1020.                 }
  1021.                 (*func)(&term->flags, IN132COLUMNS);
  1022.             }
  1023.             break;
  1024.         case 4:            /* DECSCLM (slow scroll)    */
  1025.             if (func == bitset) {
  1026.                 screen->jumpscroll = 0;
  1027.                 if (screen->scroll_amt)
  1028.                     FlushScroll(screen);
  1029.             } else
  1030.                 screen->jumpscroll = 1;
  1031.             (*func)(&term->flags, SMOOTHSCROLL);
  1032.             break;
  1033.         case 5:            /* DECSCNM            */
  1034.             j = term->flags;
  1035.             (*func)(&term->flags, REVERSE_VIDEO);
  1036.             if ((term->flags ^ j) & REVERSE_VIDEO)
  1037.                 ReverseVideo(term);
  1038.             break;
  1039.  
  1040.         case 6:            /* DECOM            */
  1041.             (*func)(&term->flags, ORIGIN);
  1042.             CursorSet(screen, 0, 0, term->flags);
  1043.             break;
  1044.  
  1045.         case 7:            /* DECAWM            */
  1046.             (*func)(&term->flags, WRAPAROUND);
  1047.             break;
  1048.         case 8:            /* DECARM            */
  1049.             j = term->flags;
  1050.             (*func)(&term->flags, AUTOREPEAT);
  1051.             if ((term->flags ^ j) & AUTOREPEAT)
  1052.                 if(term->flags & AUTOREPEAT)
  1053.                     XAutoRepeatOn();
  1054.                 else
  1055.                     XAutoRepeatOff();
  1056.             break;
  1057.         case 9:            /* MIT bogus sequence        */
  1058.             (*func)(&screen->send_mouse_pos, 1);
  1059.             break;
  1060.         case 38:        /* DECTEK            */
  1061.             if(func == bitset & !(screen->inhibit & I_TEK)) {
  1062.                 if(screen->logging) {
  1063.                     FlushLog(screen);
  1064.                     screen->logstart = Tbuffer;
  1065.                 }
  1066.                 screen->TekEmu = TRUE;
  1067.             }
  1068.             break;
  1069.         case 40:        /* 132 column mode        */
  1070.             (*func)(&screen->c132, 1);
  1071.             break;
  1072.         case 41:        /* curses hack            */
  1073.             (*func)(&screen->curses, 1);
  1074.             break;
  1075.         case 42:        /* scrollbar            */
  1076.             if(func == bitset)
  1077.                 ScrollBarOn(screen, TRUE, FALSE);
  1078.             else
  1079.                 ScrollBarOff(screen);
  1080.             break;
  1081.         case 43:        /* lines off top        */
  1082.             if(screen->sb)
  1083.                 SetSaveState(screen->sb, (func == bitset));
  1084.             break;
  1085.         case 44:        /* margin bell            */
  1086.             (*func)(&screen->marginbell, 1);
  1087.             if(!screen->marginbell)
  1088.                 screen->bellarmed = -1;
  1089.             break;
  1090.         case 45:        /* reverse wraparound    */
  1091.             (*func)(&term->flags, REVERSEWRAP);
  1092.             break;
  1093.         case 46:        /* logging        */
  1094.             if(func == bitset)
  1095.                 StartLog(screen);
  1096.             else
  1097.                 CloseLog(screen);
  1098.             break;
  1099.         case 47:        /* alternate buffer        */
  1100.             if(func == bitset)
  1101.                 ToAlternate(screen);
  1102.             else
  1103.                 FromAlternate(screen);
  1104.             break;
  1105.         case 48:        /* reverse status line    */
  1106.             j = screen->reversestatus;
  1107.             (*func)(&screen->reversestatus, 1);
  1108.             if(j != screen->reversestatus)
  1109.                 ScrnRefresh(screen, screen->max_row + 1, 0, 1,
  1110.                  screen->max_col + 1);
  1111.             break;
  1112.         case 49:        /* page mode        */
  1113.             j = screen->pagemode;
  1114.             (*func)(&screen->pagemode, 1);
  1115.             if(!j && screen->pagemode)
  1116.                 screen->pagecnt = 0;
  1117.             break;
  1118.         }
  1119.     }
  1120. }
  1121.  
  1122. /*
  1123.  * process xterm private modes save
  1124.  */
  1125. savemodes(term)
  1126. Terminal *term;
  1127. {
  1128.     register Screen    *screen    = &term->screen;
  1129.     register int i;
  1130.  
  1131.     for (i = 0; i < nparam; i++) {
  1132.         switch (param[i]) {
  1133.         case 1:            /* DECCKM            */
  1134.             screen->save_modes[0] = term->keyboard.flags &
  1135.              CURSOR_APL;
  1136.             break;
  1137.         case 3:            /* DECCOLM            */
  1138.             if(screen->c132)
  1139.                 screen->save_modes[1] = term->flags &
  1140.                  IN132COLUMNS;
  1141.             break;
  1142.         case 4:            /* DECSCLM (slow scroll)    */
  1143.             screen->save_modes[2] = term->flags & SMOOTHSCROLL;
  1144.             break;
  1145.         case 5:            /* DECSCNM            */
  1146.             screen->save_modes[3] = term->flags & REVERSE_VIDEO;
  1147.             break;
  1148.         case 6:            /* DECOM            */
  1149.             screen->save_modes[4] = term->flags & ORIGIN;
  1150.             break;
  1151.  
  1152.         case 7:            /* DECAWM            */
  1153.             screen->save_modes[5] = term->flags & WRAPAROUND;
  1154.             break;
  1155.         case 8:            /* DECARM            */
  1156.             screen->save_modes[6] = term->flags & AUTOREPEAT;
  1157.             break;
  1158.         case 9:            /* MIT bogus sequence        */
  1159.             screen->save_modes[7] = screen->send_mouse_pos;
  1160.             break;
  1161.         case 40:        /* 132 column mode        */
  1162.             screen->save_modes[8] = screen->c132;
  1163.             break;
  1164.         case 41:        /* curses hack            */
  1165.             screen->save_modes[9] = screen->curses;
  1166.             break;
  1167.         case 42:        /* scrollbar            */
  1168.             screen->save_modes[10] = screen->scrollbar;
  1169.             break;
  1170.         case 43:        /* lines off top        */
  1171.             if(screen->sb)
  1172.                 screen->save_modes[11] =
  1173.                  GetSaveState(screen->sb);
  1174.             break;
  1175.         case 44:        /* margin bell            */
  1176.             screen->save_modes[12] = screen->marginbell;
  1177.             break;
  1178.         case 45:        /* reverse wraparound    */
  1179.             screen->save_modes[13] = term->flags & REVERSEWRAP;
  1180.             break;
  1181.         case 46:        /* logging        */
  1182.             screen->save_modes[14] = screen->logging;
  1183.             break;
  1184.         case 47:        /* alternate buffer        */
  1185.             screen->save_modes[15] = screen->alternate;
  1186.             break;
  1187.         case 48:        /* reverse status line        */
  1188.             screen->save_modes[16] = screen->reversestatus;
  1189.             break;
  1190.         case 49:        /* page mode            */
  1191.             screen->save_modes[17] = screen->pagemode;
  1192.             screen->save_modes[18] = screen->pagecnt;
  1193.             break;
  1194.         }
  1195.     }
  1196. }
  1197.  
  1198. /*
  1199.  * process xterm private modes restore
  1200.  */
  1201. restoremodes(term)
  1202. Terminal *term;
  1203. {
  1204.     register Screen    *screen    = &term->screen;
  1205.     register int i, j;
  1206.  
  1207.     for (i = 0; i < nparam; i++) {
  1208.         switch (param[i]) {
  1209.         case 1:            /* DECCKM            */
  1210.             term->keyboard.flags &= ~CURSOR_APL;
  1211.             term->keyboard.flags |= screen->save_modes[0] &
  1212.              CURSOR_APL;
  1213.             break;
  1214.         case 3:            /* DECCOLM            */
  1215.             if(screen->c132) {
  1216.                 ClearScreen(screen);
  1217.                 CursorSet(screen, 0, 0, term->flags);
  1218.                 if((j = (screen->save_modes[1] & IN132COLUMNS)
  1219.                  ? 132 : 80) != ((term->flags & IN132COLUMNS)
  1220.                  ? 132 : 80) || j != screen->max_col + 1) {
  1221.                     XChangeWindow (VWindow(screen),
  1222.                      FontWidth(screen) * j + 2*screen->border
  1223.                      + screen->scrollbar,
  1224.                      FontHeight(screen) * (screen->max_row
  1225.                      + 1) + screen->statusheight +
  1226.                      Titlebar(screen) + 2 * screen->border);
  1227.                     XSync(FALSE);    /* synchronize */
  1228.                     if(QLength() > 0)
  1229.                         xevents();
  1230.                 }
  1231.                 term->flags &= ~IN132COLUMNS;
  1232.                 term->flags |= screen->save_modes[1] &
  1233.                  IN132COLUMNS;
  1234.             }
  1235.             break;
  1236.         case 4:            /* DECSCLM (slow scroll)    */
  1237.             if (screen->save_modes[2] & SMOOTHSCROLL) {
  1238.                 screen->jumpscroll = 0;
  1239.                 if (screen->scroll_amt)
  1240.                     FlushScroll(screen);
  1241.             } else
  1242.                 screen->jumpscroll = 1;
  1243.             term->flags &= ~SMOOTHSCROLL;
  1244.             term->flags |= screen->save_modes[2] & SMOOTHSCROLL;
  1245.             break;
  1246.         case 5:            /* DECSCNM            */
  1247.             if((screen->save_modes[3] ^ term->flags) &
  1248.              REVERSE_VIDEO) {
  1249.                 term->flags &= ~REVERSE_VIDEO;
  1250.                 term->flags |= screen->save_modes[3] &
  1251.                  REVERSE_VIDEO;
  1252.                 ReverseVideo(term);
  1253.             }
  1254.             break;
  1255.         case 6:            /* DECOM            */
  1256.             term->flags &= ~ORIGIN;
  1257.             term->flags |= screen->save_modes[4] & ORIGIN;
  1258.             CursorSet(screen, 0, 0, term->flags);
  1259.             break;
  1260.  
  1261.         case 7:            /* DECAWM            */
  1262.             term->flags &= ~WRAPAROUND;
  1263.             term->flags |= screen->save_modes[5] & WRAPAROUND;
  1264.             break;
  1265.         case 8:            /* DECARM            */
  1266.             if((screen->save_modes[6] ^ term->flags) & AUTOREPEAT) {
  1267.                 term->flags &= ~REVERSE_VIDEO;
  1268.                 term->flags |= screen->save_modes[6] &
  1269.                  REVERSE_VIDEO;
  1270.                 if(term->flags & AUTOREPEAT)
  1271.                     XAutoRepeatOn();
  1272.                 else
  1273.                     XAutoRepeatOff();
  1274.             }
  1275.             break;
  1276.         case 9:            /* MIT bogus sequence        */
  1277.             screen->send_mouse_pos = screen->save_modes[7];
  1278.             break;
  1279.         case 40:        /* 132 column mode        */
  1280.             screen->c132 = screen->save_modes[8];
  1281.             break;
  1282.         case 41:        /* curses hack            */
  1283.             screen->curses = screen->save_modes[9];
  1284.             break;
  1285.         case 42:        /* scrollbar            */
  1286.             if(screen->save_modes[10])
  1287.                 ScrollBarOn(screen, TRUE, FALSE);
  1288.             else
  1289.                 ScrollBarOff(screen);
  1290.             break;
  1291.         case 43:        /* lines off top        */
  1292.             if(screen->sb)
  1293.                 SetSaveState(screen->sb,screen->save_modes[11]);
  1294.             break;
  1295.         case 44:        /* margin bell            */
  1296.             if(!(screen->marginbell = screen->save_modes[12]))
  1297.                 screen->bellarmed = -1;
  1298.             break;
  1299.         case 45:        /* reverse wraparound    */
  1300.             term->flags &= ~REVERSEWRAP;
  1301.             term->flags |= screen->save_modes[13] & REVERSEWRAP;
  1302.             break;
  1303.         case 46:        /* logging        */
  1304.             if(screen->save_modes[14])
  1305.                 StartLog(screen);
  1306.             else
  1307.                 CloseLog(screen);
  1308.             break;
  1309.         case 47:        /* alternate buffer        */
  1310.             if(screen->save_modes[15])
  1311.                 ToAlternate(screen);
  1312.             else
  1313.                 FromAlternate(screen);
  1314.             break;
  1315.         case 48:        /* reverse status line        */
  1316.             if(screen->save_modes[16] != screen->reversestatus) {
  1317.                 screen->reversestatus = 
  1318.                  screen->save_modes[16];
  1319.                 ScrnRefresh(screen, screen->max_row + 1, 0, 1,
  1320.                  screen->max_col + 1);
  1321.             }
  1322.             break;
  1323.         case 49:        /* page mode            */
  1324.             screen->pagemode = screen->save_modes[17];
  1325.             screen->pagecnt = screen->save_modes[18];
  1326.             break;
  1327.         }
  1328.     }
  1329. }
  1330.  
  1331. /*
  1332.  * set a bit in a word given a pointer to the word and a mask.
  1333.  */
  1334. bitset(p, mask)
  1335. int    *p;
  1336. {
  1337.     *p |= mask;
  1338. }
  1339.  
  1340. /*
  1341.  * clear a bit in a word given a pointer to the word and a mask.
  1342.  */
  1343. bitclr(p, mask)
  1344. int    *p;
  1345. {
  1346.     *p &= ~mask;
  1347. }
  1348.  
  1349. unparseseq(ap, fd)
  1350. register ANSI    *ap;
  1351. {
  1352.     register int    c;
  1353.     register int    i;
  1354.     register int    inters;
  1355.  
  1356.     c = ap->a_type;
  1357.     if (c>=0x80 && c<=0x9F) {
  1358.         unparseputc(ESC, fd);
  1359.         c -= 0x40;
  1360.     }
  1361.     unparseputc(c, fd);
  1362.     c = ap->a_type;
  1363.     if (c==ESC || c==DCS || c==CSI || c==OSC || c==PM || c==APC) {
  1364.         if (ap->a_pintro != 0)
  1365.             unparseputc(ap->a_pintro, fd);
  1366.         for (i=0; i<ap->a_nparam; ++i) {
  1367.             if (i != 0)
  1368.                 unparseputc(';', fd);
  1369.             unparseputn(ap->a_param[i], fd);
  1370.         }
  1371.         inters = ap->a_inters;
  1372.         for (i=3; i>=0; --i)
  1373.             c = (inters >> (8*i)) & 0xff;
  1374.             if (c != 0)
  1375.                 unparseputc(c, fd);
  1376.         unparseputc(ap->a_final, fd);
  1377.     }
  1378. }
  1379.  
  1380. unparseputn(n, fd)
  1381. unsigned int    n;
  1382. {
  1383.     unsigned int    q;
  1384.  
  1385.     q = n/10;
  1386.     if (q != 0)
  1387.         unparseputn(q, fd);
  1388.     unparseputc((n%10) + '0', fd);
  1389. }
  1390.  
  1391. unparseputc(c, fd)
  1392. {
  1393.     char    buf[2];
  1394.     register i = 1;
  1395.     extern Terminal term;
  1396.  
  1397.     if((buf[0] = c) == '\r' && (term.flags & LINEFEED)) {
  1398.         buf[1] = '\n';
  1399.         i++;
  1400.     }
  1401.     if (write(fd, buf, i) != i)
  1402.         Panic("unparseputc: error writing character\n", 0);
  1403. }
  1404.  
  1405. static int alt_pagecnt;
  1406. static int alt_pagemode;
  1407. static int alt_saving;
  1408.  
  1409. ToAlternate(screen)
  1410. register Screen *screen;
  1411. {
  1412.     extern ScrnBuf Allocate();
  1413.  
  1414.     if(screen->alternate)
  1415.         return;
  1416.     if(!screen->altbuf)
  1417.         screen->altbuf = Allocate(screen->max_row + 1, screen->max_col
  1418.          + 1);
  1419.     if(screen->sb) {
  1420.         alt_saving = GetSaveState(screen->sb);
  1421.         SetSaveState(screen->sb, FALSE);
  1422.     } else
  1423.         alt_saving = TRUE;
  1424.     if(alt_pagemode = screen->pagemode)
  1425.         alt_pagecnt = screen->pagecnt;
  1426.     screen->pagemode = FALSE;
  1427.     SwitchBufs(screen);
  1428.     screen->alternate = TRUE;
  1429. }
  1430.  
  1431. FromAlternate(screen)
  1432. register Screen *screen;
  1433. {
  1434.     if(!screen->alternate)
  1435.         return;
  1436.     screen->alternate = FALSE;
  1437.     if(screen->sb)
  1438.         SetSaveState(screen->sb, alt_saving);
  1439.     if(screen->pagemode = alt_pagemode)
  1440.         screen->pagecnt = alt_pagecnt;
  1441.     SwitchBufs(screen);
  1442. }
  1443.  
  1444. SwitchBufs(screen)
  1445. register Screen *screen;
  1446. {
  1447.     register int rows, top;
  1448.     char *save [2 * MAX_ROWS];
  1449.  
  1450.     if(screen->cursor_state)
  1451.         HideCursor();
  1452.     rows = screen->max_row + 1;
  1453.     bcopy((char *)screen->buf, (char *)save, 2 * sizeof(char *) * rows);
  1454.     bcopy((char *)screen->altbuf, (char *)screen->buf, 2 * sizeof(char *) *
  1455.      rows);
  1456.     bcopy((char *)save, (char *)screen->altbuf, 2 * sizeof(char *) * rows);
  1457.  
  1458.     if((top = -screen->topline) <= screen->max_row) {
  1459.         if(screen->scroll_amt)
  1460.             FlushScroll(screen);
  1461.         if(top == 0 && !screen->statusline)
  1462.             XClear(VWindow(screen));
  1463.         else
  1464.             XTileSet(VWindow(screen), screen->border, top *
  1465.              FontHeight(screen) + screen->border + Titlebar(screen),
  1466.              Width(screen), (screen->max_row - top + 1) *
  1467.              FontHeight(screen), screen->bgndtile);
  1468.     }
  1469.     ScrnRefresh(screen, 0, 0, rows, screen->max_col + 1);
  1470. }
  1471.  
  1472. VTRun()
  1473. {
  1474.     register Screen *screen = &term.screen;
  1475.     register int i;
  1476.     
  1477.     if(!VWindow(screen) && !VTInit()) {
  1478.         if(TWindow(screen)) {
  1479.             screen->TekEmu = TRUE;
  1480.             return;
  1481.         }
  1482.         Exit(ERROR_VINIT);
  1483.     }
  1484.     screen->cursor_state = OFF;
  1485.     screen->cursor_set = ON;
  1486.     if(screen->icon_show) {
  1487.         if(screen->icon_show < 0) {
  1488.             screen->icon_show = TRUE;
  1489.             screen->mappedVwin = &screen->iconVwin;
  1490.             XMapWindow(screen->iconVwin.window);
  1491.         }
  1492.     } else if(!screen->show) {
  1493.         screen->show = TRUE;
  1494.         screen->mappedVwin = &screen->fullVwin;
  1495.         XMapWindow(VWindow(screen));
  1496.     } else
  1497.         XRaiseWindow(VWindow(screen));
  1498.     if(screen->select)
  1499.         VTSelect();
  1500.     if (L_flag > 0) {
  1501.         XWarpMouse (VWindow(screen),
  1502.                 FullWidth(screen) >> 1, FullHeight(screen) >>1);
  1503.         L_flag = -1;
  1504.     }
  1505.     bcnt = 0;
  1506.     bptr = buffer;
  1507.     while(Tpushb > Tpushback) {
  1508.         *bptr++ = *--Tpushb;
  1509.         bcnt++;
  1510.     }
  1511.     bcnt += (i = Tbcnt);
  1512.     for( ; i > 0 ; i--)
  1513.         *bptr++ = *Tbptr++;
  1514.     bptr = buffer;
  1515.     if(!setjmp(VTend))
  1516.         VTparse();
  1517.     HideCursor();
  1518.     screen->cursor_set = OFF;
  1519.     VTUnselect();
  1520. }
  1521.  
  1522. VTInit()
  1523. {
  1524.     int width, height;
  1525.     FontInfo *fInfo, *ifInfo;
  1526.     register Screen *screen = &term.screen;
  1527.     register Vertex *vp;
  1528.     register int i, j;
  1529.     char *def = "=80x24+1+1";
  1530.     char iconname[128];
  1531.     static short failed;
  1532.     Color cdef;
  1533.     OpaqueFrame twindow;
  1534.     WindowInfo wininfo;
  1535.     int x, y;
  1536.     Window win;
  1537.     extern char *malloc();
  1538.  
  1539.     if(failed)
  1540.         return(FALSE);
  1541.     
  1542.     screen->mappedVwin = &screen->fullVwin;
  1543.  
  1544.     TabReset (term.tabs);
  1545.  
  1546.     screen->fnt_norm = screen->fnt_bold = screen->fnt_icon = NULL;
  1547.        
  1548.     if ((fInfo = XOpenFont(f_n)) == NULL) {
  1549.         fprintf(stderr, "%s: Could not open font %s!\n",
  1550.             xterm_name, f_n);
  1551.         failed = TRUE;
  1552.         return(FALSE);
  1553.     }
  1554.     screen->fnt_norm = fInfo->id;
  1555.     if (!f_b || !(screen->fnt_bold = XGetFont(f_b))) {
  1556.         screen->fnt_bold = screen->fnt_norm;
  1557.         screen->enbolden = TRUE;
  1558.     }
  1559.     screen->fullVwin.f_width = fInfo->width;
  1560.     screen->fullVwin.f_height = fInfo->height;
  1561.     
  1562.     if (screen->active_icon) {
  1563.         if (!screen->fnt_icon) {
  1564.         if ((ifInfo = XOpenFont(f_i)) == NULL) {
  1565.             fprintf( stderr, "%s: Could not open font %s!\n",
  1566.                  xterm_name, f_i);
  1567.             failed = TRUE;
  1568.             return( FALSE );
  1569.         }
  1570.         screen->fnt_icon = ifInfo->id;
  1571.         } else
  1572.             XQueryFont( screen->fnt_icon, &ifInfo );
  1573.  
  1574.         screen->iconVwin.f_width = ifInfo->width;
  1575.         screen->iconVwin.f_height = ifInfo->height;
  1576.     }
  1577.  
  1578.     screen->curs = make_xterm(screen->mousecolor, screen->background,
  1579.      GXcopy);
  1580.  
  1581.     twindow.bdrwidth = screen->borderwidth;
  1582.     twindow.border = screen->graybordertile;
  1583.     twindow.background = screen->bgndtile;
  1584.     if((screen->minrows = (MINSCROLLBARHEIGHT - 2 * screen->border +
  1585.      fInfo->height - 1) / fInfo->height) < 0)
  1586.         screen->minrows = 0;
  1587.  
  1588.     i = 2 * screen->border + screen->scrollbar;
  1589.     j = 2 * screen->border + Titlebar(screen);
  1590.     if(screen->statusline)
  1591.         j += (screen->statusheight = fInfo->height + 2);
  1592.  
  1593.     if((screen->fullVwin.window = XCreateTerm ("Terminal Emulator", xterm_name,
  1594.      geo_metry, def, &twindow, 12, screen->minrows, i, j, &width, &height,
  1595.      fInfo, fInfo->width, fInfo->height)) == NULL) {
  1596.         fprintf(stderr, "%s: Can't create VT window\n");
  1597.         XCloseFont(fInfo);
  1598.         return(FALSE);
  1599.     }
  1600.     XSelectInput(VWindow(screen), WINDOWEVENTS);
  1601.     /*
  1602.      * XCreateTerm flushes all events, which might include an EnterWindow
  1603.      * or LeaveWindow.  So if the cursor is not where it is supposed to
  1604.      * be, we set select to the appropriate thing.
  1605.      */
  1606.     if(TWindow(screen) && XQueryMouse(RootWindow, &x, &y, &win)) {
  1607.         if(screen->timer) {
  1608.             Timer(0L);
  1609.             screen->timer = 0;
  1610.         }
  1611.         if(win == TWindow(screen))
  1612.             screen->select |= INWINDOW;
  1613.         else
  1614.             screen->select &= ~INWINDOW;
  1615.     }
  1616.  
  1617.     screen->fullVwin.fullwidth = twindow.width;
  1618.     screen->fullVwin.fullheight = twindow.height;
  1619.     screen->fullVwin.width = twindow.width - i;
  1620.     screen->fullVwin.height = twindow.height - j;
  1621.  
  1622.     /* Reset variables used by ANSI emulation. */
  1623.  
  1624.     screen->gsets[0] = 'B';            /* ASCII_G        */
  1625.     screen->gsets[1] = 'B';
  1626.     screen->gsets[2] = 'B';            /* DEC supplemental.    */
  1627.     screen->gsets[3] = 'B';
  1628.     screen->curgl = 0;            /* G0 => GL.        */
  1629.     screen->curgr = 2;            /* G2 => GR.        */
  1630.     screen->curss = 0;            /* No single shift.    */
  1631.  
  1632.     if(screen->iconTwin.window) {
  1633.         XQueryWindow(screen->iconTwin.window, &wininfo);
  1634.         x = wininfo.x;
  1635.         y = wininfo.y;
  1636.     } else {
  1637.         x = twindow.x + (twindow.width - screen->iconVwin.width) / 2;
  1638.         y = twindow.y + (twindow.height - screen->iconVwin.height) / 2;
  1639.         IconGeometry(screen, &x, &y);
  1640.     }
  1641.     screen->iconVwin.window =
  1642.         XCreateWindow( RootWindow, x, y, 1, 1, screen->borderwidth,
  1643.                    screen->bordertile, screen->bgndtile );
  1644.  
  1645.     XSetIconWindow( screen->fullVwin.window, screen->iconVwin.window );
  1646.  
  1647.     XDefineCursor( screen->iconVwin.window, screen->arrow );
  1648.     XSelectInput( screen->iconVwin.window,
  1649.               screen->active_icon && (term.flags & ICONINPUT)
  1650.             ? ICONWINDOWEVENTS | ICONINPUTEVENTS
  1651.                 : ICONWINDOWEVENTS );
  1652.  
  1653.     XDefineCursor( VWindow(screen), screen->curs );
  1654.     XStoreName (VWindow(screen), screen->winname);
  1655.     strcpy(iconname, screen->winname);
  1656.     strcat(iconname, " (icon)");
  1657.     XStoreName (screen->iconVwin.window, iconname);
  1658.     XSetResizeHint (VWindow(screen), 2 * screen->border + screen->scrollbar,
  1659.      2 * screen->border + Titlebar(screen) + screen->statusheight,
  1660.      fInfo->width, fInfo->height);
  1661.  
  1662.     screen->cur_col = screen->cur_row = 0;
  1663.     screen->max_col = Width(screen)  / fInfo->width - 1;
  1664.     screen->top_marg = 0;
  1665.     screen->bot_marg = screen->max_row = Height(screen) / fInfo->height - 1;
  1666.  
  1667.     screen->sc.row = screen->sc.col = screen->sc.flags = NULL;
  1668.  
  1669.     SetIconSize( screen );        /* requires max_col, max_row */
  1670.  
  1671.     /* allocate memory for screen buffer (including one for status line */
  1672.     screen->buf = screen->allbuf = (ScrnBuf) Allocate (screen->max_row + 2,
  1673.                       screen->max_col +1);
  1674.  
  1675.     screen->do_wrap = NULL;
  1676.     screen->scrolls = screen->incopy = 0;
  1677.     free((char *)fInfo);
  1678.     vp = &VTbox[1];
  1679.     (vp++)->x = FontWidth(screen) - 1;
  1680.     (vp++)->y = FontHeight(screen) - 1;
  1681.     (vp++)->x = -(FontWidth(screen) - 1);
  1682.     vp->y = -(FontHeight(screen) - 1);
  1683.     screen->box = VTbox;
  1684.     status_box[0].x = screen->border - 1;
  1685.     screen->savelines = save_lines;
  1686.     if(screen->scrollbar) {
  1687.         screen->scrollbar = 0;
  1688.         ScrollBarOn(screen, TRUE, TRUE);
  1689.         screen->sb->action = NONE;
  1690.     }
  1691.     screen->nmarginbell = n_marginbell;
  1692.     if(Titlebar(screen))
  1693.         VTTitleShow(TRUE);
  1694.     return(TRUE);
  1695. }
  1696.  
  1697. VTExpose(rep)
  1698. register XExposeWindowEvent *rep;
  1699. {
  1700.     register Screen *screen = &term.screen;
  1701.  
  1702.     if (rep && ScreenResize (screen, rep->width, rep->height, &term.flags)
  1703.      == -1)
  1704.         return;
  1705.     XClear (VWindow(screen));
  1706.     ScrnRefresh(screen, 0, 0, screen->max_row + 1 + screen->statusline,
  1707.      screen->max_col + 1);
  1708. }
  1709.  
  1710. /*
  1711.  * Shows cursor at new cursor position in screen.
  1712.  */
  1713. ShowCursor()
  1714. {
  1715.     register Screen *screen = &term.screen;
  1716.     register int fg;
  1717.     register int bg;
  1718.     register int x, y, flags;
  1719.     register Font fnt;
  1720.     char c;
  1721.  
  1722.     if (screen->icon_show && !screen->active_icon) return;
  1723.  
  1724.     if(!screen->instatus && screen->cur_row - screen->topline >
  1725.      screen->max_row)
  1726.         return;
  1727.     c = screen->buf[y = 2 * (screen->cursor_row = screen->cur_row)]
  1728.      [x = screen->cursor_col = screen->cur_col];
  1729.     flags = screen->buf[y + 1][x];
  1730.     if (c == 0)
  1731.         c = ' ';
  1732.     if(screen->instatus)
  1733.         flags ^= INVERSE;
  1734.     if(screen->select) {
  1735.         if(flags & INVERSE) {
  1736.             if(screen->cursorcolor != screen->foreground) {
  1737.                 fg = screen->foreground;
  1738.                 bg = screen->cursorcolor;
  1739.             } else {
  1740.                 fg = screen->foreground;
  1741.                 bg = screen->background;
  1742.             }
  1743.         } else {
  1744.             fg = screen->background;
  1745.             bg = screen->cursorcolor;
  1746.         }
  1747.     } else {
  1748.         if(flags & INVERSE) {
  1749.             fg = screen->background;
  1750.             bg = screen->foreground;
  1751.         } else {
  1752.             fg = screen->foreground;
  1753.             bg = screen->background;
  1754.         }
  1755.     }
  1756.     fnt = ActiveIcon(screen) ? screen->fnt_icon
  1757.           : (flags & BOLD) ? screen->fnt_bold : screen->fnt_norm;
  1758.     XText(VWindow(screen), x = CursorX (screen, screen->cur_col),
  1759.      y = CursorY(screen, screen->cur_row), &c, 1, fnt, fg, bg);
  1760.     if((flags & BOLD) && screen->enbolden)
  1761.         XTextMask(VWindow(screen), x + 1, y, &c, 1, fnt, fg);
  1762.     if(flags & UNDERLINE) {
  1763.         bg = y + FontHeight(screen) - 2;
  1764.         XLine(VWindow(screen), x, bg, x + FontWidth(screen), bg,
  1765.          1, 1, fg, GXcopy, AllPlanes);
  1766.     }
  1767.     if(!screen->select && !ActiveIcon(screen)) {
  1768.         screen->box->x = x;
  1769.         screen->box->y = y;
  1770.         XDraw(VWindow(screen), screen->box, NBOX, 1, 1, fg, GXcopy,
  1771.          AllPlanes);
  1772.     }
  1773.     screen->cursor_state = ON;
  1774. }
  1775.  
  1776. /*
  1777.  * hide cursor at previous cursor position in screen.
  1778.  */
  1779. HideCursor()
  1780. {
  1781.     register Screen *screen = &term.screen;
  1782.     register int fg;
  1783.     register int bg;
  1784.     register int x, y, flags, instatus;
  1785.     register Font fnt;
  1786.     char c;
  1787.  
  1788.     if (screen->icon_show && !screen->active_icon) return;
  1789.  
  1790.     if(!(instatus = screen->cursor_row > screen->max_row) &&
  1791.      screen->cursor_row - screen->topline > screen->max_row)
  1792.         return;
  1793.     c = screen->buf[y = 2 * screen->cursor_row][x = screen->cursor_col];
  1794.     flags = screen->buf[y + 1][x];
  1795.     if(instatus)
  1796.         flags ^= INVERSE;
  1797.     if(flags & INVERSE) {
  1798.         fg = screen->background;
  1799.         bg = screen->foreground;
  1800.     } else {
  1801.         fg = screen->foreground;
  1802.         bg = screen->background;
  1803.     }
  1804.     if (c == 0)
  1805.         c = ' ';
  1806.     y = (instatus ? (screen->cursor_row * FontHeight(screen) + 1) :
  1807.      ((screen->cursor_row - screen->topline) * FontHeight(screen))) +
  1808.      Titlebar(screen) + screen->border;
  1809.     fnt = ActiveIcon(screen) ? screen->fnt_icon
  1810.           : (flags & BOLD) ? screen->fnt_bold : screen->fnt_norm;
  1811.     XText(VWindow(screen), x = CursorX (screen, screen->cursor_col),
  1812.      y, &c, 1, fnt, fg, bg);
  1813.     if((flags & BOLD) && screen->enbolden)
  1814.         XTextMask(VWindow(screen), x + 1, y, &c, 1, fnt, fg);
  1815.     if(flags & UNDERLINE) {
  1816.         y += FontHeight(screen) - 2;
  1817.         XLine(VWindow(screen), x, y, x + FontWidth(screen), y,
  1818.          1, 1, fg, GXcopy, AllPlanes);
  1819.     }
  1820.     screen->cursor_state = OFF;
  1821. }
  1822.  
  1823. VTSelect()
  1824. {
  1825.     register Screen *screen = &term.screen;
  1826.  
  1827.     if(screen->borderwidth > 0)
  1828.         XChangeBorder(VWindow(screen), screen->bordertile);
  1829.     if(Titlebar(screen))
  1830.         VTTitleHilite();
  1831. }
  1832.  
  1833. VTUnselect()
  1834. {
  1835.     register Screen *screen = &term.screen;
  1836.  
  1837.     if(screen->borderwidth > 0)
  1838.         XChangeBorder(VWindow(screen), screen->graybordertile);
  1839.     if(Titlebar(screen))
  1840.         VTTitleUnhilite();
  1841. }
  1842.  
  1843. VTReset(full)
  1844. int full;
  1845. {
  1846.     register Screen *screen = &term.screen;
  1847.  
  1848.     /* reset scrolling region */
  1849.     screen->top_marg = 0;
  1850.     screen->bot_marg = screen->max_row;
  1851.     term.flags &= ~ORIGIN;
  1852.     if(full) {
  1853.         TabReset (term.tabs);
  1854.         term.keyboard.flags = NULL;
  1855.         screen->gsets[0] = 'B';
  1856.         screen->gsets[1] = 'B';
  1857.         screen->gsets[2] = 'B';
  1858.         screen->gsets[3] = 'B';
  1859.         screen->curgl = 0;
  1860.         screen->curgr = 2;
  1861.         screen->curss = 0;
  1862.         ClearScreen(screen);
  1863.         screen->cursor_state = OFF;
  1864.         if(!(term.flags & AUTOREPEAT))
  1865.             XAutoRepeatOn();
  1866.         if (term.flags & REVERSE_VIDEO)
  1867.             ReverseVideo(&term);
  1868.  
  1869.         term.flags = term.initflags;
  1870.         if(screen->c132 && (term.flags & IN132COLUMNS)) {
  1871.             XChangeWindow (VWindow(screen), 80 * FontWidth(screen) +
  1872.              2 * screen->border + screen->scrollbar,
  1873.              FontHeight(screen) * (screen->max_row + 1) +
  1874.              screen->statusheight + Titlebar(screen) +
  1875.              2 * screen->border);
  1876.             XSync(FALSE);    /* synchronize */
  1877.             if(QLength() > 0)
  1878.                 xevents();
  1879.         }
  1880.         CursorSet(screen, 0, 0, term.flags);
  1881.     }
  1882.     longjmp(vtjmpbuf, 1);    /* force ground state in parser */
  1883. }
  1884.  
  1885. ToStatus(col)
  1886. int col;
  1887. {
  1888.     register Screen *screen = &term.screen;
  1889.  
  1890.     if(col > screen->max_col)
  1891.         col = screen->max_col;
  1892.     if(!screen->instatus) {
  1893.         if(!screen->statusline)
  1894.             ShowStatus();
  1895.         CursorSave(&term, &screen->statussc);
  1896.         screen->instatus = TRUE;
  1897.         screen->cur_row = screen->max_row + 1;
  1898.     }
  1899.     screen->cur_col = col;
  1900. }
  1901.  
  1902. FromStatus()
  1903. {
  1904.     register Screen *screen = &term.screen;
  1905.  
  1906.     if(!screen->instatus)
  1907.         return;
  1908.     screen->instatus = FALSE;
  1909.     CursorRestore(&term, &screen->statussc);
  1910. }
  1911.  
  1912. ShowStatus()
  1913. {
  1914.     register Screen *screen = &term.screen;
  1915.     register int border = 2 * screen->border;
  1916.  
  1917.     if(screen->statusline)
  1918.         return;
  1919.     screen->statusline = 1;
  1920.     screen->statusheight = FontHeight(screen) + 2;
  1921.     XSetResizeHint(VWindow(screen), border + screen->scrollbar, border +
  1922.      Titlebar(screen) + screen->statusheight, FontWidth(screen),
  1923.      FontHeight(screen));
  1924.     XChangeWindow (VWindow(screen), FontWidth(screen) * (screen->max_col + 1)
  1925.      + border + screen->scrollbar, FontHeight(screen) *
  1926.      (screen->max_row + 1) + screen->statusheight + Titlebar(screen) +
  1927.      border);
  1928. }
  1929.  
  1930. HideStatus()
  1931. {
  1932.     register Screen *screen = &term.screen;
  1933.     register int border = 2 * screen->border;
  1934.     register int i, j;
  1935.  
  1936.     if(!screen->statusline)
  1937.         return;
  1938.     if(screen->instatus)
  1939.         FromStatus();
  1940.     screen->statusline = 0;
  1941.     screen->statusheight = 0;
  1942.     bzero(screen->buf[i = 2 * (screen->max_row + 1)], j = screen->max_col +
  1943.      1);
  1944.     bzero(screen->buf[i + 1], j);
  1945.     XSetResizeHint(VWindow(screen), border + screen->scrollbar, border +
  1946.      Titlebar(screen), FontWidth(screen), FontHeight(screen));
  1947.     XChangeWindow (VWindow(screen), FontWidth(screen) * j + border +
  1948.      screen->scrollbar, FontHeight(screen) * (screen->max_row + 1) +
  1949.      border + Titlebar(screen));
  1950. }
  1951.  
  1952. EraseStatus()
  1953. {
  1954.     register Screen *screen = &term.screen;
  1955.     register int i, j, pix;
  1956.  
  1957.     if(!screen->statusline)
  1958.         return;
  1959.     bzero(screen->buf[i = 2 * (screen->max_row + 1)], j = screen->max_col +
  1960.      1);
  1961.     bzero(screen->buf[i + 1], j);
  1962.     XPixSet(VWindow(screen), screen->border - 1, (screen->max_row + 1) *
  1963.      FontHeight(screen) + screen->border + Titlebar(screen), j *
  1964.      FontWidth(screen) + 2, screen->statusheight, screen->reversestatus ?
  1965.      screen->foreground : screen->background);
  1966.     if(!screen->reversestatus)
  1967.         StatusBox(screen);
  1968. }
  1969.  
  1970. StatusBox(screen)
  1971. register Screen *screen;
  1972. {
  1973.     status_box[0].y = (screen->max_row + 1) * FontHeight(screen) +
  1974.      screen->border + Titlebar(screen);
  1975.     status_box[3].x = -(status_box[1].x = (screen->max_col + 1) *
  1976.      FontWidth(screen) + 1);
  1977.     status_box[4].y = -(status_box[2].y = FontHeight(screen) + 1);
  1978.     XDraw(VWindow(screen), status_box, NBOX, 1, 1, screen->foreground,
  1979.      GXcopy, AllPlanes);
  1980. }
  1981.  
  1982. VTTitleShow(init)
  1983. int init;
  1984. {
  1985.     register Screen *screen = &term.screen;
  1986.     register int border = 2 * screen->border;
  1987.  
  1988.     if(!screen->title.tbar)
  1989.         VTTitleInit();
  1990.     if(!init) {
  1991.         XSetResizeHint(VWindow(screen), border + screen->scrollbar,
  1992.          border + Titlebar(screen) + screen->statusheight,
  1993.          FontWidth(screen), FontHeight(screen));
  1994.         XChangeWindow (VWindow(screen), FontWidth(screen) *
  1995.          (screen->max_col + 1) + border + screen->scrollbar,
  1996.          FontHeight(screen) * (screen->max_row + 1) + screen->statusheight
  1997.          + Titlebar(screen) + border);
  1998.     }
  1999.     if(screen->select && !screen->TekEmu)
  2000.         VTTitleHilite();
  2001.     else
  2002.         VTTitleUnhilite();
  2003.     XMapWindow(screen->title.tbar);
  2004. }
  2005.  
  2006. VTTitleHide()
  2007. {
  2008.     register Screen *screen = &term.screen;
  2009.     register int border = 2 * screen->border;
  2010.  
  2011.     XUnmapWindow(screen->title.tbar);
  2012.     XSetResizeHint(VWindow(screen), border + screen->scrollbar, border +
  2013.      screen->statusheight, FontWidth(screen), FontHeight(screen));
  2014.     XChangeWindow (VWindow(screen), FontWidth(screen) * (screen->max_col + 1)
  2015.      + border + screen->scrollbar, FontHeight(screen) *
  2016.      (screen->max_row + 1) + screen->statusheight + border);
  2017. }
  2018.  
  2019. VTTitleHilite()
  2020. {
  2021.     register Screen *screen = &term.screen;
  2022.  
  2023.     if(screen->title.hilited)
  2024.         return;
  2025.     XMapWindow(screen->title.left);
  2026.     XMapWindow(screen->title.right);
  2027.     screen->title.hilited = TRUE;
  2028. }
  2029.  
  2030. VTTitleUnhilite()
  2031. {
  2032.     register Screen *screen = &term.screen;
  2033.  
  2034.     if(!screen->title.hilited)
  2035.         return;
  2036.     XUnmapWindow(screen->title.left);
  2037.     XUnmapWindow(screen->title.right);
  2038.     screen->title.hilited = FALSE;
  2039. }
  2040.  
  2041. VTTitleResize(width)
  2042. register int width;
  2043. {
  2044.     register Screen *screen = &term.screen;
  2045.     register int i, j;
  2046.  
  2047.     if((screen->title.width = i = screen->title.fullwidth) >
  2048.      (j = width - 2 * (MINHILITE + screen->title_n_size + 1)))
  2049.         screen->title.width = (i = j) + screen->title_n_size;
  2050.     j = width - i - 2 * (screen->title_n_size + 1);
  2051.     i = j / 2;
  2052.     j -= i;
  2053.     screen->title.x = i + 1 + screen->title_n_size;
  2054.     XChangeWindow(screen->title.tbar, width, screen->titleheight - 1);
  2055.     XChangeWindow(screen->title.left, i, screen->titlefont->height);
  2056.     XConfigureWindow(screen->title.right, width - j - 1, TITLEPAD, j,
  2057.      screen->titlefont->height);
  2058. }
  2059.  
  2060. VTTitleExpose(rep)
  2061. register XExposeWindowEvent *rep;
  2062. {
  2063.     register Screen *screen = &term.screen;
  2064.  
  2065.     if(rep && (rep->x > (screen->title.x + screen->title.width) ||
  2066.      (rep->x + rep->width) < screen->title.x ||
  2067.      rep->y > (screen->title.y + screen->titlefont->height) ||
  2068.      (rep->y + rep->height) < screen->title.y))
  2069.         return;
  2070.     XText(screen->title.tbar, screen->title.x, screen->title.y,
  2071.      screen->winname, screen->winnamelen, screen->titlefont->id,
  2072.      screen->foreground, screen->background);
  2073. }
  2074.  
  2075. VTTitleInit()
  2076. {
  2077.     register Screen *screen = &term.screen;
  2078.     register int w, i, j;
  2079.     OpaqueFrame hilite[2];
  2080.     extern Pixmap make_hilite();
  2081.  
  2082.     if((screen->title.tbar = XCreateWindow(VWindow(screen), -1, -1,
  2083.      w = FullWidth(screen), screen->titleheight - 1, 1, screen->bordertile,
  2084.      screen->bgndtile)) == NULL)
  2085.         Error(ERROR_CRTITLE);
  2086.     XSelectInput(screen->title.tbar, ButtonPressed | ButtonReleased |
  2087.      ExposeWindow | EnterWindow | LeaveWindow | UnmapWindow);
  2088.     XDefineCursor(screen->title.tbar, screen->arrow);
  2089.     if(!screen->hilitetile && (screen->hilitetile =
  2090.      make_hilite(screen->foreground, screen->background)) == NULL)
  2091.         Error(ERROR_HILITE);
  2092.     screen->title.fullwidth = XQueryWidth(screen->winname,
  2093.      screen->titlefont->id);
  2094.     if((screen->title.width = i = screen->title.fullwidth) >
  2095.      (j = w - 2 * (MINHILITE + screen->title_n_size + 1)))
  2096.         screen->title.width = (i = j) + screen->title_n_size;
  2097.     j = w - i - 2 * (screen->title_n_size + 1);
  2098.     i = j / 2;
  2099.     j -= i;
  2100.     screen->title.x = i + 1 + screen->title_n_size;
  2101.     screen->title.y = TITLEPAD;
  2102.     hilite[0].x = 1;
  2103.     hilite[1].x = w - j - 1;
  2104.     hilite[0].y = hilite[1].y = TITLEPAD;
  2105.     hilite[0].width = i;
  2106.     hilite[1].width = j;
  2107.     hilite[0].height = hilite[1].height = screen->titlefont->height;
  2108.     hilite[0].bdrwidth = hilite[1].bdrwidth = 0;
  2109.     hilite[0].border = hilite[1].border = NULL;
  2110.     hilite[0].background = hilite[1].background = screen->hilitetile;
  2111.     if(XCreateWindows(screen->title.tbar, hilite, 2) != 2)
  2112.         Error(ERROR_CRLFRG);
  2113.     screen->title.left = hilite[0].self;
  2114.     screen->title.right = hilite[1].self;
  2115. }
  2116.  
  2117. #ifdef MODEMENU
  2118. #define    MMENU_SCROLL    0
  2119. #define    MMENU_VIDEO    (MMENU_SCROLL+1)
  2120. #define    MMENU_WRAP    (MMENU_VIDEO+1)
  2121. #define    MMENU_REVERSEWRAP (MMENU_WRAP+1)
  2122. #define    MMENU_NLM    (MMENU_REVERSEWRAP+1)
  2123. #define    MMENU_CURSOR    (MMENU_NLM+1)
  2124. #define    MMENU_PAD    (MMENU_CURSOR+1)
  2125. #define    MMENU_REPEAT    (MMENU_PAD+1)
  2126. #define    MMENU_SCROLLBAR    (MMENU_REPEAT+1)
  2127. #define    MMENU_PAGEMODE    (MMENU_SCROLLBAR+1)
  2128. #define    MMENU_STATUS    (MMENU_PAGEMODE+1)
  2129. #define    MMENU_REVSTATUS    (MMENU_STATUS+1)
  2130. #define    MMENU_C132    (MMENU_REVSTATUS+1)
  2131. #define    MMENU_CURSES    (MMENU_C132+1)
  2132. #define    MMENU_MARGBELL    (MMENU_CURSES+1)
  2133. #define    MMENU_TEKWIN    (MMENU_MARGBELL+1)
  2134. #define    MMENU_ALTERN    (MMENU_TEKWIN+1)
  2135. #define    MMENU_LINE    (MMENU_ALTERN+1)
  2136. #define    MMENU_RESET    (MMENU_LINE+1)
  2137. #define    MMENU_FULLRESET    (MMENU_RESET+1)
  2138. #define    MMENU_TEKMODE    (MMENU_FULLRESET+1)
  2139. #define    MMENU_HIDEVT    (MMENU_TEKMODE+1)
  2140.  
  2141. static char *vtext[] = {
  2142.     "Jump Scroll",
  2143.     "Reverse Video",
  2144.     "Auto Wraparound",
  2145.     "Reverse Wraparound",
  2146.     "Auto Linefeed",
  2147.     "Application Cursors",
  2148.     "Application Pad",
  2149.     "Auto Repeat",
  2150.     "Scrollbar",
  2151.     "Page Scroll",
  2152.     "Status Line",
  2153.     "Reverse Status Line",
  2154.     "80 <-> 132 Columns",
  2155.     "Curses Emulation",
  2156.     "Margin Bell",
  2157.     "Tek Window Showing",
  2158.     "Alternate Screen",
  2159.     "-",
  2160.     "Soft Reset",
  2161.     "Full Reset",
  2162.     "Select Tek Mode",
  2163.     "Hide VT Window",
  2164.     0,
  2165. };
  2166.  
  2167.  
  2168. static int menutermflags;
  2169. static int menukbdflags;
  2170. static int t132;
  2171. static int taltern;
  2172. static int tcurses;
  2173. static int tmarginbell;
  2174. static int tpagemode;
  2175. static int trevstatus;
  2176. static int tscrollbar;
  2177. static int tshow;
  2178. static int tstatusline;
  2179.  
  2180. Menu *setupmenu(menu)
  2181. register Menu **menu;
  2182. {
  2183.     register Screen *screen = &term.screen;
  2184.     register char **cp;
  2185.     register int flags = term.flags;
  2186.     register int kflags = term.keyboard.flags;
  2187.  
  2188.     if (*menu == NULL) {
  2189.         if ((*menu = NewMenu("Modes", re_verse)) == NULL)
  2190.             return(NULL);
  2191.         for(cp = vtext ; *cp ; cp++)
  2192.             AddMenuItem(*menu, *cp);
  2193.         if(!(flags & SMOOTHSCROLL))
  2194.             CheckItem(*menu, MMENU_SCROLL);
  2195.         if(flags & REVERSE_VIDEO)
  2196.             CheckItem(*menu, MMENU_VIDEO);
  2197.         if(flags & WRAPAROUND)
  2198.             CheckItem(*menu, MMENU_WRAP);
  2199.         if(flags & REVERSEWRAP)
  2200.             CheckItem(*menu, MMENU_REVERSEWRAP);
  2201.         if(flags & LINEFEED)
  2202.             CheckItem(*menu, MMENU_NLM);
  2203.         if(kflags & CURSOR_APL)
  2204.             CheckItem(*menu, MMENU_CURSOR);
  2205.         if(kflags & KYPD_APL)
  2206.             CheckItem(*menu, MMENU_PAD);
  2207.         if(flags & AUTOREPEAT)
  2208.             CheckItem(*menu, MMENU_REPEAT);
  2209.         if(tscrollbar = (screen->scrollbar > 0))
  2210.             CheckItem(*menu, MMENU_SCROLLBAR);
  2211.         if(tpagemode = screen->pagemode)
  2212.             CheckItem(*menu, MMENU_PAGEMODE);
  2213.         if(tstatusline = screen->statusline)
  2214.             CheckItem(*menu, MMENU_STATUS);
  2215.         if(trevstatus = screen->reversestatus)
  2216.             CheckItem(*menu, MMENU_REVSTATUS);
  2217.         if(t132 = screen->c132)
  2218.             CheckItem(*menu, MMENU_C132);
  2219.         if(tcurses = screen->curses)
  2220.             CheckItem(*menu, MMENU_CURSES);
  2221.         if(tmarginbell = screen->marginbell)
  2222.             CheckItem(*menu, MMENU_MARGBELL);
  2223.         if(tshow = screen->Tshow)
  2224.             CheckItem(*menu, MMENU_TEKWIN);
  2225.         else
  2226.             DisableItem(*menu, MMENU_HIDEVT);
  2227.         DisableItem(*menu, MMENU_ALTERN);
  2228.         if(taltern = screen->alternate) {
  2229.             CheckItem(*menu, MMENU_ALTERN);
  2230.             DisableItem(*menu, MMENU_PAGEMODE);
  2231.         }
  2232.         DisableItem(*menu, MMENU_LINE);
  2233.         if(screen->inhibit & I_TEK) {
  2234.             DisableItem(*menu, MMENU_TEKWIN);
  2235.             DisableItem(*menu, MMENU_TEKMODE);
  2236.         }
  2237.         menutermflags = flags;
  2238.         menukbdflags = kflags;
  2239.         return(*menu);
  2240.     }
  2241.     if ((menutermflags ^= flags) & SMOOTHSCROLL)
  2242.         SetItemCheck(*menu, MMENU_SCROLL, !(flags & SMOOTHSCROLL));
  2243.     if (menutermflags & REVERSE_VIDEO)
  2244.         SetItemCheck(*menu, MMENU_VIDEO, flags & REVERSE_VIDEO);
  2245.     if (menutermflags & WRAPAROUND)
  2246.         SetItemCheck(*menu, MMENU_WRAP, flags & WRAPAROUND);
  2247.     if (menutermflags & REVERSEWRAP)
  2248.         SetItemCheck(*menu, MMENU_REVERSEWRAP, flags & REVERSEWRAP);
  2249.     if (menutermflags & LINEFEED)
  2250.         SetItemCheck(*menu, MMENU_NLM, flags & LINEFEED);
  2251.     if ((menukbdflags ^= kflags) & CURSOR_APL)
  2252.         SetItemCheck(*menu, MMENU_CURSOR, kflags & CURSOR_APL);
  2253.     if (menukbdflags & KYPD_APL)
  2254.         SetItemCheck(*menu, MMENU_PAD, NULL, kflags & KYPD_APL);
  2255.     if(tscrollbar != (screen->scrollbar > 0))
  2256.         SetItemCheck(*menu, MMENU_SCROLLBAR, (tscrollbar =
  2257.          (screen->scrollbar > 0)));
  2258.     if(tpagemode != screen->pagemode)
  2259.         SetItemCheck(*menu, MMENU_PAGEMODE, (tpagemode =
  2260.          screen->pagemode));
  2261.     if(tstatusline != screen->statusline)
  2262.         SetItemCheck(*menu, MMENU_STATUS, (tstatusline =
  2263.          screen->statusline));
  2264.     if(trevstatus != screen->reversestatus)
  2265.         SetItemCheck(*menu, MMENU_REVSTATUS, (trevstatus =
  2266.          screen->reversestatus));
  2267.     if(t132 != screen->c132)
  2268.         SetItemCheck(*menu, MMENU_C132, (t132 = screen->c132));
  2269.     if(tcurses != screen->curses)
  2270.         SetItemCheck(*menu, MMENU_CURSES, (tcurses = screen->curses));
  2271.     if(tmarginbell != screen->marginbell)
  2272.         SetItemCheck(*menu, MMENU_MARGBELL, (tmarginbell =
  2273.         screen->marginbell));
  2274.     if(tshow != screen->Tshow) {
  2275.         SetItemCheck(*menu, MMENU_TEKWIN, (tshow = screen->Tshow));
  2276.         SetItemDisable(*menu, MMENU_HIDEVT, !tshow);
  2277.     }
  2278.     if(taltern != screen->alternate) {
  2279.         SetItemCheck(*menu, MMENU_ALTERN, (taltern =
  2280.          screen->alternate));
  2281.         SetItemDisable(*menu, MMENU_PAGEMODE, taltern);
  2282.     }
  2283.     menutermflags = flags;
  2284.     menukbdflags = kflags;
  2285.     return(*menu);
  2286. }
  2287.  
  2288. domenufunc(item)
  2289. int item;
  2290. {
  2291.     register Screen *screen = &term.screen;
  2292.  
  2293.     switch (item) {
  2294.     case MMENU_SCROLL:
  2295.         term.flags ^= SMOOTHSCROLL;
  2296.         if (term.flags & SMOOTHSCROLL) {
  2297.             screen->jumpscroll = FALSE;
  2298.             if (screen->scroll_amt)
  2299.                 FlushScroll(screen);
  2300.         } else
  2301.             screen->jumpscroll = TRUE;
  2302.         break;
  2303.  
  2304.     case MMENU_VIDEO:
  2305.         term.flags ^= REVERSE_VIDEO;
  2306.         ReverseVideo(&term);
  2307.         break;
  2308.  
  2309.     case MMENU_WRAP:
  2310.         term.flags ^= WRAPAROUND;
  2311.         break;
  2312.  
  2313.     case MMENU_REVERSEWRAP:
  2314.         term.flags ^= REVERSEWRAP;
  2315.         break;
  2316.  
  2317.     case MMENU_NLM:
  2318.         term.flags ^= LINEFEED;
  2319.         break;
  2320.  
  2321.     case MMENU_CURSOR:
  2322.         term.keyboard.flags ^= CURSOR_APL;
  2323.         break;
  2324.  
  2325.     case MMENU_PAD:
  2326.         term.keyboard.flags ^= KYPD_APL;
  2327.         break;
  2328.  
  2329.     case MMENU_REPEAT:
  2330.         term.flags ^= AUTOREPEAT;
  2331.         if (term.flags & AUTOREPEAT)
  2332.             XAutoRepeatOn();
  2333.         else
  2334.             XAutoRepeatOff();
  2335.         break;
  2336.  
  2337.     case MMENU_SCROLLBAR:
  2338.         if(screen->scrollbar)
  2339.             ScrollBarOff(screen);
  2340.         else
  2341.             ScrollBarOn(screen, TRUE, FALSE);
  2342.         break;
  2343.  
  2344.     case MMENU_PAGEMODE:
  2345.         if(screen->pagemode = !screen->pagemode)
  2346.             screen->pagecnt = 0;
  2347.         break;
  2348.  
  2349.     case MMENU_STATUS:
  2350.         if(screen->statusline)
  2351.             HideStatus();
  2352.         else
  2353.             ShowStatus();
  2354.         break;
  2355.  
  2356.     case MMENU_REVSTATUS:
  2357.         screen->reversestatus = !screen->reversestatus;
  2358.         ScrnRefresh(screen, screen->max_row + 1, 0, 1, screen->max_col
  2359.          + 1);
  2360.         break;
  2361.  
  2362.     case MMENU_C132:
  2363.         screen->c132 = !screen->c132;
  2364.         break;
  2365.  
  2366.     case MMENU_MARGBELL:
  2367.         if(!(screen->marginbell = !screen->marginbell))
  2368.             screen->bellarmed = -1;
  2369.         break;
  2370.  
  2371.     case MMENU_CURSES:
  2372.         screen->curses = !screen->curses;
  2373.         break;
  2374.  
  2375.     case MMENU_FULLRESET:
  2376.         VTReset(TRUE);
  2377.         break;
  2378.  
  2379.     case MMENU_RESET:
  2380.         VTReset(FALSE);
  2381.         break;
  2382.  
  2383.     case MMENU_HIDEVT:
  2384.         screen->show = FALSE;
  2385.         XUnmapWindow(VWindow(screen));
  2386.         reselectwindow(screen);
  2387.         SyncUnmap(VWindow(screen), WINDOWEVENTS);
  2388.             /* drop through */
  2389.     case MMENU_TEKMODE:
  2390.         if(!screen->TekEmu) {
  2391.             if(screen->logging) {
  2392.                 FlushLog(screen);
  2393.                 screen->logstart = Tbuffer;
  2394.             }
  2395.             screen->TekEmu = TRUE;
  2396.             if(screen->pagemode) {
  2397.                 Scroll(screen, screen->pagecnt);
  2398.                 screen->pagecnt = 0;
  2399.                 ioctl(screen->respond, TIOCSTART, NULL);
  2400.             }
  2401.             longjmp(VTend, 1);
  2402.         } else
  2403.             XRaiseWindow(TWindow(screen));
  2404.         break;
  2405.  
  2406.     case MMENU_TEKWIN:
  2407.         if(screen->Tshow = !screen->Tshow) {
  2408.             if(TWindow(screen) || TekInit()) {
  2409.                 XMapWindow(TWindow(screen));
  2410.                 screen->Tshow = TRUE;
  2411.             }
  2412.         } else {
  2413.             screen->Tshow = FALSE;
  2414.             XUnmapWindow(TWindow(screen));
  2415.             SyncUnmap(TWindow(screen), TWINDOWEVENTS);
  2416.             if(screen->TekEmu) {
  2417.                 if(screen->logging) {
  2418.                     FlushLog(screen);
  2419.                     screen->logstart = buffer;
  2420.                 }
  2421.                 longjmp(Tekend, 1);
  2422.             }
  2423.         }
  2424.         reselectwindow(screen);
  2425.         break;
  2426.     }
  2427. }
  2428. #endif MODEMENU
  2429.