home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / dos_ency / 6 / cterm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-11  |  16.8 KB  |  573 lines

  1. /* Terminal Emulator    (cterm.c)
  2.  *      Jim Kyle, 1987
  3.  *
  4.  *      Uses files CH1, CH1A, and CH2 for MASM support...
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <conio.h>                      /* special console i/o      */
  9. #include <stdlib.h>                     /* misc definitions         */
  10. #include <dos.h>                        /* defines intdos()         */
  11. #include <string.h>
  12. #define BRK  'C'-'@'                    /* control characters       */
  13. #define ESC  '['-'@'
  14. #define XON  'Q'-'@'
  15. #define XOFF 'S'-'@'
  16.  
  17. #define True  1
  18. #define False  0
  19.  
  20. #define Is_Function_Key(C) ( (C) == ESC )
  21.  
  22. static char capbfr [ 4096 ];            /* capture buffer           */
  23. static int wh,
  24.      ws;
  25.  
  26. static int I,
  27.     waitchr = 0,
  28.     vflag = False,
  29.     capbp,
  30.     capbc,
  31.     Ch,
  32.     Want_7_Bit = True,
  33.     ESC_Seq_State = 0;        /* escape sequence state variable     */
  34.  
  35. int _cx ,
  36.      _cy,
  37.      _atr = 0x07,                       /* white on black           */
  38.      _pag = 0,
  39.      oldtop = 0,
  40.      oldbot = 0x184f;
  41.  
  42. FILE * in_file = NULL;         /* start with keyboard input         */
  43. FILE * cap_file = NULL;
  44.  
  45. #include "cterm.h"             /* external declarations, etc.       */
  46.  
  47. int Wants_To_Abort ()          /* checks for interrupt of script    */
  48. { return broke ();
  49. }
  50. void
  51.  
  52. main ( argc, argv ) int argc ; /* main routine                      */
  53.  char * argv [];
  54. { char * cp,
  55.      * addext ();
  56.   if ( argc > 1 )                /* check for script filename       */
  57.     in_file = fopen ( addext ( argv [ 1 ], ".SCR" ), "r" );
  58.   if ( argc > 2 )                /* check for capture filename      */
  59.     cap_file = fopen ( addext ( argv [ 2 ], ".CAP" ), "w" );
  60.   set_int ();                    /* install CH1 module              */
  61.   Set_Vid ();                    /* get video setup                 */
  62.   cls ();                        /* clear the screen                */
  63.   cputs ( "Terminal Emulator" ); /* tell who's working              */
  64.   cputs ( "\r\n< ESC for local commands >\r\n\n" );
  65.   Want_7_Bit = True;
  66.   ESC_Seq_State = 0;
  67.   Init_Comm ();                  /* set up drivers, etc.            */
  68.   while ( 1 )                           /* main loop                */
  69.     { if (( Ch = kb_file ()) > 0 )      /* check local              */
  70.         { if ( Is_Function_Key ( Ch ))
  71.             { if ( docmd () < 0 )       /* command                  */
  72.                 break;
  73.             }
  74.           else
  75.             Send_Byte ( Ch & 0x7F );    /* else send it             */
  76.         }
  77.       if (( Ch = Read_Modem ()) >= 0 )  /* check remote             */
  78.         { if ( Want_7_Bit )
  79.             Ch &= 0x7F;                 /* trim off high bit        */
  80.           switch ( ESC_Seq_State )      /* state machine            */
  81.             {
  82.             case 0 :                    /* no Esc sequence          */
  83.               switch ( Ch )
  84.                 {
  85.                 case ESC  :             /* Esc char received        */
  86.                   ESC_Seq_State = 1;
  87.                   break;
  88.  
  89.                 default :
  90.                   if ( Ch == waitchr )  /* wait if required         */
  91.                     waitchr = 0;
  92.                   if ( Ch == 12 )       /* clear screen on FF       */
  93.                     cls ();
  94.                   else
  95.                     if ( Ch != 127 )    /* ignore rubouts           */
  96.                       { putchx ( (char) Ch );  /* handle all others */
  97.                         put_cap ( (char) Ch );
  98.                       }
  99.                 }
  100.               break;
  101.  
  102.             case 1 : /* ESC -- process any escape sequences here    */
  103.               switch ( Ch )
  104.                 {
  105.                 case 'A' :              /* VT52 up                  */
  106.                   ;                     /* nothing but stubs here   */
  107.                   ESC_Seq_State = 0;
  108.                   break;
  109.  
  110.                 case 'B' :              /* VT52 down                */
  111.                   ;
  112.                   ESC_Seq_State = 0;
  113.                   break;
  114.  
  115.                 case 'C' :              /* VT52 left                */
  116.                   ;
  117.                   ESC_Seq_State = 0;
  118.                   break;
  119.  
  120.                 case 'D' :              /* VT52 right               */
  121.                   ;
  122.                   ESC_Seq_State = 0;
  123.                   break;
  124.  
  125.                 case 'E' :              /* VT52 Erase CRT           */
  126.                   cls ();               /* actually do this one     */
  127.                   ESC_Seq_State = 0;
  128.                   break;
  129.  
  130.                 case 'H' :              /* VT52 home cursor         */
  131.                   locate ( 0, 0 );
  132.                   ESC_Seq_State = 0;
  133.                   break;
  134.  
  135.                 case 'j' :              /* VT52 Erase to EOS        */
  136.                   deos ();
  137.                   ESC_Seq_State = 0;
  138.                   break;
  139.  
  140.                 case '[' :      /* ANSI.SYS - VT100 sequence        */
  141.                   ESC_Seq_State = 2;
  142.                   break;
  143.  
  144.                 default :
  145.                   putchx ( ESC );       /* pass thru all others     */
  146.                   putchx ( (char) Ch );
  147.                   ESC_Seq_State = 0;
  148.                 }
  149.               break;
  150.  
  151.             case 2 :                    /* ANSI 3.64 decoder        */
  152.               ESC_Seq_State = 0;        /* not implemented          */
  153.             }
  154.         }
  155.       if ( broke ())                    /* check CH1A handlers      */
  156.         { cputs ( "\r\n***BREAK***\r\n" );
  157.           break;
  158.         }
  159.     }                                   /* end of main loop         */
  160.   if ( cap_file )                       /* save any capture         */
  161.     cap_flush ();
  162.   Term_Comm ();                         /* restore when done        */
  163.   rst_int ();                           /* restore break handlers   */
  164.   exit ( 0 );                           /* be nice to MS-DOS        */
  165. }
  166.  
  167. docmd ()                                /* local command shell      */
  168. { FILE * getfil ();
  169.   int wp;
  170.   wp = True;
  171.   if ( ! in_file || vflag )
  172.     cputs ( "\r\n\tCommand: " );        /* ask for command          */
  173.   else
  174.     wp = False;
  175.   Ch = toupper ( kbd_wait ());          /* get response             */
  176.   if ( wp )
  177.     putchx ( (char) Ch );
  178.   switch  ( Ch )                         /* and act on it           */
  179.     {
  180.     case 'S' :
  181.       if ( wp )
  182.         cputs ( "low speed\r\n" );
  183.       Set_Baud ( 300 );
  184.       break;
  185.  
  186.     case 'D' :
  187.       if ( wp )
  188.         cputs ( "elay (1-9 sec): " );
  189.       Ch = kbd_wait ();
  190.       if ( wp )
  191.         putchx ( (char) Ch );
  192.       Delay ( 1000 * ( Ch - '0' ));
  193.       if ( wp )
  194.         putchx ( '\n' );
  195.       break;
  196.  
  197.     case 'E' :
  198.       if ( wp )
  199.         cputs ( "ven Parity\r\n" );
  200.       Set_Parity ( 2 );
  201.       break;
  202.  
  203.     case 'F' :
  204.       if ( wp )
  205.         cputs ( "ast speed\r\n" );
  206.       Set_Baud ( 1200 );
  207.       break;
  208.  
  209.     case 'H' :
  210.       if ( wp )
  211.         { cputs ( "\r\n\tVALID COMMANDS:\r\n" );
  212.           cputs ( "\tD = delay 0-9 seconds.\r\n" );
  213.           cputs ( "\tE = even parity.\r\n" );
  214.           cputs ( "\tF = (fast) 1200-baud.\r\n" );
  215.           cputs ( "\tN = no parity.\r\n" );
  216.           cputs ( "\tO = odd parity.\r\n" );
  217.           cputs ( "\tQ = quit, return to DOS.\r\n" );
  218.           cputs ( "\tR = reset modem.\r\n" );
  219.           cputs ( "\tS = (slow) 300-baud.\r\n" );
  220.           cputs ( "\tU = use script file.\r\n" );
  221.           cputs ( "\tV = verify file input.\r\n" );
  222.           cputs ( "\tW = wait for char." );
  223.         }
  224.       break;
  225.  
  226.     case 'N' :
  227.       if ( wp )
  228.         cputs ( "o Parity\r\n" );
  229.       Set_Parity ( 1 );
  230.       break;
  231.  
  232.     case 'O' :
  233.       if ( wp )
  234.         cputs ( "dd Parity\r\n" );
  235.       Set_Parity ( 3 );
  236.       break;
  237.  
  238.     case 'R' :
  239.       if ( wp )
  240.         cputs ( "ESET Comm Port\r\n" );
  241.       Init_Comm ();
  242.       break;
  243.  
  244.     case 'Q' :
  245.       if ( wp )
  246.         cputs ( " = QUIT Command\r\n" );
  247.       Ch = ( - 1 );
  248.       break;
  249.  
  250.     case 'U' :
  251.       if ( in_file && ! vflag )
  252.         putchx ( 'U' );
  253.       cputs ( "se file: " );
  254.       getfil ();
  255.       cputs ( "File " );
  256.       cputs ( in_file ? "Open\r\n" : "Bad\r\n" );
  257.       waitchr = 0;
  258.       break;
  259.  
  260.     case 'V' :
  261.       if ( wp )
  262.         { cputs ( "erify flag toggled " );
  263.           cputs ( vflag ? "OFF\r\n" : "ON\r\n" );
  264.         }
  265.       vflag = vflag ? False : True;
  266.       break;
  267.  
  268.     case 'W' :
  269.       if ( wp )
  270.         cputs ( "ait for: <" );
  271.       waitchr = kbd_wait ();
  272.       if ( waitchr == ' ' )
  273.         waitchr = 0;
  274.       if ( wp )
  275.         { if ( waitchr )
  276.             putchx ( (char) waitchr );
  277.           else
  278.             cputs ( "no wait" );
  279.           cputs ( ">\r\n" );
  280.         }
  281.       break;
  282.  
  283.     default :
  284.       if ( wp )
  285.         { cputs ( "Don't know " );
  286.           putchx ( (char) Ch );
  287.           cputs ( "\r\nUse 'H' command for Help.\r\n" );
  288.         }
  289.       Ch = '?';
  290.     }
  291.   if ( wp )                             /* if window open...        */
  292.     { cputs ( "\r\n[any key]\r" );
  293.       while ( Read_Keyboard () == EOF ) /* wait for response        */
  294.         ;
  295.     }
  296.   return Ch ;
  297. }
  298.  
  299. kbd_wait ()                             /* wait for input           */
  300. { int c ;
  301.   while (( c = kb_file ()) == ( - 1 ))
  302.     ;
  303.   return c & 255;
  304. }
  305.  
  306. kb_file ()                              /* input from kb or file    */
  307. { int c ;
  308.   if ( in_file )                        /* USING SCRIPT             */
  309.     { c = Wants_To_Abort ();            /* use first as flag        */
  310.       if ( waitchr && ! c )
  311.         c = ( - 1 );                    /* then for char            */
  312.       else
  313.         if ( c || ( c = getc ( in_file )) == EOF || c == 26 )
  314.           { fclose ( in_file );
  315.             cputs ( "\r\nScript File Closed\r\n" );
  316.             in_file = NULL;
  317.             waitchr = 0;
  318.             c = ( - 1 );
  319.           }
  320.       else
  321.         if ( c == '\n' )                /* ignore LF's in file      */
  322.           c = ( - 1 );
  323.       if ( c == '\\' )                  /* process Esc sequence     */
  324.         c = esc ();
  325.       if ( vflag && c != ( - 1 ))       /* verify file char         */
  326.         { putchx ( '{' );
  327.           putchx ( (char) c );
  328.           putchx ( '}' );
  329.         }
  330.     }
  331.   else                                  /* USING CONSOLE            */
  332.     c = Read_Keyboard ();               /* if not using file        */
  333.   return ( c );
  334. }
  335.  
  336. esc ()                                  /* script translator        */
  337. { int c ;
  338.   c = getc ( in_file );                 /* control chars in file    */
  339.   switch ( toupper ( c ))
  340.     {
  341.     case 'E' :
  342.       c = ESC;
  343.       break;
  344.  
  345.     case 'N' :
  346.       c = '\n';
  347.       break;
  348.  
  349.     case 'R' :
  350.       c = '\r';
  351.       break;
  352.  
  353.     case 'T' :
  354.       c = '\t';
  355.       break;
  356.  
  357.     case '^' :
  358.       c = getc ( in_file ) & 31;
  359.       break;
  360.     }
  361.   return ( c );
  362. }
  363.  
  364. FILE * getfil ()
  365. { char fnm [ 20 ];
  366.   getnam ( fnm, 15 );                   /* get the name             */
  367.   if ( ! ( strchr ( fnm, '.' )))
  368.     strcat ( fnm, ".SCR" );
  369.   return ( in_file = fopen ( fnm, "r" ));
  370. }
  371.  
  372. void getnam ( b, s ) char * b;          /* take input to buffer     */
  373.  int s ;
  374. { while ( s -- > 0 )
  375.     { if (( * b = kbd_wait ()) != '\r' )
  376.         putchx ( * b ++ );
  377.       else
  378.         break ;
  379.     }
  380.   putchx ( '\n' );
  381.   * b = 0;
  382. }
  383.  
  384. char * addext ( b,                      /* add default EXTension    */
  385.      e ) char * b,
  386.      * e;
  387. { static char bfr [ 20 ];
  388.   if ( strchr ( b, '.' ))
  389.     return ( b );
  390.   strcpy ( bfr, b );
  391.   strcat ( bfr, e );
  392.   return ( bfr );
  393. }
  394.  
  395. void put_cap ( c ) char c ;
  396. { if ( cap_file && c != 13 )            /* strip out CR's           */
  397.     fputc ( c, cap_file );              /* use MS-DOS buffering     */
  398. }
  399.  
  400. void cap_flush ()                       /* end Capture mode         */
  401. { if ( cap_file )
  402.     { fclose ( cap_file );
  403.       cap_file = NULL;
  404.       cputs ( "\r\nCapture file closed\r\n" );
  405.     }
  406. }
  407.  
  408. /*      TIMER SUPPORT STUFF (IBMPC/MSDOS)                           */
  409. static long timr;                       /* timeout register         */
  410.  
  411. static union REGS rgv ;
  412.  
  413. long getmr ()
  414. { long now ;                            /* msec since midnite       */
  415.   rgv.x.ax = 0x2c00;
  416.   intdos ( & rgv, & rgv );
  417.   now = rgv.h.ch;                       /* hours                    */
  418.   now *= 60L;                           /* to minutes               */
  419.   now += rgv.h.cl;                      /* plus min                 */
  420.   now *= 60L;                           /* to seconds               */
  421.   now += rgv.h.dh;                      /* plus sec                 */
  422.   now *= 100L;                          /* to 1/100                 */
  423.   now += rgv.h.dl;                      /* plus 1/100               */
  424.   return ( 10L * now );                 /* msec value               */
  425. }
  426.  
  427. void Delay ( n ) int n ;                /* sleep for n msec         */
  428. { long wakeup ;
  429.   wakeup = getmr () + ( long ) n;       /* wakeup time              */
  430.   while ( getmr () < wakeup )
  431.     ;                                   /* now sleep                */
  432. }
  433.  
  434. void Start_Timer ( n ) int n ;          /* set timeout for n sec    */
  435. { timr = getmr () + ( long ) n * 1000L;
  436. }
  437.  
  438. Timer_Expired ()        /* if timeout return 1 else return 0        */
  439. { return ( getmr () > timr );
  440. }
  441.  
  442. Set_Vid ()
  443. { _i_v ();                              /* initialize video         */
  444.   return 0;
  445. }
  446.  
  447. void locate ( row, col ) int row ,
  448.      col;
  449. { _cy = row % 25;
  450.   _cx = col % 80;
  451.   _wrpos ( row, col );                  /* use ML from CH2.ASM      */
  452. }
  453.  
  454. void deol ()
  455. { _deol ();                             /* use ML from CH2.ASM      */
  456. }
  457.  
  458. void deos ()
  459. { deol ();
  460.   if ( _cy < 24 )                       /* if not last, clear       */
  461.     { rgv.x.ax = 0x0600;
  462.       rgv.x.bx = ( _atr << 8 );
  463.       rgv.x.cx = ( _cy + 1 ) << 8;
  464.       rgv.x.dx = 0x184F;
  465.       int86 ( 0x10, & rgv, & rgv );
  466.     }
  467.   locate ( _cy, _cx );
  468. }
  469.  
  470. void cls ()
  471. { _cls ();                              /* use ML                   */
  472. }
  473.  
  474. void cursor ( yn ) int yn ;
  475. { rgv.x.cx = yn ? 0x0607 : 0x2607;      /* ON/OFF                   */
  476.   rgv.x.ax = 0x0100;
  477.   int86 ( 0x10, & rgv, & rgv );
  478. }
  479.  
  480. void revvid ( yn ) int yn ;
  481. { if ( yn )
  482.     _atr = _color ( 8, 7 );             /* black on white           */
  483.   else
  484.     _atr = _color ( 15, 0 );            /* white on black           */
  485. }
  486.  
  487. putchx ( c ) char c ;                   /* put char to CRT          */
  488. { if ( c == '\n' )
  489.     putch ( '\r' );
  490.   putch ( c );
  491.   return c ;
  492. }
  493.  
  494. Read_Keyboard ()                    /* get keyboard character
  495.                                        returns -1 if none present   */
  496. { int c ;
  497.   if ( kbhit ())                        /* no char at all           */
  498.     return ( getch ());
  499.   return ( EOF );
  500. }
  501.  
  502. /*      MODEM SUPPORT                   */
  503. static char mparm,
  504.      wrk [ 80 ];
  505.  
  506. void Init_Comm ()               /* initialize comm port stuff       */
  507. { static int ft = 0;                    /* firstime flag            */
  508.   if ( ft ++ == 0 )
  509.     i_m ();
  510.   Set_Parity ( 1 );                     /* 8,N,1                    */
  511.   Set_Baud ( 1200 );                    /* 1200 baud                */
  512. }
  513.  
  514. #define B1200 0x80                      /* baudrate codes           */
  515. #define B300 0x40
  516.  
  517. Set_Baud ( n ) int n ;                  /* n is baud rate           */
  518. { if ( n == 300 )
  519.     mparm = ( mparm & 0x1F ) + B300;
  520.   else
  521.     if ( n == 1200 )
  522.       mparm = ( mparm & 0x1F ) + B1200;
  523.   else
  524.     return 0;                           /* invalid speed            */
  525.   sprintf ( wrk, "Baud rate = %d\r\n", n );
  526.   cputs ( wrk );
  527.   set_mdm ( mparm );
  528.   return n ;
  529. }
  530.  
  531. #define PAREVN 0x18                     /* MCR bits for commands    */
  532. #define PARODD 0x10
  533. #define PAROFF 0x00
  534. #define STOP2 0x40
  535. #define WORD8 0x03
  536. #define WORD7 0x02
  537. #define WORD6 0x01
  538.  
  539. Set_Parity ( n ) int n ;                /* n is parity code         */
  540. { static int mmode;
  541.   if ( n == 1 )
  542.     mmode = ( WORD8 | PAROFF );         /* off                      */
  543.   else
  544.     if ( n == 2 )
  545.       mmode = ( WORD7 | PAREVN );       /* on and even              */
  546.   else
  547.     if ( n == 3 )
  548.       mmode = ( WORD7 | PARODD );       /* on and odd               */
  549.   else
  550.     return 0;                           /* invalid code             */
  551.   mparm = ( mparm & 0xE0 ) + mmode;
  552.   sprintf ( wrk, "Parity is %s\r\n", ( n == 1 ? "OFF" :
  553.                                      ( n == 2 ? "EVEN" : "ODD" )));
  554.   cputs ( wrk );
  555.   set_mdm ( mparm );
  556.   return n ;
  557. }
  558.  
  559. Write_Modem ( c ) char c ;              /* return 1 if ok, else 0   */
  560. { wrtmdm ( c );
  561.   return ( 1 );                         /* never any error          */
  562. }
  563.  
  564. Read_Modem ()
  565. { return ( rdmdm ());                   /* from int bfr             */
  566. }
  567.  
  568. void Term_Comm ()               /* uninstall comm port drivers      */
  569. { u_m ();
  570. }
  571.  
  572. /* end of cterm.c */
  573.