home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / CKPM5X_S.ZIP / CKOCON.C < prev    next >
C/C++ Source or Header  |  1990-05-03  |  87KB  |  2,859 lines

  1.  char           *connv = "OS/2 connect command, 26-Jan-90";
  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. 26-Jan-90 C.P.Armstrong puts() added for PM
  17. */
  18.  
  19. /*
  20.  *
  21.  * =============================#includes===================================== 
  22.  */
  23.  
  24. #include <ctype.h>      /* Character types */
  25. #include <io.h>         /* File io function declarations */
  26. #include <process.h>    /* Process-control function declarations */
  27. #include <stdlib.h>     /* Standard library declarations */
  28. #include <sys\types.h>
  29. #include <sys\stat.h>
  30. #include <direct.h>     /* Directory function declarations */
  31. #include <stdio.h>
  32. #include <string.h>
  33. #define INCL_DOS
  34. #define INCL_DOSERRORS
  35. #define INCL_DOSDEVIOCTL
  36. #define INCL_WININPUT
  37. #define INCL_VIO
  38. #include <os2.h>     
  39. //#include "ckofns.h"  /* No room for this!! */
  40. //#include "ckopm.h"
  41. #include "ckcasc.h"
  42. #include "ckcker.h"     /* Kermit definitions */
  43. #include "ckokey.h"
  44. #include "ckofns.h"
  45. /*
  46.  *
  47.  * =============================#defines====================================== 
  48.  */
  49.  
  50. /* in ckodrv.c   */ 
  51.  void print_screen(char far *);
  52. /* in ckopm2.c */
  53. void AVIOReadCellStr();
  54. void AVIOWrtCellStr();
  55. void AVIOScrollRt();
  56. void AVIOScrollLf();
  57. void AVIOWrtNCell();
  58. void AVIOWrtCharStrAtt();
  59. void AVIOScrollUp();
  60. void AVIOSetCurPos();
  61. void AVIOGetCurType();
  62. void AVIOSetCurType();
  63. void AVIOGetCurPos();
  64. int PM_getViotitle();
  65. void PM_setViotitle();
  66. /* in ckopm1.c */
  67. int buff_getch();
  68.  
  69. #ifndef TRUE
  70. #define TRUE    1
  71. #endif
  72. #ifndef FALSE
  73. #define FALSE   0
  74. #endif
  75. #define SENDSTR2    sendstr
  76. #define SENDCHAR    sendchar
  77. #define UPWARD      6
  78. #define DOWNWARD    7
  79. #define LBUFSIZE    144 /* No of lines in extended buffer */
  80. #define DEFTABS     \
  81. "00000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000";
  82.  
  83. /*
  84.  *
  85.  * =============================typedefs====================================== 
  86.  */
  87.  
  88. typedef char    fulstring[256];
  89. typedef int     bool;
  90. typedef unsigned char screenmap[4000];
  91. typedef struct ascreen_rec {    /* Structure for saving screen info */
  92.     unsigned char   ox;
  93.     unsigned char   oy;
  94.     unsigned char   att;
  95.     screenmap       scrncpy;
  96. }               ascreen;
  97.  
  98. /*
  99.  *
  100.  * =============================externals===================================== 
  101.  */
  102.  
  103. extern int      local, speed, escape, duplex, parity, flow, seslog, cmask;
  104. extern char     ttname[], sesfil[];
  105. extern CHAR     dopar();
  106. extern bool     Term_mode;
  107. /*
  108.  *
  109.  * =============================static=variables============================== 
  110.  */
  111.  
  112. int  far conected=0;
  113. long twochartimes;
  114. char termessage[80];
  115. static FILE    *lst;
  116. static bool     lstclosed = TRUE;
  117. static char     coloroftext = 7, colorofback = 0;
  118. int colorofunderline = 4;
  119. ascreen  vt100screen, commandscreen;
  120. static enum {
  121.     mono,
  122.     colour
  123. }               adapter;
  124. unsigned char   attribute, savedattribute, line25attribute;
  125. unsigned char defaultattribute=0x07;
  126. static struct {
  127.     unsigned        reversed:1;
  128.     unsigned        blinking:1;
  129.     unsigned        underlined:1;
  130.     unsigned        bold:1;
  131.     unsigned        invisible:1;
  132. }               attrib, savedattrib;
  133. static struct paging_record {
  134.     unsigned char   numlines;   /* no. of lines in extended display buffer */
  135.     unsigned char   topline;
  136.     unsigned char   botline;
  137.     char           *buffer;
  138. };
  139.  
  140. static struct paging_record far paginginfo =
  141.     {0,0,0,NULL};
  142.  
  143. unsigned char wherex;
  144. unsigned char wherey;
  145. unsigned char margintop = 1;
  146. unsigned char marginbot = 24;
  147. int      active;
  148.  
  149. long int far threadsem=0;   /* Semaphore to show thread is running */
  150. ULONG far cr_recd_sem=0;    /* Semaphore to indicate an eol char received */
  151. int far paste_eol_char=10;  /* The end of line char */
  152. static char     usertext[(80) + 1];
  153. static char     exittext[(14) + 1];
  154. static char     helptext[(14) + 1];
  155. static char     filetext[(14) + 1];
  156. static char     hostname[(20) + 1];
  157.  
  158. static unsigned char far graphicset[32] = {
  159.                  0x20, 0x04, 0xB0, 0x1A, 0x17, 0x1B, 0x19, 0xF8,
  160.                  0xF1, 0x15, 0x12, 0xD9, 0xBF, 0xDA, 0xC0, 0xC5,
  161.                  0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC3, 0xB4, 0xC1,
  162.                  0xC2, 0xB3, 0xF3, 0xF2, 0xE3, 0x9D, 0x9C, 0xFA
  163. };
  164. static char     htab[81] = DEFTABS  /* Default tab settings */
  165. static char answerback[81] = "OS/2 Kermit\n";
  166. static int      row;
  167. #ifdef US_CHAR
  168. static unsigned char g0 = 'B';      /* Character 35 is number sign */
  169. static unsigned char g1 = 'B';
  170. #else
  171. static unsigned char g0 = 'A';      /* Char 35 is pound (sterling) sign */
  172. static unsigned char g1 = 'A';
  173. #endif /* US_CHAR */
  174. static unsigned char *g0g1 = &g0;
  175. static bool     literal = FALSE;
  176. static bool     wrapit;
  177. static bool     printon = FALSE;
  178. static bool     screenon = TRUE;
  179. bool     cursoron = TRUE;/* For speed, turn off when busy */
  180. bool     relcursor = FALSE;
  181. static bool     keypadnum = FALSE;
  182. static bool     autowrap = FALSE;
  183. bool     ansi = TRUE;
  184. static bool     keylock = FALSE;
  185. static bool     vt52graphics = FALSE;
  186. unsigned char achar;
  187. static int      column;
  188. static unsigned char saveg0, saveg1, *saveg0g1;
  189. static bool     saverelcursor, saved=FALSE;
  190. bool     dwl[24] = {
  191.        FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
  192.        FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
  193.                FALSE, FALSE, FALSE, FALSE};
  194. bool     dwls = FALSE;   /* For optimisation */
  195. static bool     deccolm = FALSE;
  196. static bool     decscnm = FALSE;
  197. static bool     linemode = FALSE;
  198. static bool     insertmode = FALSE;
  199. static bool     cursorkey = TRUE;
  200. /* escape sequence processing buffer */
  201. bool     escaping = FALSE;
  202. int      escnext = 1;
  203. int      esclast = 0;
  204. unsigned char escbuffer[129];
  205. static unsigned char sgrcols[8] = {0, 4, 2, 6, 1, 5, 3, 7};
  206.  
  207. /*---------------------------------------------------------------------------*/
  208. /* toplinetocyclicbuffer                                                   */
  209. /*---------------------------------------------------------------------------*/
  210. void toplinetocyclicbuffer()
  211. {
  212.     USHORT          n = 160;
  213.     if (paginginfo.numlines == LBUFSIZE) {
  214.     if (++paginginfo.topline == LBUFSIZE)
  215.         paginginfo.topline = 0;
  216.     } else
  217.     paginginfo.numlines++;
  218.     if (++paginginfo.botline == LBUFSIZE)
  219.     paginginfo.botline = 0;
  220.     AVIOReadCellStr((paginginfo.buffer + 160 * paginginfo.botline), &n, 0, 0);
  221. }
  222.  
  223. void sendcrlf()
  224.     {
  225.     extern int pasting;
  226.     extern ULONG cr_recd_sem;
  227.  
  228.  
  229.     sendcharduplex(CR);
  230.     if (linemode)    /* N.B. the enter key comes as a VK */
  231.         {
  232.         sendcharduplex(LF);
  233.         }
  234.  
  235.     return;
  236.     }
  237.  
  238. /*
  239.  * Send a character to the serial line in immediate mode, checking to avoid
  240.  * overwriting a character already waiting to be sent.
  241.  */
  242. void sendchar(unsigned char c) 
  243.     {
  244.     extern int pasting;
  245.     extern ULONG cr_recd_sem;
  246.     int i=0;
  247.     static int retry=5;
  248.  
  249.     DosSemSet(&cr_recd_sem);
  250.  
  251.     while (ttoc(c)<0 && i++<retry)
  252.         DosSleep(twochartimes);
  253.  
  254.     if (i>=retry) 
  255.         {
  256.         active = FALSE;
  257.         strcpy(termessage,"Cannot transmit to serial port!\n");
  258.         }
  259.     else if(pasting>0 && c==CR)
  260.         {
  261.         DosSemWait(&cr_recd_sem, 10000L);
  262.         }
  263.     }
  264.  
  265. /* ------------------------------------------------------------------ */
  266. /* ipadl25 -                                                          */
  267. /* ------------------------------------------------------------------ */
  268. void ipadl25()
  269. {   
  270.     switch(Term_mode)
  271.         {
  272.         case TEKTRONIX:   strcpy(usertext,"C-Kermit TEK4014"); 
  273.             PM_setViotitle("Tektronix 4010/4014 Emulation");
  274.             break;
  275.         case VT100:       strcpy(usertext,"C-Kermit VT102"); 
  276.             PM_setViotitle("DEC VT102 Emulation");
  277.             break;
  278.         default:          strcpy(usertext,"Unknown mode"); break;
  279.         }
  280.  
  281.     
  282.     sprintf(filetext, "%1d baud", speed);
  283.     strcpy(helptext, "Help: ^ ?");
  284.     helptext[7] = (char) ctl(escape);
  285.     strcpy(exittext, "Exit: ^ c");
  286.     exittext[7] = (char) ctl(escape);
  287.     strcpy(hostname, ttname);
  288.     line25();
  289. }
  290. /* ------------------------------------------------------------------ */
  291. static void
  292. doprinton(bool on)
  293. {
  294.     if (on) {
  295.     if (lstclosed) {
  296.         lst = fopen("prn", "w");
  297.         lstclosed = FALSE;
  298.     }
  299.     } else {
  300.     if (!(lstclosed)) {
  301.         fclose(lst);
  302.         lstclosed = TRUE;
  303.     }
  304.     }
  305.     printon = on;
  306. }
  307. /* ----------------------------------------------------------------- */
  308. /* ClrScreen -                                                       */
  309. /* ----------------------------------------------------------------- */
  310. static void clrscreen()
  311. {
  312.     int             i, j;
  313.     int             nlines;
  314.     USHORT          n;
  315.     char            cells[80][2];
  316.  
  317.     /* copy lines on screen to extended display buffer */
  318.     n = sizeof(cells);
  319.     for (i = 23; i >= 0; i--) {
  320.     AVIOReadCellStr((char *) cells, &n, i, 0);
  321.     for (j = 0; j < 80; j++) {
  322.         if (cells[j][0] != 32)
  323.         break;
  324.     }
  325.     if (j < 80)
  326.         break;
  327.     }
  328.     nlines = i;         /* no. of nonblank lines-1 */
  329.     for (i = 0; i <= nlines; ++i) {
  330.     paginginfo.botline = (paginginfo.botline + 1) % LBUFSIZE;
  331.     if (paginginfo.numlines < LBUFSIZE)
  332.         paginginfo.numlines = paginginfo.numlines + 1;
  333.     else
  334.         paginginfo.topline = (paginginfo.topline + 1) % LBUFSIZE;
  335.     AVIOReadCellStr((paginginfo.buffer + 160 * paginginfo.botline), &n, i, 0);
  336.     }
  337.     for (i = 0; i < 24; i++)
  338.     dwl[i] = FALSE;
  339.     dwls = FALSE;
  340.     clearscreen();
  341. }
  342. static void
  343. readmchar_escape()
  344. {
  345.     /* Stores character in achar directly */
  346.     if (escnext <= esclast) {
  347.     achar = escbuffer[escnext];
  348.     escnext = escnext + 1;
  349.     } else
  350.     achar = 0;
  351. }
  352. static int pnumber(achar)
  353.     unsigned char  *achar;
  354. {
  355.     int             num = 0;
  356.  
  357.     while (isdigit(*achar)) {   /* get number */
  358.     num = (num * 10) + (*achar) - 48;
  359.     readmchar_escape();
  360.     }
  361.     return (num);
  362. }
  363.  
  364. void decdwl_escape(bool dwlflag)
  365. {
  366.     unsigned char   linenumber;
  367.     unsigned char   newx;
  368.     char            cells[80][2];
  369.     int             i;
  370.     USHORT          n;
  371.     /* Decdwl */
  372.     linenumber = wherey - 1;
  373.     if (dwlflag != dwl[linenumber]) {
  374.     /* change size */
  375.     n = sizeof(cells);
  376.     AVIOReadCellStr((char *) cells, &n, linenumber, 0);
  377.     if (dwlflag) {      /* make this line double size */
  378.         for (i = 39; i >= 0; --i) { /* expand */
  379.         cells[2 * i][0] = cells[i][0];
  380.         cells[2 * i + 1][0] = ' ';
  381.         }
  382.         newx = (wherex - 1) * 2 + 1;
  383.         dwls = TRUE;
  384.     } else {        /* make this line single size */
  385.         for (i = 0; i <= 39; ++i)
  386.         cells[i][0] = cells[2 * i][0];
  387.         for (i = 40; i <= 79; ++i)
  388.         cells[i][0] = ' ';
  389.         newx = (wherex - 1) / 2 + 1;
  390.         dwls = FALSE;
  391.         for (i = 0; i < 24; i++)
  392.         if (dwl[i]) {
  393.             dwls = TRUE;
  394.             break;
  395.         }
  396.     }
  397.     AVIOWrtCellStr((char *) cells, n, linenumber, 0);
  398.     dwl[linenumber] = dwlflag;
  399.     if (newx >= 80)
  400.         newx = 79;
  401.     lgotoxy(newx, wherey);
  402.     }
  403. }    
  404.  
  405. /* Modified C.P.A. to trap switch to Tektronix mode commands */
  406.  
  407. void vtescape()
  408. {
  409.     unsigned char   j;
  410.     unsigned char   k;
  411.     unsigned char   l;
  412.     unsigned char   blankcell[2];
  413.     int             i;
  414.     int             pn[11];
  415.     bool            private;
  416.     char            tempstr[20];
  417.     int             fore, back;
  418.     escaping = FALSE;
  419.     escnext = 1;
  420.  
  421.     readmchar_escape();
  422.     
  423.     /* Trap the enter Tektronix mode commands - and set tektronix mode */
  424.     if(achar==12)  /* ESC Ctrl-L Clear Tek screen - use this to enter */
  425.         {          /* Tek mode as well as the other commands */
  426.         if(Tek_scrinit(1)==1)   /* The other Tek entry command is */
  427.             {                   /* ESC [ ? 3 8 h                  */
  428.             Term_mode=TEKTRONIX;
  429.             ipadl25();          /* Update the Vio screen mode line */
  430.             return;
  431.             }
  432.         }
  433.  
  434.     if (screenon || (achar == '[')) {
  435.     /* screen escape sequences  */
  436.     switch (achar) {
  437.         /* First Level */
  438.     case '[':
  439.         {
  440.         /* Left square bracket */
  441.         readmchar_escape();
  442.         switch (achar) {/* Second level */
  443.         case 'A':
  444.             cursorup();
  445.             wrapit = FALSE;
  446.             break;
  447.         case 'B':
  448.             cursordown();
  449.             wrapit = FALSE;
  450.             break;
  451.         case 'C':
  452.             cursorright();
  453.             if (dwl[wherey - 1])
  454.             cursorright();
  455.             break;
  456.         case 'D':
  457.             cursorleft();
  458.             if (dwl[wherey - 1])
  459.             cursorleft();
  460.             break;
  461.         case 'J':   /* Erase End of Display */
  462.             clreoscr_escape();
  463.             break;
  464.         case 'K':
  465.             clrtoeol();
  466.             break;
  467.         case '?':
  468.             private = TRUE;
  469.             readmchar_escape();
  470.             goto LB2001;
  471.         case 'f':
  472.         case 'H':   /* Cursor Home */
  473.             lgotoxy(1, relcursor ? margintop : 1);
  474.             break;
  475.         case 'g':
  476.             htab[wherex] = '0';
  477.             break;
  478.         case '}':
  479.         case 'm':   /* Normal Video - Exit all attribute modes */
  480.             attribute = defaultattribute;
  481.             attrib.blinking = FALSE;
  482.             attrib.bold = FALSE;
  483.             attrib.invisible = FALSE;
  484.             attrib.underlined = FALSE;
  485.             attrib.reversed = FALSE;
  486.             break;
  487.         case 'r':   /* Reset Margin */
  488.             setmargins(1, 24);
  489.             lgotoxy(1, 1);
  490.             break;
  491.         case 'c':
  492.         case 'h':
  493.         case 'l':
  494.         case 'n':
  495.         case 'x':
  496.             pn[1] = 0;
  497.             private = FALSE;
  498.             k = 1;
  499.             goto LB2003;
  500.         case ';':
  501.             pn[1] = 0;
  502.             private = FALSE;
  503.             k = 1;
  504.             goto LB2002;
  505.         case 'L':
  506.         case 'M':
  507.         case '@':
  508.         case 'P':
  509.             pn[1] = 1;
  510.             private = FALSE;
  511.             k = 1;
  512.             goto LB2002;
  513.         default:    /* Pn - got a number */
  514.             private = FALSE;
  515.         LB2001:
  516.             {       /* Esc [ Pn...Pn x   functions */
  517.             pn[1] = pnumber(&achar);
  518.             
  519.             /* So far the characters received should be ESC [ ? number */
  520.             /* If number is 38 then it might be an enter Tektronix mode*/
  521.             /* command.  pnumber leaves achar pointing to the character*/
  522.             /* after the buffer.  If it's an h or l then we've got our */
  523.             /* Tektronix command */
  524.             if((pn[1] == 38) && ((achar=='h') || (achar=='l')))
  525.                 {
  526.                 if(achar=='h')
  527.                     {
  528.                     if(Tek_scrinit(0)==1)
  529.                         {
  530.                         Term_mode=TEKTRONIX;
  531.                         ipadl25();
  532.                         }
  533.                     }
  534.                 return;     /* Either way return */
  535.                 }
  536.  
  537.             k = 1;
  538.         LB2002:
  539.             while (achar == ';') {  /* get Pn[k] */
  540.                 readmchar_escape();
  541.                 k++;
  542.                 if (achar == '?') {
  543.                 readmchar_escape();
  544.                 }
  545.                 pn[k] = pnumber(&achar);
  546.             }
  547.             pn[k + 1] = 1;
  548.         LB2003:
  549.             switch (achar) {    /* third level */
  550.             case 'A':
  551.                 do {
  552.                 cursorup();
  553.                 wrapit = FALSE;
  554.                 pn[1] = pn[1] - 1;
  555.                 }
  556.                 while (!(pn[1] <= 0));
  557.                 break;
  558.             case 'B':
  559.                 do {
  560.                 cursordown();
  561.                 wrapit = FALSE;
  562.                 pn[1] = pn[1] - 1;
  563.                 }
  564.                 while (!(pn[1] <= 0));
  565.                 break;
  566.             case 'C':
  567.                 do {
  568.                 cursorright();
  569.                 if (dwl[wherey - 1])
  570.                     cursorright();
  571.                 pn[1] = pn[1] - 1;
  572.                 }
  573.                 while (pn[1] > 0);
  574.                 break;
  575.             case 'D':
  576.                 do {
  577.                 cursorleft();
  578.                 if (dwl[wherey - 1])
  579.                     cursorleft();
  580.                 pn[1] = pn[1] - 1;
  581.                 } while (pn[1] > 0);
  582.                 break;
  583.             case 'f':
  584.             case 'H':
  585.                 /* Direct cursor address */
  586.                 if (pn[1] == 0)
  587.                 pn[1] = 1;
  588.                 if (relcursor)
  589.                 pn[1] += margintop - 1;
  590.                 if (pn[2] == 0)
  591.                 pn[2] = 1;
  592.                 if (dwl[pn[1] - 1]) {
  593.                 pn[2] = 2 * pn[2] - 1;
  594.                 if (pn[2] > 80)
  595.                     pn[2] = 79;
  596.                 } else if (pn[2] > 80)
  597.                 pn[2] = 80;
  598.                 wrapit = FALSE;
  599.                 lgotoxy(pn[2], pn[1]);
  600.                 break;
  601.             case 'c':   /* Device Attributes */
  602.                 if (pn[1] == 0)
  603.                 sendstr("[?6;2c");
  604.                 break;
  605.             case 'g':
  606.                 if (pn[1] == 3) {
  607.                 /* clear all tabs */
  608.                 for (j = 1; j <= 80; ++j)
  609.                     htab[j] = '0';
  610.                 } else if (pn[1] == 0)
  611.                 /* clear tab at current position */
  612.                 htab[wherex] = '0';
  613.                 break;
  614.             case 'h':   /* Set Mode */
  615.                 for (j = 1; j <= k; ++j)
  616.                 if (private)
  617.                     switch (pn[j]) {    /* Field specs */
  618.                     case 1: /* DECCKM  */
  619.                     cursorkey = TRUE;
  620.                     break;
  621.                     case 2: /* DECANM : ANSI/VT52 */
  622.                     ansi = TRUE;
  623.                     vt52graphics = FALSE;
  624.                     break;
  625.                     case 3: /* DECCOLM : Col = 132 */
  626.                     deccolm = TRUE;
  627.                     clrscreen();
  628.                     break;
  629.                     case 4: /* DECSCLM */
  630.                     break;
  631.                     case 5: /* DECSCNM */
  632.                     if (decscnm)
  633.                         break;  /* Already set */
  634.                     decscnm = TRUE;;
  635.                     reversescreen();
  636.                     defaultattribute = (coloroftext << 4) | colorofback;
  637.                     attribute = defaultattribute;
  638.                     if (attrib.reversed) {
  639.                         back = attribute & 0x07;
  640.                         fore = (attribute & 0x70) >> 4;
  641.                         if (adapter == colour && attrib.underlined) {
  642.                         fore = colorofunderline;
  643.                         }
  644.                         attribute = (back << 4) | fore;
  645.                     }
  646.                     if (attrib.underlined) {
  647.                         if (adapter == mono && !attrib.reversed)
  648.                         attribute = (attribute & 0xF8) | colorofunderline;
  649.                     }
  650.                     if (attrib.blinking)
  651.                         attribute |= 0x80;
  652.                     if (attrib.bold)
  653.                         attribute |= 8;
  654.                     if (attrib.invisible) {
  655.                         i = (attribute & 0xF8);
  656.                         attribute = i | ((i >> 4) & 7);
  657.                     }
  658.                     break;
  659.                     case 6: /* DECOM : Relative origin */
  660.                     relcursor = TRUE;
  661.                     lgotoxy(1, margintop);
  662.                     break;
  663.                     case 7: /* DECAWM */
  664.                     autowrap = TRUE;
  665.                     break;
  666.                     case 8: /* DECARM */
  667.                     break;
  668.                     case 9: /* DECINLM */
  669.                     break;
  670.                     default:
  671.                     break;
  672.                 } else
  673.                     switch (pn[j]) {
  674.                     case 2: /* Keyboard locked */
  675.                     keylock = TRUE;
  676.                     break;
  677.                     case 4: /* Ansi insert mode */
  678.                     insertmode = TRUE;
  679.                     break;
  680.                     case 20:    /* Ansi linefeed mode */
  681.                     linemode = TRUE;
  682.                     break;
  683.                     default:
  684.                     break;
  685.                     }
  686.                 break;
  687.             case 'l':
  688.                 /* Reset Mode */
  689.                 for (j = 1; j <= k; ++j)
  690.                 if (private)
  691.                     switch ((pn[j])) {  /* Field specs */
  692.                     case 1: /* DECCKM  */
  693.                     cursorkey = FALSE;
  694.                     break;
  695.                     case 2: /* DECANM : ANSI/VT52 */
  696.                     ansi = FALSE;
  697.                     vt52graphics = FALSE;
  698.                     break;
  699.                     case 3: /* DECCOLM : 80 col */
  700.                     deccolm = FALSE;
  701.                     clrscreen();
  702.                     break;
  703.                     case 4: /* DECSCLM */
  704.                     break;
  705.                     case 5: /* DECSCNM */
  706.                     if (!decscnm)
  707.                         break;
  708.                     decscnm = !decscnm;
  709.                     reversescreen();
  710.                     defaultattribute = (colorofback << 4) | coloroftext;
  711.                     attribute = defaultattribute;
  712.                     if (attrib.reversed) {
  713.                         back = attribute & 0x07;
  714.                         fore = (attribute & 0x70) >> 4;
  715.                         if (adapter == colour && attrib.underlined) {
  716.                         fore = colorofunderline;
  717.                         }
  718.                         attribute = (back << 4) | fore;
  719.                     }
  720.                     if (attrib.underlined) {
  721.                         if (adapter == mono && !attrib.reversed)
  722.                         attribute = (attribute & 0xF8) | colorofunderline;
  723.                     }
  724.                     if (attrib.blinking)
  725.                         attribute |= 0x80;
  726.                     if (attrib.bold)
  727.                         attribute |= 8;
  728.                     if (attrib.invisible) {
  729.                         i = (attribute & 0xF8);
  730.                         attribute = i | ((i >> 4) & 7);
  731.                     }
  732.                     break;
  733.                     case 6: /* DECOM : Relative origin */
  734.                     relcursor = FALSE;
  735.                     lgotoxy(1, 1);
  736.                     break;
  737.                     case 7: /* DECAWM */
  738.                     autowrap = FALSE;
  739.                     break;
  740.                     case 8: /* DECARM */
  741.                     break;
  742.                     case 9: /* DECINLM */
  743.                     break;
  744.                     default:
  745.                     break;
  746.                 } else
  747.                     switch (pn[j]) {
  748.                     case 2: /* Keyboard unlocked */
  749.                     keylock = FALSE;
  750.                     break;
  751.                     case 4: /* Ansi insert mode */
  752.                     insertmode = FALSE;
  753.                     break;
  754.                     case 20:    /* Ansi linefeed mode */
  755.                     linemode = FALSE;
  756.                     break;
  757.                     default:
  758.                     break;
  759.                     }
  760.                 break;
  761.             case 'i':   /* Printer Screen  on / off */
  762.                 for (j = 1; j <= k; ++j)
  763.                 switch ((pn[j])) {  /* Field specs */
  764.                 case 4:
  765.                     doprinton(FALSE);
  766.                     break;
  767.                 case 5:
  768.                     doprinton(TRUE);
  769.                     break;
  770.                 case 6:
  771.                     screenon = FALSE;
  772.                     break;
  773.                 case 7:
  774.                     screenon = TRUE;
  775.                     break;
  776.                 default:
  777.                     break;
  778.                 }
  779.                 break;
  780.             case 'q':
  781.                 break;
  782.             case 'n':
  783.                 if (pn[1] == 5) {   /* Device Status Report */
  784.                 sendstr("[0n");
  785.                 } else if (pn[1] == 6) {    /* Cursor Position
  786.                              * Report */
  787.                 sendstr("[");
  788.                 sprintf(tempstr, "%1d", (int) wherey);  /* row */
  789.                 SENDCHAR(tempstr[0]);
  790.                 if (tempstr[1])
  791.                     SENDCHAR(tempstr[1]);
  792.                 SENDCHAR(';');
  793.                 sprintf(tempstr, "%1d", (int) wherex);  /* col */
  794.                 SENDCHAR(tempstr[0]);
  795.                 if (tempstr[1])
  796.                     SENDCHAR(tempstr[1]);
  797.                 SENDCHAR('R');
  798.                 }
  799.                 break;
  800.             case 'x':   /* Request terminal Parameters */
  801.                 if (pn[1] > 1)
  802.                 break;
  803.                 tempstr[0] = '[';
  804.                 tempstr[1] = (pn[1] == 0) ? '2' : '3';
  805.                 tempstr[2] = ';';
  806.                 switch (parity) {
  807.                 case 'e':
  808.                 tempstr[3] = '5';
  809.                 tempstr[5] = '2';
  810.                 break;
  811.                 case 'o':
  812.                 tempstr[3] = '4';
  813.                 tempstr[5] = '2';
  814.                 break;
  815.                 case 0:
  816.                 tempstr[3] = '1';
  817.                 tempstr[5] = '1';
  818.                 break;
  819.                 default:
  820.                 tempstr[3] = '1';
  821.                 tempstr[5] = '2';
  822.                 break;
  823.                 }
  824.                 tempstr[4] = ';';
  825.                 switch (speed) {
  826.                 case 50:
  827.                 i = 0;
  828.                 break;
  829.                 case 75:
  830.                 i = 8;
  831.                 break;
  832.                 case 110:
  833.                 i = 16;
  834.                 break;
  835.                 case 133:
  836.                 i = 14;
  837.                 break;
  838.                 case 150:
  839.                 i = 32;
  840.                 break;
  841.                 case 200:
  842.                 i = 40;
  843.                 break;
  844.                 case 300:
  845.                 i = 48;
  846.                 break;
  847.                 case 600:
  848.                 i = 56;
  849.                 break;
  850.                 case 1200:
  851.                 i = 64;
  852.                 break;
  853.                 case 1800:
  854.                 i = 72;
  855.                 break;
  856.                 case 2000:
  857.                 i = 80;
  858.                 break;
  859.                 case 2400:
  860.                 i = 88;
  861.                 break;
  862.                 case 3600:
  863.                 i = 96;
  864.                 break;
  865.                 case 4800:
  866.                 i = 104;
  867.                 break;
  868.                 case 9600:
  869.                 i = 112;
  870.                 break;
  871.                 case 19200:
  872.                 i = 120;
  873.                 break;
  874.                 default:
  875.                 i = 120;
  876.                 break;
  877.                 }
  878.                 sprintf(&tempstr[6], ";%d;%d;1;0x", i, i);
  879.                 sendstr(tempstr);
  880.                 break;
  881.             case 'm':
  882.             case '}':
  883.                 for (j = 1; j <= k; ++j)
  884.                 switch ((pn[j])) {  /* Field specs */
  885.                 case 0: /* normal */
  886.                     attribute = defaultattribute;
  887.                     attrib.blinking = FALSE;
  888.                     attrib.bold = FALSE;
  889.                     attrib.invisible = FALSE;
  890.                     attrib.underlined = FALSE;
  891.                     attrib.reversed = FALSE;
  892.                     break;
  893.                 case 1: /* bold */
  894.                     attrib.bold = TRUE;
  895.                     attribute |= 8;
  896.                     break;
  897.                 case 4: /* underline */
  898.                     if (attrib.underlined)
  899.                     break;
  900.                     attrib.underlined = TRUE;
  901.                     if (adapter == mono && attrib.reversed)
  902.                     break;
  903.                     attribute = (attribute & 0xF8) | colorofunderline;
  904.                     break;
  905.                 case 5: /* blink */
  906.                     attrib.blinking = TRUE;
  907.                     attribute |= 0x80;
  908.                     break;
  909.                 case 7: /* reverse video */
  910.                     if (attrib.reversed)
  911.                     break;
  912.                     attrib.reversed = TRUE;
  913.                     fore = defaultattribute >> 4;
  914.                     back = defaultattribute & 0x07;
  915.                     if (adapter == colour && attrib.underlined) {
  916.                     fore = colorofunderline;
  917.                     }
  918.                     if (attrib.invisible)
  919.                     fore = back;
  920.                     attribute = (attribute & 0x88) | back << 4 | fore;
  921.                     break;
  922.                 case 8: /* invisible */
  923.                     if (attrib.invisible)
  924.                     break;
  925.                     attrib.invisible = TRUE;
  926.                     i = (attribute & 0xF8);
  927.                     attribute = i | ((i >> 4) & 7);
  928.                     break;
  929.                 case 30:
  930.                 case 31:
  931.                 case 32:
  932.                 case 33:
  933.                 case 34:
  934.                 case 35:
  935.                 case 36:
  936.                 case 37:
  937.                     /* select foreground */
  938.                     i = (attribute & 248);
  939.                     attribute = (i | sgrcols[pn[j] - 30]);
  940.                     break;
  941.                 case 40:
  942.                 case 41:
  943.                 case 42:
  944.                 case 43:
  945.                 case 44:
  946.                 case 45:
  947.                 case 46:
  948.                 case 47:
  949.                     /* select back ground */
  950.                     i = (attribute & 143);
  951.                     l = sgrcols[pn[j] - 40];
  952.                     attribute = (i | ((l << 4)));
  953.                     break;
  954.                 default:
  955.                     break;
  956.                 }
  957.                 break;
  958.             case 'r':   /* set margin */
  959.                 if ((k < 2) || (pn[2] == 0))
  960.                 pn[2] = 24;
  961.                 if (pn[1] == 0)
  962.                 pn[1] = 1;
  963.                 if ((pn[1] > 0) && (pn[1] < pn[2]) && (pn[2] < 25)) {
  964.                 setmargins(pn[1], pn[2]);
  965.                 lgotoxy(1, relcursor ? margintop : 1);
  966.                 }
  967.                 break;
  968.             case 'J':
  969.                 switch ((pn[1])) {
  970.                 case 0: /* clear to end of screen */
  971.                 clreoscr_escape();
  972.                 break;
  973.                 case 1: /* clear to beginning */
  974.                 clrboscr_escape();
  975.                 break;
  976.                 case 2: /* clear all of screen */
  977.                 clrscreen();
  978.                 break;
  979.                 default:
  980.                 break;
  981.                 }
  982.                 break;
  983.             case 'K':
  984.                 switch ((pn[1])) {
  985.                 case 0: /* clear to end of line */
  986.                 clrtoeol();
  987.                 break;
  988.                 case 1: /* clear to beginning */
  989.                 clrbol_escape();
  990.                 break;
  991.                 case 2: /* clear line */
  992.                 clrline_escape();
  993.                 break;
  994.                 default:
  995.                 break;
  996.                 }
  997.                 break;
  998.             case 'L':   /* Insert lines */
  999.                 for (i = 1; i <= pn[1]; ++i)
  1000.                 scroll(DOWNWARD, wherey - 1, marginbot - 1);
  1001.                 break;
  1002.             case 'M':   /* Delete lines */
  1003.                 for (i = 1; i <= pn[1]; ++i)
  1004.                 scroll(UPWARD, wherey - 1, marginbot - 1);
  1005.                 break;
  1006.             case '@':   /* Insert characters */
  1007.                 blankcell[0] = ' ';
  1008.                 blankcell[1] = defaultattribute;
  1009.                 pn[1] *= dwl[wherey - 1] ? 2 : 1;
  1010.                 if (pn[1] > 81 - wherex)
  1011.                 pn[1] = 81 - wherex;
  1012.                 AVIOScrollRt(wherey - 1, wherex - 1, wherey - 1, 79, 
  1013.                     pn[1], blankcell);
  1014.                 break;
  1015.             case 'P':   /* DeleteChar */
  1016.                 blankcell[0] = ' ';
  1017.                 blankcell[1] = defaultattribute;
  1018.                 pn[1] *= dwl[wherey - 1] ? 2 : 1;
  1019.                 if (pn[1] > 81 - wherex)
  1020.                 pn[1] = 81 - wherex;
  1021.                 AVIOScrollLf(wherey - 1, wherex - 1, wherey - 1, 79, 
  1022.                     pn[1], blankcell);
  1023.                 break;
  1024.             default:
  1025.                 break;
  1026.             }
  1027.             }
  1028.             break;
  1029.         }
  1030.         }           /* Left square bracket */
  1031.         break;
  1032.     case '7':       /* Save cursor position */
  1033.         saved = TRUE;
  1034.         row = wherey;
  1035.         column = wherex;
  1036.         savedattribute = attribute;
  1037.         savedattrib = attrib;
  1038.         saverelcursor = relcursor;
  1039.         saveg0 = g0;
  1040.         saveg1 = g1;
  1041.         saveg0g1 = g0g1;
  1042.         break;
  1043.     case '8':       /* Restore Cursor Position */
  1044.         if (!saved) {   /* Home cursor */
  1045.         lgotoxy(1, relcursor ? margintop : 1);
  1046.             break;
  1047.         }
  1048.         saved = FALSE;
  1049.         lgotoxy(column, row);
  1050.         attribute = savedattribute;
  1051.         attrib = savedattrib;
  1052.         relcursor = saverelcursor;
  1053.         g0 = saveg0;
  1054.         g1 = saveg1;
  1055.         g0g1 = saveg0g1;
  1056.         break;
  1057.     case 'A':
  1058.         if (!ansi)      /* VT52 control */
  1059.         cursorup();
  1060.         break;
  1061.     case 'B':
  1062.         if (!(ansi))
  1063.         /* VT52 control */
  1064.         cursordown();
  1065.         break;
  1066.     case 'C':
  1067.         if (!(ansi))
  1068.         /* VT52 control */
  1069.         cursorright();
  1070.         break;
  1071.     case 'D':
  1072.         if (!(ansi))
  1073.         /* VT52 control */
  1074.         cursorleft();
  1075.         else {
  1076.         /* Index */
  1077.         if ((wherey >= marginbot))
  1078.             scroll(UPWARD, margintop - 1, marginbot - 1);
  1079.         else
  1080.             cursordown();
  1081.         }
  1082.         break;
  1083.     case 'E':       /* Next Line */
  1084.         wrtch(13);
  1085.         wrtch(10);
  1086.         break;
  1087.     case 'F':
  1088.         if (!ansi)
  1089.         vt52graphics = TRUE;
  1090.         break;
  1091.     case 'G':
  1092.         if (!ansi)
  1093.         vt52graphics = FALSE;
  1094.         break;
  1095.     case 'H':
  1096.         if (ansi) {
  1097.         /* Set Tab Stop */
  1098.         htab[wherex] = 'T';
  1099.         }
  1100.         /* Set Tab Stop */
  1101.         else
  1102.         lgotoxy(1, 1);
  1103.         /* VT52 control */
  1104.         break;
  1105.     case 'I':
  1106.         if (!(ansi)) {
  1107.         /* VT52 control */
  1108.         if ((margintop < wherey))
  1109.             cursorup();
  1110.         else
  1111.             scroll(DOWNWARD, margintop - 1, marginbot - 1);
  1112.         }
  1113.         break;
  1114.     case 'J':
  1115.         if (!(ansi))
  1116.         /* VT52 control */
  1117.         clreoscr_escape();
  1118.         break;
  1119.     case 'K':
  1120.         if (!(ansi))
  1121.         /* VT52 control */
  1122.         clrtoeol();
  1123.         break;
  1124.     case 'M':
  1125.         /* Reverse Index */
  1126.         if (margintop >= wherey)
  1127.         scroll(DOWNWARD, margintop - 1, marginbot - 1);
  1128.         else
  1129.         cursorup();
  1130.         break;
  1131.     case 'Y':
  1132.         if (!(ansi)) {  /* VT52 control */
  1133.         /* direct cursor address */
  1134.         readmchar_escape();
  1135.         row = achar - 31;
  1136.         readmchar_escape();
  1137.         column = achar - 31;
  1138.         lgotoxy(column, row);
  1139.         }
  1140.         /* direct cursor address */
  1141.         break;
  1142.     case 'Z':
  1143.         if (ansi) {
  1144.         /* Device Attributes */
  1145.         /* Send  Esc[?6;2c */
  1146.         sendstr("[?6;2c");
  1147.         }
  1148.         /* Device Attributes */
  1149.         else
  1150.         /* VT52 control */
  1151.         SENDSTR2("/Z");
  1152.         break;
  1153.     case 'c':
  1154.         /* Reset */
  1155.         defaultattribute = coloroftext + (colorofback << 4);
  1156.         attribute = defaultattribute;
  1157.         attrib.blinking = FALSE;
  1158.         attrib.bold = FALSE;
  1159.         attrib.invisible = FALSE;
  1160.         attrib.underlined = FALSE;
  1161.         attrib.reversed = FALSE;
  1162.         g0 = g1 = 'A';
  1163.         g0g1 = &g0;
  1164.         printon = FALSE;
  1165.         screenon = TRUE;
  1166.         vt52graphics = FALSE;
  1167.         saved = FALSE;
  1168.         linemode = FALSE;
  1169.         insertmode = FALSE;
  1170.         cursorkey = TRUE;
  1171.         keypadnum = FALSE;
  1172.         autowrap = FALSE;
  1173.         ansi = TRUE;
  1174.         keylock = FALSE;
  1175.         deccolm = decscnm = FALSE;
  1176.         for (i = 0; i < 24; i++)
  1177.         dwl[i] = FALSE;
  1178.         dwls = FALSE;
  1179.         for (i = 1; i < 80; i++)
  1180.         htab[i] = (i % 8) == 0 ? 'T' : '0';
  1181.         relcursor = FALSE;
  1182.         setmargins(1, 24);
  1183.         clrscreen();
  1184.         break;
  1185.     case '#':
  1186.         /* Esc # sequence */
  1187.         readmchar_escape();
  1188.         switch (achar) {
  1189.         case '3':
  1190.         decdwl_escape(TRUE);
  1191.         break;
  1192.         case '4':
  1193.         decdwl_escape(TRUE);
  1194.         break;
  1195.         case '5':
  1196.         decdwl_escape(FALSE);
  1197.         break;
  1198.         case '6':
  1199.         decdwl_escape(TRUE);
  1200.         break;
  1201.         case '8':
  1202.         {
  1203.             char            cell[2];
  1204.             cell[0] = 'E';
  1205.             cell[1] = 7;
  1206.             /* Self Test */
  1207.             AVIOWrtNCell(cell, 1920, 0, 0);
  1208.             setmargins(1, 24);
  1209.             lgotoxy(1, 1);
  1210.         }
  1211.         break;
  1212.         /* Self Test */
  1213.         default:
  1214.         break;
  1215.         }
  1216.         break;
  1217.         /* Esc # sequence */
  1218.     case '=':
  1219.         keypadnum = FALSE;
  1220.         break;
  1221.     case '>':
  1222.         keypadnum = TRUE;
  1223.         break;
  1224.     case '<':
  1225.         /* VT52 control */
  1226.         ansi = TRUE;
  1227.         break;
  1228.     case '(':
  1229.         readmchar_escape();
  1230.         g0 = achar;
  1231.         break;
  1232.     case ')':
  1233.         readmchar_escape();
  1234.         g1 = achar;
  1235.         break;
  1236.     default:
  1237.         if (achar == 12) {
  1238.         lgotoxy(1, 1);
  1239.         clrscreen();
  1240.         }
  1241.         break;
  1242.     }
  1243.     /* First Level Case  */
  1244.     }
  1245.     /* screen escape sequences  */
  1246.     if (printon) {
  1247.     fprintf(lst, "%c", 27);
  1248.     if (esclast > 0) {
  1249.         /* print esc sequence */
  1250.         for (i = 1; i <= esclast; ++i)
  1251.         fprintf(lst, "%c", escbuffer[i]);
  1252.     }
  1253.     }
  1254. }
  1255. /******************************************************************************
  1256. Function:       vt100read()
  1257.  
  1258. Description:    This is the function that reads commands from the keyboard,
  1259.                 interpretes them and then sends them out over the communication
  1260.                 line.
  1261.                 
  1262.                 Unfortunately the PM does not supply all the information
  1263.                 required to use the extended keys properly.  It does not seem
  1264.                 to be possible to distinguish between the keypad and the grey
  1265.                 cursor keys with NumLock off.  Ctrl-, Shift- and Alt- function
  1266.                 keys do nor generate codes at all!.
  1267.                 
  1268.                 The 'DOS' like OS/2 kermit uses the ALT-number keys - how? They
  1269.                 do not appear here.......
  1270.  
  1271. Syntax:         vt100read(a,b)
  1272.                     unsigned char a,b; a = ASCII code, b = SCAN code
  1273.  
  1274. Returns:        nothing
  1275.  
  1276. Mods:           xx-xxx-xx C.J.Adie(?) created
  1277.                 06-Dec-89 C.P.Armstrong modified for PM. The scan codes returned
  1278.                                         by PM do not necessarily agree with the
  1279.                                         'DOS' ones.  The extended keys are 
  1280.                                         turned
  1281.                                         into "virtual" keys so the
  1282.                                         case statement has been converted to
  1283.                                         use these.  Eventually the virtual keys
  1284.                                         should be remapable.  In addition the
  1285.                                         screen rollback will be done by
  1286.                                         something other than the grey cursor
  1287.                                         keys which I want to be able to use
  1288.                                         with the remote computer.
  1289.  
  1290. ******************************************************************************/
  1291. void vt100read(a, b) unsigned char a, b;
  1292. {
  1293.     extern   int    pasting;
  1294.     unsigned char   achar;
  1295.     unsigned char   bchar;
  1296.     int             i;
  1297.     int             il;
  1298.     char            str[3];
  1299.     int             prt;
  1300.     int             st;
  1301.     unsigned char   nolblines;
  1302.     unsigned char   linesleft;
  1303.     unsigned char   nextline;
  1304.     unsigned char   nlines;
  1305.  
  1306.     /* In the PM thread the virtual keys are processed before the regular
  1307.     character keys.  This means that shift-backtab generates a unique code as
  1308.     do the main keyboard Enter and keypad enter keys. For the sake of
  1309.     consistency the virtual spacekey is returned as a character, as are the
  1310.     control characters. */
  1311.  
  1312.     achar = a;
  1313.     bchar = b;
  1314. LB1:
  1315. //    if (achar == 8) 
  1316. //        {
  1317. //        /* backspace is mapped to del */
  1318. //        achar = 127;
  1319. //        bchar = 0;
  1320. //        }
  1321.  
  1322.     if (achar != 0) 
  1323.         {
  1324.         if(achar!=CR)
  1325.             sendcharduplex(achar);
  1326.         else
  1327.             sendcrlf();
  1328.         } 
  1329.     else 
  1330.         {
  1331.         switch ((int) (bchar)) 
  1332.             {
  1333.             case VK_UP:
  1334.                 /* up */
  1335.                 if (ansi) {
  1336.                 if (cursorkey)
  1337.                     sendstrduplex("OA");
  1338.                 else
  1339.                     sendstrduplex("[A");
  1340.                 } else
  1341.                 sendstrduplex("A");
  1342.                 break;
  1343.             case VK_LEFT:
  1344.                 /* left */
  1345.                 if (ansi) {
  1346.                 if (cursorkey)
  1347.                     sendstrduplex("OD");
  1348.                 else
  1349.                     sendstrduplex("[D");
  1350.                 } else
  1351.                 sendstrduplex("D");
  1352.                 break;
  1353.             case VK_RIGHT:
  1354.                 /* right */
  1355.                 if (ansi) {
  1356.                 if (cursorkey)
  1357.                     sendstrduplex("OC");
  1358.                 else
  1359.                     sendstrduplex("[C");
  1360.                 } else
  1361.                 sendstrduplex("C");
  1362.                 break;
  1363.             case VK_DOWN:
  1364.                 /* down */
  1365.                 if (ansi) {
  1366.                 if (cursorkey)
  1367.                     sendstrduplex("OB");
  1368.                 else
  1369.                     sendstrduplex("[B");
  1370.                 } else
  1371.                 sendstrduplex("B");
  1372.                 break;
  1373.             case VK_BACKTAB:        /* Backtab */
  1374.                 /* backspace */
  1375.                 sendcharduplex(8);
  1376.                 break;
  1377.             case VK_BACKSPACE:
  1378.             case VK_DELETE:
  1379.                 /* delete */
  1380.                 sendcharduplex(127);
  1381.                 break;
  1382.             case VK_F2:
  1383.             case VK_NUMLOCK:
  1384.                 /* PF1 */
  1385.                 if (ansi)
  1386.                     sendstrduplex("OP");
  1387.                 else
  1388.                     sendstrduplex("P");
  1389.                 break;
  1390.             case KPSLASH:  /* Should be keypad / */
  1391.                 /* PF2 */
  1392.                 if (ansi)
  1393.                 sendstrduplex("OQ");
  1394.                 else
  1395.                 sendstrduplex("Q");
  1396.                 break;
  1397.             case KPSTAR:  /* Should be  keypad * */
  1398.                 /* PF3 */
  1399.                 if (ansi)
  1400.                 sendstrduplex("OR");
  1401.                 else
  1402.                 sendstrduplex("R");
  1403.                 break;
  1404.             case KPMINUS:
  1405.                 /* PF4 */
  1406.                 if (ansi)
  1407.                 sendstrduplex("OS");
  1408.                 else
  1409.                 sendstrduplex("S");
  1410.                 break;
  1411.             case KP7:
  1412.                 vt_kp_send('w'); break;
  1413.             case KP8:
  1414.                 vt_kp_send('x'); break;
  1415.             case KP9: 
  1416.                 vt_kp_send('y'); break;
  1417.             case KP4:
  1418.                 vt_kp_send('t'); break;
  1419.             case KP5:
  1420.                 vt_kp_send('u'); break;
  1421.             case KP6:
  1422.                 vt_kp_send('v'); break;
  1423.             case KP1:
  1424.                 vt_kp_send('q'); break;
  1425.             case KP2:
  1426.                 vt_kp_send('r'); break;
  1427.             case KP3:
  1428.                 vt_kp_send('s'); break;
  1429.             case KP0:
  1430.                 vt_kp_send('p'); break;
  1431.             case KPPLUS:                   /* numeric - */
  1432.                 vt_kp_send('m'); break;
  1433.             case VK_F3:                    /* numeric , no equivalent for PC */
  1434.                 vt_kp_send('l'); break;
  1435.             case KPDOT:                    /* numeric . */
  1436.                 vt_kp_send('n'); break;
  1437.             case VK_ENTER:                 /* numeric enter */
  1438.                 vt_kp_send('M'); break;
  1439.             case VK_HOME:        /* Home */
  1440.                 {
  1441.                 strcpy(usertext, " Scroll lock on");
  1442.                 strcpy(exittext, "Exit: Home");
  1443.                 *helptext = '\0';
  1444.                 line25();
  1445.                 do
  1446.                     scankey(&(achar), &(bchar));
  1447.                 while (!(bchar == VK_HOME));
  1448.                 ipadl25();
  1449.                 }
  1450.                 break;
  1451.                 
  1452.     /* These keys should not be used for the scrollback as they are useful */
  1453.     /* editing keys in the terminal emulator.                              */
  1454.             case VK_PAGEUP:        /* Not in paging mode so beep */
  1455.                 bleep();
  1456.                 break;
  1457.             case VK_PAGEDOWN:      /* Enter extended display mode */
  1458.                 if (paginginfo.numlines == 0)
  1459.                     bleep();
  1460.                 else 
  1461.                     {
  1462.                     screen_rollback(&achar,&bchar);
  1463.                     }
  1464.  
  1465.                 if (((achar != 0) || (bchar != VK_PAGEDOWN)))
  1466.                     goto LB1;
  1467.                 /* to process key */
  1468.                 break;
  1469.             default:
  1470.                 break;
  1471.             }
  1472.     /* of case bchar */
  1473.         }
  1474. }
  1475.  
  1476.  
  1477. /* ================================================================== */
  1478. /* */
  1479. /* VT100 emulate a dec vt100 terminal writing a character            */
  1480. /* */
  1481. /* ================================================================== */
  1482. void vt100(vtch)
  1483.     unsigned char   vtch;
  1484. {
  1485.     int             i, j;
  1486.     char           *s, str[2];
  1487.     /* ----------------------------------------------------------------- */
  1488.     /* ------------------------------------------------------------------ */
  1489.     /* vt100 */
  1490.     if (screenon) {
  1491.     if (vtch < 32) {    /* Control Character */
  1492.         /* Dump the line buffer first */
  1493.         chars_out();
  1494.  
  1495.         achar = vtch;   /* Let the rest of this module see the value */
  1496.         switch (achar) {
  1497.         case LF:
  1498.                 if (linemode) wherex=1;
  1499.             wrtch(achar);
  1500.             break;
  1501.         case CR:
  1502.             wrtch(achar);
  1503.             break;
  1504.         /* ESC */
  1505.         case 27:
  1506.             vtescape();
  1507.             break;
  1508.         case 14:        /* SO */
  1509.             g0g1 = &g1;
  1510.             break;
  1511.         /* SI */
  1512.         case 15:
  1513.             g0g1 = &g0;
  1514.             break;
  1515.         /* BS */
  1516.         case 8:
  1517.             wrtch(achar);
  1518.             break;
  1519.         case 12:        /* FF */
  1520.         case 11:        /* VT */
  1521.             /* take as lf */
  1522.             achar = 10;
  1523.             wrtch(10);
  1524.             break;
  1525.         case 7:     /* BEL */
  1526.             bleep();
  1527.             break;
  1528.         case 5:     /* ENQ */
  1529.             s = answerback;
  1530.             while (*s)
  1531.                 SENDCHAR(*s++);
  1532.             break;
  1533.         case 9:     /* tab character */
  1534.         j = dwl[wherey - 1] ? 2 : 1;
  1535.         i = wherex;
  1536.         if (j == 2 && htab[(i - 1) / j + 1] == 'T') {
  1537.             i++;
  1538.             cursorright();
  1539.         }
  1540.         if (i < 80)
  1541.             do {
  1542.             i++;
  1543.             cursorright();
  1544.             } while ((htab[(i - 1) / j + 1] != 'T') && (i < 81 - j));
  1545.         break;
  1546.         default:        /* ignore it */
  1547.         break;
  1548.         }
  1549.         /* end of Control Character */
  1550.     } else {
  1551.         if (vtch != DEL) {  /* Normal char */
  1552.         if (ansi) {
  1553.             if (*g0g1 == 'A') { /* UK ascii set */
  1554.             if (vtch == 35)
  1555.                 vtch = 156;
  1556.             } else if ((*g0g1 == '0') && (95 <= vtch) && (vtch <= 126)) {
  1557.             literal = TRUE;
  1558.             vtch = graphicset[vtch - 95];
  1559.             }
  1560.         } else {
  1561.             if (vt52graphics && (95 <= vtch) && (vtch <= 126)) {
  1562.             literal = TRUE;
  1563.             vtch = graphicset[vtch - 95];
  1564.             }
  1565.         }                            
  1566.  
  1567.         if (wherex != (dwl[wherey - 1] ? 79 : 80)) {
  1568.             chars_in(vtch);          /* Most chars end up here - */
  1569. //          wrtch(vtch);             /* so save them here too    */
  1570.            if (dwl[wherey - 1])
  1571. //            wrtch(' ');
  1572.             chars_in(' ');
  1573.             wrapit = FALSE;
  1574.             } 
  1575.         else 
  1576.             {
  1577.             chars_out();   /* Dump the buffer */
  1578.             if (wrapit) 
  1579.                 {   /* Next line  */
  1580.                 if (marginbot <= wherey) 
  1581.                     {  /* Scroll up */
  1582.                     scroll(UPWARD, margintop - 1, marginbot - 1);
  1583.                     lgotoxy(1, wherey);
  1584.                     } 
  1585.                 else
  1586.                     lgotoxy(1, wherey + 1);
  1587.  
  1588.                 wrtch(vtch);   /* save the character here */
  1589.  
  1590.                 if (dwl[wherey - 1])  /* add a space */
  1591.                     wrtch(' ');
  1592.  
  1593.                 wrapit = FALSE; 
  1594.                 } 
  1595.             else 
  1596.                 {                    /* put char on col 80 */
  1597.                 i = dwl[wherey - 1] ? 2 : 1;
  1598.                 str[0] = vtch;
  1599.                 str[1] = ' ';
  1600.                 AVIOWrtCharStrAtt(&vtch, i, wherey - 1, 80 - i, &attribute);
  1601.                 literal = FALSE;
  1602.                 if ((autowrap && !deccolm))
  1603.                     wrapit = TRUE;
  1604.                 }
  1605.         }
  1606.         }           /* Normal char */
  1607.     }
  1608.     }
  1609.     if (printon && (vtch != 27))
  1610.     fprintf(lst, "%c", vtch);
  1611. }
  1612.  
  1613. /* ------------------------------------------------------------------ */
  1614. /* Vt100read -                                                        */
  1615. /* ------------------------------------------------------------------ */
  1616. /* save current status of screen */
  1617. static void savescreen(scrn) ascreen *scrn;
  1618. {
  1619.     USHORT          n = sizeof(screenmap);
  1620.     scrn->ox = wherex;
  1621.     scrn->oy = wherey;
  1622.     scrn->att = attribute;
  1623.     AVIOReadCellStr((char *) (scrn->scrncpy), &n, 0, 0);
  1624. }                                                         
  1625.  
  1626. /* restore state of screen */
  1627. void restorescreen(scrn) ascreen *scrn;
  1628. {
  1629.     movetoscreen(scrn->scrncpy, 1, 1, 4000);
  1630.     attribute = scrn->att;
  1631.     wherey = scrn->oy;
  1632.     wherex = scrn->ox;
  1633.     lgotoxy(wherex, wherey);
  1634. }
  1635.  
  1636. void sendcharduplex(unsigned char c)
  1637. {
  1638.     SENDCHAR(c);
  1639.     if (duplex) {
  1640.     cwrite(c);
  1641.     if (seslog)
  1642.         if (zchout(ZSFILE, c) < 0)
  1643.         seslog = 0;
  1644.     }
  1645. }
  1646. static void
  1647. sendstrduplex(unsigned char *s)
  1648. {
  1649.     SENDCHAR(27);
  1650.     if (duplex) {
  1651.     cwrite(27);
  1652.     if (seslog)
  1653.         if (zchout(ZSFILE, 27) < 0)
  1654.         seslog = 0;
  1655.     }
  1656.     while (*s) {
  1657.     SENDCHAR(*s);
  1658.     if (duplex) {
  1659.         cwrite(*s);
  1660.         if (seslog)
  1661.         if (zchout(ZSFILE, *s) < 0)
  1662.             seslog = 0;
  1663.     }
  1664.     s++;
  1665.     }
  1666. }
  1667.  
  1668. /* CHECKSCREENMODE  --  Make sure we are in a 25 x 80 mode */
  1669. void checkscreenmode()
  1670. {
  1671. //    VIOMODEINFO     m;
  1672. //   VIOCONFIGINFO   cfg;
  1673.     char            cell[2];
  1674. //    int             i;
  1675. //
  1676. //    m.cb = 12;
  1677. //    if (AVIOGetMode(&m))
  1678. //    return;
  1679. //    cfg.cb = 10;
  1680. //    if (AVIOGetConfig(0, &cfg))
  1681. //    return;
  1682. //    switch (cfg.adapter) {
  1683. //    case 0:         /* Monochrome */
  1684. //    m.fbType = 0;
  1685. //    m.color = 0;
  1686. //    m.hres = 720;
  1687. //    m.vres = 350;
  1688. //    adapter = mono;
  1689. //    colorofunderline = 1;
  1690. //    break;
  1691. //    case 1:         /* CGA */
  1692. //    m.fbType = 1;
  1693. //    m.color = 4;
  1694. //    m.hres = 640;
  1695. //    m.vres = 200;
  1696. //    adapter = colour;
  1697. //    break;
  1698. //    default:            /* Assume EGA/VGA */
  1699. //    m.fbType = 1;
  1700. //    m.color = 4;
  1701. //    m.hres = 640;
  1702. //    m.vres = 350;
  1703. //    adapter = colour;
  1704. //    }
  1705. //    if (m.row == 25 && m.col == 80)
  1706. //    return;         /* We're happy with this */
  1707. //    m.row = 25;
  1708. //    m.col = 80;
  1709. //    if (i = AVIOSetMode(&m)) {
  1710. //    printf("Error %d returned by AVIOSetMode\n", i);
  1711. //    return;
  1712. //    }
  1713.     cell[0] = ' ';
  1714.     cell[1] = 0x07;
  1715.     AVIOScrollUp(0, 0, -1, -1, -1, cell); /* Clear the screen */
  1716.     AVIOSetCurPos(0, 0);  /* Home the cursor */
  1717.     DosBeep(1000,20);
  1718. }
  1719.  
  1720.  
  1721.    
  1722. void doesc(c) char
  1723.     c;
  1724. {
  1725.     CHAR            d;
  1726.     char            temp[50];
  1727.  
  1728.     while (1) {
  1729.     if (c == escape) {  /* Send escape character */
  1730.         d = dopar(c);
  1731.         SENDCHAR(d);
  1732.         return;
  1733.     } else
  1734.      /* Or else look it up below. */ if (isupper(c))
  1735.         c = tolower(c);
  1736.  
  1737.     switch (c) {
  1738.  
  1739.     case 'c':       /* Close connection */
  1740.     case '\03':
  1741.         active = 0;
  1742.         return;
  1743.  
  1744.     case 'b':       /* Send a BREAK signal */
  1745.     case '\02':
  1746.         ttsndb();
  1747.         return;
  1748.  
  1749.     case 'h':       /* Hangup */
  1750.     case '\010':
  1751.         tthang();
  1752.         active = 0;
  1753.         return;
  1754.  
  1755.     case '0':       /* Send a null */
  1756.         c = '\0';
  1757.         d = dopar(c);
  1758.         SENDCHAR(d);
  1759.         return;
  1760.  
  1761.     case SP:        /* Space, ignore */
  1762.         return;
  1763.  
  1764.     default:        /* Other */
  1765.         conoc(BEL);
  1766.         return;     /* Invalid esc arg, beep */
  1767.     }
  1768.     }
  1769. }
  1770.  
  1771. /* DOESC  --  Process an escape character argument  */
  1772. static int      helpcol, helprow;
  1773. static int      helpwidth;
  1774.  
  1775. void helpstart(int w, int h)
  1776. {
  1777.     unsigned char   cell[2];
  1778.  
  1779.     cell[1] = attribute | 0x08;
  1780.     helpwidth = w;
  1781.     helpcol = (80 - w) / 2;
  1782.     helprow = (24 - h) / 2;
  1783.     cell[0] = 201;      /* Top left corner */
  1784.     AVIOWrtNCell(cell, 1, helprow, helpcol);
  1785.     cell[0] = 205;      /* Horizontal */
  1786.     AVIOWrtNCell(cell, helpwidth, helprow, helpcol + 1);
  1787.     cell[0] = 187;      /* Top right corner */
  1788.     AVIOWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1);
  1789. }
  1790.  
  1791. void helpline(s)
  1792.     char           *s;
  1793. {
  1794.     unsigned char   cell[2];
  1795.     int             i;
  1796.  
  1797.     i = strlen(s);
  1798.     helprow++;
  1799.     cell[1] = attribute | 0x08;
  1800.     cell[0] = 186;      /* Vertical */
  1801.     AVIOWrtNCell(cell, 1, helprow, helpcol);
  1802.     AVIOWrtCharStrAtt(s, i, helprow, helpcol + 1, &cell[1]);
  1803.     cell[0] = ' ';
  1804.     AVIOWrtNCell(cell, helpwidth - i, helprow, helpcol + 1 + i);
  1805.     cell[0] = 186;      /* Vertical */
  1806.     AVIOWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1);
  1807. }
  1808.  
  1809. void helpend()
  1810. {
  1811.     unsigned char   cell[2];
  1812.  
  1813.     helprow++;
  1814.     cell[1] = attribute | 0x08;
  1815.     cell[0] = 200;      /* Bottom left corner */
  1816.     AVIOWrtNCell(cell, 1, helprow, helpcol);
  1817.     cell[0] = 205;      /* Horizontal */
  1818.     AVIOWrtNCell(cell, helpwidth, helprow, helpcol + 1);
  1819.     cell[0] = 188;      /* Bottom right corner */
  1820.     AVIOWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1);
  1821. }
  1822.  
  1823.  
  1824. /*---------------------------------------------------------------------------*/
  1825. /* scankey                                                                 */
  1826. /*---------------------------------------------------------------------------*/
  1827. void scankey(ach, bch) unsigned char *
  1828.                     ach, *bch;
  1829. {
  1830.     extern char far * ulVideoBuffer;  /* The screen address from ckopm1.c */
  1831.     extern int Term_mode;
  1832.     /*
  1833.      * Wait for a keypress, return the ASCII code in *ach and the scan in
  1834.      * *bch 
  1835.      */
  1836.     int k;
  1837.     do
  1838.         {
  1839.         k = buff_getch(); /* Waits for a key to be entered into the PM buffer */
  1840.         *ach = (unsigned char) (k&0xFF);
  1841.         *bch = (unsigned char) (k>>8);
  1842.         if(*bch==VK_PRINTSCRN)
  1843.             {
  1844.             print_screen(ulVideoBuffer);
  1845.             }
  1846.         else if(*bch==VK_SHPRINTSCRN)
  1847.             {
  1848.             switch(Term_mode)
  1849.                 {
  1850.                 case TEKTRONIX:
  1851.                     DosEnterCritSec();
  1852.                     Tek_process(k&0xFF00);
  1853.                     DosExitCritSec();
  1854.                     break;
  1855.                 default:
  1856.                     break;
  1857.                 }
  1858.             *bch=VK_PRINTSCRN;  /* Force getting another character */
  1859.             }
  1860.         /* If user changes the screen emu mode during a conect   */
  1861.         /* the PM thread can't call ipadl25 to update the status */
  1862.         /* line. Semaphores are used to control the processing   */
  1863.         /* of screen writing messages to the PM thread. Generally*/
  1864.         /* the poster must wait for the PM thread to clear a     */
  1865.         /* semaphore before deleting the string buffer. This     */
  1866.         /* causes deadlock when the poster is actually the PM    */
  1867.         /* thread.  The only convenient way is to get the conect */
  1868.         /* thread to do it.  This way ensures that the change is */
  1869.         /* obvious immediatly.                                   */
  1870.         else if((*bch==0) && (*ach==0))
  1871.             {
  1872.             ipadl25();
  1873.             *bch=VK_PRINTSCRN;
  1874.             }
  1875.         }while(*bch==VK_PRINTSCRN);
  1876.                                     
  1877.     if (*ach == 0xE0)       /* Extended scan code */
  1878.     if (*bch >= 0x47 && *bch <= 0x53)
  1879.         *ach = 0;
  1880. }
  1881. /*---------------------------------------------------------------------------*/
  1882. /* scrninit                                                                */
  1883. /*---------------------------------------------------------------------------*/
  1884. static int      scrninitialised = 0;
  1885. void scrninit()
  1886. {
  1887.     SEL             selector;
  1888.  
  1889.     if (!scrninitialised) {
  1890.     scrninitialised = 1;
  1891.     defaultattribute = (colorofback << 4) + coloroftext;
  1892.     attribute = defaultattribute;
  1893.     line25attribute = (coloroftext << 4) + colorofback;
  1894.     /* Initialise paging info */
  1895.     if (DosAllocSeg(LBUFSIZE * 160, &selector, 0)) {
  1896.         printf("\nDosAllocSeg fails in scrninit\n");
  1897.         exit(1);
  1898.     }
  1899.     paginginfo.buffer = MAKEP(selector, 0);
  1900.     paginginfo.numlines = 0;
  1901.     paginginfo.topline = 0;
  1902.     paginginfo.botline = LBUFSIZE - 1;
  1903.     clearscreen();
  1904.     savescreen(&vt100screen);
  1905.     }
  1906. }
  1907. /*---------------------------------------------------------------------------*/
  1908. /* bleep                                                                   */
  1909. /*---------------------------------------------------------------------------*/
  1910. void bleep()
  1911. {
  1912.     DosBeep(440, 200);
  1913. }
  1914. /*---------------------------------------------------------------------------*/
  1915. /* wrtch                                                                   */
  1916. /*---------------------------------------------------------------------------*/
  1917. void wrtch(unsigned char ch)
  1918. {
  1919.     unsigned char   cell[2];
  1920.     if (ch >= ' ' || literal) { /* Normal character */
  1921.     if (ansi && insertmode) {
  1922.         cell[0] = ch;
  1923.         cell[1] = attribute;
  1924.         AVIOScrollRt(wherey - 1, wherex - 1, wherey - 1, 79, 1, cell);
  1925.     } else
  1926.         AVIOWrtCharStrAtt(&ch, 1, wherey - 1, wherex - 1, &attribute);
  1927.     literal = FALSE;
  1928.     if (++wherex > 80) {
  1929.         wherex = 1;
  1930.         wrtch(LF);
  1931.     }
  1932.     } else {            /* Control character */
  1933.     switch (ch) {
  1934.     case LF:
  1935.         if (wherey == marginbot) {
  1936.         if (margintop == 1)
  1937.             toplinetocyclicbuffer();
  1938.         scroll(UPWARD, margintop - 1, marginbot - 1);
  1939.         } else {
  1940.         wherey++;
  1941.         if (wherey == 25)
  1942.             wherey--;
  1943.         }
  1944.         break;
  1945.     case CR:
  1946.         wherex = 1;
  1947.         break;
  1948.     case BS:
  1949.         if (wherex > 1)
  1950.         wherex--;
  1951.         break;
  1952.     case 12:
  1953.         if (wherex < 80)
  1954.         wherex++;
  1955.         break;
  1956.     case BEL:
  1957.         DosBeep(400, 350);
  1958.         break;
  1959.     default:{       /* Ignore */
  1960.         }
  1961.     }
  1962.     }
  1963.     if (cursoron)
  1964.     AVIOSetCurPos(wherey - 1, wherex - 1);
  1965. }
  1966. /*---------------------------------------------------------------------------*/
  1967. /* killcursor                                                              */
  1968. /*---------------------------------------------------------------------------*/
  1969. VIOCURSORINFO crsr_info;
  1970. void killcursor()
  1971. {
  1972.     VIOCURSORINFO   nocursor;
  1973.  
  1974.     if (!cursoron)
  1975.     return;
  1976.     AVIOGetCurType(&crsr_info);   /* Store current cursor type */
  1977.     nocursor = crsr_info;   /* MS C allows this */
  1978.     nocursor.attr = -1;
  1979.     AVIOSetCurType(&nocursor);/* Hide cursor */
  1980.     return;
  1981. }
  1982. /*---------------------------------------------------------------------------*/
  1983. /* line25                                                                  */
  1984. /*---------------------------------------------------------------------------*/
  1985. void line25()
  1986. {
  1987.     char            s[80];
  1988.     int             i;
  1989.     char            attr;
  1990.  
  1991.     for (i = 0; i < 80; i++)
  1992.     s[i] = ' ';
  1993.     strinsert(&s[00], usertext);
  1994.     strinsert(&s[36], exittext);
  1995.     strinsert(&s[20], helptext);
  1996.     strinsert(&s[65], filetext);
  1997.     strinsert(&s[50], hostname);
  1998.     attr = line25attribute;
  1999.     AVIOWrtCharStrAtt(s, 80, 24, 0, &attr);
  2000. }
  2001.  
  2002. void clreoscr_escape()
  2003. {       
  2004.     char            cell[2];
  2005.     int             i;
  2006.  
  2007.     if (wherex == 1 && wherey == 1) {
  2008.     clrscreen();
  2009.     return;
  2010.     }
  2011.     cell[0] = ' ';
  2012.     cell[1] = defaultattribute;
  2013.     i = 1920 - (((wherey - 1) * 80) + (wherex - 1));
  2014.     AVIOWrtNCell(cell, i, wherey - 1, wherex - 1);
  2015.     for (i = wherey - 1; i < 24; i++)
  2016.     dwl[i] = FALSE;
  2017.     dwls = FALSE;
  2018.     for (i = 0; i < 24; i++)
  2019.     if (dwl[i]) {
  2020.         dwls = TRUE;
  2021.         break;
  2022.     }
  2023. }
  2024.  
  2025. void clrboscr_escape()
  2026. {   
  2027.     char            cell[2];
  2028.     int             i;
  2029.  
  2030.     cell[0] = ' ';
  2031.     cell[1] = defaultattribute;
  2032.     i = ((wherey - 1) * 80) + wherex;
  2033.     AVIOWrtNCell(cell, i, 0, 0);
  2034.     for (i = 0; i < wherey; i++)
  2035.     dwl[i] = FALSE;
  2036.     dwls = FALSE;
  2037.     for (i = 0; i < 24; i++)
  2038.     if (dwl[i]) {
  2039.         dwls = TRUE;
  2040.         break;
  2041.     }
  2042. }
  2043.  
  2044. void clrbol_escape()
  2045. {       
  2046.     char            cell[2];
  2047.  
  2048.     cell[0] = ' ';
  2049.     cell[1] = defaultattribute;
  2050.     AVIOWrtNCell(cell, wherex, wherey - 1, 0);
  2051. }
  2052.  
  2053. void clrline_escape()
  2054. {
  2055.     char            cell[2];
  2056.  
  2057.     cell[0] = ' ';
  2058.     cell[1] = defaultattribute;
  2059.     AVIOWrtNCell(cell, 80, wherey - 1, 0);
  2060. }
  2061.  
  2062.  
  2063. /* ------------------------------------------------------------------ */
  2064. /* CursorUp -                                                         */
  2065. /* ------------------------------------------------------------------ */
  2066. static void cursorup()
  2067. {
  2068.     if ((relcursor ? margintop : 1) != wherey)
  2069.     lgotoxy(wherex, wherey - 1);
  2070. }
  2071. /* ------------------------------------------------------------------ */
  2072. /* CursorDown -                                                       */
  2073. /* ------------------------------------------------------------------ */
  2074. static void
  2075. cursordown()
  2076. {
  2077.     if ((relcursor ? marginbot : 24) != wherey)
  2078.     lgotoxy(wherex, wherey + 1);
  2079. }
  2080. /* ------------------------------------------------------------------ */
  2081. /* CursorRight -                                                      */
  2082. /* ------------------------------------------------------------------ */
  2083. static void
  2084. cursorright()
  2085. {
  2086.     if (wherex < (dwl[wherey - 1] ? 79 : 80))
  2087.     lgotoxy(wherex + 1, wherey);
  2088. }
  2089. /* ------------------------------------------------------------------ */
  2090. /* CursorLeft -                                                       */
  2091. /* ------------------------------------------------------------------ */
  2092. static void
  2093. cursorleft()
  2094. {
  2095.     if (wherex > 1)
  2096.     lgotoxy(wherex - 1, wherey);
  2097. }
  2098. /* ------------------------------------------------------------------ */
  2099. /* ReverseScreen                              */
  2100. /* ------------------------------------------------------------------ */
  2101. static void reversescreen()
  2102. {
  2103.     unsigned char   back;
  2104.     unsigned char   fore;
  2105.     int             i, r, c;
  2106.     USHORT          n;
  2107.     unsigned char   cell[160];
  2108.  
  2109.     n = sizeof(cell);
  2110.     for (r = 0; r < 24; r++) {  /* flip row */
  2111.     AVIOReadCellStr(cell, &n, r, 0);
  2112.     for (c = 1; c < n; c += 2) {    /* do each cell in row */
  2113.         back = (cell[c] & 0x70) >> 4;
  2114.         fore = (cell[c] & 0x07);
  2115.         if (fore == (char) colorofunderline)
  2116.         cell[c] ^= 0x70;
  2117.         else
  2118.         cell[c] = (cell[c] & 0x88) | fore << 4 | back;
  2119.     }
  2120.     AVIOWrtCellStr(cell, n, r, 0);
  2121.     }
  2122. }
  2123.  
  2124.  
  2125.  
  2126.  
  2127. /*---------------------------------------------------------------------------*/
  2128. /* clearscreen                                                             */
  2129. /*---------------------------------------------------------------------------*/
  2130.  
  2131. void clearscreen()
  2132. {
  2133.     char            cell[2];
  2134.     cell[0] = ' ';
  2135.     cell[1] = defaultattribute;
  2136.     AVIOWrtNCell(cell, 1920, 0, 0);
  2137.     lgotoxy(1, 1);
  2138. }
  2139. /*---------------------------------------------------------------------------*/
  2140. /* lgotoxy                                                                 */
  2141. /*---------------------------------------------------------------------------*/
  2142. void lgotoxy(x, y) int
  2143.     x, y;
  2144. {
  2145.     wherex = x;
  2146.     wherey = y;
  2147.     if (cursoron)
  2148.     AVIOSetCurPos(wherey - 1, wherex - 1);
  2149. }
  2150. /*---------------------------------------------------------------------------*/
  2151. /* scroll                                                                  */
  2152. /*---------------------------------------------------------------------------*/
  2153. void scroll(updown, top, bottom) 
  2154.     int       updown;
  2155.     unsigned char   top, bottom;
  2156. {    
  2157.     char            blankcell[2];
  2158.     int             i;
  2159.  
  2160.     blankcell[0] = ' ';
  2161.     blankcell[1] = defaultattribute;
  2162.     switch (updown) {
  2163.     case UPWARD:
  2164.     AVIOScrollUp(top, 0, bottom, 79, 1, blankcell);
  2165.     if (dwls) {
  2166.         for (i = top; i < bottom; i++)
  2167.         dwl[i] = dwl[i + 1];
  2168.         dwl[bottom] = FALSE;
  2169.     }
  2170.     break;
  2171.     case DOWNWARD:
  2172.     AVIOScrollDn(top, 0, bottom, 79, 1, blankcell);
  2173.     if (dwls) {
  2174.         for (i = bottom; i > top; i--)
  2175.         dwl[i] = dwl[i - 1];
  2176.         dwl[top] = FALSE;
  2177.     }
  2178.     break;
  2179.     default: /* ignore */ ;
  2180.     }
  2181.     if (dwls) {
  2182.     dwls = FALSE;
  2183.     for (i = 0; i < 24; i++)
  2184.         if (dwl[i]) {
  2185.         dwls = TRUE;
  2186.         break;
  2187.         }
  2188.     }
  2189. }
  2190.  
  2191.  
  2192. /*---------------------------------------------------------------------------*/
  2193. /* movetoscreen                                                              */
  2194. /*---------------------------------------------------------------------------*/
  2195. void movetoscreen(source, x, y, len) 
  2196.     char * source, x, y;
  2197.     int             len;
  2198. {
  2199.     AVIOWrtCellStr(source, len, y - 1, x - 1);
  2200. }
  2201.  
  2202. /*---------------------------------------------------------------------------*/
  2203. /* cleartoeol                                                              */
  2204. /*---------------------------------------------------------------------------*/
  2205. void clrtoeol()
  2206. {
  2207.     char            cell[2];
  2208.  
  2209.     cell[0] = ' ';
  2210.     cell[1] = defaultattribute;
  2211.     AVIOWrtNCell(cell, 81 - wherex, wherey - 1, wherex - 1);
  2212. }
  2213. /*---------------------------------------------------------------------------*/
  2214. /* setmargins                                                              */
  2215. /*---------------------------------------------------------------------------*/
  2216. void setmargins(top, bot) char
  2217.     top, bot;
  2218. {
  2219.     margintop = top;
  2220.     marginbot = bot;
  2221. }
  2222.  
  2223.  
  2224. /* ------------------------------------------------------------------ */
  2225. /* cwrite                                                             */
  2226. /* ------------------------------------------------------------------ */
  2227. void cwrite(ch)
  2228.     unsigned char   ch;
  2229. {
  2230.     extern int Term_mode;
  2231.  
  2232.     /* If in tektronix mode don't use this function to process the input */
  2233.     if(Term_mode == TEKTRONIX)
  2234.         {
  2235.         Tek_process(ch);
  2236.         return;
  2237.         }
  2238.  
  2239.     {
  2240.     /* check and process escape sequence */
  2241.     /* escape */
  2242.     if (ch == 27) 
  2243.         {                   
  2244.         chars_out();        /* This prevents vt100() ever seeing ESC so we */
  2245.         escaping = TRUE;    /* need to dump the line buffer here */
  2246.         esclast = 0;
  2247.         } 
  2248.     else 
  2249.         {
  2250.         if (!(escaping)) 
  2251.             {
  2252.             /* can send it to vt100 to be processed */
  2253.             vt100(ch);
  2254.             } 
  2255.         else 
  2256.             {
  2257.             /* in the middle of an escape sequence */
  2258.             if (((ch == 24) || (ch == 26)))
  2259.                 /* cancelled */
  2260.                 escaping = FALSE;
  2261.             else 
  2262.                 {
  2263.                 if (ch < 32) 
  2264.                     {
  2265.                     if (ch == 8) 
  2266.                         {  /* Backspace */
  2267.                         if (esclast >= 1)
  2268.                             esclast--;
  2269.                         }
  2270.                     else if(ch==FF)
  2271.                         {
  2272.                         /* add to buffer */
  2273.                         esclast = esclast + 1;
  2274.                         escbuffer[esclast] = ch;
  2275.                         /* The only ESC containing FF is the Tek page */
  2276.                         vtescape();
  2277.                         }
  2278.                     } 
  2279.                 else {
  2280.             /* add to control string */
  2281.             if (esclast < 128) {
  2282.                 /* add to buffer */
  2283.                 esclast = esclast + 1;
  2284.                 escbuffer[esclast] = ch;
  2285.             }        
  2286.  
  2287.             /* now check to see if sequence complete */
  2288.             {
  2289.             /* Check for Tektronix screen clear command */
  2290.  
  2291.                 if (ansi) {
  2292.                 if (escbuffer[1] != '[') {
  2293.                     char            c = escbuffer[1];
  2294.                     if ((c != '#' && c != '(' && c != ')' && c != 'O'
  2295.                      && c != '?') || esclast >= 2) {
  2296.                     if ((escbuffer[1] != 'Y'))
  2297.                         vtescape();
  2298.                     else {
  2299.                         if ((esclast == 3))
  2300.                         vtescape();
  2301.                     }
  2302.                     }
  2303.                 } else {
  2304.                     /* check for terminating character */
  2305.                     if ((((64 <= ch) && (ch <= 126)) && (esclast > 1)))
  2306.                     vtescape();
  2307.                 }
  2308.                 } else {
  2309.                 /* vt52 mode */
  2310.                 if ((escbuffer[1] != 'Y'))
  2311.                     vtescape();
  2312.                 else {
  2313.                     if (esclast == 3)
  2314.                     vtescape();
  2315.                 }
  2316.                 }
  2317.             }
  2318.             }
  2319.         }
  2320.         }
  2321.     }
  2322.     }
  2323. }
  2324.  
  2325. void strinsert(d, s) char *
  2326.                     d, *s;
  2327. {
  2328.     while (*s)
  2329.     *d++ = *s++;
  2330. }
  2331.  
  2332. void sendstr(s) char *
  2333.                     s;
  2334. {
  2335.     SENDCHAR(27);
  2336.     while (*s)
  2337.     SENDCHAR(*s++);
  2338. }
  2339.  
  2340. /*
  2341.  * RDSERWRTSCR  --  Read the comms line and write to the screen. This
  2342.  * function is executed by a separate thread. 
  2343.  */
  2344. VOID FAR rdserwrtscr(VOID)
  2345.     {
  2346.     extern ULONG cr_recd_sem;
  2347.     extern int paste_eol_char;
  2348.     int             i;
  2349.     int buf[90];
  2350.     char countin;
  2351.     char countout;
  2352.  
  2353.  
  2354.     DosSemClear(&threadsem);    /* Let him know we've started */
  2355. //    while (active) 
  2356. //        {
  2357. //        countin=0;
  2358. //        while((buf[countin]=ttinc(50))>=0 && countin<90)
  2359. //            countin++;
  2360. //
  2361. //        countout=0;
  2362. //        while(countout<=countin)
  2363. //            {
  2364. //            cwrite(buf[countout] & cmask);
  2365. //            countout++;
  2366. //            }
  2367. //
  2368. //        if(seslog)
  2369. //            {
  2370. //            countout=0;
  2371. //            while(countout<=countin && seslog!=0)
  2372. //                {
  2373. //                if(zchout(ZSFILE,buf[countout] & cmask)<0)
  2374. //                    seslog=0;
  2375. //                countout++;
  2376. //                }
  2377. //            }
  2378. //
  2379.     while (active) 
  2380.         {            
  2381.         if ((i = ttinc(-25)) >= 0) 
  2382.             {
  2383.             if (cursoron)
  2384.                 {
  2385.                 if (ttchk() > 40) 
  2386.                     {
  2387.                     killcursor();
  2388.                     cursoron = FALSE;
  2389.                     }
  2390.                  }
  2391.  
  2392.             if( (i & cmask)==paste_eol_char) /* tell the write thread we've */
  2393.                 DosSemClear(&cr_recd_sem);   /* read an EOL.                */
  2394.  
  2395.             cwrite(i & cmask);
  2396.  
  2397.             if (seslog) 
  2398.                 {
  2399.                 if (zchout(ZSFILE, i & cmask) < 0)
  2400.                     seslog = 0;
  2401.                 }
  2402.             }
  2403.         else if (!cursoron)
  2404.              newcursor();
  2405.         }
  2406.     DosEnterCritSec();      /* Stop thread 1 discarding our stack before
  2407.                  * we've gone */
  2408.     DosSemClear(&threadsem);    /* Tell him we're going to die */
  2409.     _endthread();               /* Use the C MTRTL function to end */
  2410. }
  2411.  
  2412.  
  2413. /* CONECT  --  Perform terminal connection  */
  2414. conect()
  2415. {
  2416. extern int conected;
  2417. #define THRDSTKSIZ  3072        /* ex 2048 */
  2418.     char         *  stack;  /* Pointer to stack for second thread */
  2419.     USHORT          len, x, y;
  2420.     TID             threadid;
  2421.     int             c;      /* c is a character, but must be signed
  2422.                                integer to pass thru -1, which is the
  2423.                                modem disconnection signal, and is
  2424.                                different from the character 0377 */
  2425.     char            errmsg[50], *erp, ac, bc, ss[80];
  2426.  
  2427.     char * titlebuf;
  2428.  
  2429.     if (speed < 0) {
  2430.     printf("Sorry, you must set speed first.\n");
  2431.     return (-2);
  2432.     }
  2433.     twochartimes = 22000L / speed;
  2434.     if ((escape < 0) || (escape > 0177)) {
  2435.     printf("Your escape character is not ASCII - %d\n", escape);
  2436.     return (-2);
  2437.     }
  2438.     if (ttopen(ttname, &local, 0) < 0) {
  2439.     erp = errmsg;
  2440.     sprintf(erp, "Sorry, can't open %s", ttname);
  2441.     perror(errmsg);
  2442.     return (-2);
  2443.     }
  2444.     /* Condition console terminal and communication line */
  2445.  
  2446.     if (ttvt(speed, flow) < 0) {
  2447.     printf("Sorry, Can't condition communication line\n");
  2448.     return (-2);
  2449.     }
  2450.     checkscreenmode();
  2451.     AVIOGetCurPos(&y, &x);
  2452.     wherex = x + 1;
  2453.     wherey = y + 1;
  2454.     savescreen(&commandscreen);
  2455.     scrninit();
  2456.     restorescreen(&vt100screen);
  2457.  
  2458.     /* Save the current Vio title bar */
  2459.     titlebuf = (char *) malloc( PM_getViotitle(NULL) );
  2460.     PM_getViotitle(titlebuf);
  2461.  
  2462.  
  2463.  
  2464.     /* Create a thread to read the comms line and write to the screen */
  2465.     DosSemSet(&threadsem);  /* Thread 2 will clear this when it starts */
  2466.     active = 1;             /* So thread 2 doesn't end at once */
  2467.     termessage[0] = 0;
  2468.  
  2469.     if( (stack=malloc(THRDSTKSIZ)) == NULL)
  2470.         {
  2471.         printf("Can't do connect - no memory!");
  2472.         return(-2);
  2473.         }
  2474.  
  2475.     if( (threadid=_beginthread(rdserwrtscr,stack,THRDSTKSIZ,NULL)) == -1)
  2476.         {
  2477.         printf("Sorry, can't create thread\n");
  2478.         return (-2);
  2479.         }
  2480.     DosSemWait(&threadsem, -1L);/* Wait for thread to start */
  2481.     DosSemSet(&threadsem);  /* Thread 2 will clear this on termination */
  2482.  
  2483.     ipadl25();
  2484.     conected=1;
  2485.     while (active) 
  2486.         {        /* Read the keyboard and write to comms line */
  2487.         scankey(&ac, &bc);
  2488.  
  2489.         c = ac & cmask;     /* Get character from keyboard */
  2490.         if ((c & 0177) == escape) 
  2491.             { /* Look for escape char - does not use rtl */
  2492.             c = coninc(0) & 0177;   /* Got esc, get its arg */
  2493.             if (c == '?')
  2494.                 c = helpconnect();
  2495.             doesc(c);       /* And process it */
  2496.             } 
  2497.         else 
  2498.             {        /* Ordinary character */
  2499.             if (!keylock)
  2500.                 vt100read(ac, bc);
  2501.             }
  2502.  
  2503.     }               /* while (active) */
  2504.  
  2505.  
  2506.     DosSemWait(&threadsem, -1L);/* Wait for other thread to terminate */
  2507.  
  2508.     conected=0;
  2509.     savescreen(&vt100screen);
  2510.     restorescreen(&commandscreen);
  2511.     
  2512.     /* restore the Vio title bar */
  2513.     PM_setViotitle(titlebuf);
  2514.     free(titlebuf);
  2515.     free(stack);
  2516.  
  2517.     if (termessage[0]!='\0') printf(termessage);
  2518. }
  2519.  
  2520. /* HELPCONNECT  --  Give help message for connect.  */
  2521. helpconnect()
  2522. {
  2523.     int             c;
  2524.     unsigned char   ac, bc;
  2525.     char            cell[2];
  2526.     ascreen         tempscreen;
  2527.     static char    *hlpmsg[10] = {
  2528.                   "",
  2529.                   " Type :",
  2530.                   "",
  2531.                   "    C    to close the connection",
  2532.                   "    0    (zero) to send a null",
  2533.                   "    B    to send a BREAK",
  2534.                   "    H    to hangup and close connection",
  2535.                   "   ^]    to send the escape character",
  2536.                   "  space  to cancel",
  2537.                   ""};
  2538.     *(hlpmsg[7] + 4) = ctl(escape);
  2539.     savescreen(&tempscreen);
  2540.     killcursor();
  2541.     helpstart(41, 10);
  2542.     for (c = 0; c < 10; c++)
  2543.     helpline(hlpmsg[c]);
  2544.     helpend();
  2545.     cell[0] = ' ';
  2546.     cell[1] = line25attribute;
  2547.     AVIOWrtNCell(cell, 80, 24, 0);    /* Erase line 25 */
  2548.     scankey(&ac, &bc);
  2549.     c = ac & cmask;     /* Get character from keyboard */
  2550.     newcursor();
  2551.     restorescreen(&tempscreen);
  2552.     return ((int) c);
  2553. }
  2554.  
  2555.  
  2556. /*---------------------------------------------------------------------------*/
  2557. /* newcursor                                                               */
  2558. /*---------------------------------------------------------------------------*/
  2559. void newcursor()
  2560. {
  2561.     AVIOSetCurType(&crsr_info);
  2562.     AVIOSetCurPos(wherey - 1, wherex - 1);
  2563.     cursoron = TRUE;
  2564. }
  2565.  
  2566. /* CHSTR  --  Make a printable string out of a character  */
  2567.  
  2568. char 
  2569. * chstr(c) int
  2570.     c;
  2571. {
  2572.     static char     s[8];
  2573.     char           *cp = s;
  2574.  
  2575.     if (c < SP) {
  2576.     sprintf(cp, "CTRL-%c", ctl(c));
  2577.     } else
  2578.     sprintf(cp, "'%c'\n", c);
  2579.     cp = s;
  2580.     return (cp);
  2581. }
  2582.  
  2583. void vt_kp_send(c)
  2584.     char c;
  2585.     {
  2586.     extern ansi;
  2587.  
  2588.     char str[3];
  2589.     
  2590.     if (ansi)
  2591.         strcpy(str, "O ");
  2592.     else
  2593.         strcpy(str, "? ");
  2594.     str[1] = c;
  2595.     sendstrduplex(str);
  2596.     }
  2597.  
  2598.  
  2599. void screen_rollback(pachar,pbchar)
  2600.     unsigned char *  pachar;
  2601.     unsigned char *  pbchar;
  2602.     {
  2603.     int             i;
  2604.     int             il;
  2605.     char            str[3];
  2606.     int             prt;
  2607.     int             st;
  2608.     unsigned char   nolblines;
  2609.     unsigned char   linesleft;
  2610.     unsigned char   nextline;
  2611.     unsigned char   nlines;
  2612.     ascreen     *   savedscreen;/* screen save info */
  2613.  
  2614.     if((savedscreen = (ascreen *) malloc(sizeof(ascreen)))==NULL)
  2615.         {
  2616.         bleep();
  2617.         return;
  2618.         }
  2619.  
  2620.     savescreen(savedscreen);
  2621.     killcursor();
  2622.     linesleft = paginginfo.numlines;
  2623.     nextline = paginginfo.botline;
  2624.     do 
  2625.         {
  2626.         if (*pbchar == VK_PAGEDOWN) 
  2627.             {
  2628.             if (linesleft == 0)
  2629.                 bleep();
  2630.             else 
  2631.                 {
  2632.                 /* scroll up a page */
  2633.                 nlines = linesleft;
  2634.                 if (nlines > 24)
  2635.                     nlines = 24;
  2636.                 for (il = 1; il <= nlines; ++il) 
  2637.                     {
  2638.                     scroll(DOWNWARD, 0, 23);
  2639.                     movetoscreen(paginginfo.buffer + 160 * nextline, 1, 1, 160);
  2640.                     if (nextline == 0)
  2641.                         nextline = LBUFSIZE - 1;
  2642.                     else
  2643.                         nextline = nextline - 1;
  2644.                     }
  2645.                 il--;
  2646.                 linesleft = linesleft - nlines;
  2647.                 } 
  2648.             }
  2649.         else if (*pbchar == VK_PAGEUP) 
  2650.             {
  2651.             nlines = 24;
  2652.             do 
  2653.                 {
  2654.                 nextline = nextline + 1;
  2655.                 if (nextline >= LBUFSIZE)
  2656.                     nextline = 0;
  2657.                 linesleft = linesleft + 1;
  2658.                 /* lines of ext display above top of the screen */
  2659.                 nolblines = paginginfo.numlines - linesleft;
  2660.                 /* no. of ext disp buffer lines on screen */
  2661.                 scroll(UPWARD, 0, 23);
  2662.                 if (nolblines >= 24) 
  2663.                     {
  2664.                     /* move from buffer */
  2665.                     i = nextline;
  2666.                     i = (i + 24);
  2667.                     if (i >= LBUFSIZE)
  2668.                         i = i - LBUFSIZE;
  2669.                     movetoscreen(paginginfo.buffer + 160 * i, 1, 24, 160);
  2670.                     } 
  2671.                 else 
  2672.                     {
  2673.                     /* move from the screen copy */
  2674.                     movetoscreen(&(savedscreen->scrncpy[(23 - nolblines) * 160]), 
  2675.                         1, 24, 160);
  2676.                     }
  2677.                 nlines = nlines - 1;
  2678.                 }while (!(((nlines == 0) || 
  2679.                  (linesleft == paginginfo.numlines))));
  2680.             } 
  2681.         else
  2682.             linesleft = paginginfo.numlines;
  2683.  
  2684.         if (linesleft != paginginfo.numlines) 
  2685.             {
  2686.             strcpy(helptext, "PgUp : up");
  2687.             strcpy(exittext, "PgDn : down");
  2688.             *usertext = '\0';
  2689.             *filetext = '\0';
  2690.             *hostname = '\0';
  2691.             line25();
  2692.             scankey(pachar, pbchar);
  2693.             }
  2694.         }while (linesleft != paginginfo.numlines);
  2695.  
  2696.     restorescreen(savedscreen);
  2697.     free(savedscreen);
  2698.  
  2699.     newcursor();
  2700.     ipadl25();
  2701.     return;
  2702.     }
  2703.     
  2704.     
  2705. //char linebuf[81];
  2706. char * plinebuf;
  2707. int next=0;
  2708. unsigned char wcx,wcy;
  2709. ULONG lbuf_sem=0;
  2710.  
  2711. void chars_in(c)
  2712.     unsigned char c;
  2713.     {
  2714.     extern char * plinebuf;
  2715.     extern unsigned char wherex,wherey;
  2716.     extern int next;
  2717.     extern unsigned char wcx,wcy;
  2718.     extern ULONG lbuf_sem;
  2719.     
  2720.     /* 20-Mar-90 Semaphore with chars_out() to prevent chars_in zeroing */
  2721.     /*           or providing a new plinebuf while chars_out is in the  */
  2722.     /*           process of sending the old plinebuf to be printed.     */
  2723.     /*           I think this was causing the peculiar effects when     */
  2724.     /*           many bels were received in quick succession.           */
  2725.  
  2726.     if(ttchk()==0)
  2727.         {
  2728.         if(next>0)
  2729.             chars_out();
  2730.         wrtch(c);
  2731.         }
  2732.     else
  2733.         {
  2734.         DosSemRequest(&lbuf_sem,SEM_INDEFINITE_WAIT);
  2735.         if(next>79)
  2736.             {
  2737.             plinebuf[80]=0;
  2738.             DosSemClear(&lbuf_sem);
  2739.             chars_out();
  2740.             DosSemRequest(&lbuf_sem,SEM_INDEFINITE_WAIT);
  2741.             }
  2742.  
  2743.         if(next==0)     /* Starting a new fill so save position of */
  2744.             {           /* start of string.                        */
  2745.             if((plinebuf = (char *)malloc(81))==NULL)
  2746.                 {           /* Couldn't allocate memory so write character */
  2747.                 wrtch(c);   /* directly.                                   */
  2748.                 DosSemClear(&lbuf_sem);
  2749.                 return;
  2750.                 }
  2751.             wcx = wherex-1;
  2752.             wcy = wherey-1;
  2753.             }
  2754.  
  2755.         plinebuf[next]=c;
  2756.         next++;
  2757.  
  2758.         if(++wherex>80)  /* Need to update wherex, as wrtch would have done */
  2759.             {
  2760.             DosSemClear(&lbuf_sem);
  2761.             chars_out();
  2762.             wherex = 1;
  2763.             wrtch(LF);
  2764.             }
  2765.         else
  2766.             DosSemClear(&lbuf_sem);
  2767.  
  2768.         }    
  2769.     return;
  2770.     }
  2771.     
  2772. void chars_out()
  2773.     {
  2774.     extern char * plinebuf;
  2775.     extern unsigned char wherex,wherey;
  2776.     extern int next;
  2777.     extern unsigned char wcx,wcy;
  2778.     extern unsigned char attribute;
  2779.     extern ULONG lbuf_sem;
  2780.  
  2781.     DosSemRequest(&lbuf_sem,SEM_INDEFINITE_WAIT);
  2782.     if((next>0) && (plinebuf!=NULL))
  2783.         {
  2784.         AVIOdWrtCharStrAtt(plinebuf,next,wcy,wcx,&attribute);
  2785.         next=0;
  2786.         }
  2787.     DosSemClear(&lbuf_sem);
  2788.     
  2789.     return;
  2790.     }
  2791.  
  2792. /* This function works in "kernel" mode but does not seem to work in PM    */
  2793. /* mode, unfortunately.  Using the Kbd function fail also.  This means     */
  2794. /* that NumLock cannot be used to produce an emulation of the VT100 "Gold" */
  2795. /* key.  At least I tried!!                                                */
  2796. /* As it stands this function manages to toggle the NumLock light once,    */
  2797. /* from then on no keyboard input can be entered in the PM!  Regardless of */
  2798. /* the program!!.                                                          */
  2799. int numlock_toggle()
  2800.     {
  2801.     static HFILE hkbd=0;
  2802.     SHIFTSTATE sstate;
  2803.     USHORT action,err;
  2804.     BYTE imode,omode;
  2805.  
  2806. //    if(hkbd == 0)
  2807. //        {
  2808. //        if((err=DosOpen("KBD$",&hkbd,&action,NULL,0,FILE_OPEN,
  2809. //                OPEN_ACCESS_READWRITE | 
  2810. //                OPEN_SHARE_DENYNONE | 
  2811. //                OPEN_FLAGS_FAIL_ON_ERROR,
  2812. //                NULL))!=0)
  2813. //            {
  2814. //            dbprintf("Failed to open keyboard - error = %d\n",err);
  2815. //            }
  2816. //        }
  2817. //
  2818. //    if((err=DosDevIOCtl(&imode,0L,KBD_GETINPUTMODE,IOCTL_KEYBOARD,hkbd))!=0)
  2819. //        {
  2820. //        dbprintf("Failed to get KBD_INPUTMODE\n");
  2821. //        }
  2822. //    else
  2823. //        dbprintf("input mode is %X\n",(unsigned int)imode);
  2824. //
  2825. //    omode = imode | SHIFT_REPORT_MODE;
  2826. //
  2827. //    if((err=DosDevIOCtl(0L,&omode,KBD_SETINPUTMODE,IOCTL_KEYBOARD,hkbd))!=0)
  2828. //        {
  2829. //        dbprintf("Failed to set KBD_INPUTMODE\n");
  2830. //        }
  2831. //    else
  2832. //        dbprintf("input mode set to %X\n",(unsigned int)omode);
  2833. //
  2834. //    if((err=DosDevIOCtl((PBYTE)&sstate, 0L,KBD_GETSHIFTSTATE,IOCTL_KEYBOARD,hkbd))
  2835. //            !=0)
  2836. //        {
  2837. //        dbprintf("Failed to get shift state - error = %d\n",err);
  2838. //        }
  2839. //    
  2840. //    sstate.fsState ^= NUMLOCK_ON;
  2841. //    
  2842. //    if((err=DosDevIOCtl(0L,(PBYTE)&sstate,KBD_SETSHIFTSTATE,IOCTL_KEYBOARD,hkbd))
  2843. //            !=0)
  2844. //        {
  2845. //        dbprintf("Failed to set shift state - error = %d\n",err);
  2846. //        }                                                  
  2847. //
  2848. //    if((err=DosDevIOCtl(0L,&imode,KBD_SETINPUTMODE,IOCTL_KEYBOARD,hkbd))!=0)
  2849. //        {
  2850. //        dbprintf("Failed to reset KBD_INPUTMODE\n");
  2851. //        }
  2852. //    else
  2853. //        dbprintf("input mode reset to %X\n",(unsigned int)imode);
  2854. //
  2855. ////    DosClose(hkbd);
  2856.     return(0);
  2857.     }
  2858.     
  2859.