home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc095.zip / ckocon.c < prev    next >
C/C++ Source or Header  |  1989-08-09  |  59KB  |  2,343 lines

  1. char           *connv = "OS/2 connect command, 13 Feb 89";
  2. /* C K O C O N  --  Kermit connect command for OS/2 systems */
  3. /*
  4.  * Author: Chris Adie (C.Adie@uk.ac.edinburgh) Copyright (C) 1988 Edinburgh
  5.  * University Computing Service Permission is granted to any individual or
  6.  * institution to use, copy, or redistribute this software so long as it is
  7.  * not sold for profit, provided this copyright notice is retained. 
  8.  *
  9.  *
  10.  * Incorporates a VT102 emulator, together with its screen access routines.  If
  11.  * the code looks a bit funny sometimes, its because it was machine
  12.  * translated to 'C'. 
  13.  */
  14.  
  15. /*
  16.  *
  17.  * =============================#includes===================================== 
  18.  */
  19.  
  20. #include "ckcker.h"        /* Kermit definitions */
  21. #include "ckcdeb.h"        /* Typedefs, debug formats, etc */
  22. #include <ctype.h>        /* Character types */
  23. #include <io.h>            /* File io function declarations */
  24. #include <process.h>        /* Process-control function declarations */
  25. #include <stdlib.h>        /* Standard library declarations */
  26. #include <sys\types.h>
  27. #include <sys\stat.h>
  28. #include <direct.h>        /* Directory function declarations */
  29. #include <stdio.h>
  30. #include <string.h>
  31. #define    INCL_BASE
  32. #include <os2.h>
  33.  
  34. /*
  35.  *
  36.  * =============================#defines====================================== 
  37.  */
  38.  
  39. #ifndef TRUE
  40. #define TRUE    1
  41. #endif
  42. #ifndef FALSE
  43. #define    FALSE    0
  44. #endif
  45. #define    SENDSTR2    sendstr
  46. #define    SENDCHAR    sendchar
  47. #define    UPWARD        6
  48. #define    DOWNWARD    7
  49. #define    LBUFSIZE    144    /* No of lines in extended buffer */
  50. #define DEFTABS        \
  51. "00000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000";
  52.  
  53. /*
  54.  *
  55.  * =============================typedefs====================================== 
  56.  */
  57.  
  58. typedef char    fulstring[256];
  59. typedef int     bool;
  60. typedef unsigned char screenmap[4000];
  61. typedef struct ascreen_rec {    /* Structure for saving screen info */
  62.     unsigned char   ox;
  63.     unsigned char   oy;
  64.     unsigned char   att;
  65.     screenmap       scrncpy;
  66. }               ascreen;
  67.  
  68. /*
  69.  *
  70.  * =============================externals===================================== 
  71.  */
  72.  
  73. extern int      local, speed, escape, duplex, parity, flow, seslog, cmask;
  74. extern char     ttname[], sesfil[];
  75. extern CHAR     dopar();
  76.  
  77. /*
  78.  *
  79.  * =============================static=variables============================== 
  80.  */
  81.  
  82. static long    twochartimes;
  83. static char    termessage[80];
  84. static FILE    *lst;
  85. static bool     lstclosed = TRUE;
  86. static char     coloroftext = 7, colorofback = 0;
  87. static          colorofunderline = 4;
  88. static ascreen  vt100screen, commandscreen;
  89. static enum {
  90.     mono,
  91.     colour
  92. }               adapter;
  93. unsigned char   attribute, savedattribute, line25attribute, defaultattribute;
  94. static struct {
  95.     unsigned        reversed:1;
  96.     unsigned        blinking:1;
  97.     unsigned        underlined:1;
  98.     unsigned        bold:1;
  99.     unsigned        invisible:1;
  100. }               attrib, savedattrib;
  101. static struct paging_record {
  102.     unsigned char   numlines;    /* no. of lines in extended display buffer */
  103.     unsigned char   topline;
  104.     unsigned char   botline;
  105.     char           *buffer;
  106. }               paginginfo;
  107.  
  108. static unsigned char wherex;
  109. static unsigned char wherey;
  110. static unsigned char margintop = 1;
  111. static unsigned char marginbot = 24;
  112. static int      active;
  113. static long int threadsem;    /* Semaphore to show thread is running */
  114. static char     usertext[(80) + 1];
  115. static char     exittext[(14) + 1];
  116. static char     helptext[(14) + 1];
  117. static char     filetext[(14) + 1];
  118. static char     hostname[(20) + 1];
  119.  
  120. static unsigned char graphicset[32] = {
  121.                  0x20, 0x04, 0xB0, 0x1A, 0x17, 0x1B, 0x19, 0xF8,
  122.                  0xF1, 0x15, 0x12, 0xD9, 0xBF, 0xDA, 0xC0, 0xC5,
  123.                  0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC3, 0xB4, 0xC1,
  124.                  0xC2, 0xB3, 0xF3, 0xF2, 0xE3, 0x9D, 0x9C, 0xFA
  125. };
  126. static char     htab[81] = DEFTABS    /* Default tab settings */
  127. static char answerback[81] = "OS/2 Kermit\n";
  128. static int      row;
  129. #ifdef US_CHAR
  130. static unsigned char g0 = 'B';        /* Character 35 is number sign */
  131. static unsigned char g1 = 'B';
  132. #else
  133. static unsigned char g0 = 'A';        /* Char 35 is pound (sterling) sign */
  134. static unsigned char g1 = 'A';
  135. #endif /* US_CHAR */
  136. static unsigned char *g0g1 = &g0;
  137. static bool     literal = FALSE;
  138. static bool     wrapit;
  139. static bool     printon = FALSE;
  140. static bool     screenon = TRUE;
  141. static bool     cursoron = TRUE;/* For speed, turn off when busy */
  142. static bool     relcursor = FALSE;
  143. static bool     keypadnum = FALSE;
  144. static bool     autowrap = FALSE;
  145. static bool     ansi = TRUE;
  146. static bool     keylock = FALSE;
  147. static bool     vt52graphics = FALSE;
  148. static unsigned char achar;
  149. static int      column;
  150. static unsigned char saveg0, saveg1, *saveg0g1;
  151. static bool     saverelcursor, saved=FALSE;
  152. static bool     dwl[24] = {
  153.        FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
  154.        FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
  155.                FALSE, FALSE, FALSE, FALSE};
  156. static bool     dwls = FALSE;    /* For optimisation */
  157. static bool     deccolm = FALSE;
  158. static bool     decscnm = FALSE;
  159. static bool     linemode = FALSE;
  160. static bool     insertmode = FALSE;
  161. static bool     cursorkey = TRUE;
  162. /* escape sequence processing buffer */
  163. static bool     escaping = FALSE;
  164. static int      escnext = 1;
  165. static int      esclast = 0;
  166. static unsigned char escbuffer[129];
  167. static unsigned char sgrcols[8] = {0, 4, 2, 6, 1, 5, 3, 7};
  168.  
  169. /*
  170.  * Send a character to the serial line in immediate mode, checking to avoid
  171.  * overwriting a character already waiting to be sent.
  172.  */
  173. sendchar(unsigned char c) {
  174. int i=0;
  175.     while (ttoci(c)<0 && i++<10)
  176.         DosSleep(twochartimes);
  177.     if (i>=10) {
  178.         active = FALSE;
  179.         strcpy(termessage,"Cannot transmit to serial port!\n");
  180.     }
  181. }
  182.  
  183. /* ------------------------------------------------------------------ */
  184. /* ipadl25 -                                                          */
  185. /* ------------------------------------------------------------------ */
  186. static void
  187. ipadl25()
  188. {
  189.     strcpy(usertext, " C-Kermit VT102");
  190.     sprintf(filetext, "%1d baud", speed);
  191.     strcpy(helptext, "Help: ^ ?");
  192.     helptext[7] = ctl(escape);
  193.     strcpy(exittext, "Exit: ^ c");
  194.     exittext[7] = ctl(escape);
  195.     strcpy(hostname, ttname);
  196.     line25();
  197. }
  198. /* ------------------------------------------------------------------ */
  199. /* CursorUp -                                                         */
  200. /* ------------------------------------------------------------------ */
  201. static void
  202. cursorup()
  203. {
  204.     if ((relcursor ? margintop : 1) != wherey)
  205.     lgotoxy(wherex, wherey - 1);
  206. }
  207. /* ------------------------------------------------------------------ */
  208. /* CursorDown -                                                       */
  209. /* ------------------------------------------------------------------ */
  210. static void
  211. cursordown()
  212. {
  213.     if ((relcursor ? marginbot : 24) != wherey)
  214.     lgotoxy(wherex, wherey + 1);
  215. }
  216. /* ------------------------------------------------------------------ */
  217. /* CursorRight -                                                      */
  218. /* ------------------------------------------------------------------ */
  219. static void
  220. cursorright()
  221. {
  222.     if (wherex < (dwl[wherey - 1] ? 79 : 80))
  223.     lgotoxy(wherex + 1, wherey);
  224. }
  225. /* ------------------------------------------------------------------ */
  226. /* CursorLeft -                                                       */
  227. /* ------------------------------------------------------------------ */
  228. static void
  229. cursorleft()
  230. {
  231.     if (wherex > 1)
  232.     lgotoxy(wherex - 1, wherey);
  233. }
  234. /* ------------------------------------------------------------------ */
  235. /* ReverseScreen                              */
  236. /* ------------------------------------------------------------------ */
  237. static void
  238. reversescreen()
  239. {
  240.     unsigned char   back;
  241.     unsigned char   fore;
  242.     int             i, r, c;
  243.     USHORT          n;
  244.     unsigned char   cell[160];
  245.  
  246.     n = sizeof(cell);
  247.     for (r = 0; r < 24; r++) {    /* flip row */
  248.     VioReadCellStr(cell, &n, r, 0, 0);
  249.     for (c = 1; c < n; c += 2) {    /* do each cell in row */
  250.         back = (cell[c] & 0x70) >> 4;
  251.         fore = (cell[c] & 0x07);
  252.         if (fore == colorofunderline)
  253.         cell[c] ^= 0x70;
  254.         else
  255.         cell[c] = (cell[c] & 0x88) | fore << 4 | back;
  256.     }
  257.     VioWrtCellStr(cell, n, r, 0, 0);
  258.     }
  259. }
  260.  
  261. /* ------------------------------------------------------------------ */
  262. static void
  263. doprinton(bool on)
  264. {
  265.     if (on) {
  266.     if (lstclosed) {
  267.         lst = fopen("prn", "w");
  268.         lstclosed = FALSE;
  269.     }
  270.     } else {
  271.     if (!(lstclosed)) {
  272.         fclose(lst);
  273.         lstclosed = TRUE;
  274.     }
  275.     }
  276.     printon = on;
  277. }
  278. /* ----------------------------------------------------------------- */
  279. /* ClrScreen -                                                       */
  280. /* ----------------------------------------------------------------- */
  281. static void
  282. clrscreen()
  283. {
  284.     int             i, j;
  285.     int             nlines;
  286.     USHORT          n;
  287.     char            cells[80][2];
  288.  
  289.     /* copy lines on screen to extended display buffer */
  290.     n = sizeof(cells);
  291.     for (i = 23; i >= 0; i--) {
  292.     VioReadCellStr((char *) cells, &n, i, 0, 0);
  293.     for (j = 0; j < 80; j++) {
  294.         if (cells[j][0] != 32)
  295.         break;
  296.     }
  297.     if (j < 80)
  298.         break;
  299.     }
  300.     nlines = i;            /* no. of nonblank lines-1 */
  301.     for (i = 0; i <= nlines; ++i) {
  302.     paginginfo.botline = (paginginfo.botline + 1) % LBUFSIZE;
  303.     if (paginginfo.numlines < LBUFSIZE)
  304.         paginginfo.numlines = paginginfo.numlines + 1;
  305.     else
  306.         paginginfo.topline = (paginginfo.topline + 1) % LBUFSIZE;
  307.     VioReadCellStr((paginginfo.buffer + 160 * paginginfo.botline), &n, i, 0, 0);
  308.     }
  309.     for (i = 0; i < 24; i++)
  310.     dwl[i] = FALSE;
  311.     dwls = FALSE;
  312.     clearscreen();
  313. }
  314. static void
  315. readmchar_escape()
  316. {
  317.     /* Stores character in achar directly */
  318.     if (escnext <= esclast) {
  319.     achar = escbuffer[escnext];
  320.     escnext = escnext + 1;
  321.     } else
  322.     achar = 0;
  323. }
  324. static int
  325. pnumber(achar)
  326.     unsigned char  *achar;
  327. {
  328.     int             num = 0;
  329.  
  330.     while (isdigit(*achar)) {    /* get number */
  331.     num = (num * 10) + (*achar) - 48;
  332.     readmchar_escape();
  333.     }
  334.     return (num);
  335. }
  336. static void
  337. clreoscr_escape()
  338. {
  339.     char            cell[2];
  340.     int             i;
  341.  
  342.     if (wherex == 1 && wherey == 1) {
  343.     clrscreen();
  344.     return;
  345.     }
  346.     cell[0] = ' ';
  347.     cell[1] = defaultattribute;
  348.     i = 1920 - (((wherey - 1) * 80) + (wherex - 1));
  349.     VioWrtNCell(cell, i, wherey - 1, wherex - 1, 0);
  350.     for (i = wherey - 1; i < 24; i++)
  351.     dwl[i] = FALSE;
  352.     dwls = FALSE;
  353.     for (i = 0; i < 24; i++)
  354.     if (dwl[i]) {
  355.         dwls = TRUE;
  356.         break;
  357.     }
  358. }
  359. static void
  360. clrboscr_escape()
  361. {
  362.     char            cell[2];
  363.     int             i;
  364.  
  365.     cell[0] = ' ';
  366.     cell[1] = defaultattribute;
  367.     i = ((wherey - 1) * 80) + wherex;
  368.     VioWrtNCell(cell, i, 0, 0, 0);
  369.     for (i = 0; i < wherey; i++)
  370.     dwl[i] = FALSE;
  371.     dwls = FALSE;
  372.     for (i = 0; i < 24; i++)
  373.     if (dwl[i]) {
  374.         dwls = TRUE;
  375.         break;
  376.     }
  377. }
  378. static void
  379. clrbol_escape()
  380. {
  381.     char            cell[2];
  382.  
  383.     cell[0] = ' ';
  384.     cell[1] = defaultattribute;
  385.     VioWrtNCell(cell, wherex, wherey - 1, 0, 0);
  386. }
  387. static void
  388. clrline_escape()
  389. {
  390.     char            cell[2];
  391.  
  392.     cell[0] = ' ';
  393.     cell[1] = defaultattribute;
  394.     VioWrtNCell(cell, 80, wherey - 1, 0, 0);
  395. }
  396. static void
  397. decdwl_escape(bool dwlflag)
  398. {
  399.     unsigned char   linenumber;
  400.     unsigned char   newx;
  401.     char            cells[80][2];
  402.     int             i;
  403.     USHORT          n;
  404.     /* Decdwl */
  405.     linenumber = wherey - 1;
  406.     if (dwlflag != dwl[linenumber]) {
  407.     /* change size */
  408.     n = sizeof(cells);
  409.     VioReadCellStr((char *) cells, &n, linenumber, 0, 0);
  410.     if (dwlflag) {        /* make this line double size */
  411.         for (i = 39; i >= 0; --i) {    /* expand */
  412.         cells[2 * i][0] = cells[i][0];
  413.         cells[2 * i + 1][0] = ' ';
  414.         }
  415.         newx = (wherex - 1) * 2 + 1;
  416.         dwls = TRUE;
  417.     } else {        /* make this line single size */
  418.         for (i = 0; i <= 39; ++i)
  419.         cells[i][0] = cells[2 * i][0];
  420.         for (i = 40; i <= 79; ++i)
  421.         cells[i][0] = ' ';
  422.         newx = (wherex - 1) / 2 + 1;
  423.         dwls = FALSE;
  424.         for (i = 0; i < 24; i++)
  425.         if (dwl[i]) {
  426.             dwls = TRUE;
  427.             break;
  428.         }
  429.     }
  430.     VioWrtCellStr((char *) cells, n, linenumber, 0, 0);
  431.     dwl[linenumber] = dwlflag;
  432.     if (newx >= 80)
  433.         newx = 79;
  434.     lgotoxy(newx, wherey);
  435.     }
  436. }
  437. static void
  438. vtescape()
  439. {
  440.     unsigned char   j;
  441.     unsigned char   k;
  442.     unsigned char   l;
  443.     unsigned char   blankcell[2];
  444.     int             i;
  445.     int             pn[11];
  446.     bool            private;
  447.     char            tempstr[20];
  448.     int             fore, back;
  449.     escaping = FALSE;
  450.     escnext = 1;
  451.     readmchar_escape();
  452.     if (screenon || (achar == '[')) {
  453.     /* screen escape sequences  */
  454.     switch (achar) {
  455.         /* First Level */
  456.     case '[':
  457.         {
  458.         /* Left square bracket */
  459.         readmchar_escape();
  460.         switch (achar) {/* Second level */
  461.         case 'A':
  462.             cursorup();
  463.             wrapit = FALSE;
  464.             break;
  465.         case 'B':
  466.             cursordown();
  467.             wrapit = FALSE;
  468.             break;
  469.         case 'C':
  470.             cursorright();
  471.             if (dwl[wherey - 1])
  472.             cursorright();
  473.             break;
  474.         case 'D':
  475.             cursorleft();
  476.             if (dwl[wherey - 1])
  477.             cursorleft();
  478.             break;
  479.         case 'J':    /* Erase End of Display */
  480.             clreoscr_escape();
  481.             break;
  482.         case 'K':
  483.             clrtoeol();
  484.             break;
  485.         case '?':
  486.             private = TRUE;
  487.             readmchar_escape();
  488.             goto LB2001;
  489.         case 'f':
  490.         case 'H':    /* Cursor Home */
  491.             lgotoxy(1, relcursor ? margintop : 1);
  492.             break;
  493.         case 'g':
  494.             htab[wherex] = '0';
  495.             break;
  496.         case '}':
  497.         case 'm':    /* Normal Video - Exit all attribute modes */
  498.             attribute = defaultattribute;
  499.             attrib.blinking = FALSE;
  500.             attrib.bold = FALSE;
  501.             attrib.invisible = FALSE;
  502.             attrib.underlined = FALSE;
  503.             attrib.reversed = FALSE;
  504.             break;
  505.         case 'r':    /* Reset Margin */
  506.             setmargins(1, 24);
  507.             lgotoxy(1, 1);
  508.             break;
  509.         case 'c':
  510.         case 'h':
  511.         case 'l':
  512.         case 'n':
  513.         case 'x':
  514.             pn[1] = 0;
  515.             private = FALSE;
  516.             k = 1;
  517.             goto LB2003;
  518.         case ';':
  519.             pn[1] = 0;
  520.             private = FALSE;
  521.             k = 1;
  522.             goto LB2002;
  523.         case 'L':
  524.         case 'M':
  525.         case '@':
  526.         case 'P':
  527.             pn[1] = 1;
  528.             private = FALSE;
  529.             k = 1;
  530.             goto LB2002;
  531.         default:    /* Pn - got a number */
  532.             private = FALSE;
  533.         LB2001:
  534.             {        /* Esc [ Pn...Pn x   functions */
  535.             pn[1] = pnumber(&achar);
  536.             k = 1;
  537.         LB2002:
  538.             while (achar == ';') {    /* get Pn[k] */
  539.                 readmchar_escape();
  540.                 k++;
  541.                 if (achar == '?') {
  542.                 readmchar_escape();
  543.                 }
  544.                 pn[k] = pnumber(&achar);
  545.             }
  546.             pn[k + 1] = 1;
  547.         LB2003:
  548.             switch (achar) {    /* third level */
  549.             case 'A':
  550.                 do {
  551.                 cursorup();
  552.                 wrapit = FALSE;
  553.                 pn[1] = pn[1] - 1;
  554.                 }
  555.                 while (!(pn[1] <= 0));
  556.                 break;
  557.             case 'B':
  558.                 do {
  559.                 cursordown();
  560.                 wrapit = FALSE;
  561.                 pn[1] = pn[1] - 1;
  562.                 }
  563.                 while (!(pn[1] <= 0));
  564.                 break;
  565.             case 'C':
  566.                 do {
  567.                 cursorright();
  568.                 if (dwl[wherey - 1])
  569.                     cursorright();
  570.                 pn[1] = pn[1] - 1;
  571.                 }
  572.                 while (pn[1] > 0);
  573.                 break;
  574.             case 'D':
  575.                 do {
  576.                 cursorleft();
  577.                 if (dwl[wherey - 1])
  578.                     cursorleft();
  579.                 pn[1] = pn[1] - 1;
  580.                 } while (pn[1] > 0);
  581.                 break;
  582.             case 'f':
  583.             case 'H':
  584.                 /* Direct cursor address */
  585.                 if (pn[1] == 0)
  586.                 pn[1] = 1;
  587.                 if (relcursor)
  588.                 pn[1] += margintop - 1;
  589.                 if (pn[2] == 0)
  590.                 pn[2] = 1;
  591.                 if (dwl[pn[1] - 1]) {
  592.                 pn[2] = 2 * pn[2] - 1;
  593.                 if (pn[2] > 80)
  594.                     pn[2] = 79;
  595.                 } else if (pn[2] > 80)
  596.                 pn[2] = 80;
  597.                 wrapit = FALSE;
  598.                 lgotoxy(pn[2], pn[1]);
  599.                 break;
  600.             case 'c':    /* Device Attributes */
  601.                 if (pn[1] == 0)
  602.                 sendstr("[?6;2c");
  603.                 break;
  604.             case 'g':
  605.                 if (pn[1] == 3) {
  606.                 /* clear all tabs */
  607.                 for (j = 1; j <= 80; ++j)
  608.                     htab[j] = '0';
  609.                 } else if (pn[1] == 0)
  610.                 /* clear tab at current position */
  611.                 htab[wherex] = '0';
  612.                 break;
  613.             case 'h':    /* Set Mode */
  614.                 for (j = 1; j <= k; ++j)
  615.                 if (private)
  616.                     switch (pn[j]) {    /* Field specs */
  617.                     case 1:    /* DECCKM  */
  618.                     cursorkey = TRUE;
  619.                     break;
  620.                     case 2:    /* DECANM : ANSI/VT52 */
  621.                     ansi = TRUE;
  622.                     vt52graphics = FALSE;
  623.                     break;
  624.                     case 3:    /* DECCOLM : Col = 132 */
  625.                     deccolm = TRUE;
  626.                     clrscreen();
  627.                     break;
  628.                     case 4:    /* DECSCLM */
  629.                     break;
  630.                     case 5:    /* DECSCNM */
  631.                     if (decscnm)
  632.                         break;    /* Already set */
  633.                     decscnm = TRUE;;
  634.                     reversescreen();
  635.                     defaultattribute = (coloroftext << 4) | colorofback;
  636.                     attribute = defaultattribute;
  637.                     if (attrib.reversed) {
  638.                         back = attribute & 0x07;
  639.                         fore = (attribute & 0x70) >> 4;
  640.                         if (adapter == colour && attrib.underlined) {
  641.                         fore = colorofunderline;
  642.                         }
  643.                         attribute = (back << 4) | fore;
  644.                     }
  645.                     if (attrib.underlined) {
  646.                         if (adapter == mono && !attrib.reversed)
  647.                         attribute = (attribute & 0xF8) | colorofunderline;
  648.                     }
  649.                     if (attrib.blinking)
  650.                         attribute |= 0x80;
  651.                     if (attrib.bold)
  652.                         attribute |= 8;
  653.                     if (attrib.invisible) {
  654.                         i = (attribute & 0xF8);
  655.                         attribute = i | ((i >> 4) & 7);
  656.                     }
  657.                     break;
  658.                     case 6:    /* DECOM : Relative origin */
  659.                     relcursor = TRUE;
  660.                     lgotoxy(1, margintop);
  661.                     break;
  662.                     case 7:    /* DECAWM */
  663.                     autowrap = TRUE;
  664.                     break;
  665.                     case 8:    /* DECARM */
  666.                     break;
  667.                     case 9:    /* DECINLM */
  668.                     break;
  669.                     default:
  670.                     break;
  671.                 } else
  672.                     switch (pn[j]) {
  673.                     case 2:    /* Keyboard locked */
  674.                     keylock = TRUE;
  675.                     break;
  676.                     case 4:    /* Ansi insert mode */
  677.                     insertmode = TRUE;
  678.                     break;
  679.                     case 20:    /* Ansi linefeed mode */
  680.                     linemode = TRUE;
  681.                     break;
  682.                     default:
  683.                     break;
  684.                     }
  685.                 break;
  686.             case 'l':
  687.                 /* Reset Mode */
  688.                 for (j = 1; j <= k; ++j)
  689.                 if (private)
  690.                     switch ((pn[j])) {    /* Field specs */
  691.                     case 1:    /* DECCKM  */
  692.                     cursorkey = FALSE;
  693.                     break;
  694.                     case 2:    /* DECANM : ANSI/VT52 */
  695.                     ansi = FALSE;
  696.                     vt52graphics = FALSE;
  697.                     break;
  698.                     case 3:    /* DECCOLM : 80 col */
  699.                     deccolm = FALSE;
  700.                     clrscreen();
  701.                     break;
  702.                     case 4:    /* DECSCLM */
  703.                     break;
  704.                     case 5:    /* DECSCNM */
  705.                     if (!decscnm)
  706.                         break;
  707.                     decscnm = !decscnm;
  708.                     reversescreen();
  709.                     defaultattribute = (colorofback << 4) | coloroftext;
  710.                     attribute = defaultattribute;
  711.                     if (attrib.reversed) {
  712.                         back = attribute & 0x07;
  713.                         fore = (attribute & 0x70) >> 4;
  714.                         if (adapter == colour && attrib.underlined) {
  715.                         fore = colorofunderline;
  716.                         }
  717.                         attribute = (back << 4) | fore;
  718.                     }
  719.                     if (attrib.underlined) {
  720.                         if (adapter == mono && !attrib.reversed)
  721.                         attribute = (attribute & 0xF8) | colorofunderline;
  722.                     }
  723.                     if (attrib.blinking)
  724.                         attribute |= 0x80;
  725.                     if (attrib.bold)
  726.                         attribute |= 8;
  727.                     if (attrib.invisible) {
  728.                         i = (attribute & 0xF8);
  729.                         attribute = i | ((i >> 4) & 7);
  730.                     }
  731.                     break;
  732.                     case 6:    /* DECOM : Relative origin */
  733.                     relcursor = FALSE;
  734.                     lgotoxy(1, 1);
  735.                     break;
  736.                     case 7:    /* DECAWM */
  737.                     autowrap = FALSE;
  738.                     break;
  739.                     case 8:    /* DECARM */
  740.                     break;
  741.                     case 9:    /* DECINLM */
  742.                     break;
  743.                     default:
  744.                     break;
  745.                 } else
  746.                     switch (pn[j]) {
  747.                     case 2:    /* Keyboard unlocked */
  748.                     keylock = FALSE;
  749.                     break;
  750.                     case 4:    /* Ansi insert mode */
  751.                     insertmode = FALSE;
  752.                     break;
  753.                     case 20:    /* Ansi linefeed mode */
  754.                     linemode = FALSE;
  755.                     break;
  756.                     default:
  757.                     break;
  758.                     }
  759.                 break;
  760.             case 'i':    /* Printer Screen  on / off */
  761.                 for (j = 1; j <= k; ++j)
  762.                 switch ((pn[j])) {    /* Field specs */
  763.                 case 4:
  764.                     doprinton(FALSE);
  765.                     break;
  766.                 case 5:
  767.                     doprinton(TRUE);
  768.                     break;
  769.                 case 6:
  770.                     screenon = FALSE;
  771.                     break;
  772.                 case 7:
  773.                     screenon = TRUE;
  774.                     break;
  775.                 default:
  776.                     break;
  777.                 }
  778.                 break;
  779.             case 'q':
  780.                 break;
  781.             case 'n':
  782.                 if (pn[1] == 5) {    /* Device Status Report */
  783.                 sendstr("[0n");
  784.                 } else if (pn[1] == 6) {    /* Cursor Position
  785.                              * Report */
  786.                 sendstr("[");
  787.                 sprintf(tempstr, "%1d", (int) wherey);    /* row */
  788.                 SENDCHAR(tempstr[0]);
  789.                 if (tempstr[1])
  790.                     SENDCHAR(tempstr[1]);
  791.                 SENDCHAR(';');
  792.                 sprintf(tempstr, "%1d", (int) wherex);    /* col */
  793.                 SENDCHAR(tempstr[0]);
  794.                 if (tempstr[1])
  795.                     SENDCHAR(tempstr[1]);
  796.                 SENDCHAR('R');
  797.                 }
  798.                 break;
  799.             case 'x':    /* Request terminal Parameters */
  800.                 if (pn[1] > 1)
  801.                 break;
  802.                 tempstr[0] = '[';
  803.                 tempstr[1] = (pn[1] == 0) ? '2' : '3';
  804.                 tempstr[2] = ';';
  805.                 switch (parity) {
  806.                 case 'e':
  807.                 tempstr[3] = '5';
  808.                 tempstr[5] = '2';
  809.                 break;
  810.                 case 'o':
  811.                 tempstr[3] = '4';
  812.                 tempstr[5] = '2';
  813.                 break;
  814.                 case 0:
  815.                 tempstr[3] = '1';
  816.                 tempstr[5] = '1';
  817.                 break;
  818.                 default:
  819.                 tempstr[3] = '1';
  820.                 tempstr[5] = '2';
  821.                 break;
  822.                 }
  823.                 tempstr[4] = ';';
  824.                 switch (speed) {
  825.                 case 50:
  826.                 i = 0;
  827.                 break;
  828.                 case 75:
  829.                 i = 8;
  830.                 break;
  831.                 case 110:
  832.                 i = 16;
  833.                 break;
  834.                 case 133:
  835.                 i = 14;
  836.                 break;
  837.                 case 150:
  838.                 i = 32;
  839.                 break;
  840.                 case 200:
  841.                 i = 40;
  842.                 break;
  843.                 case 300:
  844.                 i = 48;
  845.                 break;
  846.                 case 600:
  847.                 i = 56;
  848.                 break;
  849.                 case 1200:
  850.                 i = 64;
  851.                 break;
  852.                 case 1800:
  853.                 i = 72;
  854.                 break;
  855.                 case 2000:
  856.                 i = 80;
  857.                 break;
  858.                 case 2400:
  859.                 i = 88;
  860.                 break;
  861.                 case 3600:
  862.                 i = 96;
  863.                 break;
  864.                 case 4800:
  865.                 i = 104;
  866.                 break;
  867.                 case 9600:
  868.                 i = 112;
  869.                 break;
  870.                 case 19200:
  871.                 i = 120;
  872.                 break;
  873.                 default:
  874.                 i = 120;
  875.                 break;
  876.                 }
  877.                 sprintf(&tempstr[6], ";%d;%d;1;0x", i, i);
  878.                 sendstr(tempstr);
  879.                 break;
  880.             case 'm':
  881.             case '}':
  882.                 for (j = 1; j <= k; ++j)
  883.                 switch ((pn[j])) {    /* Field specs */
  884.                 case 0:    /* normal */
  885.                     attribute = defaultattribute;
  886.                     attrib.blinking = FALSE;
  887.                     attrib.bold = FALSE;
  888.                     attrib.invisible = FALSE;
  889.                     attrib.underlined = FALSE;
  890.                     attrib.reversed = FALSE;
  891.                     break;
  892.                 case 1:    /* bold */
  893.                     attrib.bold = TRUE;
  894.                     attribute |= 8;
  895.                     break;
  896.                 case 4:    /* underline */
  897.                     if (attrib.underlined)
  898.                     break;
  899.                     attrib.underlined = TRUE;
  900.                     if (adapter == mono && attrib.reversed)
  901.                     break;
  902.                     attribute = (attribute & 0xF8) | colorofunderline;
  903.                     break;
  904.                 case 5:    /* blink */
  905.                     attrib.blinking = TRUE;
  906.                     attribute |= 0x80;
  907.                     break;
  908.                 case 7:    /* reverse video */
  909.                     if (attrib.reversed)
  910.                     break;
  911.                     attrib.reversed = TRUE;
  912.                     fore = defaultattribute >> 4;
  913.                     back = defaultattribute & 0x07;
  914.                     if (adapter == colour && attrib.underlined) {
  915.                     fore = colorofunderline;
  916.                     }
  917.                     if (attrib.invisible)
  918.                     fore = back;
  919.                     attribute = (attribute & 0x88) | back << 4 | fore;
  920.                     break;
  921.                 case 8:    /* invisible */
  922.                     if (attrib.invisible)
  923.                     break;
  924.                     attrib.invisible = TRUE;
  925.                     i = (attribute & 0xF8);
  926.                     attribute = i | ((i >> 4) & 7);
  927.                     break;
  928.                 case 30:
  929.                 case 31:
  930.                 case 32:
  931.                 case 33:
  932.                 case 34:
  933.                 case 35:
  934.                 case 36:
  935.                 case 37:
  936.                     /* select foreground */
  937.                     i = (attribute & 248);
  938.                     attribute = (i | sgrcols[pn[j] - 30]);
  939.                     break;
  940.                 case 40:
  941.                 case 41:
  942.                 case 42:
  943.                 case 43:
  944.                 case 44:
  945.                 case 45:
  946.                 case 46:
  947.                 case 47:
  948.                     /* select back ground */
  949.                     i = (attribute & 143);
  950.                     l = sgrcols[pn[j] - 40];
  951.                     attribute = (i | ((l << 4)));
  952.                     break;
  953.                 default:
  954.                     break;
  955.                 }
  956.                 break;
  957.             case 'r':    /* set margin */
  958.                 if ((k < 2) || (pn[2] == 0))
  959.                 pn[2] = 24;
  960.                 if (pn[1] == 0)
  961.                 pn[1] = 1;
  962.                 if ((pn[1] > 0) && (pn[1] < pn[2]) && (pn[2] < 25)) {
  963.                 setmargins(pn[1], pn[2]);
  964.                 lgotoxy(1, relcursor ? margintop : 1);
  965.                 }
  966.                 break;
  967.             case 'J':
  968.                 switch ((pn[1])) {
  969.                 case 0:    /* clear to end of screen */
  970.                 clreoscr_escape();
  971.                 break;
  972.                 case 1:    /* clear to beginning */
  973.                 clrboscr_escape();
  974.                 break;
  975.                 case 2:    /* clear all of screen */
  976.                 clrscreen();
  977.                 break;
  978.                 default:
  979.                 break;
  980.                 }
  981.                 break;
  982.             case 'K':
  983.                 switch ((pn[1])) {
  984.                 case 0:    /* clear to end of line */
  985.                 clrtoeol();
  986.                 break;
  987.                 case 1:    /* clear to beginning */
  988.                 clrbol_escape();
  989.                 break;
  990.                 case 2:    /* clear line */
  991.                 clrline_escape();
  992.                 break;
  993.                 default:
  994.                 break;
  995.                 }
  996.                 break;
  997.             case 'L':    /* Insert lines */
  998.                 for (i = 1; i <= pn[1]; ++i)
  999.                 scroll(DOWNWARD, wherey - 1, marginbot - 1);
  1000.                 break;
  1001.             case 'M':    /* Delete lines */
  1002.                 for (i = 1; i <= pn[1]; ++i)
  1003.                 scroll(UPWARD, wherey - 1, marginbot - 1);
  1004.                 break;
  1005.             case '@':    /* Insert characters */
  1006.                 blankcell[0] = ' ';
  1007.                 blankcell[1] = defaultattribute;
  1008.                 pn[1] *= dwl[wherey - 1] ? 2 : 1;
  1009.                 if (pn[1] > 81 - wherex)
  1010.                 pn[1] = 81 - wherex;
  1011.                 VioScrollRt(wherey - 1, wherex - 1, wherey - 1, 79, pn[1], blankcell, 0);
  1012.                 break;
  1013.             case 'P':    /* DeleteChar */
  1014.                 blankcell[0] = ' ';
  1015.                 blankcell[1] = defaultattribute;
  1016.                 pn[1] *= dwl[wherey - 1] ? 2 : 1;
  1017.                 if (pn[1] > 81 - wherex)
  1018.                 pn[1] = 81 - wherex;
  1019.                 VioScrollLf(wherey - 1, wherex - 1, wherey - 1, 79, pn[1], blankcell, 0);
  1020.                 break;
  1021.             default:
  1022.                 break;
  1023.             }
  1024.             }
  1025.             break;
  1026.         }
  1027.         }            /* Left square bracket */
  1028.         break;
  1029.     case '7':        /* Save cursor position */
  1030.         saved = TRUE;
  1031.         row = wherey;
  1032.         column = wherex;
  1033.         savedattribute = attribute;
  1034.         savedattrib = attrib;
  1035.         saverelcursor = relcursor;
  1036.         saveg0 = g0;
  1037.         saveg1 = g1;
  1038.         saveg0g1 = g0g1;
  1039.         break;
  1040.     case '8':        /* Restore Cursor Position */
  1041.         if (!saved) {    /* Home cursor */
  1042.         lgotoxy(1, relcursor ? margintop : 1);
  1043.             break;
  1044.         }
  1045.         saved = FALSE;
  1046.         lgotoxy(column, row);
  1047.         attribute = savedattribute;
  1048.         attrib = savedattrib;
  1049.         relcursor = saverelcursor;
  1050.         g0 = saveg0;
  1051.         g1 = saveg1;
  1052.         g0g1 = saveg0g1;
  1053.         break;
  1054.     case 'A':
  1055.         if (!ansi)        /* VT52 control */
  1056.         cursorup();
  1057.         break;
  1058.     case 'B':
  1059.         if (!(ansi))
  1060.         /* VT52 control */
  1061.         cursordown();
  1062.         break;
  1063.     case 'C':
  1064.         if (!(ansi))
  1065.         /* VT52 control */
  1066.         cursorright();
  1067.         break;
  1068.     case 'D':
  1069.         if (!(ansi))
  1070.         /* VT52 control */
  1071.         cursorleft();
  1072.         else {
  1073.         /* Index */
  1074.         if ((wherey >= marginbot))
  1075.             scroll(UPWARD, margintop - 1, marginbot - 1);
  1076.         else
  1077.             cursordown();
  1078.         }
  1079.         break;
  1080.     case 'E':        /* Next Line */
  1081.         wrtch(13);
  1082.         wrtch(10);
  1083.         break;
  1084.     case 'F':
  1085.         if (!ansi)
  1086.         vt52graphics = TRUE;
  1087.         break;
  1088.     case 'G':
  1089.         if (!ansi)
  1090.         vt52graphics = FALSE;
  1091.         break;
  1092.     case 'H':
  1093.         if (ansi) {
  1094.         /* Set Tab Stop */
  1095.         htab[wherex] = 'T';
  1096.         }
  1097.         /* Set Tab Stop */
  1098.         else
  1099.         lgotoxy(1, 1);
  1100.         /* VT52 control */
  1101.         break;
  1102.     case 'I':
  1103.         if (!(ansi)) {
  1104.         /* VT52 control */
  1105.         if ((margintop < wherey))
  1106.             cursorup();
  1107.         else
  1108.             scroll(DOWNWARD, margintop - 1, marginbot - 1);
  1109.         }
  1110.         break;
  1111.     case 'J':
  1112.         if (!(ansi))
  1113.         /* VT52 control */
  1114.         clreoscr_escape();
  1115.         break;
  1116.     case 'K':
  1117.         if (!(ansi))
  1118.         /* VT52 control */
  1119.         clrtoeol();
  1120.         break;
  1121.     case 'M':
  1122.         /* Reverse Index */
  1123.         if (margintop >= wherey)
  1124.         scroll(DOWNWARD, margintop - 1, marginbot - 1);
  1125.         else
  1126.         cursorup();
  1127.         break;
  1128.     case 'Y':
  1129.         if (!(ansi)) {    /* VT52 control */
  1130.         /* direct cursor address */
  1131.         readmchar_escape();
  1132.         row = achar - 31;
  1133.         readmchar_escape();
  1134.         column = achar - 31;
  1135.         lgotoxy(column, row);
  1136.         }
  1137.         /* direct cursor address */
  1138.         break;
  1139.     case 'Z':
  1140.         if (ansi) {
  1141.         /* Device Attributes */
  1142.         /* Send  Esc[?6;2c */
  1143.         sendstr("[?6;2c");
  1144.         }
  1145.         /* Device Attributes */
  1146.         else
  1147.         /* VT52 control */
  1148.         SENDSTR2("/Z");
  1149.         break;
  1150.     case 'c':
  1151.         /* Reset */
  1152.         defaultattribute = coloroftext + (colorofback << 4);
  1153.         attribute = defaultattribute;
  1154.         attrib.blinking = FALSE;
  1155.         attrib.bold = FALSE;
  1156.         attrib.invisible = FALSE;
  1157.         attrib.underlined = FALSE;
  1158.         attrib.reversed = FALSE;
  1159.         g0 = g1 = 'A';
  1160.         g0g1 = &g0;
  1161.         printon = FALSE;
  1162.         screenon = TRUE;
  1163.         vt52graphics = FALSE;
  1164.         saved = FALSE;
  1165.         linemode = FALSE;
  1166.         insertmode = FALSE;
  1167.         cursorkey = TRUE;
  1168.         keypadnum = FALSE;
  1169.         autowrap = FALSE;
  1170.         ansi = TRUE;
  1171.         keylock = FALSE;
  1172.         deccolm = decscnm = FALSE;
  1173.         for (i = 0; i < 24; i++)
  1174.         dwl[i] = FALSE;
  1175.         dwls = FALSE;
  1176.         for (i = 1; i < 80; i++)
  1177.         htab[i] = (i % 8) == 0 ? 'T' : '0';
  1178.         relcursor = FALSE;
  1179.         setmargins(1, 24);
  1180.         clrscreen();
  1181.         break;
  1182.     case '#':
  1183.         /* Esc # sequence */
  1184.         readmchar_escape();
  1185.         switch (achar) {
  1186.         case '3':
  1187.         decdwl_escape(TRUE);
  1188.         break;
  1189.         case '4':
  1190.         decdwl_escape(TRUE);
  1191.         break;
  1192.         case '5':
  1193.         decdwl_escape(FALSE);
  1194.         break;
  1195.         case '6':
  1196.         decdwl_escape(TRUE);
  1197.         break;
  1198.         case '8':
  1199.         {
  1200.             char            cell[2];
  1201.             cell[0] = 'E';
  1202.             cell[1] = 7;
  1203.             /* Self Test */
  1204.             VioWrtNCell(cell, 1920, 0, 0, 0);
  1205.             setmargins(1, 24);
  1206.             lgotoxy(1, 1);
  1207.         }
  1208.         break;
  1209.         /* Self Test */
  1210.         default:
  1211.         break;
  1212.         }
  1213.         break;
  1214.         /* Esc # sequence */
  1215.     case '=':
  1216.         keypadnum = FALSE;
  1217.         break;
  1218.     case '>':
  1219.         keypadnum = TRUE;
  1220.         break;
  1221.     case '<':
  1222.         /* VT52 control */
  1223.         ansi = TRUE;
  1224.         break;
  1225.     case '(':
  1226.         readmchar_escape();
  1227.         g0 = achar;
  1228.         break;
  1229.     case ')':
  1230.         readmchar_escape();
  1231.         g1 = achar;
  1232.         break;
  1233.     default:
  1234.         if (achar == 12) {
  1235.         lgotoxy(1, 1);
  1236.         clrscreen();
  1237.         }
  1238.         break;
  1239.     }
  1240.     /* First Level Case  */
  1241.     }
  1242.     /* screen escape sequences  */
  1243.     if (printon) {
  1244.     fprintf(lst, "%c", 27);
  1245.     if (esclast > 0) {
  1246.         /* print esc sequence */
  1247.         for (i = 1; i <= esclast; ++i)
  1248.         fprintf(lst, "%c", escbuffer[i]);
  1249.     }
  1250.     }
  1251. }
  1252. /* ================================================================== */
  1253. /* */
  1254. /* VT100 emulate a dec vt100 terminal writing a character            */
  1255. /* */
  1256. /* ================================================================== */
  1257. static void
  1258. vt100(vtch)
  1259.     unsigned char   vtch;
  1260. {
  1261.     int             i, j;
  1262.     char           *s, str[2];
  1263.     /* ----------------------------------------------------------------- */
  1264.     /* ------------------------------------------------------------------ */
  1265.     /* vt100 */
  1266.     if (screenon) {
  1267.     if (vtch < 32) {    /* Control Character */
  1268.         achar = vtch;    /* Let the rest of this module see the value */
  1269.         switch (achar) {
  1270.         case LF:
  1271.             if (linemode) wherex=1;
  1272.         wrtch(achar);
  1273.         break;
  1274.         case CR:
  1275.         wrtch(achar);
  1276.         break;
  1277.         /* ESC */
  1278.         case 27:
  1279.         vtescape();
  1280.         break;
  1281.         case 14:        /* SO */
  1282.         g0g1 = &g1;
  1283.         break;
  1284.         /* SI */
  1285.         case 15:
  1286.         g0g1 = &g0;
  1287.         break;
  1288.         /* BS */
  1289.         case 8:
  1290.         wrtch(achar);
  1291.         break;
  1292.         case 12:        /* FF */
  1293.         case 11:        /* VT */
  1294.         /* take as lf */
  1295.         achar = 10;
  1296.         wrtch(10);
  1297.         break;
  1298.         case 7:        /* BEL */
  1299.         bleep();
  1300.         break;
  1301.         case 5:        /* ENQ */
  1302.         s = answerback;
  1303.         while (*s)
  1304.             SENDCHAR(*s++);
  1305.         break;
  1306.         case 9:        /* tab character */
  1307.         j = dwl[wherey - 1] ? 2 : 1;
  1308.         i = wherex;
  1309.         if (j == 2 && htab[(i - 1) / j + 1] == 'T') {
  1310.             i++;
  1311.             cursorright();
  1312.         }
  1313.         if (i < 80)
  1314.             do {
  1315.             i++;
  1316.             cursorright();
  1317.             } while ((htab[(i - 1) / j + 1] != 'T') && (i < 81 - j));
  1318.         break;
  1319.         default:        /* ignore it */
  1320.         break;
  1321.         }
  1322.         /* end of Control Character */
  1323.     } else {
  1324.         if (vtch != DEL) {    /* Normal char */
  1325.         if (ansi) {
  1326.             if (*g0g1 == 'A') {    /* UK ascii set */
  1327.             if (vtch == 35)
  1328.                 vtch = 156;
  1329.             } else if ((*g0g1 == '0') && (95 <= vtch) && (vtch <= 126)) {
  1330.             literal = TRUE;
  1331.             vtch = graphicset[vtch - 95];
  1332.             }
  1333.         } else {
  1334.             if (vt52graphics && (95 <= vtch) && (vtch <= 126)) {
  1335.             literal = TRUE;
  1336.             vtch = graphicset[vtch - 95];
  1337.             }
  1338.         }
  1339.         if (wherex != (dwl[wherey - 1] ? 79 : 80)) {
  1340.             wrtch(vtch);
  1341.             if (dwl[wherey - 1])
  1342.             wrtch(' ');
  1343.             wrapit = FALSE;
  1344.         } else {
  1345.             if (wrapit) {    /* Next line  */
  1346.             if (marginbot <= wherey) {    /* Scroll up */
  1347.                 scroll(UPWARD, margintop - 1, marginbot - 1);
  1348.                 lgotoxy(1, wherey);
  1349.             } else
  1350.                 lgotoxy(1, wherey + 1);
  1351.             wrtch(vtch);
  1352.             if (dwl[wherey - 1])
  1353.                 wrtch(' ');
  1354.             wrapit = FALSE;
  1355.             } else {    /* put char on col 80 */
  1356.             i = dwl[wherey - 1] ? 2 : 1;
  1357.             str[0] = vtch;
  1358.             str[1] = ' ';
  1359.             VioWrtCharStrAtt(&vtch, i, wherey - 1, 80 - i, &attribute, 0);
  1360.             literal = FALSE;
  1361.             if ((autowrap && !deccolm))
  1362.                 wrapit = TRUE;
  1363.             }
  1364.         }
  1365.         }            /* Normal char */
  1366.     }
  1367.     }
  1368.     if (printon && (vtch != 27))
  1369.     fprintf(lst, "%c", vtch);
  1370. }
  1371.  
  1372. /* ------------------------------------------------------------------ */
  1373. /* Vt100read -                                                        */
  1374. /* ------------------------------------------------------------------ */
  1375. /* save current status of screen */
  1376. static void
  1377.     savescreen(scrn) ascreen *scrn;
  1378. {
  1379.     USHORT          n = sizeof(screenmap);
  1380.     scrn->ox = wherex;
  1381.     scrn->oy = wherey;
  1382.     scrn->att = attribute;
  1383.     VioReadCellStr((char *) (scrn->scrncpy), &n, 0, 0, 0);
  1384. }
  1385. /* restore state of screen */
  1386. static void
  1387.     restorescreen(scrn) ascreen *scrn;
  1388. {
  1389.     movetoscreen(scrn->scrncpy, 1, 1, 4000);
  1390.     attribute = scrn->att;
  1391.     wherey = scrn->oy;
  1392.     wherex = scrn->ox;
  1393.     lgotoxy(wherex, wherey);
  1394. }
  1395. static void
  1396. sendcharduplex(unsigned char c)
  1397. {
  1398.     SENDCHAR(c);
  1399.     if (duplex) {
  1400.     cwrite(c);
  1401.     if (seslog)
  1402.         if (zchout(ZSFILE, c) < 0)
  1403.         seslog = 0;
  1404.     }
  1405. }
  1406. static void
  1407. sendstrduplex(unsigned char *s)
  1408. {
  1409.     SENDCHAR(27);
  1410.     if (duplex) {
  1411.     cwrite(27);
  1412.     if (seslog)
  1413.         if (zchout(ZSFILE, 27) < 0)
  1414.         seslog = 0;
  1415.     }
  1416.     while (*s) {
  1417.     SENDCHAR(*s);
  1418.     if (duplex) {
  1419.         cwrite(*s);
  1420.         if (seslog)
  1421.         if (zchout(ZSFILE, *s) < 0)
  1422.             seslog = 0;
  1423.     }
  1424.     s++;
  1425.     }
  1426. }
  1427. static void
  1428.     vt100read(a, b) unsigned char a, b;
  1429. {
  1430.     unsigned char   achar;
  1431.     unsigned char   bchar;
  1432.     int             i;
  1433.     int             il;
  1434.     char            str[3];
  1435.     int             prt;
  1436.     int             st;
  1437.     unsigned char   nolblines;
  1438.     unsigned char   linesleft;
  1439.     unsigned char   nextline;
  1440.     unsigned char   nlines;
  1441.     ascreen         savedscreen;/* screen save info */
  1442.  
  1443.     achar = a;
  1444.     bchar = b;
  1445. LB1:
  1446.     if (((achar == 8) && (bchar == 14))) {
  1447.     /* backspace is mapped to del */
  1448.     achar = 127;
  1449.     bchar = 0;
  1450.     }
  1451.     if (achar != 0) {
  1452.     sendcharduplex(achar);
  1453.     if (achar == CR && linemode)
  1454.         sendcharduplex(LF);
  1455.     } else {
  1456.     switch ((int) (bchar)) {
  1457.     case 72:
  1458.         /* up */
  1459.         if (ansi) {
  1460.         if (cursorkey)
  1461.             sendstrduplex("OA");
  1462.         else
  1463.             sendstrduplex("[A");
  1464.         } else
  1465.         sendstrduplex("A");
  1466.         break;
  1467.     case 75:
  1468.         /* left */
  1469.         if (ansi) {
  1470.         if (cursorkey)
  1471.             sendstrduplex("OD");
  1472.         else
  1473.             sendstrduplex("[D");
  1474.         } else
  1475.         sendstrduplex("D");
  1476.         break;
  1477.     case 77:
  1478.         /* right */
  1479.         if (ansi) {
  1480.         if (cursorkey)
  1481.             sendstrduplex("OC");
  1482.         else
  1483.             sendstrduplex("[C");
  1484.         } else
  1485.         sendstrduplex("C");
  1486.         break;
  1487.     case 80:
  1488.         /* down */
  1489.         if (ansi) {
  1490.         if (cursorkey)
  1491.             sendstrduplex("OB");
  1492.         else
  1493.             sendstrduplex("[B");
  1494.         } else
  1495.         sendstrduplex("B");
  1496.         break;
  1497.     case 15:        /* Backtab */
  1498.         /* backspace */
  1499.         sendcharduplex(8);
  1500.         break;
  1501.     case 83:
  1502.         /* delete */
  1503.         sendcharduplex(127);
  1504.         break;
  1505.     case 59:
  1506.         /* PF1 */
  1507.         if (ansi)
  1508.         sendstrduplex("OP");
  1509.         else
  1510.         sendstrduplex("P");
  1511.         break;
  1512.     case 60:
  1513.         /* PF2 */
  1514.         if (ansi)
  1515.         sendstrduplex("OQ");
  1516.         else
  1517.         sendstrduplex("Q");
  1518.         break;
  1519.     case 61:
  1520.         /* PF3 */
  1521.         if (ansi)
  1522.         sendstrduplex("OR");
  1523.         else
  1524.         sendstrduplex("R");
  1525.         break;
  1526.     case 62:
  1527.         /* PF4 */
  1528.         if (ansi)
  1529.         sendstrduplex("OS");
  1530.         else
  1531.         sendstrduplex("S");
  1532.         break;
  1533.     case 120:
  1534.     case 121:
  1535.     case 122:
  1536.     case 123:
  1537.     case 124:
  1538.     case 125:
  1539.     case 126:
  1540.     case 127:
  1541.     case 128:
  1542.     case 129:
  1543.         /* numeric 1-9,0 */
  1544.         {
  1545.         bchar = 'q' + bchar - 120;
  1546.         if (bchar == 'z')
  1547.             bchar = 'p';
  1548.         /* alt 0 */
  1549.         if (ansi)
  1550.             strcpy(str, "O ");
  1551.         else
  1552.             strcpy(str, "? ");
  1553.         str[1] = bchar;
  1554.         sendstrduplex(str);
  1555.         }
  1556.         break;
  1557.     case 63:
  1558.     case 64:
  1559.         /* numeric - */
  1560.         if (ansi)
  1561.         sendstrduplex("Om");
  1562.         else
  1563.         sendstrduplex("?m");
  1564.         break;
  1565.     case 65:
  1566.     case 66:
  1567.         /* numeric , */
  1568.         if (ansi)
  1569.         sendstrduplex("Ol");
  1570.         else
  1571.         sendstrduplex("?l");
  1572.         break;
  1573.     case 67:
  1574.         /* numeric + */
  1575.         if (ansi)
  1576.         sendstrduplex("On");
  1577.         else
  1578.         sendstrduplex("?n");
  1579.         break;
  1580.     case 68:
  1581.         /* numeric enter */
  1582.         if (ansi)
  1583.         sendstrduplex("OM");
  1584.         else
  1585.         sendstrduplex("?M");
  1586.         break;
  1587.     case 71:        /* Home */
  1588.         {
  1589.         strcpy(usertext, " Scroll lock on");
  1590.         strcpy(exittext, "Exit: Home");
  1591.         *helptext = '\0';
  1592.         line25();
  1593.         do
  1594.             scankey(&(achar), &(bchar));
  1595.         while (!((achar == 0) && (bchar == 71)));
  1596.         ipadl25();
  1597.         }
  1598.         break;
  1599.     case 81:        /* Page down */
  1600.         bleep();
  1601.         /* since not in extened display mode */
  1602.         break;
  1603.     case 73:        /* Page up   enter extended display mode */
  1604.         if (paginginfo.numlines == 0)
  1605.         bleep();
  1606.         else {
  1607.         savescreen(&savedscreen);
  1608.         killcursor();
  1609.         linesleft = paginginfo.numlines;
  1610.         nextline = paginginfo.botline;
  1611.         do {
  1612.             if (bchar == 73) {
  1613.             if (linesleft == 0)
  1614.                 bleep();
  1615.             else {
  1616.                 /* scroll up a page */
  1617.                 nlines = linesleft;
  1618.                 if (nlines > 24)
  1619.                 nlines = 24;
  1620.                 {
  1621.                 for (il = 1; il <= nlines; ++il) {
  1622.                     scroll(DOWNWARD, 0, 23);
  1623.                     movetoscreen(paginginfo.buffer + 160 * nextline, 1, 1, 160);
  1624.                     if (nextline == 0)
  1625.                     nextline = LBUFSIZE - 1;
  1626.                     else
  1627.                     nextline = nextline - 1;
  1628.                 }
  1629.                 il--;
  1630.                 }
  1631.                 linesleft = linesleft - nlines;
  1632.             }
  1633.             } else if (bchar == 81) {
  1634.             nlines = 24;
  1635.             do {
  1636.                 nextline = nextline + 1;
  1637.                 if (nextline >= LBUFSIZE)
  1638.                 nextline = 0;
  1639.                 linesleft = linesleft + 1;
  1640.                 /* lines of ext display above top of the screen */
  1641.                 nolblines = paginginfo.numlines - linesleft;
  1642.                 /* no. of ext disp buffer lines on screen */
  1643.                 scroll(UPWARD, 0, 23);
  1644.                 if (nolblines >= 24) {
  1645.                 /* move from buffer */
  1646.                 i = nextline;
  1647.                 i = (i + 24);
  1648.                 if (i >= LBUFSIZE)
  1649.                     i = i - LBUFSIZE;
  1650.                 movetoscreen(paginginfo.buffer + 160 * i, 1, 24, 160);
  1651.                 } else {
  1652.                 /* move from the screen copy */
  1653.                 movetoscreen(&(savedscreen.scrncpy[(23 - nolblines) * 160]), 1, 24, 160);
  1654.                 }
  1655.                 nlines = nlines - 1;
  1656.             }
  1657.             while (!(((nlines == 0) || (linesleft == paginginfo.numlines))));
  1658.             } else
  1659.             linesleft = paginginfo.numlines;
  1660.             if (linesleft != paginginfo.numlines) {
  1661.             strcpy(helptext, "PgUp : up");
  1662.             strcpy(exittext, "PgDn : down");
  1663.             *usertext = '\0';
  1664.             *filetext = '\0';
  1665.             *hostname = '\0';
  1666.             line25();
  1667.             scankey(&(achar), &(bchar));
  1668.             }
  1669.         }
  1670.         while (linesleft != paginginfo.numlines);
  1671.         restorescreen(&savedscreen);
  1672.         newcursor();
  1673.         ipadl25();
  1674.         if (((achar != 0) || (bchar != 45)))
  1675.             goto LB1;
  1676.         /* to process key */
  1677.         }
  1678.         break;
  1679.     default:
  1680.         break;
  1681.     }
  1682.     /* of case bchar */
  1683.     }
  1684. }
  1685. /* ------------------------------------------------------------------ */
  1686. /* cwrite                                                             */
  1687. /* ------------------------------------------------------------------ */
  1688. cwrite(ch)
  1689.     unsigned char   ch;
  1690. {
  1691.     {
  1692.     /* check and process escape sequence */
  1693.     /* escape */
  1694.     if (ch == 27) {
  1695.         escaping = TRUE;
  1696.         esclast = 0;
  1697.     } else {
  1698.         if (!(escaping)) {
  1699.         /* can send it to vt100 to be processed */
  1700.         vt100(ch);
  1701.         } else {
  1702.         /* in the middle of an escape sequence */
  1703.         if (((ch == 24) || (ch == 26)))
  1704.             /* cancelled */
  1705.             escaping = FALSE;
  1706.         else {
  1707.             if (ch < 32) {
  1708.             if (ch == 8) {    /* Backspace */
  1709.                 if (esclast >= 1)
  1710.                 esclast--;
  1711.             }
  1712.             } else {
  1713.             /* add to control string */
  1714.             if (esclast < 128) {
  1715.                 /* add to buffer */
  1716.                 esclast = esclast + 1;
  1717.                 escbuffer[esclast] = ch;
  1718.             }
  1719.             /* now check to see if sequence complete */
  1720.             {
  1721.                 if (ansi) {
  1722.                 if (escbuffer[1] != '[') {
  1723.                     char            c = escbuffer[1];
  1724.                     if ((c != '#' && c != '(' && c != ')' && c != 'O'
  1725.                      && c != '?') || esclast >= 2) {
  1726.                     if ((escbuffer[1] != 'Y'))
  1727.                         vtescape();
  1728.                     else {
  1729.                         if ((esclast == 3))
  1730.                         vtescape();
  1731.                     }
  1732.                     }
  1733.                 } else {
  1734.                     /* check for terminating character */
  1735.                     if ((((64 <= ch) && (ch <= 126)) && (esclast > 1)))
  1736.                     vtescape();
  1737.                 }
  1738.                 } else {
  1739.                 /* vt52 mode */
  1740.                 if ((escbuffer[1] != 'Y'))
  1741.                     vtescape();
  1742.                 else {
  1743.                     if (esclast == 3)
  1744.                     vtescape();
  1745.                 }
  1746.                 }
  1747.             }
  1748.             }
  1749.         }
  1750.         }
  1751.     }
  1752.     }
  1753. }
  1754.  
  1755. /*---------------------------------------------------------------------------*/
  1756. /* scankey                                                                 */
  1757. /*---------------------------------------------------------------------------*/
  1758. scankey(ach, bch) unsigned char *
  1759.                     ach, *bch;
  1760. {
  1761.     /*
  1762.      * Wait for a keypress, return the ASCII code in *ach and the scan in
  1763.      * *bch 
  1764.      */
  1765.     KBDKEYINFO      k;
  1766.  
  1767.     KbdCharIn(&k, 0, 0);
  1768.     *ach = k.chChar;
  1769.     *bch = k.chScan;
  1770.     if (*ach == 0xE0)        /* Extended scan code */
  1771.     if (*bch >= 0x47 && *bch <= 0x53)
  1772.         *ach = 0;
  1773. }
  1774. /*---------------------------------------------------------------------------*/
  1775. /* scrninit                                                                */
  1776. /*---------------------------------------------------------------------------*/
  1777. static int      scrninitialised = 0;
  1778. scrninit()
  1779. {
  1780.     SEL             selector;
  1781.  
  1782.     if (!scrninitialised) {
  1783.     scrninitialised = 1;
  1784.     defaultattribute = (colorofback << 4) + coloroftext;
  1785.     attribute = defaultattribute;
  1786.     line25attribute = (coloroftext << 4) + colorofback;
  1787.     /* Initialise paging info */
  1788.     if (DosAllocSeg(LBUFSIZE * 160, &selector, 0)) {
  1789.         printf("\nDosAllocSeg fails in scrninit\n");
  1790.         exit(1);
  1791.     }
  1792.     paginginfo.buffer = MAKEP(selector, 0);
  1793.     paginginfo.numlines = 0;
  1794.     paginginfo.topline = 0;
  1795.     paginginfo.botline = LBUFSIZE - 1;
  1796.     clearscreen();
  1797.     savescreen(&vt100screen);
  1798.     }
  1799. }
  1800. /*---------------------------------------------------------------------------*/
  1801. /* bleep                                                                   */
  1802. /*---------------------------------------------------------------------------*/
  1803. bleep()
  1804. {
  1805.     DosBeep(440, 200);
  1806. }
  1807. /*---------------------------------------------------------------------------*/
  1808. /* wrtch                                                                   */
  1809. /*---------------------------------------------------------------------------*/
  1810. wrtch(unsigned char ch)
  1811. {
  1812.     unsigned char   cell[2];
  1813.     if (ch >= ' ' || literal) {    /* Normal character */
  1814.     if (ansi && insertmode) {
  1815.         cell[0] = ch;
  1816.         cell[1] = attribute;
  1817.         VioScrollRt(wherey - 1, wherex - 1, wherey - 1, 79, 1, cell, 0);
  1818.     } else
  1819.         VioWrtCharStrAtt(&ch, 1, wherey - 1, wherex - 1, &attribute, 0);
  1820.     literal = FALSE;
  1821.     if (++wherex > 80) {
  1822.         wherex = 1;
  1823.         wrtch(LF);
  1824.     }
  1825.     } else {            /* Control character */
  1826.     switch (ch) {
  1827.     case LF:
  1828.         if (wherey == marginbot) {
  1829.         if (margintop == 1)
  1830.             toplinetocyclicbuffer();
  1831.         scroll(UPWARD, margintop - 1, marginbot - 1);
  1832.         } else {
  1833.         wherey++;
  1834.         if (wherey == 25)
  1835.             wherey--;
  1836.         }
  1837.         break;
  1838.     case CR:
  1839.         wherex = 1;
  1840.         break;
  1841.     case BS:
  1842.         if (wherex > 1)
  1843.         wherex--;
  1844.         break;
  1845.     case 12:
  1846.         if (wherex < 80)
  1847.         wherex++;
  1848.         break;
  1849.     case BEL:
  1850.         DosBeep(400, 350);
  1851.         break;
  1852.     default:{        /* Ignore */
  1853.         }
  1854.     }
  1855.     }
  1856.     if (cursoron)
  1857.     VioSetCurPos(wherey - 1, wherex - 1, 0);
  1858. }
  1859. /*---------------------------------------------------------------------------*/
  1860. /* clearscreen                                                             */
  1861. /*---------------------------------------------------------------------------*/
  1862. clearscreen()
  1863. {
  1864.     char            cell[2];
  1865.     cell[0] = ' ';
  1866.     cell[1] = defaultattribute;
  1867.     VioWrtNCell(cell, 1920, 0, 0, 0);
  1868.     lgotoxy(1, 1);
  1869. }
  1870. /*---------------------------------------------------------------------------*/
  1871. /* lgotoxy                                                                 */
  1872. /*---------------------------------------------------------------------------*/
  1873. lgotoxy(x, y) char
  1874.     x, y;
  1875. {
  1876.     wherex = x;
  1877.     wherey = y;
  1878.     if (cursoron)
  1879.     VioSetCurPos(wherey - 1, wherex - 1, 0);
  1880. }
  1881. /*---------------------------------------------------------------------------*/
  1882. /* scroll                                                                  */
  1883. /*---------------------------------------------------------------------------*/
  1884. scroll(updown, top, bottom) int
  1885.     updown;
  1886.     unsigned char   top, bottom;
  1887. {
  1888.     char            blankcell[2];
  1889.     int             i;
  1890.  
  1891.     blankcell[0] = ' ';
  1892.     blankcell[1] = defaultattribute;
  1893.     switch (updown) {
  1894.     case UPWARD:
  1895.     VioScrollUp(top, 0, bottom, 79, 1, blankcell, 0);
  1896.     if (dwls) {
  1897.         for (i = top; i < bottom; i++)
  1898.         dwl[i] = dwl[i + 1];
  1899.         dwl[bottom] = FALSE;
  1900.     }
  1901.     break;
  1902.     case DOWNWARD:
  1903.     VioScrollDn(top, 0, bottom, 79, 1, blankcell, 0);
  1904.     if (dwls) {
  1905.         for (i = bottom; i > top; i--)
  1906.         dwl[i] = dwl[i - 1];
  1907.         dwl[top] = FALSE;
  1908.     }
  1909.     break;
  1910.     default: /* ignore */ ;
  1911.     }
  1912.     if (dwls) {
  1913.     dwls = FALSE;
  1914.     for (i = 0; i < 24; i++)
  1915.         if (dwl[i]) {
  1916.         dwls = TRUE;
  1917.         break;
  1918.         }
  1919.     }
  1920. }
  1921. /*---------------------------------------------------------------------------*/
  1922. /* movetoscreen                                                            */
  1923. /*---------------------------------------------------------------------------*/
  1924. movetoscreen(source, x, y, len) char *
  1925.                     source, x, y;
  1926.     int             len;
  1927. {
  1928.     VioWrtCellStr(source, len, y - 1, x - 1, 0);
  1929. }
  1930. /*---------------------------------------------------------------------------*/
  1931. /* toplinetocyclicbuffer                                                   */
  1932. /*---------------------------------------------------------------------------*/
  1933. toplinetocyclicbuffer()
  1934. {
  1935.     USHORT          n = 160;
  1936.     if (paginginfo.numlines == LBUFSIZE) {
  1937.     if (++paginginfo.topline == LBUFSIZE)
  1938.         paginginfo.topline = 0;
  1939.     } else
  1940.     paginginfo.numlines++;
  1941.     if (++paginginfo.botline == LBUFSIZE)
  1942.     paginginfo.botline = 0;
  1943.     VioReadCellStr((paginginfo.buffer + 160 * paginginfo.botline), &n, 0, 0, 0);
  1944. }
  1945. /*---------------------------------------------------------------------------*/
  1946. /* cleartoeol                                                              */
  1947. /*---------------------------------------------------------------------------*/
  1948. clrtoeol()
  1949. {
  1950.     char            cell[2];
  1951.  
  1952.     cell[0] = ' ';
  1953.     cell[1] = defaultattribute;
  1954.     VioWrtNCell(cell, 81 - wherex, wherey - 1, wherex - 1, 0);
  1955. }
  1956. /*---------------------------------------------------------------------------*/
  1957. /* setmargins                                                              */
  1958. /*---------------------------------------------------------------------------*/
  1959. setmargins(top, bot) char
  1960.     top, bot;
  1961. {
  1962.     margintop = top;
  1963.     marginbot = bot;
  1964. }
  1965. /*---------------------------------------------------------------------------*/
  1966. /* killcursor                                                              */
  1967. /*---------------------------------------------------------------------------*/
  1968. static VIOCURSORINFO crsr_info;
  1969. killcursor()
  1970. {
  1971.     VIOCURSORINFO   nocursor;
  1972.  
  1973.     if (!cursoron)
  1974.     return;
  1975.     VioGetCurType(&crsr_info, 0);    /* Store current cursor type */
  1976.     nocursor = crsr_info;    /* MS C allows this */
  1977.     nocursor.attr = -1;
  1978.     VioSetCurType(&nocursor, 0);/* Hide cursor */
  1979.     return;
  1980. }
  1981. /*---------------------------------------------------------------------------*/
  1982. /* newcursor                                                               */
  1983. /*---------------------------------------------------------------------------*/
  1984. newcursor()
  1985. {
  1986.     VioSetCurType(&crsr_info, 0);
  1987.     VioSetCurPos(wherey - 1, wherex - 1, 0);
  1988.     cursoron = TRUE;
  1989. }
  1990. /*---------------------------------------------------------------------------*/
  1991. /* line25                                                                  */
  1992. /*---------------------------------------------------------------------------*/
  1993. line25()
  1994. {
  1995.     char            s[80];
  1996.     int             i;
  1997.     char            attr;
  1998.  
  1999.     for (i = 0; i < 80; i++)
  2000.     s[i] = ' ';
  2001.     strinsert(&s[00], usertext);
  2002.     strinsert(&s[36], exittext);
  2003.     strinsert(&s[20], helptext);
  2004.     strinsert(&s[65], filetext);
  2005.     strinsert(&s[50], hostname);
  2006.     attr = line25attribute;
  2007.     VioWrtCharStrAtt(s, 80, 24, 0, &attr, 0);
  2008. }
  2009.  
  2010. strinsert(d, s) char *
  2011.                     d, *s;
  2012. {
  2013.     while (*s)
  2014.     *d++ = *s++;
  2015. }
  2016.  
  2017. sendstr(s) char *
  2018.                     s;
  2019. {
  2020.     SENDCHAR(27);
  2021.     while (*s)
  2022.     SENDCHAR(*s++);
  2023. }
  2024.  
  2025. /*
  2026.  * RDSERWRTSCR  --  Read the comms line and write to the screen. This
  2027.  * function is executed by a separate thread. 
  2028.  */
  2029. VOID FAR
  2030. rdserwrtscr(VOID)
  2031. {
  2032.     int             i;
  2033.  
  2034.     DosSemClear(&threadsem);    /* Let him know we've started */
  2035.     while (active) {
  2036.     if ((i = ttinc(50)) >= 0) {
  2037.         DosEnterCritSec();
  2038.         if (cursoron)
  2039.         if (ttchk() > 40) {
  2040.             killcursor();
  2041.             cursoron = FALSE;
  2042.         }
  2043.         cwrite(i & cmask);
  2044.         if (seslog) {
  2045.         if (zchout(ZSFILE, i & cmask) < 0)
  2046.             seslog = 0;
  2047.         }
  2048.         DosExitCritSec();
  2049.     } else if (!cursoron) {
  2050.         DosEnterCritSec();
  2051.         newcursor();
  2052.         DosExitCritSec();
  2053.     }
  2054.     }
  2055.     DosEnterCritSec();        /* Stop thread 1 discarding our stack before
  2056.                  * we've gone */
  2057.     DosSemClear(&threadsem);    /* Tell him we're going to die */
  2058. }
  2059.  
  2060.  
  2061. /* CONECT  --  Perform terminal connection  */
  2062. conect()
  2063. {
  2064. #define THRDSTKSIZ    2048
  2065.     char            stack[THRDSTKSIZ];    /* Stack for second thread */
  2066.     USHORT          len, x, y;
  2067.     TID             threadid;
  2068.     int             c;        /* c is a character, but must be signed
  2069.                  * integer to pass thru -1, which is the
  2070.                  * modem disconnection signal, and is
  2071.                  * different from the character 0377 */
  2072.     char            errmsg[50], *erp, ac, bc, ss[80];
  2073.  
  2074.     if (speed < 0) {
  2075.     printf("Sorry, you must set speed first.\n");
  2076.     return (-2);
  2077.     }
  2078.     twochartimes = 22000L / speed;
  2079.     if ((escape < 0) || (escape > 0177)) {
  2080.     printf("Your escape character is not ASCII - %d\n", escape);
  2081.     return (-2);
  2082.     }
  2083.     if (ttopen(ttname, &local, 0) < 0) {
  2084.     erp = errmsg;
  2085.     sprintf(erp, "Sorry, can't open %s", ttname);
  2086.     perror(errmsg);
  2087.     return (-2);
  2088.     }
  2089.     /* Condition console terminal and communication line */
  2090.  
  2091.     if (ttvt(speed, flow) < 0) {
  2092.     printf("Sorry, Can't condition communication line\n");
  2093.     return (-2);
  2094.     }
  2095.     checkscreenmode();
  2096.     VioGetCurPos(&y, &x, 0);
  2097.     wherex = x + 1;
  2098.     wherey = y + 1;
  2099.     savescreen(&commandscreen);
  2100.     scrninit();
  2101.     restorescreen(&vt100screen);
  2102.     ipadl25();
  2103.  
  2104.     /* Create a thread to read the comms line and write to the screen */
  2105.  
  2106.     DosSemSet(&threadsem);    /* Thread 2 will clear this when it starts */
  2107.     active = 1;            /* So thread 2 doesn't end at once */
  2108.     termessage[0] = 0;
  2109.     if (DosCreateThread(rdserwrtscr, &threadid, (PBYTE) (stack + THRDSTKSIZ))) {
  2110.     printf("Sorry, can't create thread\n");
  2111.     return (-2);
  2112.     }
  2113.     DosSemWait(&threadsem, -1L);/* Wait for thread to start */
  2114.     DosSemSet(&threadsem);    /* Thread 2 will clear this on termination */
  2115.  
  2116.     while (active) {        /* Read the keyboard and write to comms line */
  2117.     scankey(&ac, &bc);
  2118.     c = ac & cmask;        /* Get character from keyboard */
  2119.     DosEnterCritSec();    /* Protect the run time library */
  2120.     if ((c & 0177) == escape) {    /* Look for escape char */
  2121.         c = coninc(0) & 0177;    /* Got esc, get its arg */
  2122.         if (c == '?')
  2123.         c = helpconnect();
  2124.         doesc(c);        /* And process it */
  2125.     } else {        /* Ordinary character */
  2126.         if (!keylock)
  2127.         vt100read(ac, bc);
  2128.     }
  2129.     DosExitCritSec();    /* Let other guy use run time library */
  2130.     }                /* while (active) */
  2131.  
  2132.     DosSemWait(&threadsem, -1L);/* Wait for other thread to terminate */
  2133.  
  2134.     savescreen(&vt100screen);
  2135.     restorescreen(&commandscreen);
  2136.     if (termessage[0]!='\0') printf(termessage);
  2137. }
  2138.  
  2139. /* HELPCONNECT  --  Give help message for connect.  */
  2140. helpconnect()
  2141. {
  2142.     int             c;
  2143.     unsigned char   ac, bc;
  2144.     char            cell[2];
  2145.     ascreen         tempscreen;
  2146.     static char    *hlpmsg[10] = {
  2147.                   "",
  2148.                   " Type :",
  2149.                   "",
  2150.                   "    C    to close the connection",
  2151.                   "    0    (zero) to send a null",
  2152.                   "    B    to send a BREAK",
  2153.                   "    H    to hangup and close connection",
  2154.                   "   ^]    to send the escape character",
  2155.                   "  space  to cancel",
  2156.                   ""};
  2157.     *(hlpmsg[7] + 4) = ctl(escape);
  2158.     savescreen(&tempscreen);
  2159.     killcursor();
  2160.     helpstart(41, 10);
  2161.     for (c = 0; c < 10; c++)
  2162.     helpline(hlpmsg[c]);
  2163.     helpend();
  2164.     cell[0] = ' ';
  2165.     cell[1] = line25attribute;
  2166.     VioWrtNCell(cell, 80, 24, 0, 0);    /* Erase line 25 */
  2167.     scankey(&ac, &bc);
  2168.     c = ac & cmask;        /* Get character from keyboard */
  2169.     newcursor();
  2170.     restorescreen(&tempscreen);
  2171.     return ((int) c);
  2172. }
  2173.  
  2174. static int      helpcol, helprow;
  2175. static int      helpwidth;
  2176.  
  2177. helpstart(int w, int h)
  2178. {
  2179.     unsigned char   cell[2];
  2180.  
  2181.     cell[1] = attribute | 0x08;
  2182.     helpwidth = w;
  2183.     helpcol = (80 - w) / 2;
  2184.     helprow = (24 - h) / 2;
  2185.     cell[0] = 201;        /* Top left corner */
  2186.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  2187.     cell[0] = 205;        /* Horizontal */
  2188.     VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0);
  2189.     cell[0] = 187;        /* Top right corner */
  2190.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  2191. }
  2192.  
  2193. helpline(s)
  2194.     char           *s;
  2195. {
  2196.     unsigned char   cell[2];
  2197.     int             i;
  2198.  
  2199.     i = strlen(s);
  2200.     helprow++;
  2201.     cell[1] = attribute | 0x08;
  2202.     cell[0] = 186;        /* Vertical */
  2203.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  2204.     VioWrtCharStrAtt(s, i, helprow, helpcol + 1, &cell[1], 0);
  2205.     cell[0] = ' ';
  2206.     VioWrtNCell(cell, helpwidth - i, helprow, helpcol + 1 + i, 0);
  2207.     cell[0] = 186;        /* Vertical */
  2208.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  2209. }
  2210.  
  2211. helpend()
  2212. {
  2213.     unsigned char   cell[2];
  2214.  
  2215.     helprow++;
  2216.     cell[1] = attribute | 0x08;
  2217.     cell[0] = 200;        /* Bottom left corner */
  2218.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  2219.     cell[0] = 205;        /* Horizontal */
  2220.     VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0);
  2221.     cell[0] = 188;        /* Bottom right corner */
  2222.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  2223. }
  2224.  
  2225. /* CHSTR  --  Make a printable string out of a character  */
  2226.  
  2227. char           *
  2228. chstr(c) int
  2229.     c;
  2230. {
  2231.     static char     s[8];
  2232.     char           *cp = s;
  2233.  
  2234.     if (c < SP) {
  2235.     sprintf(cp, "CTRL-%c", ctl(c));
  2236.     } else
  2237.     sprintf(cp, "'%c'\n", c);
  2238.     cp = s;
  2239.     return (cp);
  2240. }
  2241.  
  2242. /* DOESC  --  Process an escape character argument  */
  2243.  
  2244. doesc(c) char
  2245.     c;
  2246. {
  2247.     CHAR            d;
  2248.     char            temp[50];
  2249.  
  2250.     while (1) {
  2251.     if (c == escape) {    /* Send escape character */
  2252.         d = dopar(c);
  2253.         SENDCHAR(d);
  2254.         return;
  2255.     } else
  2256.      /* Or else look it up below. */ if (isupper(c))
  2257.         c = tolower(c);
  2258.  
  2259.     switch (c) {
  2260.  
  2261.     case 'c':        /* Close connection */
  2262.     case '\03':
  2263.         active = 0;
  2264.         return;
  2265.  
  2266.     case 'b':        /* Send a BREAK signal */
  2267.     case '\02':
  2268.         ttsndb();
  2269.         return;
  2270.  
  2271.     case 'h':        /* Hangup */
  2272.     case '\010':
  2273.         tthang();
  2274.         active = 0;
  2275.         return;
  2276.  
  2277.     case '0':        /* Send a null */
  2278.         c = '\0';
  2279.         d = dopar(c);
  2280.         SENDCHAR(d);
  2281.         return;
  2282.  
  2283.     case SP:        /* Space, ignore */
  2284.         return;
  2285.  
  2286.     default:        /* Other */
  2287.         conoc(BEL);
  2288.         return;        /* Invalid esc arg, beep */
  2289.     }
  2290.     }
  2291. }
  2292.  
  2293. /* CHECKSCREENMODE  --  Make sure we are in a 25 x 80 mode */
  2294. checkscreenmode()
  2295. {
  2296.     VIOMODEINFO     m;
  2297.     VIOCONFIGINFO   cfg;
  2298.     char            cell[2];
  2299.     int             i;
  2300.  
  2301.     m.cb = 12;
  2302.     if (VioGetMode(&m, 0))
  2303.     return;
  2304.     cfg.cb = 10;
  2305.     if (VioGetConfig(0, &cfg, 0))
  2306.     return;
  2307.     switch (cfg.adapter) {
  2308.     case 0:            /* Monochrome */
  2309.     m.fbType = 0;
  2310.     m.color = 0;
  2311.     m.hres = 720;
  2312.     m.vres = 350;
  2313.     adapter = mono;
  2314.     colorofunderline = 1;
  2315.     break;
  2316.     case 1:            /* CGA */
  2317.     m.fbType = 1;
  2318.     m.color = 4;
  2319.     m.hres = 640;
  2320.     m.vres = 200;
  2321.     adapter = colour;
  2322.     break;
  2323.     default:            /* Assume EGA/VGA */
  2324.     m.fbType = 1;
  2325.     m.color = 4;
  2326.     m.hres = 640;
  2327.     m.vres = 350;
  2328.     adapter = colour;
  2329.     }
  2330.     if (m.row == 25 && m.col == 80)
  2331.     return;            /* We're happy with this */
  2332.     m.row = 25;
  2333.     m.col = 80;
  2334.     if (i = VioSetMode(&m, 0)) {
  2335.     printf("Error %d returned by VioSetMode\n", i);
  2336.     return;
  2337.     }
  2338.     cell[0] = ' ';
  2339.     cell[1] = 0x07;
  2340.     VioScrollUp(0, 0, -1, -1, -1, cell, 0);    /* Clear the screen */
  2341.     VioSetCurPos(0, 0, 0);    /* Home the cursor */
  2342. }
  2343.