home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 11 / 11.iso / n / n002 / 4.ddi / DEMOS.ZIP / ANSITERM.C next >
Encoding:
C/C++ Source or Header  |  1991-07-16  |  56.9 KB  |  1,627 lines

  1. /*
  2.     ANSIterm.c -  ANSI terminal emulator with Intelligent modem
  3.                   support  and file transfer protocols
  4.   
  5.     You are free to use this program as you see fit, with or
  6.     without the copyright notices.
  7.   
  8.     (C) Copyright 1986, 1987, 1988, 1989, 1991 South Mountain Software, Inc.
  9.   
  10. */
  11.   
  12. #include    <stdio.h>               /* Standard terminal stuff */
  13. #include    <dos.h>
  14. #include    <stdlib.h>
  15. #include    <string.h>
  16.   
  17. #include    "eclproto.h"
  18. #include    "im.h"                  /* Intelligent modem services */
  19. #include    "xm.h"                  /* XMODEM services */
  20. #include    "xc.h"                  /* Communications services */
  21. #include    "i86.h"                 /* int86 header for bios access */
  22. /*  Keyboard definitions   */
  23.   
  24. #define FK1         0x3B00          /* Function key 1 */
  25. #define FK2         0x3C00          /* Function key 2 */
  26. #define FK3         0x3D00          /* Function key 3 */
  27. #define FK4         0x3E00          /* Function key 4 */
  28. #define FK5         0x3F00          /* Function key 5 */
  29. #define FK6         0x4000          /* Function key 6 */
  30. #define RUB1        0x08            /* Rubout */
  31. #define RUB2        0x7F            /* Rubout */
  32. #define RET         0x0D            /* CR */
  33.   
  34. #define UP_ARROW     0x4800
  35. #define DOWN_ARROW   0x5000
  36. #define RIGHT_ARROW  0x4d00
  37. #define LEFT_ARROW   0x4b00
  38. #define BACKSPACE    0x0e08
  39. #define ESC          0x1b
  40. #ifndef SAVE_STATROW                /* if non-zero, STATUSROW will not be
  41.                                      overwritten. - this is default */
  42. #define SAVE_STATROW 23
  43. #endif
  44.   
  45. /*  Dirty definitions */
  46.   
  47. #define CLEAN       0               /* <dirty> no cleanup necessary */
  48. #define CLRSCREEN   1               /* <dirty> clear screen */
  49. #define CLRSTATUS   2               /* <dirty> clear status part only */
  50.   
  51. /*  Miscellaneous  */
  52.   
  53. #define MIN_BUFFERS  8              /* Minimum buffers required */
  54. #define SCROLL       1              /* Scroll flag value */
  55. #define CLEARS       0              /* Clear the screen value */
  56. #define MAXFIELD    79              /* Maximum field */
  57. #define STATUSROW   24              /* Row address of status row */
  58. #define SCRWIDTH    79              /* Last column */
  59. #define STATCOLUMN  57              /* Starting column of rightmost status */
  60. #define STATWIDTH   22              /* Width of the rightmost status */
  61.   
  62. /*  Field indices (into the <text> array structure) */
  63.   
  64. #define INTRO1      0               /* <text> structure entry */
  65. #define INTRO2      1
  66. #define INTRO3      2
  67. #define DATA_FILE   3
  68. #define ONLINEMSG   4
  69. #define DATA_DEFAUL 5
  70. #define MAIN_F1     6
  71. #define MAIN_F2     7
  72. #define MAIN_F3     8
  73. #define MAIN_F4     9
  74. #define DUMMY       10
  75. #define NOCONN      11
  76. #define NULL_STR    12
  77. #define DIALING     13
  78. #define INITMODEM   14
  79. #define HANGUP      15
  80. #define XUPLOAD     16
  81. #define XDOWNLOAD   17
  82. #define XEXIT       18
  83.   
  84. #define XMODEM      19
  85. #define SESSION     20
  86. #define FAILED      21
  87. #define CANCELLD    22
  88. #define USERABORT   23
  89. #define FILEOPEN    24
  90. #define FILEIO      25
  91. #define GETUPLOAD   26
  92. #define GETDOWNLOAD 27
  93.   
  94. #define COMPORT     28
  95. #define COMBAUD     37
  96. #define COMPARITY   47
  97. #define COMDATA     50
  98. #define COMSTOP     52
  99.   
  100. #define COM_HELP    54
  101. #define COM_ACCEPT  55
  102. #define COM_ABORT   56
  103. #define COM_ACP     57
  104. #define YMODEM      58
  105. #define XM_CRC      59
  106. #define XM_1K       60
  107. #define KERMIT      61
  108. #define ZMODEM      62
  109. #define XMODEM_EXIT 63
  110. #define PRT_ON      64
  111. #define PRT_OFF     65
  112. #define NO_CARRIER  66
  113. #define NO_DIALTONE 67
  114. #define LINE_BUSY   68
  115. #define DWNLD_PATH  69
  116. #define NOMODOPEN   70
  117. #define CONN        71
  118.   
  119. #define TABWIDTH     4                 /* set a tab every TABWIDTH */
  120. #define LEFT_BRACKET '['               /* escape char for ANSI */
  121.   
  122. /* external defined globals */
  123. extern int km_7bit[];
  124.   
  125. /* forward function declarations */
  126. static int is_break(void);  /* Test for the presence of a Ctrl-Break abort */
  127. static int eterm_init(void);    /* Load in the default ETERM data configuration file */
  128. static int main_menu(int dirty_flag);
  129. static int donline(void);  /* donline - display on-line status message */
  130. static int window_sc(int row,int row_count,int column,char attribute,int flag);                           /* SCROLL or CLEARS flag */
  131. static int dfield(int index);
  132. static int echo(char ch);
  133. static void sclear(int column);
  134. static void wclear(void);
  135. static int config(void);
  136. static int transfer(void);
  137. static int getinput(char *buffer);
  138. static void process_escape_sequence(int mode,char ch);
  139. static void delete_1_char(void);
  140. static int insert_1_char(void);
  141. static int term_curup(void);
  142. static int term_curdown(void);
  143. static int term_curfwd(void);
  144. static int term_clreol(void);
  145. static int term_clreos(void);
  146. static int term_curinsrt(void);
  147. static int term_curdelet(void);
  148. static int term_scroll(int up_row,int up_col,int low_row,int low_col,int dir);
  149. static int set_video_mode(void);
  150. static void memory_to_screen(unsigned words, unsigned offset,char *buffer);
  151. static void screen_to_memory(unsigned words,unsigned offset,char *buffer);
  152. static int prthelp(void);
  153.   
  154. /* Module Globals */
  155. static int in_underscore_mode = 0;     /* flag for ANSI */
  156. static int in_standout_mode = 0;       /* flag for ANSI */
  157. static int command_in_progress = 0; /* flag to signal end of ESC sequence */
  158. static int waiting_for_bracket = 0; /* flag when '[' should be next char */
  159. static int ansi_first_num = 0;      /* flag when working on numerics */
  160. static int num_ptr = 0;             /* keeps place in numeric strings */
  161. static char num1[3], num2[3];          /* string buffers to hold numbers */
  162. static int int1, int2;                 /* integers formed from num strings */
  163. static int lprt_status = 0;         /* 0 = no printer, else go to printer */
  164. static int video_mode = 0;          /* current video mode set here */
  165. static char scrbuf[3*160];          /* buffer to hold 2 lines of screen */
  166. static int modem_type = IM_STANDARD_TYPE;  /* default standard type modem */
  167. static int hwhs;                    /* Hardware Handshaking flag */
  168. static int uart_mode;               /* enable/disable 16550 flag */
  169. static int trigger;                 /* 16550 receive interrupt trigger value */
  170.   
  171.   
  172. /*
  173.     === constants ========================================================
  174. */
  175.   
  176. static char    config_file[]=  "ETERM.DAT";
  177.   
  178. static
  179. struct {
  180.     int row;                            /* Row coordinate */
  181.     int col;                            /* Column coordinate */
  182.     int wid;                            /* Width */
  183.     char *str;                          /* Character string */
  184. } text[] = {
  185.     { 5, 9, 0, "South Mountain Software Terminal Emulator"}, /* INTRO1 */
  186.     { 7, 9, 0, "Copyright (C) 1987, 1988, 1989, 1991 South Mountain Software, Inc."}, /* INTRO2 */
  187.     { 9, 9, 0, "Revision 4.0"},
  188.   
  189.     { STATUSROW, STATCOLUMN, STATWIDTH, "Using ETERM.DAT setup" },
  190.     { STATUSROW, STATCOLUMN, STATWIDTH, "ANSI emulation" },
  191.     { STATUSROW, STATCOLUMN, STATWIDTH, "Default setup" },
  192.   
  193.     { STATUSROW,  0, 11, "F1 TRANSFER" },
  194.     { STATUSROW, 12,  8, "F2 Setup" },
  195.     { STATUSROW, 21,  8, "F3 Clear" },
  196.     { STATUSROW, 41, 13, "[Ctl-Brk]Exit" },
  197.     { STATUSROW, STATCOLUMN - 2, 1, "\360" },
  198.     { STATUSROW, STATCOLUMN, STATWIDTH, "No connection" },
  199.     { STATUSROW, 0, SCRWIDTH, "" },
  200.     { STATUSROW, STATCOLUMN, STATWIDTH, "Dialing ..." },
  201.     { STATUSROW, STATCOLUMN, STATWIDTH, "Setup modem ..." },
  202.     { STATUSROW, STATCOLUMN, STATWIDTH, "Hanging up ..." },
  203.   
  204.     { STATUSROW, 0 , 11, "[F1] Upload" },
  205.     { STATUSROW, 13, 13, "[F2] Download" },
  206.     { STATUSROW, 27, 17, "[Ctrl-Break] Exit" },
  207.   
  208.     { STATUSROW, STATCOLUMN, STATWIDTH+2, "TRANSFER successful" },
  209.     { STATUSROW, STATCOLUMN, STATWIDTH, "Session error" },
  210.     { STATUSROW, STATCOLUMN, STATWIDTH+2, "TRANSFER failed" },
  211.     { STATUSROW, STATCOLUMN, STATWIDTH+2, "TRANSFER cancelled" },
  212.     { STATUSROW, STATCOLUMN, STATWIDTH, "User aborted" },
  213.     { STATUSROW, STATCOLUMN, STATWIDTH, "File open error" },
  214.     { STATUSROW, STATCOLUMN, STATWIDTH, "File I/O error" },
  215.     { STATUSROW, 0, STATCOLUMN - 1, "Upload filename: " },
  216.     { STATUSROW, 0, STATCOLUMN - 1, "Download filename: " },
  217.   
  218.     { STATUSROW, 0, 9, "[F1] COM1" },
  219.     { STATUSROW, 0, 9, "[F1] COM2" },
  220.     { STATUSROW, 0, 9, "[F1] COM3" },
  221.     { STATUSROW, 0, 9, "[F1] COM4" },
  222.     { STATUSROW, 0, 9, "[F1] COM5" },
  223.     { STATUSROW, 0, 9, "[F1] COM6" },
  224.     { STATUSROW, 0, 9, "[F1] COM7" },
  225.     { STATUSROW, 0, 9, "[F1] COM8" },
  226.     { STATUSROW, 0, 9, "[F1] COM9" },
  227.   
  228.     { STATUSROW, 10,  9, "[F2] 57K " },
  229.     { STATUSROW, 10,  9, "[F2] 115K" },
  230.     { STATUSROW, 10,  9, "[F2] 300 " },
  231.     { STATUSROW, 10,  9, "[F2] 600 " },
  232.     { STATUSROW, 10,  9, "[F2] 1200" },
  233.     { STATUSROW, 10,  9, "[F2] 2400" },
  234.     { STATUSROW, 10,  9, "[F2] 4800" },
  235.     { STATUSROW, 10,  9, "[F2] 9600" },
  236.     { STATUSROW, 10,  9, "[F2] 19K " },
  237.     { STATUSROW, 10,  9, "[F2] 38K " },
  238.   
  239.     { STATUSROW, 20, 12, "[F3] NO PAR" },
  240.     { STATUSROW, 20, 12, "[F3] ODD PAR" },
  241.     { STATUSROW, 20, 12, "[F3] EVN PAR" },
  242.   
  243.     { STATUSROW, 33, 11, "[F4] 7 DATA" },
  244.     { STATUSROW, 33, 11, "[F4] 8 DATA" },
  245.   
  246.     { STATUSROW, 45, 11, "[F5] 1 STOP" },
  247.     { STATUSROW, 45, 11, "[F5] 2 STOP" },
  248.   
  249.     { STATUSROW, STATCOLUMN, STATWIDTH, "\021\304\304\331 or Ctrl-Break" },
  250.     { STATUSROW, STATCOLUMN, STATWIDTH, "Setup accepted" },
  251.     { STATUSROW, STATCOLUMN, STATWIDTH, "Setup cancelled" },
  252.     { STATUSROW, STATCOLUMN, STATWIDTH, "Accepted, reload ETERM" },
  253.   
  254.     { STATUSROW,  0, 11, "[F1] YMODEM" },
  255.     { STATUSROW, 12, 15, "[F2] XMODEM/CRC" },
  256.     { STATUSROW, 28, 14, "[F3] XMODEM-1K" },
  257.     { STATUSROW, 43, 11, "[F4] KERMIT"},
  258.     { STATUSROW, 55, 11, "[F5] ZMODEM"},
  259.     { STATUSROW, 67, 13, "[Ctl-Brk]Exit" },
  260.     { STATUSROW, 30,10, "F4 PRT ON "},
  261.     { STATUSROW, 30,10, "F4 PRT OFF"},
  262.   
  263.     { STATUSROW, STATCOLUMN, STATWIDTH, "NO CARRIER" },
  264.     { STATUSROW, STATCOLUMN, STATWIDTH, "NO DIALTONE" },
  265.     { STATUSROW, STATCOLUMN, STATWIDTH, "BUSY - NO CONNECT" },
  266.     { STATUSROW, 0, STATCOLUMN - 1, "Download Pathname: " },
  267.     { STATUSROW, STATCOLUMN, STATWIDTH, "Unable to open modem" },
  268.   
  269.   
  270.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 300" },
  271.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 600 Baud" },
  272.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 1200 Baud" },
  273.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 2400 Baud" },
  274.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 4800 Baud" },
  275.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 9600 Baud" },
  276.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 19200 Baud" },
  277.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 38400 Baud" },
  278.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 57K Baud" },
  279.     { STATUSROW, STATCOLUMN, STATWIDTH, "Connect 115K Baud" },
  280.     { 0, 0, 0, "" }
  281.   
  282. };
  283. /*
  284.     ======================================================================
  285. */
  286. /*
  287.     === global data base =================================================
  288.   
  289.     ETERM.DAT   Configuration data base format:
  290. */
  291.   
  292. static int Port = COM1;                    /* Default communications port */
  293. static int Baud = BAUD1200;                /* Default baud rate */
  294. static int Parity = NOPAR;                 /* Default parity */
  295. static int Data = DATA8;                   /* Default data bit size */
  296. static int Stop = STOP1;                   /* Default stop bit */
  297. static int attr_status = 0x70;             /* Default attribute */
  298. static int attr_text   = 0x07;             /* Text window (emulator) attribute */
  299. static int max_ports;                      /* Maximum supported ports - rev 2.0 */
  300.   
  301. static int dirty = CLRSCREEN;              /* Clear screen initially */
  302.   
  303.   
  304.   
  305. static char xmodeminfo[] =
  306. "Blocks transferred [%d]  refused [%d]  timeouts [%d]  garbled [%d]";
  307.   
  308. void main(
  309. int argc,                           /* Argument count */
  310. char *argv[])                       /* Argument variables */
  311. {
  312.     int status = 2;                 /* Index into status messages */
  313.     int key;                        /* Scan code and ASCII key */
  314.     char charin;                    /* character read in */
  315.     int  ic_delay;
  316.     int err;
  317.     int rc;      /* return code */
  318.   
  319. #ifdef MULTI_TEST
  320.     unsigned address;               /* used in setport debugging (F5) */
  321.     int startport, irq;
  322.     int board,
  323.     int  p_addr;
  324. #endif
  325.   
  326.     if (!((argc==4)||(argc==5)||(argc==6)||(argc==2)))
  327.       {
  328.       prthelp();
  329.       return;
  330.       }
  331.     if(argc == 2)
  332.       {
  333.       if((argv[1][1] != 'd' && argv[1][1] != 'D')
  334.          || (argv[1][0] != '/' && argv[1][0] != '-') )
  335.             {
  336.             prthelp();
  337.             return;
  338.             }
  339.       }
  340.  
  341.  
  342.     set_video_mode();               /* get/set video mode */
  343.   
  344.     switch (xc_entr(MIN_BUFFERS)) {
  345.         case 0:                         /* Enough buffers are available */
  346.             status = 0;                 /* Assume all is OK */
  347.             max_ports = 9;              /* hardcode maxports to COM9 */
  348.         /* do port initialization */
  349.             if(argc > 2 && argc <= 6)
  350.                {
  351.                    hwhs = atoi(argv[1]);
  352.                    uart_mode = atoi(argv[2]);
  353.                    trigger = atoi(argv[3]);
  354.                   set_16550(Port,uart_mode,trigger);
  355.                }
  356.             else
  357.                {  /* see if /d or -D for default */
  358.                if(argc == 2)
  359.                   {
  360.                         hwhs = uart_mode = trigger = 0;
  361.                      set_16550(Port,uart_mode,trigger);
  362.                   }
  363.                }
  364.  
  365.             eterm_init();
  366.             xck_link();              /* Enable Ctrl-Break processing */
  367.   
  368. /*  *** Optionally, dial the modem ***  */
  369.   
  370.             if (argc>=5) {
  371.                 dfield(INITMODEM);
  372.                 modem_type = atoi(argv[4]);
  373.                 if (modem_type == IM_STANDARD_TYPE)
  374.                    ic_delay = 2;
  375.                 else 
  376.                    ic_delay = 2;
  377.                 im_setmodem(Port,modem_type,ic_delay);
  378.                 rc = im_fopen(Port);
  379.                 if (rc == 0 && argc == 6)  {
  380.                      im_spkr(Port,IM_SPKR_OFF);
  381.                      dfield(DIALING);
  382.                      rc = im_dial(Port, argv[5]);
  383.                      if (rc >= 0)  {
  384.                          if (im_modem[Port].modem_type==IM_STANDARD_TYPE) {
  385.                              if (rc == IM_CONCT) {
  386.                           /* if newly connected Baud rate differs from
  387.                              initial, then change Baud rate */
  388.                                  if (im_modem[Port].im_baud != Baud)  {
  389.                                      Baud = im_modem[Port].im_baud;
  390.                                      xc_init(Port, Baud, NOPAR, DATA8, STOP1);
  391.                                  }
  392.                              /* display correct connect message */
  393.                                  dfield((CONN+(Baud)-2));
  394.                              }
  395.                              else
  396.                                  dfield(NOCONN);
  397.                          }
  398.                          else  {
  399.                              switch (rc)  {
  400.                                  case 3:
  401.                                      dfield(NO_CARRIER);
  402.                                      break;
  403.                                  case 6:
  404.                                      dfield(NO_DIALTONE);
  405.                                      break;
  406.                                  case 7:
  407.                                      dfield(LINE_BUSY);
  408.                                      break;
  409.                                  default:
  410.                                 /* display correct connect message */
  411.                                      dfield((CONN+(Baud)-2));
  412.                              }
  413.                          }
  414.                      }
  415.                      else
  416.                         dfield(NOCONN);
  417.                      }
  418.                 else
  419.                     if(rc != 0)
  420.                        dfield(NOMODOPEN);
  421.                     
  422.             }
  423.   
  424.             xct_link();
  425.             xct_pend(20);
  426.             wclear();
  427.             xct_unlk();
  428.   
  429. /*  *** Process every key or incoming character ***  */
  430.   
  431.             while (status == 0) {
  432.                 if (xck_keyt()) {
  433.                     if (dirty) {
  434.                         donline();         /* Change status message */
  435.                         dirty = CLEAN;     /* Clear the refresh flag & screen */
  436.                     }
  437.                     switch (key = xck_getc()) {
  438.                         case FK1:               /* File Transfer */
  439.                             transfer();
  440.                             main_menu(CLRSTATUS);
  441.                             break;
  442.                         case FK2:               /* Setup */
  443.                             config();
  444.                             main_menu(CLRSTATUS);
  445.                             break;
  446.                         case FK3:               /* Refresh */
  447.                             main_menu(CLRSTATUS);
  448.                             wclear();
  449.                             break;
  450.                         case FK4:
  451.                             lprt_status = (lprt_status) ? 0 : 1 ;
  452.                             if(lprt_status)
  453.                                 dfield(PRT_ON);
  454.                             else
  455.                                 dfield(PRT_OFF);
  456.                             break;
  457.   
  458. /**   code for FK5 and FK6 only used in debugging  **/
  459. #ifdef RTS_TEST
  460.                         case FK5:
  461.                             xc_rts(Port,1);
  462.                             break;
  463.                         case FK6:
  464.                             xc_rts(Port,0);
  465.                             break;
  466. #endif
  467. #ifdef DTR_TEST
  468.                         case FK5:
  469.                             xc_dtr(Port,1);
  470.                             break;
  471.                         case FK6:
  472.                             xc_dtr(Port,0);
  473.                             break;
  474. #endif
  475. #ifdef MULTI_TEST
  476.                         case FK5:
  477.                             wclear();
  478.                             printf("\nenter 0 for MU440 or 1 for digibord or 2 for stargate\n: ");
  479.                             printf("enter 3 for stargate secondary, 4 for digimc 5 for setport\n: ");
  480.                             printf("enter 6 to quit this option\n");
  481.                             scanf("%d",&board);
  482.                             if(board != 6)
  483.                             {
  484.                                 printf("enter starting port and irq: ");
  485.                                 scanf("%d %d",&startport,&irq);
  486.                                 printf("enter baud rate for port1 (300=2, 1200=4, 9600=7");
  487.                                 scanf("%d",&Baud);
  488.   
  489.                                 printf("enter  Port (COM1=0, COM2=1, ... COM9=8) : "); /*jhl 8-9-89*/
  490.                                 scanf("%d",&Port);
  491.                                 if(board == 1){
  492.                                     printf("enter status port address in HEX: ");
  493.                                     scanf("%x",&address);
  494.                                     setdigi(1,address,irq,startport,0);
  495.                         /**********  used for testing two digiboards
  496.                          if(1){
  497.                             printf("enter port address in hex or 0 for default: ");
  498.                             scanf("%x",&p_addr);
  499.                             if(p_addr) xc_cport(port1,p_addr);
  500.                          }
  501.                         **********/
  502.                                 }
  503.                                 if(board == 0) setast(1,0x2bf,irq,startport,0);
  504.                                 if(board == 2) setstar(0,0x7f8,irq,startport,0);
  505.                                 if(board == 3) setstar(1,0x580,irq,startport,0);
  506.                                 if(board == 4) setdigimc(1,0xdbc0,irq,startport,0);
  507.                                 if(board == 5)
  508.                                 {
  509.                                     printf("enter address in hex: ");
  510.                                     scanf("%x",&address);
  511.                                     setport(address,1,irq,startport,0);
  512.                                 }
  513.   
  514.                                 xc_link(Port, hwhs);
  515.                                 xc_init(Port, Baud, NOPAR, DATA8, STOP1);
  516.                                 xc_dtr(Port,1);
  517.                                 xc_rts(Port,1);
  518.                                 wclear();
  519.                             }
  520.                             break;
  521.                         case FK6:
  522.                             xc_exit();
  523.                             xc_entr(8);
  524.                                    set_16550(Port,uart_mode,trigger);
  525.                             eterm_init();
  526.                             xck_link();
  527.                             xct_link();
  528.                             xct_pend(20);
  529.                             wclear();
  530.                             xct_unlk();
  531.                             break;
  532. #endif
  533. #ifdef IM_DIAL_TEST
  534.                         case FK5:
  535.                             printf("im_baud = %d\n",im_baud);
  536.                             break;
  537. #endif
  538.   
  539.                         case UP_ARROW:
  540.                             xc_putc(Port,ESC);
  541.                             xc_putc(Port,LEFT_BRACKET);
  542.                             xc_putc(Port,'A');
  543.                             break;
  544.                         case DOWN_ARROW:
  545.                             xc_putc(Port,ESC);
  546.                             xc_putc(Port,LEFT_BRACKET);
  547.                             xc_putc(Port,'B');
  548.                             break;
  549.                         case LEFT_ARROW:
  550.                             xc_putc(Port,ESC);
  551.                             xc_putc(Port,LEFT_BRACKET);
  552.                             xc_putc(Port,'D');
  553.                             break;
  554.                         case RIGHT_ARROW:
  555.                             xc_putc(Port,ESC);
  556.                             xc_putc(Port,LEFT_BRACKET);
  557.                             xc_putc(Port,'C');
  558.                             break;
  559.                         case BACKSPACE:
  560.                             xc_putc(Port,0x08);
  561.                             break;
  562.                         default:                /* Send key out to the comm port */
  563.                             if (is_break())
  564.                                 status = 1;
  565.                             else
  566.                                 err =   xc_putc(Port, (char) key);
  567.                             if(err < 0)
  568.                                 printf("transmit error = %d\n",err);
  569.                     }
  570.                 }
  571.                 if (xc_test(Port)) {         /* Display the incoming character */
  572.                     charin = (char)(xc_getc(Port));
  573.   
  574.                     if (!command_in_progress){
  575.                         if (charin != ESC)      /* is it ANSI ESC sequence */
  576.                             echo(charin);
  577.                         else{
  578.                             command_in_progress = 1;
  579.                             process_escape_sequence(0,'\0'); /* initialize esc codes */
  580.                         }
  581.                     }else
  582.                         process_escape_sequence(1,charin);
  583.                 }
  584.             }
  585.   
  586. /*  *** Optionally, hang up the modem ***  */
  587.   
  588.             if (argc==6) {
  589.                 dfield(HANGUP);
  590.                 im_commd(Port);
  591.                 im_hangu(Port);
  592.                 im_close(Port);
  593.             }
  594.             wclear();                   /* Clear the entire thing */
  595.             sclear(SCRWIDTH);
  596.             xc_dtr(Port, 0);
  597.             xc_rts(Port, 0);
  598.             xc_unlk(Port);
  599.                if (uart_mode)
  600.                    set_16550(Port,0,0);  /* turn 16550 off */
  601.             xc_exit();                  /* Turn off interrupts (everything) */
  602.             break;
  603.         case -1:
  604.             printf("XCOMMS is not properly installed\n");
  605.             break;
  606.         case -2:
  607.             printf("Internal error - No XCOMMS\n");
  608.             break;
  609.         default:
  610.             xc_exit();                  /* Remove XCOMMS interrupt */
  611.             printf("Not enough buffers are allocated for ETERM\n");
  612.             break;
  613.     }
  614.     exit(0);
  615. }
  616.   
  617.   
  618. /*
  619.     === support functions (in order of appearance) ======================
  620.   
  621.     is_break    Check for Ctrl-Break
  622.     eterm_init  Initialize the screen display, optionally read in
  623.                 the ETERM.DAT configuration file
  624.     main_menu   Display main menu
  625.     donline     Display on-line message
  626.     window_sc      Perform a window scroll up or clear for an entire line
  627.                 or lines given the attribute
  628.     dfield      Display field on the bottom line using the
  629.                 attr_status attribute
  630.     echo        Echo the character on screen and optionally scroll
  631.     sclear      Status line clear up to specified column
  632.     wclear      Window text screen clear
  633.     config      Process the configuration options and save
  634.     xmodem      Transfer files up or down
  635.     getinput    A simple in-line response reader function
  636.   
  637.     ======================================================================
  638. */
  639. static int is_break(void)  /* Test for the presence of a Ctrl-Break abort */
  640. {
  641.     int status;
  642.   
  643.     status = xck_test();
  644.     if (status) {
  645.         while (xck_keyt())
  646.             xck_getc();
  647.     }
  648.     return(status);
  649. }
  650.   
  651.   
  652. /*
  653.     eterm_init - Initialize the screen display, optionally read in
  654.                  the ETERM.DAT configuration file
  655.   
  656. */
  657.   
  658.   
  659. static int eterm_init(void)    /* Load in the default ETERM data configuration file */
  660. {
  661.     FILE *Stream;
  662.     int setup_message;
  663.                                     /* Clear both window areas */
  664.     if ((Stream = fopen(config_file, "r")) != NULL) {
  665.         setup_message = DATA_FILE;
  666.         fread(&Port, sizeof(Port), 1, Stream);
  667.         fread(&Baud, sizeof(Baud), 1, Stream);
  668.         fread(&Parity, sizeof(Parity), 1, Stream);
  669.         fread(&Data, sizeof(Data), 1, Stream);
  670.         fread(&Stop, sizeof(Stop), 1, Stream);
  671.         fread(&attr_status, sizeof(attr_status), 1, Stream);
  672.         fread(&attr_text, sizeof(attr_text), 1, Stream);
  673.   
  674.         fclose(Stream);
  675.     } else {
  676.         setup_message = DATA_DEFAUL;
  677.     }
  678.     sclear(SCRWIDTH);
  679.     wclear();
  680.     dfield(setup_message);
  681.   
  682.     xcv_scur(text[INTRO1].row, text[INTRO1].col);
  683.     puts(text[INTRO1].str);
  684.     xcv_scur(text[INTRO2].row, text[INTRO2].col);
  685.     puts(text[INTRO2].str);
  686.     xcv_scur(text[INTRO3].row, text[INTRO3].col);
  687.     puts(text[INTRO3].str);
  688.     xcv_scur(0, 0);                 /* Home the cursor */
  689.   
  690.     main_menu(CLRSCREEN);           /* On-line message with function keys */
  691.   
  692.     xc_link(Port, hwhs);
  693.     xc_dtr(Port, 1);                /* *** Rev 1.2 New *** */
  694.     xc_rts(Port, 1);                /* *** Rev 1.2 New *** */
  695.     if(Baud < 2)
  696.         Baud += BAUD38400 + 1;
  697.     xc_init(Port, Baud, Parity, Data, Stop);
  698.     return(0);                      /* Always successful! */
  699. }
  700.   
  701. /*  Display the main_menu options except for the status field (at the right).
  702.     The dirty flag is passed and determines what to do when a character is
  703.     either received or typed.
  704. */
  705. static int main_menu(int dirty_flag)
  706. {
  707.     sclear(STATCOLUMN - 1);
  708.     dfield(MAIN_F1);
  709.     dfield(MAIN_F2);
  710.     dfield(MAIN_F3);
  711.     dfield(MAIN_F4);
  712.     if(lprt_status)
  713.         dfield(PRT_ON);
  714.     else
  715.         dfield(PRT_OFF);
  716.     dirty = dirty_flag;
  717.     return(0);                      /* Always successful! */
  718. }
  719.   
  720.   
  721. static int donline(void)  /* donline - display on-line status message */
  722. {
  723.     dfield(ONLINEMSG);
  724.     return(0);                      /* Always successful! */
  725. }
  726.   
  727.   
  728. /*
  729.     window_sc - perform a window scroll up or clear for an entire line
  730.              or lines given the attribute
  731.   
  732.              To clear the bottom line, do this:
  733.                 window_sc(24, 1, SCRWIDTH, '\007', CLEARS);
  734.              To scroll the upper 24 lines, do this:
  735.                 window_sc(0, 24, SCRWIDTH, '\007', SCROLL);
  736.   
  737.              The cursor address does NOT change!
  738.   
  739. */
  740. static int window_sc(
  741. int row,                            /* Row address starting at 0 */
  742. int row_count,                      /* Number of rows to scroll or clear */
  743. int column,                         /* Last column number */
  744. char attribute,                     /* Attribute for the window */
  745. int flag)                           /* SCROLL or CLEARS flag */
  746. {
  747.     xcv_scrl(row, 0, row + row_count - 1, column, attribute, flag);
  748.     return(0);                      /* Always succeeds! */
  749. }
  750.   
  751. /*
  752.     dfield - display field on the bottom line using the
  753.              attr_status attribute
  754.   
  755.              To display "F2 Download" at column 16 in a 20 column width
  756.              pass a <text> structure array index that points to the
  757.              entry:
  758.   
  759.   
  760.             struct {
  761.                 int row;
  762.                 int col;
  763.                 int wid;
  764.                 char *str;
  765.             } text[] = {
  766.                     . . .
  767.                 { STATUSROW, 0, STATCOLUMN - 1, "Download filename: " },
  768.                     . . .
  769.   
  770.                 dfield(XDOWNLOAD);
  771.   
  772.              The cursor is not moved
  773.   
  774. */
  775. static int dfield(
  776. int index)                          /* Index into text array */
  777. {
  778.     char _string[MAXFIELD];         /* Maximum string field width */
  779.     int i;                          /* Counter variable */
  780.     int width = text[index].wid;    /* Maximum LEGAL field width */
  781.     int column = text[index].col;   /* Number of columns */
  782.     char *string = text[index].str;
  783.     int oldrow, oldcol;             /* Old cursor address */
  784.   
  785.     if (width > MAXFIELD)
  786.         width = MAXFIELD;           /* Specified field is too big */
  787.                                     /* Create the fixed field */
  788.     for (i = 0; (_string[i] = *string++); ++i)
  789.         ;
  790.     for (; (i < width); ++i)
  791.         _string[i] = ' ';
  792.     xcv_gcur(&oldrow, &oldcol);     /* Save the cursor location */
  793.   
  794.                                     /* Write out the field */
  795.     for (i = 0; (i < width); ++i) {
  796.         xcv_scur(STATUSROW, column + i);
  797.         xcv_chat(_string[i], attr_status);
  798.     }
  799.     xcv_scur(oldrow, oldcol);       /* Restore the cursor */
  800.     return(0);                      /* Always succeeds! */
  801. }
  802.   
  803. static int echo(    /* Display a character and optionally scroll up one line */
  804. char ch)
  805. {
  806.   
  807.     int oldrow, oldcol;
  808.   
  809.     if (lprt_status)        /* send to printer if toggled on */
  810.         fputc(ch,stdprn);
  811.   
  812.     if(ch != 0x09)         /* horizontal tab */
  813.     {
  814.         if( (ch == 13) || (ch == 7) || (ch == 8) )
  815.             xcv_wtty(ch);
  816.         else if(ch == 10)
  817.         {
  818.             xcv_gcur(&oldrow,&oldcol);
  819.             if(oldrow < SAVE_STATROW)
  820.                 xcv_wtty(ch);
  821.             else
  822.             {
  823.                 term_scroll(0,0,SAVE_STATROW,79,0);
  824.                 xcv_scur(SAVE_STATROW,0);
  825.   
  826.             }
  827.         }
  828.         else if(!in_standout_mode) /* not in reverse video mode? */
  829.         {
  830.             xcv_chat(ch,7);
  831.             term_curfwd();
  832.         }
  833.         else
  834.         {
  835.             xcv_chat(ch,0x70);
  836.             term_curfwd();
  837.         }
  838.     }
  839.     else{
  840.         xcv_gcur(&oldrow, &oldcol);
  841.         if(oldcol < TABWIDTH)      /* if not past first tab */
  842.             xcv_scur(oldrow,TABWIDTH-1);
  843.         term_curfwd();
  844.         xcv_gcur(&oldrow, &oldcol);
  845.         while(oldcol % TABWIDTH){
  846.             term_curfwd();
  847.             xcv_gcur(&oldrow, &oldcol);
  848.             if(oldcol < TABWIDTH)   /* handle case where wraps to new line */
  849.                 xcv_scur(oldrow,TABWIDTH);
  850.         }
  851.     }
  852.     return(0);                      /* Always succeeds! */
  853. }
  854.   
  855. static void sclear(                  /* Clear status line */
  856. int column)                         /* Last column */
  857. {
  858.     window_sc(STATUSROW, 1, column, (char)attr_text, CLEARS);
  859.   
  860. }
  861.   
  862. static void wclear(void)                        /* Clear window text area */
  863. {
  864.     xcv_scur(0, 0);                 /* Home cursor */
  865.     window_sc(0, STATUSROW, SCRWIDTH, (char)attr_text, CLEARS);
  866. }
  867.   
  868. static int config(void)        /* Configure the comm port attributes onto disk file */
  869. {
  870.     int message = 0;
  871.     int ch;
  872.     FILE *Stream;
  873.     int old_port = Port;            /* Save the old port */
  874.     int port_exists;
  875.   
  876.   
  877.     sclear(STATCOLUMN - 1);
  878.     dfield(COM_HELP);
  879.   
  880.     while (message == 0) {
  881.         dfield(COMPORT + Port);
  882.         dfield(COMBAUD + Baud);
  883.         dfield(COMPARITY + Parity);
  884.         dfield(COMDATA + Data);
  885.         dfield(COMSTOP + Stop);
  886.         switch (ch = xck_getc()) {
  887.             case FK1:
  888.                 if (++Port == max_ports)
  889.                     Port = 0;
  890.                 break;
  891.             case FK2:
  892.                 if (++Baud > BAUD38400)
  893.                     Baud = 0;
  894.                 break;
  895.             case FK3:
  896.                 if (++Parity > 2)
  897.                     Parity = 0;
  898.                 break;
  899.             case FK4:
  900.                 if (++Data > 1)
  901.                     Data = 0;
  902.                 break;
  903.             case FK5:
  904.                 if (++Stop > 1)
  905.                     Stop = 0;
  906.                 break;
  907.             default:
  908.                 if (is_break())
  909.                     message = COM_ABORT;
  910.                 if ((ch & 0xFF) == RET) {
  911.                     if(Port < 2)
  912.                     {
  913.                         port_exists = xc_tport(Port);
  914.                         if(port_exists != 0)
  915.                         {
  916.                             wclear();
  917.                             printf("\n\aPort %d does not exist\n",Port);
  918.                             printf("Reset parameters for valid port\n");
  919.                             break;
  920.                         }
  921.                     }
  922.                     Stream = fopen(config_file, "w");
  923.                     fwrite(&Port, sizeof(Port), 1, Stream);
  924.                     fwrite(&Baud, sizeof(Baud), 1, Stream);
  925.                     fwrite(&Parity, sizeof(Parity), 1, Stream);
  926.                     fwrite(&Data, sizeof(Data), 1, Stream);
  927.                     fwrite(&Stop, sizeof(Stop), 1, Stream);
  928.                     fwrite(&attr_status, sizeof(attr_status), 1, Stream);
  929.                     fwrite(&attr_text, sizeof(attr_text), 1, Stream);
  930.                     fclose(Stream);
  931.                     if (old_port == Port) {
  932.                         if(Baud < 2)
  933.                             Baud += BAUD38400 + 1;
  934.                         xc_init(Port, Baud, Parity, Data, Stop);
  935.                         message = COM_ACCEPT;
  936.                     } else {
  937.                         message = COM_ACCEPT;
  938.                         xc_link(Port, hwhs);
  939.                         xc_dtr(Port, 1);
  940.                         xc_rts(Port, 1);
  941.                         if(Baud < 2)
  942.                             Baud += BAUD38400 + 1;
  943.                         xc_init(Port, Baud, Parity, Data, Stop);
  944.                     }
  945.                 }
  946.                 break;
  947.         }               /* End of character switch */
  948.     }               /* End of while loop */
  949.     dfield(message);
  950.     return(0);
  951. }
  952.   
  953. static int transfer(void)    /* Perform file protocol upload or download */
  954. {
  955.     int exitflag = 2;
  956.     int row, column;
  957.     char answer[33];
  958.     int transfer;
  959.     int ret_value;
  960.     int oldcol,oldrow;
  961. /*  Ask the user to either upload or download */
  962.   
  963.     sclear(STATCOLUMN - 1);
  964.     dfield(XUPLOAD);
  965.     dfield(XDOWNLOAD);
  966.     dfield(XEXIT);
  967.     while (exitflag == 2) {
  968.         switch (xck_getc()) {
  969.             case FK1:                           /* Upload */
  970.                 exitflag = 0;
  971.                 break;
  972.             case FK2:                           /* Download */
  973.                 exitflag = 1;
  974.                 break;
  975.             default:                            /* Exit abnormally */
  976.                 if (is_break())
  977.                     exitflag = -1;
  978.         }
  979.     }
  980.     if (exitflag == -1)
  981.         dfield(USERABORT);
  982.     else {
  983.             /* *********** REV 2.0 ask the type of XMODEM transfer ********* */
  984.         sclear(SCRWIDTH);
  985.         dfield(YMODEM);
  986.         dfield(XM_CRC);
  987.         dfield(XM_1K);
  988.         dfield(KERMIT);
  989.         dfield(ZMODEM);
  990.         dfield(XMODEM_EXIT);
  991.         switch (xck_getc()) {
  992.             case FK1:                           /* YMODEM */
  993.                 sclear(SCRWIDTH);
  994.                 if (exitflag == 0)
  995.                     dfield(GETUPLOAD);
  996.                 else
  997.                     dfield(DWNLD_PATH);
  998.                 xcv_gcur(&row, &column);
  999.                 xcv_scur(STATUSROW, 20);
  1000.                 if (getinput(answer) < 0)
  1001.                 {
  1002.                     dfield(USERABORT);
  1003.                     exitflag = -1;
  1004.                     break;
  1005.                 }
  1006.                 transfer = 0;
  1007.                 break;
  1008.             case FK2:                           /* XMODEM/CRC option*/
  1009.                 sclear(SCRWIDTH);
  1010.                 if (exitflag == 0)
  1011.                     dfield(GETUPLOAD);
  1012.                 else
  1013.                     dfield(GETDOWNLOAD);
  1014.                 xcv_gcur(&row, &column);
  1015.                 xcv_scur(STATUSROW, 20);
  1016.                 if (getinput(answer) <= 0)
  1017.                 {
  1018.                     dfield(USERABORT);
  1019.                     exitflag = -1;
  1020.                     break;
  1021.                 }
  1022.                 transfer = 1;
  1023.                 break;
  1024.             case FK3:                           /* XMODEM 1K option*/
  1025.                 sclear(SCRWIDTH);
  1026.                 if (exitflag == 0)
  1027.                     dfield(GETUPLOAD);
  1028.                 else
  1029.                     dfield(GETDOWNLOAD);
  1030.                 xcv_gcur(&row, &column);
  1031.                 xcv_scur(STATUSROW, 20);
  1032.                 if (getinput(answer) <= 0)
  1033.                 {
  1034.                     dfield(USERABORT);
  1035.                     exitflag = -1;
  1036.                     break;
  1037.                 }
  1038.                 transfer = 2;
  1039.                 break;
  1040.             case FK4:                           /* KERMIT */
  1041.                 sclear(SCRWIDTH);
  1042.                 if (exitflag == 0)
  1043.                     dfield(GETUPLOAD);
  1044.                 else
  1045.                     dfield(DWNLD_PATH);
  1046.                 xcv_gcur(&row, &column);
  1047.                 xcv_scur(STATUSROW, 20);
  1048.                 if (getinput(answer) < 0)
  1049.                 {
  1050.                     dfield(USERABORT);
  1051.                     exitflag = -1;
  1052.                     break;
  1053.                 }
  1054.                 transfer = 3;
  1055.                 break;
  1056.             case FK5:                           /* ZMODEM */
  1057.                 sclear(SCRWIDTH);
  1058.                 if (exitflag == 0)
  1059.                     dfield(GETUPLOAD);
  1060.                 else
  1061.                     dfield(DWNLD_PATH);
  1062.                 xcv_gcur(&row, &column);
  1063.                 xcv_scur(STATUSROW, 20);
  1064.                 if (getinput(answer) < 0)
  1065.                 {
  1066.                     dfield(USERABORT);
  1067.                     exitflag = -1;
  1068.                     break;
  1069.                 }
  1070.                 transfer = 4;
  1071.                 break;
  1072.             default:                            /* Exit abnormally */
  1073.                 if (is_break()) {
  1074.                     exitflag = -1;
  1075.                     dfield(USERABORT);
  1076.                 }
  1077.         }
  1078.             /* ************************************************************* */
  1079.   
  1080.         if (exitflag >= 0) {
  1081.             dfield(NULL_STR);
  1082.   
  1083.             if (exitflag == 0)  {                /* Execute upload/download */
  1084.                 switch (transfer) {
  1085.                     case 0:
  1086.                         screen_to_memory(2*80,160 * 22,scrbuf);
  1087.                         window_sc(22,23,SCRWIDTH,7,CLEARS);
  1088.                         xcv_gcur(&oldcol,&oldrow);
  1089.                         xcv_scur(22,0);
  1090.                         ret_value = ym_putf(Port, answer, 1, 1);
  1091.                         memory_to_screen(2*80,160 * 22,scrbuf);
  1092.                         ret_value = (ret_value == 0) ? 0 : -2;
  1093.                         xcv_scur(oldcol,oldrow);
  1094.                         dfield(XMODEM - ret_value);
  1095.                         break;
  1096.                     case 1:
  1097.                         dfield(XMODEM + (-xmk_putf(Port, answer, xmodeminfo, 1, XMODEM_128, XMODEM_CRC)));
  1098.                         break;
  1099.                     case 2:
  1100.                         dfield(XMODEM + (-xmk_putf(Port, answer, xmodeminfo, 1, XMODEM_1K, XMODEM_CRC)));
  1101.                         break;
  1102.                     case 3:
  1103.                         screen_to_memory(3*80,160 * 21,scrbuf);
  1104.                         window_sc(21,23,SCRWIDTH,7,CLEARS);
  1105.                         xcv_gcur(&oldcol,&oldrow);
  1106.                         xcv_scur(21,0);
  1107.                         if (Data==DATA7)
  1108.                             km_7bit[Port] = 1;
  1109.                         ret_value = km_putf(Port, answer, 1, 1);
  1110.                         memory_to_screen(3*80,160 * 21,scrbuf);
  1111.                         dfield(XMODEM - ret_value);
  1112.                         xcv_scur(oldcol,oldrow);
  1113.                         break;
  1114.                     case 4:
  1115.                         screen_to_memory(3*80,160 * 21,scrbuf);
  1116.                         window_sc(21,23,SCRWIDTH,7,CLEARS);
  1117.                         xcv_gcur(&oldcol,&oldrow);
  1118.                         xcv_scur(21,0);
  1119.                         ret_value = zm_putf(Port, answer, 1, 1);
  1120.                         memory_to_screen(3*80,160 * 21,scrbuf);
  1121.                         dfield(XMODEM - ret_value);
  1122.                         xcv_scur(oldcol,oldrow);
  1123.                         break;
  1124.                 }
  1125.             } else {
  1126.                 switch (transfer) {
  1127.                     case 0:
  1128.                         screen_to_memory(2*80,160 * 22,scrbuf);
  1129.                         window_sc(22,23,SCRWIDTH,7,CLEARS);
  1130.                         xcv_gcur(&oldcol,&oldrow);
  1131.                         xcv_scur(22,0);
  1132.                         ret_value = ym_getf(Port,answer, 1, 1);
  1133.                         memory_to_screen(2*80,160 * 22,scrbuf);
  1134.                         ret_value = (ret_value == 0) ? 0 : -2;
  1135.                         dfield(XMODEM - ret_value);
  1136.                         xcv_scur(oldcol,oldrow);
  1137.                         break;
  1138.                     case 1:
  1139.                         dfield(XMODEM + (-xmk_getf(Port, answer, xmodeminfo, 1, XMODEM_128, XMODEM_CRC)));
  1140.                         break;
  1141.                     case 2:
  1142.                         dfield(XMODEM + (-xmk_getf(Port, answer, xmodeminfo, 1, XMODEM_1K, XMODEM_CRC)));
  1143.                         break;
  1144.                     case 3:
  1145.                         screen_to_memory(3*80,160 * 21,scrbuf);
  1146.                         window_sc(21,23,SCRWIDTH,7,CLEARS);
  1147.                         xcv_gcur(&oldcol,&oldrow);
  1148.                         xcv_scur(21,0);
  1149.                         if (Data==DATA7)
  1150.                             km_7bit[Port] = 1;
  1151.                         ret_value = km_getf(Port, answer, 1, 1);
  1152.                         memory_to_screen(3*80,160 * 21,scrbuf);
  1153.                         dfield(XMODEM - ret_value);
  1154.                         xcv_scur(oldcol,oldrow);
  1155.                         break;
  1156.                     case 4:
  1157.                         screen_to_memory(3*80,160 * 21,scrbuf);
  1158.                         window_sc(21,23,SCRWIDTH,7,CLEARS);
  1159.                         xcv_gcur(&oldcol,&oldrow);
  1160.                         xcv_scur(21,0);
  1161.                         ret_value = zm_getf(Port, answer, 1, 1);
  1162.                         memory_to_screen(3*80,160 * 21,scrbuf);
  1163.                         dfield(XMODEM - ret_value);
  1164.                         xcv_scur(oldcol,oldrow);
  1165.                         break;
  1166.                 }
  1167.             }
  1168.         }
  1169.     }
  1170.     xcv_scur(row, column);
  1171.     return(exitflag);
  1172. }
  1173.   
  1174.   
  1175. /*
  1176.     getinput - Given the character string buffer address, accept the
  1177.     user input string and return the number of characters entered.  Accept
  1178.     input at the current cursor location.
  1179.     Returns:
  1180.   
  1181.         0   Only Enter key pressed
  1182.         >0  The character string of n characters returned
  1183.         -1  Ctrl-Break pressed
  1184. */
  1185. static int getinput(
  1186. char *buffer)
  1187. {
  1188.     int i = 0;
  1189.     int exitflag = 0;
  1190.     char ch;
  1191.     int row, column;
  1192.   
  1193.     while (exitflag == 0) {
  1194.         if (is_break()) {
  1195.             i = -1;
  1196.             break;
  1197.         }
  1198.         switch ((ch = (char)xck_getc()) & 0xFF) {
  1199.             case RET:
  1200.                 buffer[i] = '\000';
  1201.                 exitflag = 1;               /* Exit file entry */
  1202.                 break;
  1203.             case RUB1:
  1204.             case RUB2:
  1205.                 if (i) {
  1206.                     --i;
  1207.                     xcv_gcur(&row, &column);
  1208.                     xcv_scur(row, column - 1);
  1209.                     xcv_wtty(' ');
  1210.                     xcv_scur(row, column - 1);
  1211.                 }
  1212.                 break;
  1213.             default:
  1214.                 buffer[i++] = ch;
  1215.                 xcv_wtty(ch);
  1216.         }
  1217.     }
  1218.     return(i);                          /* Return size of answer */
  1219. }
  1220.   
  1221. /* process ANSI control sequences */
  1222.   
  1223.   
  1224. static void process_escape_sequence(
  1225. int mode,      /* 0 = initialize strings, 1 = in_progress */
  1226. char ch)       /* current character being processed */
  1227. {
  1228.   
  1229.   
  1230.     if(mode == 0)
  1231.     {
  1232.         int1 = int2 = 0;
  1233.         num1[0] = num1[1] = num1[2] = '\0'; /* force string to nulls */
  1234.         num2[0] = num2[1] = num2[2] = '\0'; /* force string to nulls */
  1235.         waiting_for_bracket = 1;
  1236.         return;
  1237.     }
  1238.   
  1239.     if(waiting_for_bracket)       /* '[' should follow ESC or not a valid
  1240.                                     ESC sequence. Note 'G' sequences are
  1241.                                     an exception to this but not processed
  1242.                                     here. */
  1243.     {
  1244.         if(ch == LEFT_BRACKET)
  1245.         {
  1246.             waiting_for_bracket = 0;
  1247.             ansi_first_num = 0;
  1248.             num_ptr = 0;
  1249.             return;
  1250.         }
  1251.         else
  1252.         {                       /* not a valid sequence */
  1253.             waiting_for_bracket = 0;
  1254.             command_in_progress = 0;
  1255.             return;
  1256.         }
  1257.     }
  1258.   
  1259.   
  1260.     switch (ch)
  1261.     {
  1262.         case 'L':                  /* insert lines */
  1263.             term_curinsrt();
  1264.             command_in_progress = 0; break;
  1265.         case 'K':                  /* clear to end of line */
  1266.             term_clreol();
  1267.             command_in_progress = 0; break;
  1268.         case 'H':                  /* home cursor or position cursor */
  1269.   
  1270.   
  1271.             if(num1[0] == '\0' && num2[0] == '\0')
  1272.             {
  1273.                 xcv_scur(0,0);
  1274.                 command_in_progress = 0; break;
  1275.             }
  1276.             else
  1277.             {
  1278.                 int1 = atoi(num1);
  1279.                 int2 = atoi(num2);
  1280.                 xcv_scur(int1-1,int2-1);
  1281.                 command_in_progress = 0; break;
  1282.             }
  1283.         case 'P':                  /* delete character */
  1284.             delete_1_char();
  1285.             command_in_progress = 0; break;
  1286.         case 'M':                  /* delete line */
  1287.             term_curdelet();
  1288.             command_in_progress = 0; break;
  1289.         case 'B':                  /* cursor down one line */
  1290.             term_curdown();
  1291.             command_in_progress = 0; break;
  1292.         case 'Z':                  /* back tab */
  1293.             command_in_progress = 0; break;           /* **** NA **** */
  1294.         case 'm':                  /* begin/end underscore(standout) mode */
  1295.             in_underscore_mode = (in_underscore_mode) ? 0 : 1;
  1296.             in_standout_mode = (in_standout_mode) ? 0 : 1;
  1297.             command_in_progress = 0; break;
  1298.   
  1299.          /*  there is some confusion because of 2 'J' codes in termcap. */
  1300.          /*  the other one is for clear to end of display */
  1301.   
  1302.         case 'J':                  /* clear screen, home cursor */
  1303.             if(num1[0] == '2'){
  1304.                 term_scroll(0,0,SAVE_STATROW,79,2);
  1305.                 xcv_scur(0,0);
  1306.             }else{
  1307.                 term_clreos();
  1308.             }
  1309.             command_in_progress = 0; break;
  1310.         case 'C':                  /* cursor right */
  1311.             term_curfwd();       /* will advance cursor to new line */
  1312.             command_in_progress = 0; break;
  1313.         case 'A':                  /* cursor up */
  1314.             term_curup();
  1315.             command_in_progress = 0; break;
  1316.         case '@':                  /* insert character */
  1317.             insert_1_char();
  1318.             command_in_progress = 0; break;
  1319.         case 'S':                  /* scroll forward */
  1320.             term_scroll(0,0,SAVE_STATROW,79,0);
  1321.             command_in_progress = 0; break;
  1322.         case 'T':                  /* scroll backward */
  1323.             term_scroll(0,0,SAVE_STATROW,79,1);
  1324.             command_in_progress = 0; break;
  1325.   
  1326.         case '0': case '1': case '2': case '3': case '4': case '5':
  1327.         case '6': case '7': case '8': case '9':
  1328.   
  1329.             if(ansi_first_num == 0)
  1330.             {
  1331.                 num1[num_ptr++] = ch;
  1332.                 if(num_ptr > 2)   /* invalid number */
  1333.                 {
  1334.                     command_in_progress = 0;
  1335.                     return;
  1336.                 }
  1337.             }
  1338.             else
  1339.             {
  1340.                 num2[num_ptr++] = ch;
  1341.                 if(num_ptr > 2)   /* invalid number */
  1342.                 {
  1343.                     command_in_progress = 0;
  1344.                     return;
  1345.                 }
  1346.             }
  1347.             break;
  1348.         case ';':                  /* number separator */
  1349.             num_ptr = 0;
  1350.             ansi_first_num = 1;
  1351.             break;
  1352.   
  1353.         default:
  1354.             waiting_for_bracket = 0;
  1355.             command_in_progress = 0;
  1356.             return;
  1357.     }
  1358. }
  1359.   
  1360.   
  1361. static void delete_1_char(void)     /* delet a character on the screen */
  1362. {
  1363.     char buf[162];
  1364.     int row, col;
  1365.     int i;
  1366.   
  1367.     xcv_gcur(&row,&col);
  1368.     screen_to_memory(80,row*160,buf);
  1369.     buf[161] = buf[159];
  1370.     buf[160] = ' ';
  1371.     for(i=col*2;i<160;i++)
  1372.     {
  1373.         buf[i] = buf[i+2];
  1374.     }
  1375.     memory_to_screen(80,row*160,buf);
  1376.     return;
  1377. }
  1378.   
  1379. static int insert_1_char(void)
  1380. {
  1381.     char buf[160];
  1382.     int row, col;
  1383.     int i,j;
  1384.   
  1385.     xcv_gcur(&row,&col);
  1386.     screen_to_memory(80,row*160,buf);
  1387.     j = (col * 2) + 2;
  1388.     for(i=159;i>=j;i--)
  1389.     {
  1390.         buf[i] = buf[i-2];
  1391.     }
  1392.     buf[(col*2)] = ' ';
  1393.     memory_to_screen(80,row*160,buf);
  1394.     return(0);
  1395. }
  1396.   
  1397.   
  1398.   
  1399. /* function to move cursor up one line */
  1400. static int term_curup(void)
  1401. {
  1402.     int row,col; /* current cursor position retrieved */
  1403.   
  1404.     xcv_gcur(&row,&col); /* get current cursor position */
  1405.     if (row == 0)  /* cannot go up beyond first row */
  1406.         return(-1);
  1407.     else
  1408.         xcv_scur(row-1,col);
  1409.     return(0);
  1410. }
  1411.   
  1412.   
  1413. /* function to move cursor down one row */
  1414. static int term_curdown(void)
  1415. {
  1416.     int row,col; /* current cursor position retrieved */
  1417.   
  1418.     xcv_gcur(&row,&col); /* get current cursor position */
  1419.     if (row == SAVE_STATROW)  /* cannot go down past last row */
  1420.         return(-1);
  1421.     else
  1422.         xcv_scur(row+1,col);
  1423.     return(0);
  1424. }
  1425.   
  1426.   
  1427. /* advance cursor one position. if past eol, go to next row, col 1  */
  1428. static int term_curfwd(void)
  1429. {
  1430.     int row,col; /* current cursor position retrieved */
  1431.   
  1432.     xcv_gcur(&row,&col); /* get current cursor position */
  1433.     if (col >= 79){   /* is cursor in last column position */
  1434.         if ( row >= SAVE_STATROW )  /* cannot advance past last row */
  1435.         {
  1436.             term_scroll(0,0,SAVE_STATROW,79,0);
  1437.             xcv_scur(SAVE_STATROW,0);
  1438.   
  1439.         }
  1440.         else
  1441.             xcv_scur(row+1,0);  /* advance to next row */
  1442.     }else
  1443.         xcv_scur(row,col+1);
  1444.     return(0);
  1445. }
  1446.   
  1447.   
  1448. /* clear from cursor to end of line  */
  1449. static int term_clreol(void)
  1450. {
  1451.     int row,col; /* current cursor position retrieved */
  1452.     int i,j; /* local work variables */
  1453.   
  1454.     xcv_gcur(&row,&col); /* get current cursor position */
  1455.     i = 80 - col;  /* number of columns to clear */
  1456.     for(j=0;j<i;j++)
  1457.     {
  1458.         xcv_chat(' ',7);  /* use write character and attribute function */
  1459.         if(j < (i-1))      /* don't want to advance past eol */
  1460.             term_curfwd();
  1461.     }
  1462.     xcv_scur(row,col);
  1463.     return(0);
  1464. }
  1465.   
  1466.   
  1467.   
  1468. /* clear from cursor to end of screen */
  1469. static int term_clreos(void)
  1470. {
  1471.     int row,col; /* current cursor position retrieved */
  1472.   
  1473.     term_clreol();           /* clear first line to eol */
  1474.     xcv_gcur(&row,&col);     /* get cursor position */
  1475.     if(row == SAVE_STATROW)
  1476.         return(0);
  1477.     else
  1478.         term_scroll(row+1,0,SAVE_STATROW,79,2);   /* scroll to clear */
  1479.     xcv_scur(row,col);
  1480.     return(0);
  1481. }
  1482.   
  1483.   
  1484. /* insert one line from cursor */
  1485. static int term_curinsrt(void)
  1486. {
  1487.     int row,col; /* current cursor position retrieved with xcv_gcur */
  1488.     xcv_gcur(&row,&col);
  1489.     term_scroll(row,0,SAVE_STATROW,79,1);
  1490.     return(0);
  1491. }
  1492.   
  1493.   
  1494.   
  1495. /* delete 1 row starting at row passed*/
  1496. static int term_curdelet(void)
  1497. {
  1498.     int row,col; /* current cursor position retrieved with xcv_gcur */
  1499.     xcv_gcur(&row,&col);
  1500.     term_scroll(row,0,SAVE_STATROW,79,0);
  1501.     return(0);
  1502. }
  1503.   
  1504. /* do BIOS call to scroll down or up */
  1505.   
  1506. static int term_scroll( /* function to scroll a window on the screen */
  1507. int up_row, /* the row of the upper left hand corner of the window */
  1508. int up_col, /* the column of the upper left hand corner */
  1509. int low_row, /* the row of the lower right hand corner of the window */
  1510. int low_col, /* the column of the lower right hand corner */
  1511. int dir) /* the direction to scroll; 0 for up, 1 for down, 2 to clear */
  1512.   
  1513. {
  1514.     union i86_reg regs;
  1515.     if (dir == 0)
  1516.     {
  1517.         regs.breg.AH=6;
  1518.         regs.breg.AL= 1;
  1519.     }
  1520.     else if (dir == 1)
  1521.     {
  1522.         regs.breg.AH=7;
  1523.         regs.breg.AL= 1;
  1524.     }
  1525.     else if (dir == 2)
  1526.     {
  1527.         regs.breg.AH=6;
  1528.         regs.breg.AL= 0;
  1529.     }
  1530.     regs.breg.BH = 7;
  1531.     regs.breg.CH = (char)up_row;
  1532.     regs.breg.CL = (char)up_col;
  1533.     regs.breg.DH = (char)low_row;
  1534.     regs.breg.DL = (char)low_col;
  1535.     i86_int(0x10,®s);
  1536.     return(0);
  1537. }
  1538.   
  1539. static int set_video_mode(void)           /* gets and/or sets video mode to 80 column */
  1540. {
  1541.     union i86_reg regs;
  1542.     regs.breg.AH=0x0f;
  1543.     i86_int(0x10,®s);
  1544.     if(regs.breg.AL == 7)    /* mono adapter */
  1545.     {
  1546.         video_mode = 7;
  1547.     }
  1548.     else                     /* color adapter */
  1549.     {
  1550.         regs.breg.AH = 0;     /* set video mode function */
  1551.         regs.breg.AL = 3;     /* 80 col color mode */
  1552.         i86_int(0x10,®s);
  1553.         video_mode = 3;
  1554.     }
  1555.     return(0);
  1556. }
  1557.   
  1558. /* memory_to_screen() and screen_to_memory() move data from/to video ram */
  1559.   
  1560. static void memory_to_screen(
  1561. unsigned words,
  1562. unsigned offset,
  1563. char *buffer)
  1564. {
  1565.     void far *address;      /* used to point to video ram */
  1566.     unsigned segment;       /* video ram segment */
  1567.     unsigned bufseg,bufoff; /* buffer segment and offset */
  1568.   
  1569.     if(video_mode == 7)
  1570.         segment = 0xb000; /* mono */
  1571.     else
  1572.         segment = 0xb800; /* color */
  1573.   
  1574.     address = (void far *)buffer;
  1575.     bufseg = FP_SEG(address);
  1576.     bufoff = FP_OFF(address);
  1577.     movedata(bufseg,bufoff,segment,offset,words*2);
  1578. }
  1579.   
  1580.   
  1581. static void screen_to_memory(
  1582. unsigned words,
  1583. unsigned offset,
  1584. char *buffer)
  1585. {
  1586.     void far *address;      /* used to point to video ram */
  1587.     unsigned segment;       /* video ram segment */
  1588.     unsigned bufseg,bufoff; /* buffer segment and offset */
  1589.   
  1590.     if(video_mode == 7)
  1591.         segment = 0xb000; /* mono */
  1592.     else
  1593.         segment = 0xb800; /* color */
  1594.   
  1595.     address = (void far *)buffer;
  1596.     bufseg = FP_SEG(address);
  1597.     bufoff = FP_OFF(address);
  1598.     movedata(segment,offset,bufseg,bufoff,words*2);
  1599. }
  1600.   
  1601. static int prthelp(void)
  1602. {
  1603.         printf("\nFORMAT : \nansiterm [hwhs] [mode] [trig]  OR  ansiterm [hwhs] [mode] [trig] [mt] [num]");
  1604.         printf("\n         OR ansiterm /d (for defaults)");
  1605.         printf("\nWHERE:\n  hwhs: Hardware Handshaking");
  1606.         printf("\n        0 = Hardware Handshaking is disabled (default)");
  1607.         printf("\n        1 = Both CTS (Clear to Send) and DSR (Data Set Ready)");
  1608.         printf("\n            are used for Hardware Handshaking");
  1609.         printf("\n        2 = Only CTS is used for Hardware Handshaking");
  1610.         printf("\n        3 = Only DSR is used for Hardware Handshaking");
  1611.           printf("\n  mode: Serial Port UART Chip mode (use 0 if you do not have a 16550)");
  1612.           printf("\n        0 = NS16550A Character mode, FIFOs Disabled (default)");
  1613.           printf("\n        1 = NS16550A FIFOs Enabled ");
  1614.           printf("\n  trig: NS16550A FIFO Receive buffer trigger level (use 0 if no 16550)");
  1615.           printf("\n        0 = Generate interrupt after 1 character received (default)");
  1616.           printf("\n        1 = Generate interrupt after 4 characters received");
  1617.           printf("\n        2 = Generate interrupt after 8 characters received");
  1618.           printf("\n        3 = Generate interrupt after 14 characters received");
  1619.         printf("\n  mt: modem type");
  1620.           printf("\n        0 = Hayes Ultra; 1 = USR Courier;     2 = Microcom QX or UDS Fastalk;");
  1621.           printf("\n        3 = Telebit;     4 = MultiTech;       5 = GVC SM96;");
  1622.           printf("\n        6 = Ventel;      7 = Digicom Systems; 8 = Generic type;");
  1623.           printf("\n                     9 = Standard type (default);");
  1624.         printf("\n  num: Telephone number for modem to dial (default is NO number to dial)");
  1625.         return(0);
  1626. }
  1627.