home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / STERM.ZIP / STERMV.C < prev   
Text File  |  1990-11-23  |  18KB  |  598 lines

  1.  
  2. /* STERMV.C - Video output functions */
  3.  
  4.  
  5.    #include <string.h>
  6.    #include <stdio.h>
  7.    #include <process.h>
  8.    #define  INCL_SUB
  9.    #define  INCL_DOS
  10.    #include <os2kernl.h>
  11.    #define STERMV
  12.    #include "sterm.h"
  13.  
  14.  
  15.  
  16.    static UCHAR im0s;    /* insert off - cursor start line */
  17.    static UCHAR im0e;    /* insert off - cursor end   line */
  18.    static UCHAR im1s;    /* insert on  - cursor start line */
  19.    static UCHAR im1e;    /* insert on  - cursor end   line */
  20.    static UCHAR vdata[128];    /* video data */
  21.    static UCHAR vbfc = 0x07;   /* current video attribute */
  22.    static USHORT vcol;            /* current col */
  23.    static USHORT vrow;            /* current row */
  24.    static VIOMODEINFO viodata; /* used by vioget.../vioset... functions */
  25.    static VIOCURSORINFO vcurs; /* used by viogetcurs, etc. */
  26.  
  27.  
  28.    static USHORT ScreenSize = 25;        /* current screen size in rows */
  29.  
  30.    static UCHAR fldattr = 0x07;          /* current video attribute */
  31.  
  32.  
  33.  
  34.    /********************************************************************/
  35.  
  36.    void clrscrn( void )
  37.  
  38.    {
  39.  
  40.    /* mono or color adapter/display and how many rows ? */
  41.    viodata.cb = 12;
  42.    VioGetMode( (PVIOMODEINFO) &viodata, 0 );
  43.    if ( ( viodata.fbType & 0x0001 ) == 0 || ( viodata.fbType & 0x0004 ) != 0 )
  44.       fldattr = fldmono;
  45.    else
  46.       fldattr = fldcolor;
  47.    ScreenSize = viodata.row;
  48.  
  49.    /* cursor start/end ? */
  50.    VioGetCurType( (PVIOCURSORINFO) &vcurs, 0 );
  51.    im0s = vcurs.yStart - 1;
  52.    im0e = vcurs.cEnd;
  53.    im1s = 1;
  54.    im1e = vcurs.yStart;
  55.  
  56.    /* clear the screen - put the real cursor in top left */
  57.    vbfc = fldattr;
  58.    vdata[0] = ' ';
  59.    vdata[1] = vbfc;
  60.    vrow = 1;
  61.    vcol = 1;
  62.    VioWrtNCell( (PUCHAR) vdata,
  63.                 ScreenSize * 80,
  64.                 vrow - 1,
  65.                 vcol - 1,
  66.                 0 );
  67.    setcursor( vrow, vcol, -1 );
  68.    }
  69.  
  70.    /********************************************************************/
  71.  
  72.    void clreor( )
  73.  
  74.    {
  75.  
  76.    /* clear to end of current row */
  77.    vdata[0] = ' ';
  78.    vdata[1] = vbfc;
  79.    VioWrtNCell( (UCHAR far *) vdata,
  80.                 ( 81 - vcol ),
  81.                 vrow - 1,
  82.                 vcol - 1,
  83.                 0 );
  84.    }
  85.  
  86.    /********************************************************************/
  87.  
  88.    void gotorc( r, c )
  89.  
  90.    int r;
  91.    int c;
  92.  
  93.    {
  94.  
  95.    /* save the new virtual cursor position */
  96.    vrow = r;
  97.    vcol = c;
  98.    }
  99.  
  100.    /********************************************************************/
  101.  
  102.    static void outstr( PUCHAR s, USHORT len )
  103.  
  104.  
  105.    {
  106.    BOOL newline = FALSE;
  107.    BOOL advance = TRUE;
  108.    UCHAR attrch[2];
  109.  
  110.    /* trim CR and LF from end of string */
  111.    while ( (len) && ( ( s[len-1] == '\r' ) ||
  112.                       ( s[len-1] == '\n' ) ) )
  113.       {  /* line ends with CR */
  114.       if ( s[len-1] == '\r' )
  115.          newline = TRUE;
  116.       len--;
  117.       }
  118.  
  119.  
  120.  
  121.    /* if backspace, reset cursor, blank */
  122.    if ( len == 1)
  123.       switch ( s[0] )
  124.         {
  125.         case '\b' : {
  126.                     s[0] = ' ';
  127.                     if ( vcol > 1 )
  128.                        vcol--;
  129.                     advance = FALSE;
  130.                     break;
  131.                     }
  132.         case '\n' : return; /* ignore linefeed */
  133.         default: {}
  134.         }
  135.  
  136.    /* write string at the current virtual cursor position */
  137.    if ( len )
  138.       VioWrtCharStrAtt( (PUCHAR) s,
  139.                      len,
  140.                      vrow - 1,
  141.                      vcol - 1,
  142.                      (PBYTE) &vbfc,
  143.                      0 );
  144.  
  145.    /* if line ends with CR */
  146.    if ( newline )  /* carriage return */
  147.       {
  148.       vrow++;
  149.       if ( vrow > ScreenSize )
  150.          {
  151.          vrow = ScreenSize;
  152.          attrch[1] = vbfc;
  153.          attrch[0] = ' ';
  154.          VioScrollUp( 0, 0, ScreenSize-1, 79, 1, (PBYTE) attrch, 0 );
  155.          }
  156.       vcol = 1;
  157.       }
  158.    else
  159.    if ( advance )
  160.       vcol = vcol + len;
  161.  
  162.    setcursor( vrow, vcol, -1 );
  163.  
  164.    }
  165.  
  166.  
  167.    /********************************************************************/
  168.  
  169.    void setcursor( int r, int c, int im )
  170.  
  171.  
  172.    {
  173.  
  174.    /* move the real cursor and optionally set its size */
  175.    VioSetCurPos( r -1,
  176.                  c - 1,
  177.                  0 );
  178.    if ( im >= 0 )
  179.       {
  180.       if ( im )
  181.          {
  182.          vcurs.yStart = im1s;
  183.          vcurs.cEnd = im1e;
  184.          }
  185.       else
  186.          {
  187.          vcurs.yStart = im0s;
  188.          vcurs.cEnd = im0e;
  189.          }
  190.       VioSetCurType( (PVIOCURSORINFO) &vcurs, 0 );
  191.       }
  192.    }
  193.  
  194.  
  195.  
  196. #define NUL '\x00'   /* null byte */
  197. #define ENQ '\x05'   /* transmit answerback msg */
  198. #define BEL '\x07'   /* alarm */
  199. #define BS  '\b'     /* backspace */
  200. #define HT  '\x09'   /* horizontal tab */
  201. #define LF  '\x0A'   /* linefeed */
  202. #define VT  '\x0B'   /* same as linefeed */
  203. #define FF  '\x0C'   /* ditto */
  204. #define CR  '\x0D'   /* cursor to left margin current line */
  205. #define SO  '\x0E'   /* select G1 charset (ignored) */
  206. #define SI  '\x0F'   /* select G0 charset ESC[ process */
  207. #define XON '\x11'   /* resume transmission */
  208. #define XOFF '\x13'  /* transmit only XON XOFF */
  209. #define CAN '\x18'   /* cancel control seq. */
  210. #define SUB '\x1A'   /* same as CAN */
  211. #define ESC '\x1B'   /* leadin to control seq. */
  212. #define DEL '\x7F'   /* deleted on input */
  213.  
  214.  
  215.  
  216. /* SIMVT output emulation
  217.    called from vidout with each char, may
  218.    return \0 if char is deleted or part of ctl seq */
  219.  
  220. static enum { nada, havesc, havlead, getpc1, havpc1,
  221.               havescO, eatCR, eatone } cstat;
  222.  
  223. static short pc1,      /* 1st parm numeric */
  224.              pc2;      /* 2nd parm numeric */
  225.  
  226.  
  227. /* process completed ESC [ sequence */
  228. static UCHAR procseq( UCHAR ic )
  229.   {
  230.   cstat = nada;
  231.   switch ( ic )
  232.      {
  233.      /* cursor backward, max to left margin */
  234.      case 'D': {
  235.                if ( vcol > 1 )
  236.                   vcol--;
  237.                setcursor( vrow, vcol, -1 );
  238.                return( NUL );
  239.                }
  240.      /* cursor down, max to bottom */
  241.      case 'B': {
  242.                if ( vrow < ScreenSize )
  243.                   vrow++;
  244.                setcursor( vrow, vcol, -1 );
  245.                return( NUL );
  246.                }
  247.      /* cursor right, max to right margin */
  248.      case 'C': {
  249.                if ( vcol < 80 )
  250.                   vcol++;
  251.                setcursor( vrow, vcol, -1 );
  252.                return( NUL );
  253.                }
  254.      /* cursor up, max to top */
  255.      case 'A': {
  256.                if ( vrow > 1 )
  257.                   vrow--;
  258.                setcursor( vrow, vcol, -1 );
  259.                return( NUL );
  260.                }
  261.      /* gotorc pc1, pc2  */
  262.      case 'f':
  263.      case 'H': {
  264.                if ( pc1 == 0 )
  265.                   pc1 = 1;
  266.                if ( pc2 == 0 )
  267.                   pc2 = 1;
  268.                gotorc( pc1, pc2 );
  269.                setcursor( vrow, vcol, -1 );
  270.                return( NUL );
  271.                }
  272.  
  273.      /* set display attributes */
  274.      case 'm': {
  275.                cstat = nada;
  276.                switch ( pc1 )
  277.                  {
  278.                  case 0: { /* off */
  279.                          vbfc = fldattr;
  280.                          break;
  281.                          }
  282.                  case 1: { /* hilite - if it won't blink */
  283.  
  284.                          if ( fldattr & 0x08 )
  285.                             vbfc = fldattr | 0x0F;
  286.                          else vbfc = fldattr | 0x08;
  287.                          break;
  288.                          }
  289.                  case 4:  /* underscore */
  290.                  case 5:  /* blink */
  291.                  case 7: ; /* reverse */
  292.                  }
  293.                return( NUL );
  294.                }
  295.  
  296.      /* device attributes */
  297.      case 'c': {
  298.                return( NUL );
  299.                }
  300.      /* erase display according to pc1 */
  301.      case 'J': {
  302.                switch ( pc1 )
  303.                  { /* map into a clear */
  304.                  case 0:
  305.                  case 1:
  306.                  case 2: clrscrn();
  307.  
  308.                  default: {}
  309.                  }
  310.                return( NUL );
  311.                }
  312.      /* erase line according to pc1 */
  313.      case 'K': { /* map into EEOL */
  314.                case 0:
  315.                case 1:
  316.                case 2: clreor();
  317.                return( NUL );
  318.                }
  319.  
  320.  
  321.  
  322.      default: return( '?' );
  323.      }
  324.   } /* end procseq */
  325.  
  326.  
  327. UCHAR vid100( UCHAR ic, BOOL fromkey )
  328.    {
  329.    CHAR linbuf[WSLEN];  /* delete-insert buffer */
  330.    USHORT bufl;  /* num of chars to change */
  331.  
  332.    switch ( cstat )
  333.       {
  334.       /* begin escape seq. or pass back char */
  335.       case nada:    {
  336.                     if ( ic == ESC )
  337.                        {
  338.                        pc1 = pc2 = 0;
  339.                        cstat = havesc;
  340.                        return( NUL );
  341.                        }
  342.                     /* allow no ctl chars, but BSP, LF, DEL */
  343.                     if ( ic < ' ' )
  344.                        {
  345.                        if ( !fromkey )
  346.                           return( NUL );
  347.                        switch ( ic )
  348.                          {
  349.                          case '\b':  return( ic );
  350.                          case '\n': /* behave as newline */
  351.                                  {
  352.                                  if ( vrow < ScreenSize )
  353.                                     {
  354.                                     vrow++; vcol = 1;
  355.                                     setcursor( vrow, vcol, -1 );
  356.                                     }
  357.                                  return( NUL );
  358.                                  }
  359.                          /* delete char */
  360.                          case '\x02': {  /* read/shift curr. row */
  361.                                       bufl = 80 - vcol;
  362.                                       VioReadCharStr( (PCH) linbuf,
  363.                                          (PUSHORT) &bufl, vrow-1, vcol, 0 );
  364.                                       linbuf[bufl] = ' ';
  365.                                       linbuf[bufl+1] = ' ';
  366.                                       VioWrtCharStrAtt( (PCH) linbuf,
  367.                                             bufl,
  368.                                             vrow - 1,
  369.                                             vcol - 1,
  370.                                             (PBYTE) &vbfc,
  371.                                              0 );
  372.                                       setcursor( vrow, vcol, -1 );
  373.                                       return( NUL );
  374.                                       }
  375.                          default:  return( NUL );
  376.                          }
  377.                        } /* if less than blank */
  378.  
  379.                     /* if insert mode, push line over */
  380.                     if ( ( insmode ) && ( fromkey ) )
  381.                        {
  382.                        bufl = 80 - vcol;
  383.                        VioReadCharStr( (PCH) linbuf,
  384.                           (PUSHORT) &bufl, vrow-1, vcol-1, 0 );
  385.                        VioWrtCharStrAtt( (PCH) linbuf,
  386.                                             bufl,
  387.                                             vrow - 1,
  388.                                             vcol,
  389.                                             (PBYTE) &vbfc,
  390.                                              0 );
  391.                        }
  392.                     return( ic );
  393.                     }
  394.       /* if square bracket, we have leadin */
  395.       case havesc:  {
  396.  
  397.                     switch ( ic )
  398.                        {
  399.                        /* sqbracket for full leadin */
  400.                        case '[': {
  401.                                  cstat = havlead;
  402.                                  return( NUL );
  403.                                  }
  404.                        /* esc seq. being cancelled */
  405.                        case SUB:
  406.                        case CAN: {
  407.                                  cstat = nada;
  408.                                  return( NUL );
  409.                                  }
  410.  
  411.  
  412.                        /* VT52 set of sequences */
  413.                        case 'O': {
  414.                                  cstat = havescO;
  415.                                  return( NUL );
  416.                                  }
  417.                        case '=': { /* enable alt. keypad (ignore) */
  418.                                  cstat = nada;                                                                    cstat = nada;
  419.                                  return( NUL);
  420.                                  }
  421.  
  422.                        case 'i': /* for now = EEOF */
  423.                        case 'e': { /* erase eof */
  424.                                  cstat = nada;
  425.                                  clreor();
  426.                                  return( NUL );
  427.                                  }
  428.                        /* cursor to 1st pos next line,
  429.                           scrollup if bottom */
  430.                        case 'E': {
  431.                                  if ( vrow < ScreenSize )
  432.                                     {
  433.                                     vrow++; vcol = 1;
  434.                                     setcursor( vrow, vcol, -1 );
  435.                                     }
  436.                                  cstat = nada;
  437.                                  return( NUL );
  438.                                  }
  439.                        default: return( '?' );
  440.                        }
  441.                     }
  442.  
  443.       /* have ESC O sequence for 3270 input,
  444.          just process clear (M), PA2 ('m') and eat the CR
  445.          that is coming. The rest are PF, PA keys */
  446.  
  447.       case havescO: {
  448.                     if ( ( ic == 'M' ) ||
  449.                          ( ic == 'm' ) )
  450.                        clrscrn();
  451.                     cstat = eatCR;
  452.                     return( NUL );
  453.                     }
  454.  
  455.       /* consume a CR, else an error */
  456.       case eatCR: {
  457.                   cstat = nada;
  458.                   if ( ic == CR )
  459.                      return( NUL );
  460.                   else
  461.                      return( '?' );
  462.                   }
  463.  
  464.       /* consume parms to 'h' */
  465.       case eatone: {
  466.                    if ( ic == 'h' )
  467.                       {
  468.                       cstat = nada;
  469.                       }
  470.                    return( NUL );
  471.                    }
  472.  
  473.       /* set to collect numeric, or process direct */
  474.       case havlead: {
  475.                     if ( ( ic >= '0' ) && ( ic <= '9' ) )
  476.                        {
  477.                        cstat = getpc1;
  478.                        pc1 = (short) (ic - '0');
  479.                        return( NUL );
  480.                        }
  481.  
  482.                     switch ( ic )
  483.                        {
  484.                        /* leading ';' means pc1 = 0 */
  485.                        case ';': {
  486.                                  cstat = havpc1;
  487.                                  return( NUL );
  488.                                  }
  489.                        /* up cursor, scrolldown if top */
  490.                        case 'M': {
  491.                                  cstat = nada;
  492.                                  return( NUL );
  493.                                  }
  494.  
  495.                        case '?':
  496.                                  {  /* set mode parms */
  497.                                  cstat = eatone;
  498.                                  return( NUL);
  499.                                  }
  500.                        case 'h': { /* end of set mode */
  501.                                  cstat = nada; return ( NUL );
  502.                                  }
  503.  
  504.                        default: return( procseq( ic ) );
  505.                        }
  506.  
  507.                     }
  508.       /* accumulate numeric in pc1, or handle ';', or short escseq */
  509.       case getpc1:  {
  510.                     if ( ( ic >= '0' ) && ( ic <= '9' ) )
  511.                        {
  512.                        pc1 = (pc1 * 10) + (USHORT) (ic - '0');
  513.                        return( NUL );
  514.                        }
  515.                     if ( ic == ';' )
  516.                        {
  517.                        cstat = havpc1;
  518.                        return( NUL );
  519.                        }
  520.  
  521.                     return( procseq( ic ) );
  522.  
  523.                     }
  524.  
  525.  
  526.       /* we had a ';', may be another numeric */
  527.       case havpc1:  {
  528.                     /* collect pc2 */
  529.                     if ( ( ic >= '0' ) && ( ic <= '9' ) )
  530.                        {
  531.                        pc2 = (pc2 * 10) + (short) (ic - '0');
  532.                        return( NUL );
  533.                        }
  534.                     /* allow redundant ';' */
  535.                     if ( ic == ';' )
  536.                        {
  537.                        return( NUL );
  538.                        }
  539.  
  540.                     return( procseq( ic ) );
  541.  
  542.                     }
  543.       default: return( '?' );
  544.       }
  545.  
  546.    }  /* end vid100 */
  547.  
  548.  
  549.  
  550.  
  551. /* Write to Screen with VIO functions
  552.    Will block reading 'vwork' pipe.
  553.    'MsgH' will contain function, data length
  554.    functions: display, terminate */
  555. void vidout(void)
  556.    {
  557.    MsgH vidmsg;
  558.    USHORT abytes,
  559.           ix;
  560.    UCHAR  vline[WSLEN];
  561.    UCHAR  sbyt;
  562.  
  563.  
  564.    cstat = nada;
  565.  
  566.    while ( TRUE )
  567.       {
  568.       DosRead( vworkR, (PVOID) &vidmsg, sizeof(MsgH), (PUSHORT) &abytes );
  569.       if ( vidmsg.mtype == termin )
  570.          _dosendthread();
  571.  
  572.       if ( vidmsg.mtype == immed )
  573.          {
  574.          if ( keymode == SIMVT )
  575.             vidmsg.imdat = vid100( vidmsg.imdat, vidmsg.doecho );
  576.  
  577.          if ( vidmsg.imdat != '\0' )
  578.             outstr( (PUCHAR) &vidmsg.imdat, 1 );
  579.          } /* immediate byte */
  580.       else
  581.       if ( vidmsg.mtype == dhead )
  582.          {
  583.          DosRead( vworkR, (PVOID) vline, vidmsg.mlen, (PUSHORT) &abytes );
  584.          for ( ix = 0; ix < abytes; ix++ )
  585.              {
  586.              if ( keymode == SIMVT )
  587.                 sbyt = vid100( vline[ix], vidmsg.doecho );
  588.              if ( sbyt != '\0' )
  589.                 outstr( (PVOID) &sbyt, 1 );
  590.              }
  591.          } /* end if data header */
  592.       } /* end while true */
  593.    }  /* end vidout */
  594.  
  595.  
  596.  
  597.  /* end of stermv */
  598.