home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / sna / sli3270 / wsli3270.c < prev    next >
C/C++ Source or Header  |  1997-04-09  |  74KB  |  1,565 lines

  1. /**MOD+***********************************************************************/
  2. /* Module:  wsli3270.c                                                       */
  3. /*                                                                           */
  4. /* Purpose: Simple 3270 emulator                                             */
  5. /*                                                                           */
  6. /* (C) COPYRIGHT DATA CONNECTION LIMITED 1991                                */
  7. /*                                                                           */
  8. /**MOD-***********************************************************************/
  9.  
  10.  
  11. /*****************************************************************************/
  12. /* SLI Sample Program                                                        */
  13. /*                                                                           */
  14. /* (C) Copyright 1990 - 1993 Data Connection Ltd.                            */
  15. /*                                                                           */
  16. /* This program is a crude 3270 emulator.  It uses the SLI API to access     */
  17. /* the LU session.  Outbound data from the host is displayed on the screen   */
  18. /* unformatted.  If the outbound data is an RQD request an automatic         */
  19. /* positive response is sent.  Inbound data can be entered at the keyboard   */
  20. /*                                                                           */
  21. /*                                                                           */
  22. /* The program is invoked with two parameters - the name of the LUA LU       */
  23. /* to use and a logon string.  This is must match an LUA LU in the           */
  24. /* configuration file.  This LU should be configured for a 327? on the host. */
  25. /*                                                                           */
  26. /* The program can only access hosts that use simple unformatted logon       */
  27. /* requests                                                                  */
  28. /*                                                                           */
  29. /* The CSV CONVERT function is used to convert data between ASCII and        */
  30. /* EBCDIC.  This uses the type G conversion table, so the environment        */
  31. /* variable COMTBLG must be set to point to a suitable file.                 */
  32. /*                                                                           */
  33. /* Keys that work are:                                                       */
  34. /*                                                                           */
  35. /*     Alt-1 to Alt-9 are PF1 to PF9                                         */
  36. /*     backspace                                                             */
  37. /*     Letters, numbers and symbols                                          */
  38. /*                                                                           */
  39. /*****************************************************************************/
  40.  
  41.  
  42. /*****************************************************************************/
  43. /* SYSTEM INCLUDES                                                           */
  44. /*****************************************************************************/
  45. #include <windows.h>
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <stdlib.h>
  49. #include <winlua.h>
  50. #include <wincsv.h>
  51.  
  52. typedef unsigned char  UCHAR;
  53. typedef unsigned short USHORT;
  54. typedef unsigned long  ULONG;
  55.  
  56.  
  57. /*****************************************************************************/
  58. /* Program constants                                                         */
  59. /*****************************************************************************/
  60. #define DATASIZE 4096                  /* Max size of RU                     */
  61.  
  62. #define BETB     1                     /* Between brackets                   */
  63. #define SEND     2                     /* In bracket and can send            */
  64. #define RECV     3                     /* In bracket, but cannot send        */
  65.  
  66. #define APPNAME                "WSLI3270"
  67. #define SLI_WINDOW_MESSAGE     "WinSLI"
  68.  
  69. #define DISPLAY_BUFFER_SIZE    3200    /* size of circular display buffer    */
  70.  
  71. /*****************************************************************************/
  72. /* State variables                                                           */
  73. /*                                                                           */
  74. /* We can only have one read or write verb outstanding per flow.  These      */
  75. /* state variables keep track of these verbs and what we need to do with     */
  76. /* them.                                                                     */
  77. /*****************************************************************************/
  78.  
  79. UINT  write_state;
  80. #define NO_WRITE              1
  81. #define WRITE_OUTSTANDING     2        /* waiting for write to complete      */
  82. #define WRITE_QUEUED          3        /* have data to write                 */
  83.  
  84. UINT  read_state;
  85. #define NO_READ               1
  86. #define READ_OUTSTANDING      2        /* read verb outstanding              */
  87. #define RSP_QUEUED            3        /* have a response to write           */
  88. #define RSP_OUTSTANDING       4        /* waiting for a response to complete */
  89.  
  90. UINT  rpq_state;
  91. #define NO_RPQ                1
  92. #define RPQ_OUTSTANDING       2        /* waiting for an RPQ to complete     */
  93. #define RPQ_QUEUED            3        /* have RPQ to send                   */
  94.  
  95. /***************************************************************************/
  96. /* Global variables                                                        */
  97. /*                                                                         */
  98. /***************************************************************************/
  99. LUA_VERB_RECORD read_verb;             /* SLI recv verb                    */
  100. LUA_VERB_RECORD close_verb;             /* SLI recv verb                    */
  101. LUA_VERB_RECORD other_verb;            /* SLI open or send verb            */
  102. LUA_VERB_RECORD rpq_verb;              /* SLI_SEND for RPQs                */
  103.  
  104. UCHAR rpq_data[] = {
  105.  
  106.   0x88,
  107.   0x00, 0x0C, 0x81, 0x80, 0x80, 0x81, 0x85, 0x86, 0x87, 0x88, 0x95, 0xA6,
  108.  
  109.   0x00, 0x17, 0x81, 0x81, 0x21, 0x00, 0x00, 0x50, 0x00, 0x18, 0x00, 0x00,
  110.   0x0A, 0x02, 0xE5, 0x00, 0x02, 0x00, 0x6F, 0x09, 0x10, 0x07, 0x80,
  111.  
  112.   0x00, 0x14, 0x81, 0x85, 0x02, 0x00, 0x09, 0x0E, 0x00, 0x00, 0x00, 0x00,
  113.   0x07, 0x00, 0x00, 0x00, 0x02, 0xB9, 0x01, 0x1D,
  114.  
  115.   0x00, 0x16, 0x81, 0x86, 0x00, 0x08, 0x00, 0xF4, 0xF1, 0x00, 0xF2, 0x00,
  116.   0xF3, 0x00, 0xF4, 0x00, 0xF5, 0x00, 0xF6, 0x00, 0xF7, 0x00,
  117.  
  118.   0x00, 0x0D, 0x81, 0x87, 0x04, 0x00, 0xF0, 0xF1, 0x00, 0xF2, 0x00, 0xF4,
  119.   0x00,
  120.  
  121.   0x00, 0x07, 0x81, 0x88, 0x00, 0x01, 0x02,
  122.  
  123.   0x00, 0x0C, 0x81, 0x95, 0x00, 0x00, 0x7F, 0xFF, 0x7F, 0xFF, 0x01, 0x01,
  124.  
  125.   0x00, 0x11, 0x81, 0xA6, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x50, 0x00,
  126.   0x18, 0x00, 0x50, 0x00, 0x18};
  127.  
  128. #define RPQ_LENGTH (sizeof(rpq_data))
  129.  
  130. UCHAR display_buffer[DISPLAY_BUFFER_SIZE] = {0};
  131. UINT  buffer_end   = 0;             /* end of data in display buffer         */
  132. BOOL  wrapped      = FALSE;         /* has buffer wrapped?                   */
  133.  
  134.  
  135. /*****************************************************************************/
  136. /* Global Variables                                                          */
  137. /*****************************************************************************/
  138. HANDLE hInst = 0;                   /* current instance                      */
  139. UINT   verb_complete = 0;           /* verb completion message               */
  140. HANDLE hWnd = 0;                    /* Handle to program window              */
  141.  
  142. BOOL   init_done = FALSE;           /* SLI_OPEN completed                    */
  143.  
  144.  
  145.  
  146. unsigned char read_data[DATASIZE];     /* Outbound RU                       */
  147. #define WRITE_EXTRA 6
  148. unsigned char write_array[DATASIZE + WRITE_EXTRA] =
  149.                                           {0x7d, 0x40, 0x40, 0x11, 0x40, 0x40};
  150.                                        /* Inbound RU                         */
  151. unsigned char *write_data = write_array + WRITE_EXTRA;
  152.                                        /* Pointer to inbound RU              */
  153. UINT data_offset = 0;                  /* offset into read_data              */
  154. UINT write_len   = 0;                  /* length of write data               */
  155.  
  156. struct convert convert_to_asc;         /* Outbound convert verb              */
  157. struct convert convert_to_ebc;         /* Inbound convert verb               */
  158.  
  159. BOOL terminating = FALSE;              /* are we already in closedown() ?    */
  160.  
  161. unsigned long sense = 0l;              /* sense code                         */
  162.  
  163. unsigned char lu_name[9] = "        "; /* LU name                            */
  164. unsigned long sid;                     /* SLI session ID                     */
  165. int send_state = BETB;                 /* LU session send state              */
  166.  
  167. #define LOGON_MAX  25                  /* maximum logon string length        */
  168.  
  169. UCHAR logon_data[LOGON_MAX+1] = {0};
  170. UCHAR logon_length   = 0;
  171.  
  172. UCHAR  string[64]={0};
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179. void            csv_init            (void);
  180. void            issue_init          (void);
  181. void            issue_close        (void);
  182. void            issue_read          (void);
  183. void            other_done          (LUA_VERB_RECORD FAR *verb);
  184. void            read_done           (LUA_VERB_RECORD FAR *verb);
  185. void            issue_rsp           (unsigned long  sense);
  186. void            rsp_done            (LUA_VERB_RECORD FAR *verb);
  187. void            closedown           (void);
  188. BOOL            do_write            (void);
  189. void            wait_verb_complete  (LUA_VERB_RECORD FAR *verb);
  190. void            set_semaphore       (LUA_VERB_RECORD FAR *verb);
  191. BOOL            do_keyboard_stuff   (UINT, UCHAR);
  192. BOOL            check_verb_complete (LUA_VERB_RECORD FAR *verb);
  193. void            parse_data          (UCHAR FAR *, USHORT);
  194. BOOL            issue_rpq           (void);
  195. void            verb_complete_proc  (LUA_VERB_RECORD FAR * verb);
  196. void          add_to_display_buffer (UCHAR FAR *);
  197.  
  198. /*****************************************************************************/
  199. /* Windows function prototypes.                                              */
  200. /*****************************************************************************/
  201. int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
  202. long FAR PASCAL WndProc(HWND, UINT, UINT, LONG);
  203.  
  204.  
  205.  
  206.  
  207. /***PROC+*********************************************************************/
  208. /* Name:     WinMain                                                         */
  209. /*                                                                           */
  210. /* Purpose:  Main Windows function                                           */
  211. /*                                                                           */
  212. /* Params:   IN current instance handle                                      */
  213. /*           IN previous instance handle                                     */
  214. /*           IN pointer to command line                                      */
  215. /*           IN show window type                                             */
  216. /*                                                                           */
  217. /* Returns:  int                                                             */
  218. /*                                                                           */
  219. /**PROC-**********************************************************************/
  220.  
  221. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  222.  
  223. HINSTANCE hInstance;                         /* current instance             */
  224. HINSTANCE hPrevInstance;                     /* previous instance            */
  225. LPSTR     lpCmdLine;                         /* command line                 */
  226. int       nCmdShow;                          /* show-window type (open/icon) */
  227. {
  228.   /***************************************************************************/
  229.   /* LOCAL VARIABLES                                                         */
  230.   /***************************************************************************/
  231.   MSG   msg;                                 /* message                      */
  232.   int   xscreen;
  233.   int   yscreen;
  234.   int   delta;
  235.   WNDCLASS class;
  236.   LUADATA  LUAData;
  237.   UINT  cmdlength;                           /* length of command line       */
  238.   UINT  lu_name_length;                      /* length of LU name            */
  239.  
  240.  
  241.   if (!hPrevInstance)
  242.   {
  243.     class.style         = CS_HREDRAW | CS_VREDRAW;
  244.     class.lpfnWndProc   = (WNDPROC)WndProc;
  245.     class.cbClsExtra    = 0;
  246.     class.cbWndExtra    = 0;
  247.     class.hInstance     = hInstance;
  248.     class.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  249.     class.hCursor       = LoadCursor(NULL, IDC_ARROW);
  250.     class.hbrBackground = GetStockObject(WHITE_BRUSH);
  251.     class.lpszMenuName  = NULL;
  252.     class.lpszClassName = APPNAME;
  253.  
  254.     if (!RegisterClass(&class))
  255.     {
  256.       return (0);
  257.     }
  258.   }
  259.  
  260.   /***************************************************************************/
  261.   /* save current instance handle                                            */
  262.   /***************************************************************************/
  263.   hInst = hInstance;
  264.  
  265.   /***************************************************************************/
  266.   /* Set initial states                                                      */
  267.   /***************************************************************************/
  268.   write_state = NO_WRITE;
  269.   read_state  = NO_READ;
  270.   rpq_state   = NO_RPQ;
  271.  
  272.   /***************************************************************************/
  273.   /* get details of display                                                  */
  274.   /***************************************************************************/
  275.   xscreen = GetSystemMetrics(SM_CXSCREEN);
  276.   yscreen = GetSystemMetrics(SM_CYSCREEN);
  277.  
  278.   /***************************************************************************/
  279.   /* invent somewhere to put window                                          */
  280.   /***************************************************************************/
  281.   delta = xscreen / 100;
  282.  
  283.   /***************************************************************************/
  284.   /* create display window                                                   */
  285.   /***************************************************************************/
  286.   hWnd = CreateWindow(APPNAME,                    /* window class            */
  287.         "SLI3270",                                /* window name             */
  288.         WS_OVERLAPPEDWINDOW,                      /* window style            */
  289.         (xscreen/2) + delta,                      /* x position              */
  290.         yscreen / 8,                              /* y position              */
  291.         (xscreen / 2) - (delta * 2),              /* width                   */
  292.         3 * yscreen / 4,                          /* height                  */
  293.         NULL,                                     /* parent handle           */
  294.         NULL,                                     /* menu or child ID        */
  295.         hInstance,                                /* instance                */
  296.         NULL);                                    /* additional info         */
  297.  
  298.   if (!hWnd)
  299.   {
  300.     return (0);
  301.   }
  302.  
  303.   ShowWindow(hWnd, nCmdShow);                     /* Shows the window        */
  304.   UpdateWindow(hWnd);                             /* Sends WM_PAINT message  */
  305.  
  306.  
  307.   /***************************************************************************/
  308.   /* Register message used for async completion                              */
  309.   /***************************************************************************/
  310.   verb_complete = RegisterWindowMessage(SLI_WINDOW_MESSAGE);
  311.  
  312.   if (verb_complete == 0)
  313.   {
  314.     return (0);
  315.   }
  316.  
  317.   WinSLIStartup (0x0001, &LUAData);
  318.  
  319.   /***************************************************************************/
  320.   /* Issue SLI_OPEN to get the ball rolling.  Setup up the LU name           */
  321.   /***************************************************************************/
  322.   cmdlength = _fstrlen(lpCmdLine);
  323.   for (lu_name_length = 0; lu_name_length < cmdlength; lu_name_length++)
  324.   {
  325.     if (lpCmdLine[lu_name_length] == ' ')
  326.     {
  327.       break;
  328.     }
  329.     else
  330.     {
  331.       lu_name[lu_name_length] = lpCmdLine[lu_name_length];
  332.     }
  333.   }
  334.   if (lu_name_length == cmdlength)
  335.   {
  336.     /*************************************************************************/
  337.     /* Need  a logon string                                                  */
  338.     /*************************************************************************/
  339.     closedown();
  340.   }
  341.   else
  342.   {
  343.     while (lpCmdLine[lu_name_length] == ' ')
  344.     {
  345.       lu_name_length++;
  346.     }
  347.     logon_length = _fstrlen(lpCmdLine + lu_name_length);
  348.     _fstrncpy ((UCHAR FAR *)logon_data,
  349.                lpCmdLine + lu_name_length,
  350.                logon_length);
  351.     convert_to_ebc.opcode       = SV_CONVERT;
  352.     convert_to_ebc.direction    = SV_ASCII_TO_EBCDIC;
  353.     convert_to_ebc.char_set     = SV_G;
  354.     convert_to_ebc.source       = logon_data;
  355.     convert_to_ebc.target       = logon_data;
  356.     convert_to_ebc.len          = (unsigned short) logon_length;
  357.     ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_ebc));
  358.  
  359.     /*************************************************************************/
  360.     /* Set up CSV convert verbs                                              */
  361.     /*************************************************************************/
  362.     csv_init();
  363.  
  364.     issue_init ();
  365.   }
  366.  
  367.   while(GetMessage(&msg,NULL,0,0))
  368.   {
  369.     TranslateMessage(&msg);
  370.     DispatchMessage(&msg);
  371.   }
  372.  
  373.   return msg.wParam;         /* save exit parameter for return               */
  374. }
  375.  
  376. /***PROC+*********************************************************************/
  377. /* Name:     WndProc                                                         */
  378. /*                                                                           */
  379. /* Purpose:  Windows call-back routine                                       */
  380. /*                                                                           */
  381. /* Params:   IN window handle                                                */
  382. /*           IN message type                                                 */
  383. /*           IN additional information 1                                     */
  384. /*           IN additional information 2                                     */
  385. /*                                                                           */
  386. /* Returns:  long                                                            */
  387. /*                                                                           */
  388. /* Operation:set up window characteristics and register it                   */
  389. /*           return success or failure                                       */
  390. /*                                                                           */
  391. /**PROC-**********************************************************************/
  392.  
  393. long FAR PASCAL WndProc(hWnd, message, wParam, lParam)
  394. HWND hWnd;                                /* window handle                   */
  395. UINT message;                             /* type of message                 */
  396. UINT wParam;                              /* additional information          */
  397. LONG lParam;                              /* additional information          */
  398. {
  399.   /***************************************************************************/
  400.   /* LOCAL VARIABLES                                                         */
  401.   /***************************************************************************/
  402.   HDC          hDC;              /* handle to our device context             */
  403.   TEXTMETRIC   tm;               /* holds info on the current font           */
  404.   PAINTSTRUCT  ps;               /*  paint structure                         */
  405.   RECT         rc;               /* holds info on the size oof our window    */
  406.   ULONG        width;            /* width of window in chars                 */
  407.   ULONG        height;           /* height of window in chars                */
  408.   UINT         buffer_offset;    /* offset withing display buffer            */
  409.   UINT         buffer_length;    /* length of data in buffer                 */
  410.   UINT         out_length;       /* lngth of text to output                  */
  411.   UINT         out_length2;      /* and again                                */
  412.   static int   xChar, yChar;     /* width & height of the average char       */
  413.   int          position;         /* number of lines down the screen          */
  414.   BOOL         whole_data;       /* do we have data to send?                 */
  415.  
  416.   if ((message == verb_complete) &&
  417.       (!terminating))
  418.   {
  419.     /*************************************************************************/
  420.     /* Message is SLI verb completed.  We are not terminating, so process    */
  421.     /* the message.                                                          */
  422.     /*************************************************************************/
  423.     verb_complete_proc ((LUA_VERB_RECORD FAR *) lParam);
  424.     return(0l);
  425.   }
  426.  
  427.   switch (message)
  428.   {
  429.     case WM_CREATE:
  430.       /***********************************************************************/
  431.       /* Window creation message.  Get some infomation about our font and    */
  432.       /* save it for later                                                   */
  433.       /***********************************************************************/
  434.       hDC= GetDC(hWnd);
  435.       GetTextMetrics (hDC, &tm);
  436.       xChar = (int)tm.tmAveCharWidth;
  437.       yChar = (int)(tm.tmHeight + tm.tmExternalLeading);
  438.       ReleaseDC(hWnd, hDC);
  439.       return 0l;
  440.       break;
  441.  
  442.     case WM_CHAR:
  443.     case WM_SYSCHAR:
  444.       /***********************************************************************/
  445.       /* Character or Alt+char hit                                           */
  446.       /***********************************************************************/
  447.       if ((init_done)                 &&
  448.           (!terminating)              &&
  449.           (write_state == NO_WRITE)   &&
  450.           (rpq_state   == NO_RPQ)     &&
  451.           (read_state  != RSP_QUEUED) &&
  452.           (read_state  != RSP_OUTSTANDING))
  453.       {
  454.         /*********************************************************************/
  455.         /* Someone pressed a key and we are in a state to deal with it       */
  456.         /*********************************************************************/
  457.         whole_data = do_keyboard_stuff (message, (UCHAR)wParam);
  458.         if (whole_data)
  459.         {
  460.           /*******************************************************************/
  461.           /* We have data to send                                            */
  462.           /* Attempt to write the data out                                   */
  463.           /*******************************************************************/
  464.           if (do_write())
  465.           {
  466.             write_state = WRITE_OUTSTANDING;
  467.           }
  468.           else
  469.           {
  470.             write_state = WRITE_QUEUED;
  471.           }
  472.         }
  473.         return(0l);
  474.       }
  475.       break;
  476.  
  477.     case WM_PAINT:
  478.       BeginPaint (hWnd, &ps);
  479.       /***********************************************************************/
  480.       /* Determine the size of the Window in characters                      */
  481.       /***********************************************************************/
  482.       GetClientRect (hWnd, &rc);
  483.       height = rc.bottom / yChar;
  484.       width  = rc.right  / xChar;
  485.       /***********************************************************************/
  486.       /* subtract 2 from height for the status line                          */
  487.       /***********************************************************************/
  488.       height -= 2;
  489.       /***********************************************************************/
  490.       /* Work out how early in the buffer we can start                       */
  491.       /***********************************************************************/
  492.       if (!wrapped)
  493.       {
  494.         /*********************************************************************/
  495.         /* buffer is not wrapped                                             */
  496.         /*********************************************************************/
  497.         buffer_length = buffer_end;
  498.         buffer_offset = (buffer_length > (width * height)) ?
  499.                          buffer_end - (width * height) :
  500.                          0;
  501.       }
  502.       else
  503.       {
  504.         /*********************************************************************/
  505.         /* buffer is wrapped                                                 */
  506.         /*********************************************************************/
  507.         buffer_length = DISPLAY_BUFFER_SIZE;
  508.         if (buffer_length > width * height)
  509.         {
  510.           /*******************************************************************/
  511.           /* buffer is too big.  Work out where best to start in the buffer/ */
  512.           /*******************************************************************/
  513.           if (buffer_end > width * height)
  514.           {
  515.             buffer_offset = buffer_end - (width * height);
  516.           }
  517.           else
  518.           {
  519.             buffer_offset = DISPLAY_BUFFER_SIZE +
  520.                             buffer_end -
  521.                             (width * height);
  522.           }
  523.         }
  524.         else
  525.         {
  526.           /*******************************************************************/
  527.           /* We can fit everything in                                        */
  528.           /*******************************************************************/
  529.           buffer_offset = buffer_end;
  530.         }
  531.       }
  532.       /***********************************************************************/
  533.       /* We've worked out where to start printing from, so start printing    */
  534.       /***********************************************************************/
  535.       position = 0;
  536.       out_length = width;
  537.       if (buffer_offset > buffer_end)
  538.       {
  539.         while (buffer_offset < DISPLAY_BUFFER_SIZE)
  540.         {
  541.           if (DISPLAY_BUFFER_SIZE - buffer_offset < width)
  542.           {
  543.             out_length = DISPLAY_BUFFER_SIZE - buffer_offset;
  544.           }
  545.           else
  546.           {
  547.             out_length = width;
  548.           }
  549.           TextOut(ps.hdc,
  550.                   0,
  551.                   yChar * position,
  552.                   display_buffer + buffer_offset,
  553.                   out_length);
  554.           buffer_offset += out_length;
  555.           position++;
  556.         }
  557.         buffer_offset = 0;
  558.       }
  559.       /***********************************************************************/
  560.       /* If last line printed was a partial line, print the rest of the line */
  561.       /***********************************************************************/
  562.       if (out_length < width)
  563.       {
  564.         out_length2 = out_length;
  565.         if (buffer_end < (width - out_length))
  566.         {
  567.           out_length = buffer_end;
  568.         }
  569.         else
  570.         {
  571.           out_length = width - out_length;
  572.         }
  573.         TextOut(ps.hdc,
  574.                 xChar * out_length2,
  575.                 yChar * (position - 1),
  576.                 display_buffer,
  577.                 out_length);
  578.         buffer_offset += out_length;
  579.  
  580.       }
  581.       /***********************************************************************/
  582.       /* Now print to the end of the buffer                                  */
  583.       /***********************************************************************/
  584.       while (buffer_offset < buffer_end)
  585.       {
  586.         if (buffer_end - buffer_offset < width)
  587.         {
  588.           out_length = buffer_end - buffer_offset;
  589.         }
  590.         else
  591.         {
  592.           out_length = width;
  593.         }
  594.         TextOut(ps.hdc,
  595.                 0,
  596.                 yChar * position,
  597.                 display_buffer + buffer_offset,
  598.                 out_length);
  599.         buffer_offset += out_length;
  600.         position++;
  601.       }
  602.       /***********************************************************************/
  603.       /* Now fill in the status line                                         */
  604.       /***********************************************************************/
  605.       out_length  = wsprintf (string,
  606.                               "%s",
  607.                    (UCHAR FAR *)((send_state == BETB) ? "BETB" : "INB"));
  608.       TextOut(ps.hdc,
  609.               0,
  610.               (UINT) (yChar * (height + 2)),
  611.               string,
  612.               out_length);
  613.       /***********************************************************************/
  614.       /* Now write the input line.  Only in NO_WRITE state, o.w.  data is in */
  615.       /* EBCDIC                                                              */
  616.       /***********************************************************************/
  617.       if (write_state == NO_WRITE)
  618.       {
  619.         TextOut(ps.hdc,
  620.                 0,
  621.                 (UINT) (yChar * (height+1)),
  622.                 write_data,
  623.                 data_offset);
  624.       }
  625.       EndPaint(hWnd, &ps);
  626.       break;
  627.  
  628.     case WM_CLOSE:
  629.       if (!terminating)
  630.       {
  631.         /*********************************************************************/
  632.         /* Tell the SLI we are going                                         */
  633.         /*********************************************************************/
  634.         terminating = TRUE;
  635.         issue_close();
  636.         WinSLICleanup();
  637.       }
  638.       break;
  639.  
  640.     case WM_DESTROY:
  641.       PostQuitMessage(0);
  642.       return 0l;
  643.       break;
  644.  
  645.     default:
  646.       break;
  647.   }
  648.   return (DefWindowProc(hWnd, message, wParam, lParam));
  649. }
  650.  
  651. /**PROC+**********************************************************************/
  652. /* Name:      verb_complete_proc                                             */
  653. /*                                                                           */
  654. /* Purpose:   deal with verb completion                                      */
  655. /*                                                                           */
  656. /* Returns:   void                                                           */
  657. /*                                                                           */
  658. /* Params:    IN verb - pointer to completed verb                            */
  659. /*                                                                           */
  660. /* Operation: Determine which verb has completed and perform the appropriate */
  661. /* action                                                                    */
  662. /**PROC-**********************************************************************/
  663. VOID verb_complete_proc (verb)
  664.  
  665. LUA_VERB_RECORD FAR * verb;
  666. {
  667.  
  668.   switch (verb->common.lua_opcode)
  669.   {
  670.  
  671.     case LUA_OPCODE_SLI_CLOSE:
  672.       break;
  673.  
  674.     case LUA_OPCODE_SLI_OPEN:
  675.       /***********************************************************************/
  676.       /* Received ACTLU.  Save the SID for use on other verbs, flag init     */
  677.       /* done so that we can write data, and issue first read                */
  678.       /***********************************************************************/
  679.       sid = other_verb.common.lua_sid;
  680.       init_done = TRUE;
  681.       issue_read();
  682.       break;
  683.  
  684.     case LUA_OPCODE_SLI_RECEIVE:
  685.       /***********************************************************************/
  686.       /* Read completed.  Call read dne processor to display data and        */
  687.       /* determine if a response is required.                                */
  688.       /* If no response is required issue a new read                         */
  689.       /* if a response is required issue the response if we can              */
  690.       /***********************************************************************/
  691.       read_done (verb);
  692.       if (terminating == TRUE)
  693.         break;
  694.       if (read_state == NO_READ)
  695.       {
  696.         /*********************************************************************/
  697.         /* No work to do, issue a new read verb                              */
  698.         /*********************************************************************/
  699.         read_state = READ_OUTSTANDING;
  700.         issue_read();
  701.       }
  702.       else if ((read_state  == RSP_QUEUED) &&
  703.                (write_state != WRITE_OUTSTANDING) &&
  704.                (rpq_state   != RPQ_OUTSTANDING))
  705.       {
  706.         /*********************************************************************/
  707.         /* We need to send a response to the RU we have just received.  The  */
  708.         /* write flow is free, so send it                                    */
  709.         /*********************************************************************/
  710.         read_state = RSP_OUTSTANDING;
  711.         issue_rsp (sense);
  712.       }
  713.  
  714.       if ((rpq_state   == RPQ_QUEUED) &&
  715.           (write_state != WRITE_OUTSTANDING) &&
  716.           (read_state  != RSP_OUTSTANDING))
  717.       {
  718.         /*********************************************************************/
  719.         /* We need to send a read partition query response and we can, so do */
  720.         /* it.                                                               */
  721.         /*********************************************************************/
  722.         if (issue_rpq())
  723.         {
  724.           rpq_state = RPQ_OUTSTANDING;
  725.         }
  726.       }
  727.       break;
  728.  
  729.     case LUA_OPCODE_SLI_SEND:
  730.       /***********************************************************************/
  731.       /* Determine what kind of SLI_SEND completed                          */
  732.       /* either                                                              */
  733.       /* -  writing user data                                                */
  734.       /* -  writing a RPQ response                                           */
  735.       /* -  writing a RSP to host data                                       */
  736.       /***********************************************************************/
  737.       if (write_state == WRITE_OUTSTANDING)
  738.       {
  739.         write_state = NO_WRITE;
  740.         write_data[0] = '\0';
  741.       }
  742.       else if (rpq_state == RPQ_OUTSTANDING)
  743.       {
  744.         rpq_state = NO_RPQ;
  745.       }
  746.       else if (read_state == RSP_OUTSTANDING)
  747.       {
  748.         read_state = NO_READ;
  749.         issue_read();
  750.       }
  751.       /***********************************************************************/
  752.       /* Perform the next action depending on what work their is to do.      */
  753.       /***********************************************************************/
  754.       if (read_state == RSP_QUEUED)
  755.       {
  756.         /*********************************************************************/
  757.         /* We need to issue a RSP to an RU we have received.  Do it          */
  758.         /*********************************************************************/
  759.         read_state = RSP_OUTSTANDING;
  760.         issue_rsp (sense);
  761.       }
  762.       else if (rpq_state == RPQ_QUEUED)
  763.       {
  764.         /*********************************************************************/
  765.         /* We need to issue a response to a read partion query.  Send it if  */
  766.         /* the bracket state allows.                                         */
  767.         /*********************************************************************/
  768.         if (issue_rpq())
  769.         {
  770.           rpq_state = RPQ_OUTSTANDING;
  771.         }
  772.       }
  773.       else if (write_state == WRITE_QUEUED)
  774.       {
  775.         /*********************************************************************/
  776.         /* We have user data to send to the Host.  Send it if the bracket    */
  777.         /* state allows                                                      */
  778.         /*********************************************************************/
  779.         if (do_write())
  780.         {
  781.           write_state = WRITE_OUTSTANDING;
  782.         }
  783.       }
  784.       break;
  785.  
  786.     default:
  787.       break;
  788.   }
  789. }  /* verb_complete_proc                                                     */
  790.  
  791. /**PROC+**********************************************************************/
  792. /* Name:      csv_init                                                       */
  793. /*                                                                           */
  794. /* Purpose:   set up CSV convert verbs                                       */
  795. /*                                                                           */
  796. /* Returns:   void                                                           */
  797. /*                                                                           */
  798. /* Params:    none                                                           */
  799. /*                                                                           */
  800. /* Operation: sets uup two CSV convert verbs, one in each direction.  Only   */
  801. /* the length needs to be set when the verb is called                        */
  802. /**PROC-**********************************************************************/
  803. void csv_init (void)
  804. {
  805.   convert_to_asc.opcode       = SV_CONVERT;
  806.   convert_to_asc.direction    = SV_EBCDIC_TO_ASCII;
  807.   convert_to_asc.char_set     = SV_G;
  808.   convert_to_asc.source       = read_data;
  809.   convert_to_asc.target       = read_data;
  810.  
  811.   convert_to_ebc.opcode       = SV_CONVERT;
  812.   convert_to_ebc.direction    = SV_ASCII_TO_EBCDIC;
  813.   convert_to_ebc.char_set     = SV_G;
  814.   convert_to_ebc.source       = write_data;
  815.   convert_to_ebc.target       = write_data;
  816. }  /* csv_init                                                               */
  817.  
  818.  
  819. /**PROC+**********************************************************************/
  820. /* Name:      issue_init                                                     */
  821. /*                                                                           */
  822. /* Purpose:   build a verb and send it                                       */
  823. /*                                                                           */
  824. /* Returns:   void                                                           */
  825. /*                                                                           */
  826. /* Params:    None                                                           */
  827. /*                                                                           */
  828. /* Operation: Build an OPEN verb and issue it.                               */
  829. /**PROC-**********************************************************************/
  830. void issue_init(void)
  831. {
  832.   memset(&other_verb, 0, sizeof(other_verb));
  833.   other_verb.common.lua_verb             = LUA_VERB_SLI;
  834.   other_verb.common.lua_opcode           = LUA_OPCODE_SLI_OPEN;
  835.   other_verb.common.lua_verb_length    = sizeof(struct LUA_COMMON)+
  836.                           sizeof(other_verb.specific.open.lua_init_type) +
  837.                           sizeof(other_verb.specific.open.lua_resv65) +
  838.                           sizeof(other_verb.specific.open.lua_wait) +
  839.                           sizeof(other_verb.specific.open.lua_ending_delim);
  840.   memcpy(other_verb.common.lua_luname, lu_name, 8);
  841.   other_verb.specific.open.lua_init_type = LUA_INIT_TYPE_SEC_LOG;
  842.   other_verb.common.lua_data_length      = logon_length;
  843.   other_verb.common.lua_data_ptr         = logon_data;
  844.   other_verb.specific.open.lua_open_extension[0].lua_routine_type =
  845.                                                           LUA_ROUTINE_TYPE_END;
  846.  
  847.   WinSLI(hWnd, (LUA_VERB_RECORD FAR *) &other_verb);
  848.  
  849.   /***************************************************************************/
  850.   /* The sid is valid immediately.  Save it now.                             */
  851.   /***************************************************************************/
  852.   sid = other_verb.common.lua_sid;
  853.  
  854.   if (!other_verb.common.lua_flag2.async)
  855.   {
  856.     /*************************************************************************/
  857.     /* Verb completed immediately.  Post our own completion message          */
  858.     /*************************************************************************/
  859.     PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&other_verb);
  860.   }
  861.  
  862. }  /* issue_init                                                             */
  863.  
  864.  
  865. /**PROC+**********************************************************************/
  866. /* Name:      issue_read                                                     */
  867. /*                                                                           */
  868. /* Purpose:   build a read verb and send it                                  */
  869. /*                                                                           */
  870. /* Returns:   void                                                           */
  871. /*                                                                           */
  872. /* Params:    none                                                           */
  873. /*                                                                           */
  874. /* Operation: Build a read verb for all flows and issue it                   */
  875. /**PROC-**********************************************************************/
  876. void issue_read (void)
  877. {
  878.   memset(&read_verb, 0, sizeof(read_verb));
  879.   memset(read_data, 0, DATASIZE);
  880.   read_verb.common.lua_verb             = LUA_VERB_SLI;
  881.   read_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON);
  882.   read_verb.common.lua_opcode           = LUA_OPCODE_SLI_RECEIVE;
  883.   read_verb.common.lua_sid              = sid;
  884.   read_verb.common.lua_max_length       = DATASIZE;
  885.   read_verb.common.lua_data_ptr         = (char FAR *) read_data;
  886.   read_verb.common.lua_flag1.lu_norm    = 1;
  887.   read_verb.common.lua_flag1.lu_exp     = 1;
  888.   read_verb.common.lua_flag1.sscp_norm  = 1;
  889.   read_verb.common.lua_flag1.sscp_exp   = 1;
  890.   WinSLI(hWnd, (LUA_VERB_RECORD FAR *)&(read_verb));
  891.   if (!read_verb.common.lua_flag2.async)
  892.   {
  893.     /*************************************************************************/
  894.     /* Verb completed immediately.  Post our own completion message          */
  895.     /*************************************************************************/
  896.     PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&read_verb);
  897.   }
  898.  
  899. }  /* issue_read                                                             */
  900.  
  901. void issue_close (void)
  902. {
  903.   memset(&close_verb, 0, sizeof(close_verb));
  904.   memset(read_data, 0, DATASIZE);
  905.   close_verb.common.lua_verb             = LUA_VERB_SLI;
  906.   close_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON);
  907.   close_verb.common.lua_opcode           = LUA_OPCODE_SLI_CLOSE;
  908.   close_verb.common.lua_sid              = sid;
  909.   WinSLI(hWnd, (LUA_VERB_RECORD FAR *)&(close_verb));
  910.   if (!close_verb.common.lua_flag2.async)
  911.   {
  912.     /*************************************************************************/
  913.     /* Verb completed immediately.  Post our own completion message          */
  914.     /*************************************************************************/
  915.     PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&close_verb);
  916.   }
  917.  
  918. }  /* issue_read                                                             */
  919.  
  920.  
  921.  
  922.  
  923. /**PROC+**********************************************************************/
  924. /* Name:      read_done                                                      */
  925. /*                                                                           */
  926. /* Purpose:   handle completed read verb                                     */
  927. /*                                                                           */
  928. /* Returns:   void                                                           */
  929. /*                                                                           */
  930. /* Params:    IN verb - completed read verb                                  */
  931. /*                                                                           */
  932. /* Operation: If the completed verb contains data, first parse it and then   */
  933. /*            display it.                                                    */
  934. /*            If message is a BIND or an UNBIND, set the LU-LU session state */
  935. /*            accordingly                                                    */
  936. /*            Also check for EB, CD and change session state flags           */
  937. /**PROC-**********************************************************************/
  938. void read_done(verb)
  939. LUA_VERB_RECORD FAR * verb;
  940. {
  941.   BOOL           rsp_required = FALSE; /* is a resonse required              */
  942.  
  943.   sense = 0l;
  944.  
  945.   if (verb->common.lua_prim_rc == LUA_OK)
  946.   {
  947.     if (verb->common.lua_message_type == LUA_MESSAGE_TYPE_LU_DATA)
  948.     {
  949.       if (verb->common.lua_data_length > 0)
  950.       {
  951.         /*********************************************************************/
  952.         /* We now have to parse the data.  For the moment we only look for   */
  953.         /* RPQ requests.                                                     */
  954.         /*********************************************************************/
  955.         parse_data (read_data, (USHORT) (verb->common.lua_data_length));
  956.  
  957.         /*********************************************************************/
  958.         /* Display outbound data.                                            */
  959.         /*********************************************************************/
  960.         convert_to_asc.len = (unsigned short) verb->common.lua_data_length;
  961.         ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_asc));
  962.         add_to_display_buffer (read_data);
  963.       }
  964.  
  965.       /***********************************************************************/
  966.       /* Set session state.                                                  */
  967.       /***********************************************************************/
  968.       if (verb->common.lua_rh.ebi)
  969.       {
  970.         send_state = BETB;
  971.       }
  972.       else if (verb->common.lua_rh.cdi)
  973.       {
  974.         send_state = SEND;
  975.       }
  976.       else
  977.       {
  978.         send_state = RECV;
  979.       }
  980.       InvalidateRect (hWnd, NULL, TRUE);
  981.     }
  982.  
  983.     /*************************************************************************/
  984.     /* Respond to any RQD request.                                           */
  985.     /*************************************************************************/
  986.     if ((verb->common.lua_message_type != LUA_MESSAGE_TYPE_RSP)  &&
  987.         (verb->common.lua_rh.ri == 0))                  /* definite response */
  988.     {
  989.       rsp_required = TRUE;
  990.     }
  991.   }
  992.   else if (verb->common.lua_prim_rc != LUA_STATUS)
  993.   {
  994.     closedown();
  995.   }
  996.  
  997.   /***************************************************************************/
  998.   /* Continue processing with either another read or a write positive rsp.   */
  999.   /* (The callback from issuing response will then issue another read) If    */
  1000.   /* we've already gone into closedown, stop here                            */
  1001.   /***************************************************************************/
  1002.   if (!terminating)
  1003.   {
  1004.     if (rsp_required)
  1005.     {
  1006.       read_state = RSP_QUEUED;
  1007.     }
  1008.     else
  1009.     {
  1010.       read_state = NO_READ;
  1011.     }
  1012.   }
  1013. }  /* read_done                                                              */
  1014.  
  1015.  
  1016. /**PROC+**********************************************************************/
  1017. /* Name:      issue_rsp                                                      */
  1018. /*                                                                           */
  1019. /* Purpose:   issue a response for a request from the host                   */
  1020. /*                                                                           */
  1021. /* Returns:   void                                                           */
  1022. /*                                                                           */
  1023. /* Params:    IN sense - sense code for the response                         */
  1024. /*                                                                           */
  1025. /* Operation: Build a response and write it out.  Uses the read verb control */
  1026. /*            block because it has the necessary information.                */
  1027. /*                                                                           */
  1028. /**PROC-**********************************************************************/
  1029. void issue_rsp(sense)
  1030. unsigned long sense;
  1031. {
  1032.   read_verb.common.lua_opcode           = LUA_OPCODE_SLI_SEND;
  1033.   read_verb.common.lua_max_length       = 0;
  1034.   read_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON) +
  1035.                                 sizeof(read_verb.specific.lua_sequence_number);
  1036.   read_verb.common.lua_rh.rri           = 1;         /* response             */
  1037.   read_verb.common.lua_post_handle      = NULL;
  1038.   read_verb.common.lua_flag1.lu_norm    = 0;
  1039.   read_verb.common.lua_flag1.lu_exp     = 0;
  1040.   read_verb.common.lua_flag1.sscp_norm  = 0;
  1041.   read_verb.common.lua_flag1.sscp_exp   = 0;
  1042.   read_verb.common.lua_message_type     = LUA_MESSAGE_TYPE_RSP;
  1043.   memset(read_verb.common.lua_resv56, '\0', 7);
  1044.  
  1045. #if 0
  1046.   read_verb.common.lua_rh.eci           = 0;
  1047.   read_verb.common.lua_rh.bci           = 0;
  1048.   read_verb.common.lua_rh.dr1i          = 0;
  1049.   read_verb.common.lua_rh.dr2i          = 0;
  1050.   read_verb.common.lua_rh.qri           = 0;
  1051.   read_verb.common.lua_rh.pi            = 0;
  1052.   read_verb.common.lua_rh.bbi           = 0;
  1053.   read_verb.common.lua_rh.ebi           = 0;
  1054.   read_verb.common.lua_rh.cdi           = 0;
  1055.   read_verb.common.lua_rh.csi           = 0;
  1056.   read_verb.common.lua_rh.edi           = 0;
  1057.   read_verb.common.lua_rh.pdi           = 0;
  1058. #endif
  1059.  
  1060.   /***************************************************************************/
  1061.   /* If we have been given a sense code this must be a negative response     */
  1062.   /***************************************************************************/
  1063.   if (sense)
  1064.   {
  1065.     read_verb.common.lua_data_length      = 4;
  1066.     memcpy(read_data, &sense, 4);
  1067.     read_verb.common.lua_rh.ri            = 1;       /* negative rsp         */
  1068.   }
  1069.   else
  1070.   {
  1071.     read_verb.common.lua_data_ptr         = NULL;
  1072.     read_verb.common.lua_data_length      = 0;
  1073.     read_verb.common.lua_rh.ri            = 0;       /* positive rsp         */
  1074.   }
  1075.   /***************************************************************************/
  1076.   /* Send the response back on the flow from which the request came          */
  1077.   /***************************************************************************/
  1078.   if (read_verb.common.lua_flag2.lu_norm)
  1079.   {
  1080.     read_verb.common.lua_flag1.lu_norm = 1;
  1081.     read_verb.common.lua_flag2.lu_norm = 0;
  1082.   }
  1083.   else if (read_verb.common.lua_flag2.lu_exp)
  1084.   {
  1085.     read_verb.common.lua_flag1.lu_exp = 1;
  1086.     read_verb.common.lua_flag2.lu_exp = 0;
  1087.   }
  1088.   else if (read_verb.common.lua_flag2.sscp_norm)
  1089.   {
  1090.     read_verb.common.lua_flag1.sscp_norm = 1;
  1091.     read_verb.common.lua_flag2.sscp_norm = 0;
  1092.   }
  1093.   else if (read_verb.common.lua_flag2.sscp_exp)
  1094.   {
  1095.     read_verb.common.lua_flag1.sscp_exp = 1;
  1096.     read_verb.common.lua_flag2.sscp_exp = 0;
  1097.   }
  1098.   read_verb.common.lua_flag2.async = 0;
  1099.   /***************************************************************************/
  1100.   /* Send out the verb                                                       */
  1101.   /***************************************************************************/
  1102.   WinSLI(hWnd, (LUA_VERB_RECORD FAR *)&read_verb);     /* write the response */
  1103.   if (!read_verb.common.lua_flag2.async)
  1104.   {
  1105.     /*************************************************************************/
  1106.     /* Verb completed immediately.  Post our own completion message          */
  1107.     /*************************************************************************/
  1108.     PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&read_verb);
  1109.   }
  1110. }  /* issue_rsp                                                              */
  1111.  
  1112.  
  1113. /**PROC+**********************************************************************/
  1114. /* Name:      rsp_done                                                       */
  1115. /*                                                                           */
  1116. /* Purpose:   handle completion of SLI_SEND, when SLI_SEND has written a     */
  1117. /*            response                                                       */
  1118. /*                                                                           */
  1119. /* Returns:   void                                                           */
  1120. /*                                                                           */
  1121. /* Params:    IN verb - completed verb                                       */
  1122. /*                                                                           */
  1123. /* Operation: If verb did not complete OK terminate                          */
  1124. /*                                                                           */
  1125. /**PROC-**********************************************************************/
  1126. void rsp_done (verb)
  1127. LUA_VERB_RECORD FAR * verb;
  1128. {
  1129.   if (verb->common.lua_prim_rc != LUA_OK)   /* failed to write the response */
  1130.   {                                         /* so stop here                 */
  1131.     closedown();
  1132.   }
  1133. }  /* rsp_done                                                               */
  1134.  
  1135.  
  1136. /**PROC+**********************************************************************/
  1137. /* Name:      closedown                                                      */
  1138. /*                                                                           */
  1139. /* Purpose:   terminate the application cleanly                              */
  1140. /*                                                                           */
  1141. /* Returns:   void                                                           */
  1142. /*                                                                           */
  1143. /* Params:    none                                                           */
  1144. /*                                                                           */
  1145. /* Operation: Issue a WinSLICleanup() to tell SLI the we are about to go,    */
  1146. /* and then post a close message so that we do.                              */
  1147. /*                                                                           */
  1148. /**PROC-**********************************************************************/
  1149. void closedown (void)
  1150. {
  1151.   if (!terminating)                /* check we haven't already got here from */
  1152.   {                                /* another section of the code            */
  1153.     terminating = TRUE;            /* then make sure we can't get here again */
  1154.     issue_close();
  1155.     WinSLICleanup();
  1156.     PostMessage (hWnd, WM_CLOSE, 0, 0l);
  1157.   }
  1158. }  /* closedown                                                              */
  1159.  
  1160.  
  1161.  
  1162. /**PROC+**********************************************************************/
  1163. /* Name:      do_keyboard_stuff                                              */
  1164. /*                                                                           */
  1165. /* Purpose:   poll keyboard for data                                         */
  1166. /*                                                                           */
  1167. /* Returns:   BOOL - TRUE => we have data to send                            */
  1168. /*                                                                           */
  1169. /* Params:    none                                                           */
  1170. /*                                                                           */
  1171. /* Operation: Look for Alt-1 to Alt-9 and ascii chars.                       */
  1172. /*                                                                           */
  1173. /**PROC-**********************************************************************/
  1174. BOOL do_keyboard_stuff (type, key)
  1175.  
  1176. UINT  type;
  1177. UCHAR key;
  1178.  
  1179. {
  1180.   BOOL   data_to_send;             /* do we have data to send?               */
  1181.  
  1182.   data_to_send = FALSE;
  1183.  
  1184.   if (type == WM_SYSCHAR)
  1185.   {
  1186.     /*************************************************************************/
  1187.     /* Alt key pressed                                                       */
  1188.     /*************************************************************************/
  1189.     if ((key >= '1') &&
  1190.         (key <= '9'))
  1191.     {
  1192.       /***********************************************************************/
  1193.       /* ALT-1 to ALT-9 0xF1 is the AID code for PF1.  Follow this with the  */
  1194.       /* cursor address                                                      */
  1195.       /***********************************************************************/
  1196.       *write_data = 0xF1 + key - '1';
  1197.       *(write_data + 1) = 0x40;
  1198.       *(write_data + 2) = 0x40;
  1199.       write_len = 3;
  1200.       data_to_send = TRUE;
  1201.     }
  1202.   }
  1203.   else
  1204.   {
  1205.     /*************************************************************************/
  1206.     /* Ordinary ASCII char                                                   */
  1207.     /* Key should be real data.  Add it to the string                        */
  1208.     /*************************************************************************/
  1209.     if (key == 13)
  1210.     {
  1211.       /***********************************************************************/
  1212.       /* If user pressed return key then send the data.  Reset data_offset   */
  1213.       /* for next data.                                                      */
  1214.       /***********************************************************************/
  1215.       write_data[data_offset++] = '\0';
  1216.       data_to_send = TRUE;
  1217.       data_offset  = 0;
  1218.  
  1219.       /***********************************************************************/
  1220.       /* Convert data to EBCDIC                                              */
  1221.       /***********************************************************************/
  1222.       convert_to_ebc.len = (unsigned short) (strlen(write_data) );
  1223.       if (convert_to_ebc.len > 0)
  1224.       {
  1225.         ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_ebc));
  1226.       }
  1227.       write_len = convert_to_ebc.len;
  1228.  
  1229.       /***********************************************************************/
  1230.       /* Allow for ENTER AID if necessary                                    */
  1231.       /***********************************************************************/
  1232.       write_data -= WRITE_EXTRA;
  1233.       write_len  += WRITE_EXTRA;
  1234.     }
  1235.     else if (key == 8)
  1236.     {
  1237.       /***********************************************************************/
  1238.       /* Backspace.  Delete last char                                        */
  1239.       /***********************************************************************/
  1240.       if (data_offset > 0)
  1241.       {
  1242.         data_offset--;
  1243.       }
  1244.     }
  1245.     else if (key != 0)
  1246.     {
  1247.       /***********************************************************************/
  1248.       /* ASCII char.  Add it to the data buffer                              */
  1249.       /***********************************************************************/
  1250.       write_data[data_offset++] = (UCHAR) key;
  1251.  
  1252.     }
  1253.     /*************************************************************************/
  1254.     /* Invalidate our window so that the new data is displayed               */
  1255.     /*************************************************************************/
  1256.     InvalidateRect (hWnd, NULL, TRUE);
  1257.   }
  1258.  
  1259.  
  1260.   return(data_to_send);
  1261. }  /* do_keyboard_stuff                                                      */
  1262.  
  1263.  
  1264.  
  1265. /**PROC+**********************************************************************/
  1266. /* Name:      do_write                                                       */
  1267. /*                                                                           */
  1268. /* Purpose:   issue a write verb                                             */
  1269. /*                                                                           */
  1270. /* Returns:   BOOL - TRUE => data sent OK                                    */
  1271. /*                                                                           */
  1272. /* Params:    none                                                           */
  1273. /*                                                                           */
  1274. /* Operation: convert data to EBCDIC and send it on the right session        */
  1275. /*                                                                           */
  1276. /**PROC-**********************************************************************/
  1277. BOOL do_write (void)
  1278.  
  1279. {
  1280.   BOOL ok;
  1281.  
  1282.   ok = TRUE;
  1283.  
  1284.  
  1285.   /***************************************************************************/
  1286.   /* Set up the vcb                                                          */
  1287.   /***************************************************************************/
  1288.   memset(&other_verb, 0, sizeof(other_verb));
  1289.   other_verb.common.lua_verb             = LUA_VERB_SLI;
  1290.   other_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON) +
  1291.                          sizeof(other_verb.specific.lua_sequence_number);
  1292.   other_verb.common.lua_opcode           = LUA_OPCODE_SLI_SEND;
  1293.   other_verb.common.lua_message_type     = LUA_MESSAGE_TYPE_LU_DATA;
  1294.   other_verb.common.lua_sid              = sid;
  1295.   other_verb.common.lua_data_length      = write_len;
  1296.   other_verb.common.lua_data_ptr         = (char far *) write_data;
  1297.   other_verb.common.lua_rh.dr1i          = 1;
  1298.  
  1299.   /***************************************************************************/
  1300.   /* On the LU session we must add the <enter> key prefix.  All inbound      */
  1301.   /* requests flow RQE with the BBI and CDI flags set depending on the       */
  1302.   /* current session state.                                                  */
  1303.   /***************************************************************************/
  1304.   other_verb.common.lua_rh.ri          = 1;
  1305.   if (send_state == BETB)
  1306.   {
  1307.     /*************************************************************************/
  1308.     /* Between bracket, so open bracket and give direction.  Note that we    */
  1309.     /* can do this since we will always be contention winner.                */
  1310.     /*************************************************************************/
  1311.     other_verb.common.lua_rh.bbi         = 1;
  1312.     other_verb.common.lua_rh.cdi         = 1;
  1313.     send_state = RECV;
  1314.   }
  1315.   else if (send_state = SEND)
  1316.   {
  1317.     /*************************************************************************/
  1318.     /* In bracket and we have direction, so simply give direction.           */
  1319.     /*************************************************************************/
  1320.     other_verb.common.lua_rh.cdi         = 1;
  1321.     send_state = RECV;
  1322.   }
  1323.   else
  1324.   {
  1325.     /*************************************************************************/
  1326.     /* In bracket and we do not have direction, so do not send.              */
  1327.     /*************************************************************************/
  1328.     ok = FALSE;
  1329.   }
  1330.  
  1331.   if (ok)
  1332.   {
  1333.     /*************************************************************************/
  1334.     /* Issue write verb                                                      */
  1335.     /*************************************************************************/
  1336.     WinSLI(hWnd, (LUA_VERB_RECORD FAR *) &other_verb);
  1337.     if (!other_verb.common.lua_flag2.async)
  1338.     {
  1339.       /***********************************************************************/
  1340.       /* Verb completed immediately.  Post our own completion message        */
  1341.       /***********************************************************************/
  1342.       PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&other_verb);
  1343.     }
  1344.  
  1345.     /*************************************************************************/
  1346.     /* Reset write_data to point to correct point in write_array             */
  1347.     /*************************************************************************/
  1348.     write_data = write_array + WRITE_EXTRA;
  1349.   }
  1350.  
  1351.   return(ok);
  1352. }  /* do_write ()                                                            */
  1353.  
  1354.  
  1355.  
  1356. /**PROC+**********************************************************************/
  1357. /* Name:      parse_data                                                     */
  1358. /*                                                                           */
  1359. /* Purpose:   parse data from the host                                       */
  1360. /*                                                                           */
  1361. /* Returns:   void                                                           */
  1362. /*                                                                           */
  1363. /* Params:    IN  data - pointer to data                                     */
  1364. /*                                                                           */
  1365. /* Operation: Looks through data for read partition query from host.  Could  */
  1366. /* be expanded to format data from host                                      */
  1367. /*                                                                           */
  1368. /**PROC-**********************************************************************/
  1369. void parse_data (data, length)
  1370.  
  1371. UCHAR FAR * data;
  1372. USHORT      length;
  1373. {
  1374.   USHORT  field_length;
  1375.  
  1376.   switch (*(data++))
  1377.   {
  1378.     case 0xF3:                       /* write structured field               */
  1379.       /***********************************************************************/
  1380.       /* Next byte is the WCC - ignore                                       */
  1381.       /***********************************************************************/
  1382.       data++;
  1383.       length -= 2;
  1384.  
  1385.       while (length > 0)
  1386.       {
  1387.         /*********************************************************************/
  1388.         /* We're just looking for a Read Partion query                       */
  1389.         /*********************************************************************/
  1390.         field_length = (((USHORT) *data) << 8) || ((USHORT) *(data + 1));
  1391.         if ((*(data+2) == 0x01) &&   /* Read partition                       */
  1392.             (*(data+3) == 0xFF) &&   /* Query                                */
  1393.             (*(data+4) == 0x02))     /* not a list                           */
  1394.         {
  1395.           /*******************************************************************/
  1396.           /* Build an RPQ and flag it to be sent                             */
  1397.           /*******************************************************************/
  1398.           rpq_state = RPQ_QUEUED;
  1399.         }
  1400.         data   += field_length;
  1401.         length -= field_length;
  1402.       }
  1403.  
  1404.  
  1405.       break;
  1406.  
  1407.     default:
  1408.       break;
  1409.  
  1410.   }
  1411. }  /* parse_data                                                             */
  1412.  
  1413.  
  1414.  
  1415. /**PROC+**********************************************************************/
  1416. /* Name:      issue_rpq                                                      */
  1417. /*                                                                           */
  1418. /* Purpose:   issue a response to a Read partition query                     */
  1419. /*                                                                           */
  1420. /* Returns:   BOOL - TRUE => sent OK                                         */
  1421. /*                                                                           */
  1422. /* Params:    none                                                           */
  1423. /*                                                                           */
  1424. /* Operation: Builds and sends an RPQ reesponse                              */
  1425. /*                                                                           */
  1426. /**PROC-**********************************************************************/
  1427. BOOL issue_rpq (void)
  1428.  
  1429. {
  1430.   BOOL issue_rpq;
  1431.  
  1432.   issue_rpq = TRUE;
  1433.   /***************************************************************************/
  1434.   /* Set up the vcb                                                          */
  1435.   /***************************************************************************/
  1436.   memset(&rpq_verb, 0, sizeof(rpq_verb));
  1437.   rpq_verb.common.lua_verb             = LUA_VERB_SLI;
  1438.   rpq_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON) +
  1439.                          sizeof(rpq_verb.specific.lua_sequence_number);
  1440.   rpq_verb.common.lua_opcode           = LUA_OPCODE_SLI_SEND;
  1441.   rpq_verb.common.lua_sid              = sid;
  1442.   rpq_verb.common.lua_message_type     = LUA_MESSAGE_TYPE_LU_DATA;
  1443.   rpq_verb.common.lua_data_length      = RPQ_LENGTH;
  1444.   rpq_verb.common.lua_data_ptr         = (char far *) rpq_data;
  1445.   rpq_verb.common.lua_rh.dr1i          = 1;
  1446.  
  1447.   /***************************************************************************/
  1448.   /* All inbound requests flow RQD with the BBI and CDI flags set depending  */
  1449.   /* on the current session state.                                           */
  1450.   /***************************************************************************/
  1451.   rpq_verb.common.lua_rh.ri          = 1;
  1452.   if (send_state == BETB)
  1453.   {
  1454.     /*************************************************************************/
  1455.     /* Between bracket, so open bracket and give direction.  Note that we    */
  1456.     /* can do this since we will always be contention winner.                */
  1457.     /*************************************************************************/
  1458.     rpq_verb.common.lua_rh.bbi         = 1;
  1459.     rpq_verb.common.lua_rh.cdi         = 1;
  1460.     send_state = RECV;
  1461.   }
  1462.   else if (send_state = SEND)
  1463.   {
  1464.     /*************************************************************************/
  1465.     /* In bracket and we have direction, so simply give direction.           */
  1466.     /*************************************************************************/
  1467.     rpq_verb.common.lua_rh.cdi         = 1;
  1468.     send_state = RECV;
  1469.   }
  1470.   else
  1471.   {
  1472.     /*************************************************************************/
  1473.     /* In bracket and we do not have direction, so do not send.              */
  1474.     /*************************************************************************/
  1475.     issue_rpq = FALSE;
  1476.   }
  1477.  
  1478.   if (issue_rpq)
  1479.   {
  1480.     WinSLI(hWnd, (LUA_VERB_RECORD FAR *) &rpq_verb);
  1481.     if (!rpq_verb.common.lua_flag2.async)
  1482.     {
  1483.       /***********************************************************************/
  1484.       /* Verb completed immediately.  Post our own completion message        */
  1485.       /***********************************************************************/
  1486.       PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&rpq_verb);
  1487.     }
  1488.   }
  1489.  
  1490.   return(issue_rpq);
  1491. }  /* issue_rpq                                                              */
  1492.  
  1493. /**PROC+**********************************************************************/
  1494. /* Name:      add_to_display_buffer                                          */
  1495. /*                                                                           */
  1496. /* Purpose:   add data to the display buffer                                 */
  1497. /*                                                                           */
  1498. /* Returns:   void                                                           */
  1499. /*                                                                           */
  1500. /* Params:    IN data - data to be displayed                                 */
  1501. /*                                                                           */
  1502. /* Operation: Add the zero terminated data string to the circular display    */
  1503. /* buffer.  Cope with wrapping                                               */
  1504. /*                                                                           */
  1505. /**PROC-**********************************************************************/
  1506. void add_to_display_buffer (data)
  1507.  
  1508. UCHAR FAR * data;
  1509. {
  1510.   UINT data_length;         /* length of new data to display                 */
  1511.   BOOL need_to_wrap;        /* do we need to wrap to the start of the buffer */
  1512.   UINT copy_length;         /* length of data to copy                        */
  1513.  
  1514.  
  1515.   data_length = _fstrlen (data);
  1516.  
  1517.   /***************************************************************************/
  1518.   /* Work out whether the data will go over the end of the dispaly buffer.   */
  1519.   /* If it will, wrap it back over the start of the buffer.                  */
  1520.   /***************************************************************************/
  1521.   need_to_wrap = (buffer_end + data_length > DISPLAY_BUFFER_SIZE);
  1522.  
  1523.   if (need_to_wrap)
  1524.   {
  1525.     copy_length = DISPLAY_BUFFER_SIZE - buffer_end;
  1526.     wrapped = TRUE;
  1527.   }
  1528.   else
  1529.   {
  1530.     copy_length = data_length;
  1531.   }
  1532.  
  1533.   /***************************************************************************/
  1534.   /* Copy as much data as will fit into the buffer                           */
  1535.   /***************************************************************************/
  1536.   _fmemcpy ((UCHAR FAR *) (display_buffer + buffer_end),
  1537.             data,
  1538.             copy_length);
  1539.  
  1540.   /***************************************************************************/
  1541.   /* If there is more data to copy, copy it to the start of the buffer       */
  1542.   /* Set up the new end point.                                               */
  1543.   /***************************************************************************/
  1544.   if (need_to_wrap)
  1545.   {
  1546.     _fmemcpy ((UCHAR FAR *)display_buffer,
  1547.               data + copy_length,
  1548.               data_length - copy_length);
  1549.  
  1550.     buffer_end   = data_length - copy_length;
  1551.   }
  1552.   else
  1553.   {
  1554.     buffer_end   += data_length;
  1555.   }
  1556.  
  1557.   /***************************************************************************/
  1558.   /* Cause the window to be re-painted                                       */
  1559.   /***************************************************************************/
  1560.   InvalidateRect (hWnd, NULL, TRUE);
  1561.  
  1562. }  /* add_to_display_buffer                                                  */
  1563.  
  1564. 
  1565.