home *** CD-ROM | disk | FTP | other *** search
/ Boot Disc 8 / boot-disc-1997-04.iso / PDA_Soft / Psion / comms / p3nfs / nfsc / vt100.c < prev    next >
C/C++ Source or Header  |  1996-05-26  |  22KB  |  1,023 lines

  1. /*
  2.  * vt100 emulator for p3nfs
  3.  * Rudolf Koenig, Michael Schroeder
  4.  * 5.1.1996
  5.  * Copyright GNU Public License
  6.  */
  7.  
  8. #include <p_serial.h>        /* set.P_SRCHAR */
  9. #include <plib.h>        /* P_FTEXT & co */
  10. #include <wlib.h>        /* WMSG_KEY */
  11. #include "nfsc.h"        /* set */
  12.  
  13. #ifdef HAVE_TERMEMU
  14.  
  15. P_RECT ttyrect;            /* Scroll region */
  16. W_CURSOR wc;
  17.  
  18. #define MAXARGS 10
  19. #define MAXLINE 80        /* Longest line possible */
  20.  
  21. static WORD c_x, c_y, l_x, l_y;
  22. static char sbuf[MAXLINE], bufoff, isbold;    /* Speedup buffer */
  23. static UINT clearmode;
  24.  
  25. #define E_NORMAL    255
  26. #define E_ESCAPE    254
  27.  
  28. #define E_WRAP_MODE    0x01
  29. #define E_ORIGIN_MODE    0x02
  30. #define E_INSERT_MODE     0x04
  31. #define E_ISINVERTED    0x08
  32.  
  33. static unsigned char
  34.     e_args[MAXARGS],    /* Escape seq. arguments */
  35.     e_state = E_NORMAL,    /* escape state machine */
  36.     e_interm,        /* Intermediate character (?*..) */
  37.     e_flags,        /* WRAP_MODE & co */
  38.     e_gstyle,        /* Bold * co */
  39.     e_gflags,        /* gray plane */
  40.     tabs[MAXLINE + 1];
  41.  
  42. static unsigned char altchar[0x20] = {
  43.   0x20,
  44.   0x04,0xb1,0x12,0x12,0x12,0x12,0xf8,0xf1,
  45.   0x12,0x12,0xd9,0xbf,0xda,0xc0,0xc5,0xc4,
  46.   0xc4,0xc4,0xc4,0xc4,0xc3,0xb4,0xc1,0xc2,
  47.   0xb3,0x11,0x10,0xf4,0xce,0x9c,0xfa
  48. };
  49. static unsigned char gl, font, charsets[4];
  50.  
  51. GLREF_C VOID Reset(void)
  52. {
  53.   int i;
  54.   G_GC gc;
  55.  
  56.   for(i = 0; i < MAXLINE; i++) /* Reset the tabs */
  57.     tabs[i] = i && (i & 7) == 0;
  58.   c_x = 0;
  59.   c_y = ascent;
  60.   bufoff  = 0;
  61.   e_state = E_NORMAL;
  62.   e_flags = E_WRAP_MODE;
  63.   clearmode = G_TRMODE_CLR;
  64.   cur_appl = 0;
  65.   gl = 0;
  66.   font = charsets[0] = charsets[1] = charsets[2] = charsets[3] = 'B';
  67.  
  68.   isbold  = 0;
  69.   e_gstyle = G_STY_MONO;    /* monospaced fonts, please */
  70.   e_gflags = G_GC_FLAG_BOTH_PLANES;
  71.   gc.style = e_gstyle;
  72.   gc.flags = e_gflags;
  73.   gSetGC(hgc, G_GC_MASK_STYLE|G_GC_MASK_GREY, &gc);
  74.  
  75.   ttyrect.tl.x = 0;
  76.   ttyrect.tl.y = 0;
  77.   ttyrect.br.x = t_w;
  78.   ttyrect.br.y = t_h;
  79.   wc.width  = charwidth;    /* Cursor */
  80.   wc.height = charheight;
  81.   wc.ascent = ascent;
  82.   wc.pos.x  = c_x;
  83.   wc.pos.y  = c_y;
  84.   wTextCursor(main_win, &wc);
  85. }
  86.  
  87. #define C_EOD    0
  88. #define C_BOD    1
  89. #define C_D    2
  90. #define C_EOL    3
  91. #define C_BOL    4
  92. #define C_L    5
  93.  
  94. static void
  95. clear(int n)
  96. {
  97.   P_RECT pr;
  98.  
  99.   switch(n)
  100.     {
  101.       /*----------------------------------------------- clear to end of page */
  102.       case C_EOD:
  103.         if(c_y + charheight < t_h) /* clear but the line itself */
  104.       {
  105.         pr.tl.x = 0;
  106.         pr.tl.y = c_y - ascent + charheight;
  107.         pr.br.x = t_w;
  108.         pr.br.y = t_h;
  109.         gClrRect(&pr, clearmode);
  110.       }
  111.       /*------------------------------------------------------- clear to eol */
  112.       case C_EOL:
  113.         pr.tl.x = c_x;
  114.         pr.tl.y = c_y - ascent;
  115.     pr.br.x = t_w;
  116.     pr.br.y = pr.tl.y + charheight;
  117.     gClrRect(&pr, clearmode);
  118.     break;
  119.       /*------------------------------------- clear to beginning of the page */
  120.       case C_BOD:
  121.         if(c_y > ascent) /* clear but the line itself */
  122.       {
  123.         pr.tl.x = 0;
  124.         pr.tl.y = 0;
  125.         pr.br.x = t_w;
  126.         pr.br.y = c_y - ascent;
  127.         gClrRect(&pr, clearmode);
  128.       }
  129.       /*------------------------------------- clear to beginning of the line */
  130.       case C_BOL:
  131.     if(c_x > 0)
  132.       {
  133.         pr.tl.x = 0;
  134.         pr.tl.y = c_y - ascent;
  135.         pr.br.x = c_x + charwidth;
  136.         pr.br.y = c_y - ascent + charheight;
  137.         gClrRect(&pr, clearmode);
  138.       }
  139.     break;
  140.       /*---------------------------------------------- clear the whole screen */
  141.       case C_D:
  142.     pr.tl.x = pr.tl.y = 0;
  143.     pr.br.x = t_w;
  144.     pr.br.y = t_h;
  145.     gClrRect(&pr, clearmode);
  146.     break;
  147.       /*---------------------------------------------- clear the whole line */
  148.       case C_L:
  149.     pr.tl.x = 0;
  150.     pr.tl.y = c_y - ascent;
  151.     pr.br.x = t_w;
  152.     pr.br.y = pr.tl.y + charheight;
  153.     gClrRect(&pr, clearmode);
  154.     break;
  155.     }
  156. }
  157.  
  158. /* Scroll horizontally, using the ttyrect */
  159.  
  160. static void
  161. h_scroll(int right, int pixel, int doclear)
  162. {
  163.   P_RECT  r;
  164.   P_POINT o;
  165.  
  166.   r.tl.x = c_x;
  167.   r.tl.y = c_y - ascent;
  168.   r.br.y = r.tl.y + charheight;
  169.   r.br.x = t_w;
  170.   o.y    = 0;
  171.  
  172.   if(right)
  173.     {
  174.       o.x = pixel;
  175.       r.br.x -= pixel;
  176.       wScrollRect(main_win, &r, &o);
  177.       r.br.x = r.tl.x + pixel;
  178.     }
  179.   else
  180.     {
  181.       o.x = -pixel;
  182.       r.tl.x += pixel;
  183.       wScrollRect(main_win, &r, &o);
  184.       r.tl.x = r.br.x - pixel;
  185.     }
  186.   if(doclear)
  187.     gClrRect(&r, clearmode);
  188. }
  189.  
  190. /* It works only within the scroll region (ttyrect) */
  191. static void
  192. v_scroll(int down, int pixel)
  193. {
  194.   P_POINT o;
  195.   int i;
  196.  
  197.   if(down)
  198.     {
  199.       i = ttyrect.br.y;
  200.       o.y = pixel;
  201.       o.x = 0;
  202.       ttyrect.br.y -= pixel;
  203.       wScrollRect(main_win, &ttyrect, &o);
  204.       ttyrect.br.y = ttyrect.tl.y + pixel;
  205.       gClrRect(&ttyrect, clearmode);
  206.       ttyrect.br.y = i;
  207.     }
  208.   else
  209.     {
  210.       i = ttyrect.tl.y;
  211.       o.y = -pixel;
  212.       o.x = 0;
  213.       ttyrect.tl.y += pixel;
  214.       wScrollRect(main_win, &ttyrect, &o);
  215.       ttyrect.tl.y = ttyrect.br.y - pixel;
  216.       gClrRect(&ttyrect, clearmode);
  217.       ttyrect.tl.y = i;
  218.     }
  219. }
  220.  
  221. static void
  222. nl(void)
  223. {
  224.   if(c_y + charheight > ttyrect.br.y)
  225.     {
  226.       if(c_y < ttyrect.br.y)
  227.     v_scroll(0, charheight);
  228.     }
  229.   else
  230.     c_y += charheight;
  231. }
  232.  
  233. static void
  234. flsbuf(void)
  235. {
  236.   int dx;
  237.  
  238.   if(bufoff == 0)
  239.     return;
  240.   dx = bufoff * charwidth;
  241.   c_x -= dx;
  242.   if(e_flags & E_INSERT_MODE)
  243.     h_scroll(1, dx, 0);
  244.   gPrintText(c_x, c_y, sbuf, bufoff);
  245.   c_x += dx;
  246.   bufoff = 0;
  247. }
  248.  
  249. static void
  250. put(unsigned char ch)
  251. {
  252.   int i, n;
  253.   char lbuf[32];
  254.   int a0, a1;
  255.   int nargs;
  256.  
  257.   if(e_state == E_NORMAL)
  258.     {
  259.       if(ch >= ' ')
  260.     {
  261.       if(c_x >= t_w)            /* last column printable  */
  262.         {
  263.           if(e_flags & E_WRAP_MODE)
  264.             {
  265.           flsbuf();
  266.           nl();
  267.           c_x = 0;
  268.         }
  269.           else
  270.             {
  271.           c_x = t_w - charwidth;
  272.           if (bufoff > 0)
  273.             bufoff--;
  274.             }
  275.         }
  276.           if(ch > 127)
  277.         ch = iso2cp(ch);
  278.       switch (font)
  279.         {
  280.           case 'A':
  281.             if (ch == '#')
  282.           ch = 0x9c;
  283.         break;
  284.           case '0':
  285.             if (ch >= 0x5f && ch <= 0x7e)
  286.           ch = altchar[ch - 0x5f];
  287.         break;
  288.           default:
  289.             break;
  290.         }
  291.       sbuf[bufoff++] = ch;
  292.       /* We can't write bold characters buffered, as they are
  293.          1 Pixel wider and we NEED a monospaced font */
  294.       c_x += charwidth;
  295.       if(isbold)
  296.         flsbuf();
  297.       return;
  298.     }
  299.       flsbuf();
  300.  
  301.       /* hack: normalize c_x for nowrap mode */
  302.       if (!(e_flags & E_WRAP_MODE) && c_x >= t_w)
  303.         c_x = t_w - charwidth;
  304.  
  305.       switch(ch)
  306.     {
  307.     case 7:        /* Bell*/
  308.       p_sound(5, 320);
  309.       break;
  310.     case '\b':    /* BackSpace */
  311.       if(c_x > 0)
  312.         c_x -= charwidth;
  313.       return;
  314.     case '\t':
  315.       n = c_x / charwidth;          /* current column */
  316.       if (n >= cols)        /* curses bug workaround */
  317.         {
  318.           nl();
  319.           n = 0;
  320.         }
  321.       n++;
  322.       while (!tabs[n] && n < cols - 1)
  323.         n++;
  324.       c_x = n * charwidth;
  325.       return;
  326.     case '\n':
  327.       nl();
  328.       return;
  329.     case '\r':
  330.       c_x = 0;
  331.       return;
  332.     case 0x1b:        /* Escape */
  333.       e_state = E_ESCAPE;
  334.       e_interm = 0;
  335.       return;
  336.     case 0x0e:        /* C-n */
  337.     case 0x0f:        /* C-o */
  338.       font = charsets[gl = 0x0f - ch];
  339.       break;
  340.     default:
  341.       break;
  342.     }
  343.       return;
  344.     }
  345.  
  346.   if(ch < ' ')        /* that's the way a vt100 does it */
  347.     {
  348.       int oldstate = e_state;
  349.       e_state = E_NORMAL;
  350.       put(ch);
  351.       if (e_state != E_ESCAPE)
  352.         e_state = oldstate;
  353.       return;
  354.     }
  355.  
  356.   if(e_state == E_ESCAPE) /* first character after escape */
  357.     {
  358.       if(ch <= '/')
  359.         {
  360.       e_interm = e_interm ? -1 : ch;
  361.       return;
  362.     }
  363.       switch (e_interm)
  364.     {
  365.     case 0:
  366.       switch(ch)
  367.         {
  368.         case 'E': /* CR/NL */
  369.           nl();
  370.           c_x = 0;
  371.           return;
  372.         case 'D': /* Scroll down */
  373.           nl();
  374.           break;
  375.         case 'M': /* Scroll up */
  376.           if(c_y - charheight < ttyrect.tl.y)
  377.         {
  378.           if(c_y > ttyrect.tl.y)
  379.             v_scroll(1, charheight);
  380.         }
  381.           else
  382.         c_y -= charheight;
  383.           break;
  384.         case 'H':
  385.           n = c_x/charwidth;      /* current column */
  386.           tabs[n] = 1;
  387.           break;
  388.         case 'Z':
  389.           p_atos(lbuf, "\033[?1;2c"); 
  390.           P_WRITE(serial, lbuf, p_slen(lbuf));
  391.           break;
  392.         case '7': /* save cursor position */
  393.           l_x = c_x; l_y = c_y;
  394.           break;
  395.         case '8': /* restore cursor */
  396.           c_x = l_x; c_y = l_y;
  397.           break;
  398.         case 'c': /* Reset */
  399.           clear(2);
  400.           Reset();
  401.           break;;
  402.         case '[': /* the longer ones */
  403.           e_state = 0;
  404.           e_interm = 0;
  405.           e_args[0] = e_args[1] = 0;
  406.           return;
  407.         case 'n':
  408.         case 'o':
  409.           font = charsets[gl = ch - ('n' - 2)];
  410.           return;
  411.         default:
  412.           break;
  413.         }
  414.       break;
  415.     case '#':
  416.       if (ch == '8')        /* fill with 'E' */
  417.         {
  418.           for (i = 0; i < cols; i++)
  419.               sbuf[i] = 'E';
  420.           for (i = 0; i < rows; i++)
  421.         gPrintText(0, i * charheight + ascent, sbuf, cols);
  422.         }
  423.       break;
  424.     case '(':
  425.     case ')':
  426.     case '*':
  427.     case '+':
  428.       charsets[e_interm - '('] = ch;
  429.       font = charsets[gl];
  430.       break;
  431.     default:
  432.       break;
  433.     }
  434.       e_state = E_NORMAL;
  435.       return;
  436.     }
  437.  
  438.   /* e_state >= 0 : longer escape sequences */
  439.  
  440.   if(ch >= '0' && ch <= '9')        /* Arguments */
  441.     {
  442.       if(e_state < MAXARGS)
  443.     e_args[e_state] = e_args[e_state] * 10 + (ch - '0');
  444.       return;
  445.     }
  446.  
  447.   if(ch == ';' || ch == ':')
  448.     {
  449.       e_state++;
  450.       if(e_state < MAXARGS)
  451.     e_args[e_state] = 0;
  452.       return;
  453.     }
  454.  
  455.   if(ch <= 0x3f)            /* Intermediate */
  456.     {
  457.       e_interm = e_interm ? -1 : ch;
  458.       return;
  459.     }
  460.  
  461.   nargs = e_state + 1;
  462.   if (nargs >= MAXARGS)
  463.     nargs = MAXARGS;
  464.  
  465.   a0 = e_args[0];
  466.   if (a0 == 0)
  467.     a0++;
  468.   a1 = e_args[1];
  469.   if (a1 == 0)
  470.     a1++;
  471.  
  472.   e_state = E_NORMAL;            /* Last character in sequence */
  473.  
  474.   switch (e_interm)
  475.     {
  476.     case 0:
  477.       switch(ch)
  478.     {
  479.     case 's':                /* save cursor position */
  480.       l_x = c_x; l_y = c_y;
  481.       break;
  482.  
  483.     case '8':                /* restore cursor */
  484.       c_x = l_x; c_y = l_y;
  485.       break;
  486.  
  487.     case 'H':                /* Cursor movement */
  488.     case 'f':
  489.       c_y = (a0 - 1) * charheight;
  490.       c_x = (a1 - 1) * charwidth;
  491.  
  492.       if(e_flags & E_ORIGIN_MODE)
  493.         {
  494.           if(c_y > ttyrect.br.y - charheight) c_y = ttyrect.br.y - charheight;
  495.           if(c_x > ttyrect.br.x - charwidth)  c_x = ttyrect.br.x - charwidth;
  496.           c_y += ttyrect.tl.y;
  497.           c_x += ttyrect.tl.x;
  498.         }
  499.       else
  500.         {
  501.           if(c_y > t_h - charheight) c_y = t_h - charheight;
  502.           if(c_x > t_w - charwidth)  c_x = t_w - charwidth;
  503.         }
  504.       c_y += ascent;
  505.       return;
  506.  
  507.     case 'J':                /* Clear Display*/
  508.       if(e_args[0] < 3)
  509.         clear(e_args[0]);
  510.       return;
  511.  
  512.     case 'K':                /* Clear Line */
  513.       if(e_args[0] < 3)
  514.         clear(e_args[0] + 3);
  515.       return;
  516.  
  517.     case 'A':                /* Up / don't scroll */
  518.       if(c_y > ttyrect.tl.y) /* Damn scroll region */
  519.         {
  520.           c_y -= a0 * charheight;
  521.           if(c_y < ttyrect.tl.y)
  522.         c_y = ttyrect.tl.y + ascent;
  523.         }
  524.       else
  525.         {
  526.           c_y -= a0 * charheight;
  527.           if(c_y < 0)
  528.         c_y = ascent;
  529.         }
  530.       return;
  531.  
  532.     case 'B':                /* Down / don't scroll*/
  533.       if(c_y < ttyrect.br.y) 
  534.         {
  535.           c_y += a0 * charheight;
  536.           if(c_y >= ttyrect.br.y)
  537.         c_y = ttyrect.br.y - charheight + ascent;
  538.         }
  539.       else
  540.         {
  541.           c_y += a0 * charheight;
  542.           if(c_y >= t_h)
  543.         c_y = t_h - charheight + ascent;
  544.         }
  545.       return;
  546.  
  547.     case 'C':                /* Right */
  548.       c_x += a0 * charwidth;
  549.       if(c_x >= t_w)
  550.         c_x = t_w - charwidth;
  551.       return;
  552.  
  553.     case 'D':                /* Left */
  554.       c_x -= a0 * charwidth;
  555.       if(c_x < 0)
  556.         c_x = 0;
  557.       return;
  558.  
  559.     case 'm':                /* Attributes */
  560.       {
  561.         G_GC gc;
  562.  
  563.         for(i = 0; i < nargs; i++)
  564.           switch(e_args[i])
  565.         {
  566.         case  0: e_gstyle  = G_STY_MONO;
  567.              e_gflags  = G_GC_FLAG_BOTH_PLANES;
  568.              isbold = 0;
  569.              break;
  570.         case  1: e_gstyle |= G_STY_BOLD; isbold = 1;    break;
  571.         case  2: e_gflags  = G_GC_FLAG_GREY_PLANE;    break;
  572.         case  3: e_gstyle |= G_STY_ITALIC;        break;
  573.         case  4: e_gstyle |= G_STY_UNDERLINE;        break;
  574.         case  5: /* Blinking */
  575.         case  7: e_gstyle |= G_STY_INVERSE;        break;
  576.         case 22: e_gflags  = G_GC_FLAG_BOTH_PLANES;    break;
  577.         case 23: e_gstyle &= ~G_STY_ITALIC;        break;
  578.         case 24: e_gstyle &= ~G_STY_UNDERLINE;    break;
  579.         case 25: /* Not Blinking */
  580.         case 27: e_gstyle &= ~G_STY_INVERSE;        break;
  581.         default: break;
  582.         }
  583.         gc.style = e_flags & E_ISINVERTED ? e_gstyle ^ G_STY_INVERSE
  584.                           : e_gstyle;
  585.         gc.flags = e_gflags;
  586.         gSetGC(hgc, G_GC_MASK_STYLE|G_GC_MASK_GREY, &gc);
  587.       }
  588.  
  589.     case 'g':                /* Tab clear */
  590.       if(e_args[0] == 3)
  591.         for(i = 0; i < MAXLINE; i++) /* Clear all the tabs */
  592.           tabs[i] = 0;
  593.       if(e_args[0] == 0)
  594.         tabs[c_x / charwidth] = 0;
  595.       break;
  596.  
  597.     case 'r':                /* Scroll region */
  598.       i = (a0 - 1) * charheight;
  599.       n = a1 * charheight;
  600.  
  601.       for(i = 0; i < nargs; i++)     /* Reset region ? */
  602.         if(e_args[i] != 0)
  603.           break;
  604.       if(i == nargs)        /* Yes */
  605.         n = t_w;
  606.  
  607.       if(i > t_h) i = t_h;
  608.       if(n > t_h) n = t_h;
  609.  
  610.       if(i >= n)
  611.         return;
  612.  
  613.       ttyrect.tl.y = i;
  614.       ttyrect.br.y = n;
  615.       c_x = 0;
  616.       c_y = ascent;
  617.       if (e_flags & E_ORIGIN_MODE)
  618.         {
  619.           c_y += ttyrect.tl.y;
  620.           c_x += ttyrect.tl.x;
  621.         }
  622.       return;
  623.  
  624.     case 'I':    /* Forward tabs */
  625.       while (a0-- > 0)
  626.         put('\t');
  627.       return;
  628.  
  629.     case 'Z':    /* Backward tabs */
  630.       n = c_x / charwidth;      /* current column */
  631.       while (a0-- > 0)
  632.         {
  633.           if (n > 0)
  634.         n--;
  635.           while (!tabs[n] && n > 0)
  636.         n--;
  637.         }
  638.       c_x = n * charwidth;
  639.       return;
  640.  
  641.     case 'M':            /* delete lines (scroll up) */
  642.     case 'L':            /* Insert lines (scroll down) */
  643.       if(c_y > ttyrect.br.y || c_y < ttyrect.tl.y)
  644.         return;            /* not in scroll region */
  645.       n = ttyrect.tl.y;
  646.       ttyrect.tl.y = c_y - ascent;
  647.       i = a0 * charheight;
  648.       if(ttyrect.tl.y + i > ttyrect.br.y)
  649.         i = ttyrect.br.y - ttyrect.tl.y;
  650.       v_scroll(ch == 'M' ? 0 : 1, i);
  651.       ttyrect.tl.y = n;
  652.       break;
  653.  
  654.     case 'P':            /* delete characters (scroll left) */
  655.     case '@':            /* Insert characters (scroll right) */
  656.       if(c_x > t_w)
  657.         return;
  658.       i = a0 * charwidth;
  659.  
  660.       if(c_x + i > t_w)
  661.         i = t_w - c_x;
  662.       h_scroll(ch == 'P' ? 0 : 1, i, 1);
  663.       break;
  664.  
  665.     case 'h':            /* Set Mode */
  666.     case 'l':            /* Reset Mode */
  667.       for(i = 0; i < nargs; i++)
  668.         {
  669.           switch(e_args[i])
  670.         {
  671.         case 4:
  672.           e_flags &= ~E_INSERT_MODE;
  673.           if (ch == 'h')
  674.             e_flags |= E_INSERT_MODE;
  675.           break;
  676.         default:
  677.           break;
  678.         }
  679.         }
  680.       return;
  681.  
  682.     case 'c':
  683.       if (e_args[0] == 0)
  684.         {
  685.           p_atos(lbuf, "\033[?1;2c"); 
  686.           P_WRITE(serial, lbuf, p_slen(lbuf));
  687.         }
  688.       return;
  689.  
  690.     case 'n':
  691.       if(a0 == 5)        /* terminal status */
  692.         {
  693.           p_atos(lbuf, "\033[0n");
  694.           P_WRITE(serial, lbuf, p_slen(lbuf));
  695.         }
  696.       if(a0 == 6)        /* get position / resize needs it */
  697.         {
  698.           p_atos(lbuf, "\033[%d;%dR", 
  699.         (c_y-ascent) / charheight + 1, c_x / charwidth + 1);
  700.           P_WRITE(serial, lbuf, p_slen(lbuf));
  701.         }
  702.       return;
  703.  
  704.     case 'x':            /* decreqtparm */
  705. /*
  706.  * Response CSI sol; par; nbits; xspeed; rspeed; clkmul; flags x
  707.  *                        DECREPTPARM Report of terminal parameters
  708.  *        sol
  709.  *        0       terminal can send unsolicited reports, supported as sol = 1
  710.  *        1       terminal reports only on request
  711.  *        2       this is a report (DECREPTPARM)
  712.  *        3       terminal reporting only on request
  713.  *        par = 1 none, 2 space, 3 mark, 4 odd, 5 even
  714.  *        nbits = 1 (8 bits/char), 2 (7 bits/char)
  715.  *        xspeed, rspeed = transmit and receive speed index:
  716.  *  0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128 correspond to speeds of
  717.  *  50,75,110,134.5,150,200,300,600,1200,1800,2000,2400,3600,4800,9600,19200,
  718.  *        clkmul = 1 (clock rate multiplier is 16)
  719.  *        flags = 0-15 (Setup Block #5), always 0 here
  720.  */
  721.       if (a0 == 1)
  722.         {
  723.           /* Convert baudrate */
  724.           a0 = set.tty.tbaud - 1;
  725.           if(a0 >= P_BAUD_300 && a0 < P_BAUD_7200)
  726.             a0++;
  727.           a0 *= 8;
  728.           p_atos(lbuf, "\033[%d;%d;%d;%d;%d;1;0x",
  729.             e_args[0] + 2,
  730.         (set.tty.frame & P_PARITY) ? 6 - set.tty.parity : 0,
  731.         4 - (set.tty.frame & P_DATA_FRM),
  732.         a0, a0);
  733.           P_WRITE(serial, lbuf, p_slen(lbuf));
  734.         }
  735.       return;
  736.  
  737.     default:
  738.       break;
  739.     }
  740.       break;
  741.  
  742.     case '?':        /* DEC private */
  743.       switch(ch)
  744.     {
  745.       case 'h':
  746.       case 'l':
  747.         for(i = 0; i < nargs; i++)
  748.           {
  749.         switch(e_args[i])
  750.           {
  751.           case 1: 
  752.             cur_appl = ch == 'h';
  753.             break;
  754.           case 5: 
  755.             if((ch == 'h' && !(e_flags & E_ISINVERTED)) ||
  756.                (ch == 'l' && (e_flags & E_ISINVERTED)))
  757.               {
  758.                   G_GC gc;
  759.             P_RECT p;
  760.  
  761.             p.tl.x = 0; p.tl.y = 0;
  762.             p.br.x = t_w; p.br.y = t_h;
  763.             gClrRect(&p, G_TRMODE_INV);
  764.             e_flags ^= E_ISINVERTED;
  765.             gc.style = e_gstyle;
  766.             if (e_flags & E_ISINVERTED)
  767.               {
  768.                 gc.style ^= G_STY_INVERSE;
  769.                 clearmode = G_TRMODE_SET;
  770.               }
  771.             else
  772.               clearmode = G_TRMODE_CLR;
  773.             gSetGC(hgc, G_GC_MASK_STYLE, &gc);
  774.               }
  775.             break;
  776.           case 6: 
  777.             e_flags &= ~E_ORIGIN_MODE;
  778.             if (ch == 'h')
  779.               e_flags |= E_ORIGIN_MODE;
  780.             c_x = 0;
  781.             c_y = ascent;
  782.             if (e_flags & E_ORIGIN_MODE)
  783.               {
  784.             c_y += ttyrect.tl.y;
  785.             c_x += ttyrect.tl.x;
  786.               }
  787.             break;
  788.           case 7:
  789.             e_flags &= ~E_WRAP_MODE;
  790.             if (ch == 'h')
  791.               e_flags |= E_WRAP_MODE;
  792.             break;
  793.           }
  794.           }
  795.         break;
  796.       default:
  797.         break;
  798.     }
  799.       break;
  800.     case '>':
  801.       if (ch == 'c' && e_args[0] == 0)
  802.     {
  803.       p_atos(lbuf, "\033[>%d;%d;0c", 'P', VERSION);
  804.       P_WRITE(serial, lbuf, p_slen(lbuf));
  805.     }
  806.       break;
  807.     default:
  808.       break;
  809.     }
  810. }
  811.  
  812. GLDEF_C VOID TtyEmu(unsigned char *buf, INT len)  
  813. {
  814.   extern void *logfd;
  815.  
  816.   if(logfd)                /* Log into the file */
  817.     p_write(logfd, buf, len);
  818.   while(len-- > 0)
  819.     {
  820.       if(debug)
  821.         {
  822.       char mfb[6];
  823.       if(*buf >=' ' && *buf < 0x80)
  824.         AddToHistory(*buf);
  825.       else
  826.         {
  827.           p_atos(mfb, "%02x", *buf);
  828.           AddToHistory('\\');
  829.           AddToHistory(mfb[0]);
  830.           AddToHistory(mfb[1]);
  831.         }
  832.         }
  833.  
  834.       /* Last line in scroll region && Jumpscroll */
  835.       if(*buf == '\n' && (set.flags & FLAGS_JUMPSCROLL) &&
  836.      c_y + charheight > ttyrect.br.y && c_y < ttyrect.br.y)
  837.         {
  838.       int i, n;
  839.  
  840.       n = 1;
  841.       for(i = 1; i < len; i++)
  842.         if(buf[i] < ' ')
  843.           {
  844.         if(buf[i] == '\n')
  845.           n++;
  846.         else if(buf[i] != '\r')
  847.           break;
  848.           }
  849.  
  850.       if(n >= rows)
  851.         {
  852.               c_y = ascent;
  853.           clear(C_D);
  854.         }
  855.       else if(n > 1)
  856.         {
  857.           v_scroll(0, n*charheight);
  858.           c_y -= n * charheight;
  859.         }
  860.     }
  861.  
  862.       put(*buf++);
  863.     }
  864.  
  865.   flsbuf();
  866.  
  867.   wc.pos.x = c_x; wc.pos.y = c_y;
  868.   if(c_x >= t_w)             /* last column printable */
  869.     wc.pos.x = t_w - charwidth;
  870.   wTextCursor(main_win, &wc);
  871.  
  872.   wFlush();
  873. }
  874.  
  875. void
  876. AddFnKey(key, modifier, str)
  877.   int key;
  878.   int modifier;
  879.   char *str;
  880. {
  881.   extern struct fkey *fk;
  882.   struct fkey **fp, *f;
  883.   char *s;
  884.   int l;
  885.  
  886.   for(fp = &fk; *fp; fp = &(*fp)->next)
  887.     if((*fp)->key == key && (*fp)->modifier == modifier)
  888.       break;
  889.   
  890.   l = *str + sizeof(struct fkey) + 1; 
  891.   if((f = (struct fkey *)p_realloc(*fp, l)) == 0)
  892.     {
  893.       extern char c_nomem[];
  894.  
  895.       wInfoMsgCorner(c_nomem, W_CORNER_BOTTOM_RIGHT);
  896.       return;
  897.     }
  898.  
  899.   f->key = key;
  900.   f->modifier = modifier;
  901.   if(!*fp)
  902.     f->next = 0;
  903.   s = (char *)f + sizeof(struct fkey);
  904.   p_bcpy(s, str+1, *str);
  905.   s[*str] = 0;
  906.   *fp = f;
  907. }
  908.  
  909. /* 
  910.  * Parse \<nnn> and \s<nn>
  911.  * NOTE: \<nn> and \<n> are also accepted.
  912.  */
  913. void
  914. SendFnKey(f)
  915.   struct fkey *f;
  916. {
  917.   char *s;
  918.   unsigned char n;
  919.  
  920. #define isnum(s) s >= '0' && s <= '9'
  921.   for(s = (char *)f + sizeof(struct fkey); *s; s++)
  922.     {
  923.       if(*s == '\\')
  924.         {
  925.       if(s[1] == 's') /* sleep */
  926.         {
  927.           s++; n = 0;
  928.           if(isnum(s[1])) { s++; n =          s[0] - '0'; }
  929.           if(isnum(s[1])) { s++; n = n * 10 + s[0] - '0'; }
  930.           p_sleep((ULONG)n);
  931.           continue;
  932.         }
  933.       else if(isnum(s[1]))
  934.         {
  935.           s++; n = s[0] - '0';
  936.           if(isnum(s[1])) { s++; n = n * 10 + s[0] - '0'; }
  937.           if(isnum(s[1])) { s++; n = n * 10 + s[0] - '0'; }
  938.         }
  939.       else if(s[1] == 0)        /* \somenthing or */
  940.         break;
  941.       else
  942.         n = *s++;
  943.     }
  944.       else
  945.     n = *s;
  946.  
  947.       P_WRITE(serial, (char *)&n, 1); 
  948.     }
  949. }
  950.  
  951. char cant_open_the_file[] = "Can't open the file";
  952.  
  953. #define BLEN 128
  954. void
  955. LoadFnKey(fname, warn)
  956.   char *fname;
  957.   int warn;
  958. {
  959.   VOID *fcb;
  960.   char buf[BLEN], *p;
  961.   extern struct fkey *fk;
  962.   struct fkey **fp, *f;
  963.   int len;
  964.   UWORD key, modifier;
  965.  
  966.   /* First delete all definitions */
  967.   for(fp = &fk, f = fk; *fp; f = *fp)
  968.     {
  969.       *fp = f->next;
  970.       p_free(f);
  971.     }
  972.  
  973.   fname[*fname+1] = 0;
  974.   if(p_open(&fcb, fname+1, P_FTEXT | P_FSHARE))
  975.     {
  976.       if(warn)
  977.     wInfoMsgCorner(cant_open_the_file, W_CORNER_BOTTOM_RIGHT);
  978.       return;
  979.     }
  980.   while((len = p_read(fcb, buf, BLEN)) > 0)
  981.     {
  982.       if(*buf == '#')    /* Allow comments */
  983.         continue;
  984.       p = buf;   p_stog(&p, &key, 16);
  985.       p = buf+5; p_stog(&p, &modifier, 16);
  986.       p = buf+7; *p = len - 8;
  987.       AddFnKey(key, modifier, p);
  988.     }
  989.   p_close(fcb);
  990.   if(warn)
  991.     wInfoMsgCorner("Definition loaded", W_CORNER_BOTTOM_RIGHT);
  992.   return;
  993. }
  994.  
  995. void
  996. SaveFnKey(fname)
  997.   char *fname;
  998. {
  999.   VOID *fcb;
  1000.   char buf[BLEN];
  1001.   extern struct fkey *fk;
  1002.   struct fkey *f;
  1003.  
  1004.   fname[*fname+1] = 0;
  1005.   if(p_open(&fcb, fname+1, P_FTEXT | P_FREPLACE | P_FUPDATE))
  1006.     {
  1007.       wInfoMsgCorner(cant_open_the_file, W_CORNER_BOTTOM_RIGHT);
  1008.       return;
  1009.     }
  1010.   p_atos(buf, "# Key(Hex) Modifier(Hex) String");
  1011.   p_write(fcb, buf, p_slen(buf));
  1012.   for(f = fk; f; f = f->next)
  1013.     {
  1014.       p_atos(buf, "%04x %02x %s", f->key, f->modifier, (char *)f+sizeof(*f));
  1015.       p_write(fcb, buf, p_slen(buf));
  1016.     }
  1017.   p_close(fcb);
  1018.   wInfoMsgCorner("Definition saved", W_CORNER_BOTTOM_RIGHT);
  1019.   return;
  1020. }
  1021.  
  1022. #endif /* HAVE_TERMEMU */
  1023.