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 / rui3270 / wrui3270.c < prev    next >
C/C++ Source or Header  |  1997-04-09  |  75KB  |  1,565 lines

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