WRUI3270.C
/**MOD+***********************************************************************/ 
/* Module:  wrui3270.exe                                                     */ 
/*                                                                           */ 
/* Purpose: simple 3270 emulator                                             */ 
/*                                                                           */ 
/* (C) COPYRIGHT DATA CONNECTION LIMITED 1991                                */ 
/*                                                                           */ 
/**MOD-***********************************************************************/ 
 
 
/*****************************************************************************/ 
/* RUI Sample Program                                                        */ 
/*                                                                           */ 
/* (C) Copyright 1990 - 1993 Data Connection Ltd.                            */ 
/*                                                                           */ 
/* This program is a crude 3270 emulator.  It uses the RUI API to access     */ 
/* both the SSCP and LU sessions.  Outbound data from the host is            */ 
/* displayed on the screen unformatted.  Both SSCP and LU data are shown.    */ 
/* If the outbound data is an RQD request an automatic positive response     */ 
/* is sent.  Inbound data can be entered at the keyboard and is sent on      */ 
/* the current session.  This current session can be toggled between the     */ 
/* SSCP and LU sessions by hitting the [ (left square bracket) key           */ 
/* followed by <cr> (carriage return), although it switches                  */ 
/* automatically on receipt of BIND or UNBIND.                               */ 
/*                                                                           */ 
/* The program is invoked with a single parameter - the name of the LUA LU   */ 
/* to use.  This is converted to upper case and must match an LUA LU in      */ 
/* the configuration file.  This LU should be configured for a 327? on the   */ 
/* host.                                                                     */ 
/*                                                                           */ 
/* It works reasonably well with TSO provided that complex formatted         */ 
/* logon screens are not used.                                               */ 
/*                                                                           */ 
/*                                                                           */ 
/* The CSV CONVERT function is used to convert data between ASCII and        */ 
/* EBCDIC.  This uses the type G conversion table, so the environment        */ 
/* variable COMTBLG must be set to point to a suitable file.                 */ 
/*                                                                           */ 
/* Keys that work are:                                                       */ 
/*                                                                           */ 
/*     Alt-1 to Alt-0 are PF1 to PF0                                         */ 
/*     backspace                                                             */ 
/*     Letters, numbers and symbols                                          */ 
/*                                                                           */ 
/*****************************************************************************/ 
 
 
/*****************************************************************************/ 
/* SYSTEM INCLUDES                                                           */ 
/*****************************************************************************/ 
#include <windows.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <winlua.h> 
#include <wincsv.h> 
 
typedef unsigned char  UCHAR; 
typedef unsigned short USHORT; 
typedef unsigned long  ULONG; 
 
 
/*****************************************************************************/ 
/* Program constants                                                         */ 
/*****************************************************************************/ 
#define DATASIZE 4096                  /* Max size of RU                     */ 
#define SWITKEY  0x5B                  /* '['   to switch sessions           */ 
 
#define BETB     1                     /* Between brackets                   */ 
#define SEND     2                     /* In bracket and can send            */ 
#define RECV     3                     /* In bracket, but cannot send        */ 
 
#define APPNAME                "WRUI3270" 
#define RUI_WINDOW_MESSAGE     "WinRUI" 
 
#define DISPLAY_BUFFER_SIZE    3200    /* size of circular display buffer    */ 
 
/*****************************************************************************/ 
/* State variables                                                           */ 
/*                                                                           */ 
/* We can only have one read or write verb outstanding per flow.  These      */ 
/* state variables keep track of these verbs and what we need to do with     */ 
/* them.                                                                     */ 
/*****************************************************************************/ 
 
UINT  write_state; 
#define NO_WRITE              1 
#define WRITE_OUTSTANDING     2        /* waiting for write to complete      */ 
#define WRITE_QUEUED          3        /* have data to write                 */ 
 
UINT  read_state; 
#define NO_READ               1 
#define READ_OUTSTANDING      2        /* read verb outstanding              */ 
#define RSP_QUEUED            3        /* have a response to write           */ 
#define RSP_OUTSTANDING       4        /* waiting for a response to complete */ 
 
UINT  rpq_state; 
#define NO_RPQ                1 
#define RPQ_OUTSTANDING       2        /* waiting for an RPQ to complete     */ 
#define RPQ_QUEUED            3        /* have RPQ to send                   */ 
 
/***************************************************************************/ 
/* Global variables                                                        */ 
/*                                                                         */ 
/* Inbound data is sent as typed on the SSCP session.  On the LU session   */ 
/* it is prefixed with the <enter> key AID plus a two byte cursor address. */ 
/***************************************************************************/ 
LUA_VERB_RECORD read_verb;             /* RUI read verb                    */ 
LUA_VERB_RECORD other_verb;            /* RUI init, write or term verb     */ 
LUA_VERB_RECORD rpq_verb;              /* RUI_WRITE for RPQs               */ 
 
UCHAR rpq_data[] = { 
 
  0x88, 
  0x00, 0x0C, 0x81, 0x80, 0x80, 0x81, 0x85, 0x86, 0x87, 0x88, 0x95, 0xA6, 
 
  0x00, 0x17, 0x81, 0x81, 0x21, 0x00, 0x00, 0x50, 0x00, 0x18, 0x00, 0x00, 
  0x0A, 0x02, 0xE5, 0x00, 0x02, 0x00, 0x6F, 0x09, 0x10, 0x07, 0x80, 
 
  0x00, 0x14, 0x81, 0x85, 0x02, 0x00, 0x09, 0x0E, 0x00, 0x00, 0x00, 0x00, 
  0x07, 0x00, 0x00, 0x00, 0x02, 0xB9, 0x01, 0x1D, 
 
  0x00, 0x16, 0x81, 0x86, 0x00, 0x08, 0x00, 0xF4, 0xF1, 0x00, 0xF2, 0x00, 
  0xF3, 0x00, 0xF4, 0x00, 0xF5, 0x00, 0xF6, 0x00, 0xF7, 0x00, 
 
  0x00, 0x0D, 0x81, 0x87, 0x04, 0x00, 0xF0, 0xF1, 0x00, 0xF2, 0x00, 0xF4, 
  0x00, 
 
  0x00, 0x07, 0x81, 0x88, 0x00, 0x01, 0x02, 
 
  0x00, 0x0C, 0x81, 0x95, 0x00, 0x00, 0x7F, 0xFF, 0x7F, 0xFF, 0x01, 0x01, 
 
  0x00, 0x11, 0x81, 0xA6, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x50, 0x00, 
  0x18, 0x00, 0x50, 0x00, 0x18}; 
 
#define RPQ_LENGTH (sizeof(rpq_data)) 
 
UCHAR display_buffer[DISPLAY_BUFFER_SIZE] = {0}; 
UINT  buffer_end   = 0;             /* end of data in display buffer         */ 
BOOL  wrapped      = FALSE;         /* has buffer wrapped?                   */ 
 
 
/*****************************************************************************/ 
/* Global Variables                                                          */ 
/*****************************************************************************/ 
HANDLE hInst = 0;                   /* current instance                      */ 
UINT   verb_complete = 0;           /* verb completion message               */ 
HANDLE hWnd = 0;                    /* Handle to program window              */ 
 
BOOL   init_done = FALSE;           /* RUI_INIT completed                    */ 
 
 
 
unsigned char read_data[DATASIZE];     /* Outbound RU                       */ 
#define WRITE_EXTRA 6 
unsigned char write_array[DATASIZE + WRITE_EXTRA] = 
                                          {0x7d, 0x40, 0x40, 0x11, 0x40, 0x40}; 
                                       /* Inbound RU                         */ 
unsigned char *write_data = write_array + WRITE_EXTRA; 
                                       /* Pointer to inbound RU              */ 
UINT data_offset = 0;                  /* offset into read_data              */ 
UINT write_len   = 0;                  /* length of write data               */ 
 
struct convert convert_to_asc;         /* Outbound convert verb              */ 
struct convert convert_to_ebc;         /* Inbound convert verb               */ 
 
BOOL terminating = FALSE;              /* are we already in closedown() ?    */ 
BOOL lu_session  = FALSE;              /* LU session inbound flag            */ 
 
unsigned long sense = 0l;              /* sense code                         */ 
 
unsigned char lu_name[9] = "        "; /* LU name                            */ 
unsigned long sid;                     /* RUI session ID                     */ 
int send_state = BETB;                 /* LU session send state              */ 
int last_status = WLUAGETLU;           /* Current status of Session     *STAT*/ 
 
UCHAR  string[64]={0}; 
 
 
 
 
void pascal far LOADDS RUI (LUA_VERB_RECORD FAR *); 
 
extern int      WINAPI GetFmiReturnCode(unsigned short,                /*STAT*/ 
                                        unsigned short,                /*STAT*/ 
                                        unsigned short,                /*STAT*/ 
                                        unsigned char FAR *);          /*STAT*/ 
 
void            csv_init            (void); 
void            issue_init          (void); 
void            issue_read          (void); 
void            other_done          (LUA_VERB_RECORD FAR *verb); 
void            read_done           (LUA_VERB_RECORD FAR *verb); 
void            issue_rsp           (unsigned long  sense); 
void            rsp_done            (LUA_VERB_RECORD FAR *verb); 
void            closedown           (void); 
BOOL            do_write            (void); 
void            wait_verb_complete  (LUA_VERB_RECORD FAR *verb); 
void            set_semaphore       (LUA_VERB_RECORD FAR *verb); 
BOOL            do_keyboard_stuff   (UINT, UCHAR); 
BOOL            check_verb_complete (LUA_VERB_RECORD FAR *verb); 
void            parse_data          (UCHAR FAR *, USHORT); 
BOOL            issue_rpq           (void); 
void            verb_complete_proc  (LUA_VERB_RECORD FAR * verb); 
void          add_to_display_buffer (UCHAR FAR *); 
 
/*****************************************************************************/ 
/* Windows function prototypes.                                              */ 
/*****************************************************************************/ 
int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int); 
long FAR PASCAL WndProc(HWND, UINT, UINT, LONG); 
 
 
 
 
/***PROC+*********************************************************************/ 
/* Name:     WinMain                                                         */ 
/*                                                                           */ 
/* Purpose:  Main Windows function                                           */ 
/*                                                                           */ 
/* Params:   IN current instance handle                                      */ 
/*           IN previous instance handle                                     */ 
/*           IN pointer to command line                                      */ 
/*           IN show window type                                             */ 
/*                                                                           */ 
/* Returns:  int                                                             */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
 
int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow) 
 
HINSTANCE hInstance;                         /* current instance             */ 
HINSTANCE hPrevInstance;                     /* previous instance            */ 
LPSTR     lpCmdLine;                         /* command line                 */ 
int       nCmdShow;                          /* show-window type (open/icon) */ 
{ 
  /***************************************************************************/ 
  /* LOCAL VARIABLES                                                         */ 
  /***************************************************************************/ 
  MSG   msg;                                 /* message                      */ 
  int   xscreen; 
  int   yscreen; 
  int   delta; 
  WNDCLASS class; 
  LUADATA  LUAData; 
 
 
  if (!hPrevInstance) 
  { 
    class.style         = CS_HREDRAW | CS_VREDRAW; 
    class.lpfnWndProc   = (WNDPROC)WndProc; 
    class.cbClsExtra    = 0; 
    class.cbWndExtra    = 0; 
    class.hInstance     = hInstance; 
    class.hIcon         = LoadIcon(NULL, IDI_APPLICATION); 
    class.hCursor       = LoadCursor(NULL, IDC_ARROW); 
    class.hbrBackground = GetStockObject(WHITE_BRUSH); 
    class.lpszMenuName  = NULL; 
    class.lpszClassName = APPNAME; 
 
    if (!RegisterClass(&class)) 
    { 
      return (0); 
    } 
  } 
 
  /***************************************************************************/ 
  /* save current instance handle                                            */ 
  /***************************************************************************/ 
  hInst = hInstance; 
 
  /***************************************************************************/ 
  /* Set initial states                                                      */ 
  /***************************************************************************/ 
  write_state = NO_WRITE; 
  read_state  = NO_READ; 
  rpq_state   = NO_RPQ; 
 
  /***************************************************************************/ 
  /* Set up CSV convert verbs                                                */ 
  /***************************************************************************/ 
  csv_init(); 
 
  /***************************************************************************/ 
  /* get details of display                                                  */ 
  /***************************************************************************/ 
  xscreen = GetSystemMetrics(SM_CXSCREEN); 
  yscreen = GetSystemMetrics(SM_CYSCREEN); 
 
  /***************************************************************************/ 
  /* invent somewhere to put window                                          */ 
  /***************************************************************************/ 
  delta = xscreen / 100; 
 
  /***************************************************************************/ 
  /* create display window                                                   */ 
  /***************************************************************************/ 
  hWnd = CreateWindow(APPNAME,                    /* window class            */ 
        "RUI3270",                                /* window name             */ 
        WS_OVERLAPPEDWINDOW,                      /* window style            */ 
        (xscreen/2) + delta,                      /* x position              */ 
        yscreen / 8,                              /* y position              */ 
        (xscreen / 2) - (delta * 2),              /* width                   */ 
        3 * yscreen / 4,                          /* height                  */ 
        NULL,                                     /* parent handle           */ 
        NULL,                                     /* menu or child ID        */ 
        hInstance,                                /* instance                */ 
        NULL);                                    /* additional info         */ 
 
  if (!hWnd) 
  { 
    return (0); 
  } 
 
  ShowWindow(hWnd, nCmdShow);                     /* Shows the window        */ 
  UpdateWindow(hWnd);                             /* Sends WM_PAINT message  */ 
 
 
  /***************************************************************************/ 
  /* Register message used for async completion                              */ 
  /***************************************************************************/ 
  verb_complete = RegisterWindowMessage(RUI_WINDOW_MESSAGE); 
 
  if (verb_complete == 0) 
  { 
    return (0); 
  } 
 
  WinRUIStartup (0x0001, &LUAData); 
 
  /***************************************************************************/ 
  /* Issue RUI_INIT to get the ball rolling.  Setup up the LU name           */ 
  /***************************************************************************/ 
  _fmemcpy ((UCHAR FAR *)lu_name, 
            lpCmdLine, 
            _fstrlen(lpCmdLine)); 
  issue_init (); 
 
  while(GetMessage(&msg,NULL,0,0)) 
  { 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
  } 
 
  return msg.wParam;         /* save exit parameter for return               */ 
} 
 
/***PROC+*********************************************************************/ 
/* Name:     WndProc                                                         */ 
/*                                                                           */ 
/* Purpose:  Windows call-back routine                                       */ 
/*                                                                           */ 
/* Params:   IN window handle                                                */ 
/*           IN message type                                                 */ 
/*           IN additional information 1                                     */ 
/*           IN additional information 2                                     */ 
/*                                                                           */ 
/* Returns:  long                                                            */ 
/*                                                                           */ 
/* Operation:set up window characteristics and register it                   */ 
/*           return success or failure                                       */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
 
long FAR PASCAL WndProc(hWnd, message, wParam, lParam) 
HWND hWnd;                                /* window handle                   */ 
UINT message;                             /* type of message                 */ 
UINT wParam;                              /* additional information          */ 
LONG lParam;                              /* additional information          */ 
{ 
  /***************************************************************************/ 
  /* LOCAL VARIABLES                                                         */ 
  /***************************************************************************/ 
  HDC          hDC;              /* handle to our device context             */ 
  TEXTMETRIC   tm;               /* holds info on the current font           */ 
  PAINTSTRUCT  ps;               /*  paint structure                         */ 
  RECT         rc;               /* holds info on the size oof our window    */ 
  ULONG        width;            /* width of window in chars                 */ 
  ULONG        height;           /* height of window in chars                */ 
  UINT         buffer_offset;    /* offset withing display buffer            */ 
  UINT         buffer_length;    /* length of data in buffer                 */ 
  UINT         out_length;       /* lngth of text to output                  */ 
  UINT         out_length2;      /* and again                                */ 
  static int   xChar, yChar;     /* width & height of the average char       */ 
  int          position;         /* number of lines down the screen          */ 
  BOOL         whole_data;       /* do we have data to send?                 */ 
  char         status_buff[80];  /* Current status                      *STAT*/ 
 
  if ((message == verb_complete) && 
      (!terminating)) 
  { 
    /*************************************************************************/ 
    /* Message is RUI verb completed.  We are not terminating, so process    */ 
    /* the message.                                                          */ 
    /*************************************************************************/ 
    if (wParam == 0)                                                   /*STAT*/ 
    {                                                                  /*STAT*/ 
      verb_complete_proc ((LUA_VERB_RECORD FAR *) lParam); 
    }                                                                  /*STAT*/ 
    else                                                               /*STAT*/ 
    {                                                                  /*STAT*/ 
      /***********************************************************************/ 
      /* Message is Notification of LUA Session State Change            *STAT*/ 
      /***********************************************************************/ 
      last_status = WinRUIGetLastInitStatus(lParam,                    /*STAT*/ 
                                            NULL,                      /*STAT*/ 
                                            WLUA_NTFY_MSG_SID,         /*STAT*/ 
                                            0);                        /*STAT*/ 
      /******************************************************************STAT*/ 
      /* Cause the window to be re-painted                              *STAT*/ 
      /******************************************************************STAT*/ 
      InvalidateRect (hWnd, NULL, TRUE);                               /*STAT*/ 
    }                                                                  /*STAT*/ 
    return(0l); 
  } 
 
  switch (message) 
  { 
    case WM_CREATE: 
      /***********************************************************************/ 
      /* Window creation message.  Get some infomation about our font and    */ 
      /* save it for later                                                   */ 
      /***********************************************************************/ 
      hDC= GetDC(hWnd); 
      GetTextMetrics (hDC, &tm); 
      xChar = (int)tm.tmAveCharWidth; 
      yChar = (int)(tm.tmHeight + tm.tmExternalLeading); 
      ReleaseDC(hWnd, hDC); 
      return 0l; 
      break; 
 
    case WM_CHAR: 
    case WM_SYSCHAR: 
      /***********************************************************************/ 
      /* Character or Alt+char hit                                           */ 
      /***********************************************************************/ 
      if ((init_done)                 && 
          (!terminating)              && 
          (write_state == NO_WRITE)   && 
          (rpq_state   == NO_RPQ)     && 
          (read_state  != RSP_QUEUED) && 
          (read_state  != RSP_OUTSTANDING)) 
      { 
        /*********************************************************************/ 
        /* Someone pressed a key and we are in a state to deal with it       */ 
        /*********************************************************************/ 
        whole_data = do_keyboard_stuff (message, (UCHAR)wParam); 
        if (whole_data) 
        { 
          /*******************************************************************/ 
          /* We have data to send                                            */ 
          /* Attempt to write the data out                                   */ 
          /*******************************************************************/ 
          if (do_write()) 
          { 
            write_state = WRITE_OUTSTANDING; 
          } 
          else 
          { 
            write_state = WRITE_QUEUED; 
          } 
        } 
        return(0l); 
      } 
      break; 
 
    case WM_PAINT: 
      BeginPaint (hWnd, &ps); 
      /***********************************************************************/ 
      /* Determine the size of the Window in characters                      */ 
      /***********************************************************************/ 
      GetClientRect (hWnd, &rc); 
      height = rc.bottom / yChar; 
      width  = rc.right  / xChar; 
      /***********************************************************************/ 
      /* subtract 2 from height for the status line                          */ 
      /***********************************************************************/ 
      height -= 2; 
      /***********************************************************************/ 
      /* Work out how early in the buffer we can start                       */ 
      /***********************************************************************/ 
      if (!wrapped) 
      { 
        /*********************************************************************/ 
        /* buffer is not wrapped                                             */ 
        /*********************************************************************/ 
        buffer_length = buffer_end; 
        buffer_offset = (buffer_length > (width * height)) ? 
                         buffer_end - (width * height) : 
                         0; 
      } 
      else 
      { 
        /*********************************************************************/ 
        /* buffer is wrapped                                                 */ 
        /*********************************************************************/ 
        buffer_length = DISPLAY_BUFFER_SIZE; 
        if (buffer_length > width * height) 
        { 
          /*******************************************************************/ 
          /* buffer is too big.  Work out where best to start in the buffer/ */ 
          /*******************************************************************/ 
          if (buffer_end > width * height) 
          { 
            buffer_offset = buffer_end - (width * height); 
          } 
          else 
          { 
            buffer_offset = DISPLAY_BUFFER_SIZE + 
                            buffer_end - 
                            (width * height); 
          } 
        } 
        else 
        { 
          /*******************************************************************/ 
          /* We can fit everything in                                        */ 
          /*******************************************************************/ 
          buffer_offset = buffer_end; 
        } 
      } 
      /***********************************************************************/ 
      /* We've worked out where to start printing from, so start printing    */ 
      /***********************************************************************/ 
      position = 0; 
      out_length = width; 
      if (buffer_offset > buffer_end) 
      { 
        while (buffer_offset < DISPLAY_BUFFER_SIZE) 
        { 
          if (DISPLAY_BUFFER_SIZE - buffer_offset < width) 
          { 
            out_length = DISPLAY_BUFFER_SIZE - buffer_offset; 
          } 
          else 
          { 
            out_length = width; 
          } 
          TextOut(ps.hdc, 
                  0, 
                  yChar * position, 
                  display_buffer + buffer_offset, 
                  out_length); 
          buffer_offset += out_length; 
          position++; 
        } 
        buffer_offset = 0; 
      } 
      /***********************************************************************/ 
      /* If last line printed was a partial line, print the rest of the line */ 
      /***********************************************************************/ 
      if (out_length < width) 
      { 
        out_length2 = out_length; 
        if (buffer_end < (width - out_length)) 
        { 
          out_length = buffer_end; 
        } 
        else 
        { 
          out_length = width - out_length; 
        } 
        TextOut(ps.hdc, 
                xChar * out_length2, 
                yChar * (position - 1), 
                display_buffer, 
                out_length); 
        buffer_offset += out_length; 
 
      } 
      /***********************************************************************/ 
      /* Now print to the end of the buffer                                  */ 
      /***********************************************************************/ 
      while (buffer_offset < buffer_end) 
      { 
        if (buffer_end - buffer_offset < width) 
        { 
          out_length = buffer_end - buffer_offset; 
        } 
        else 
        { 
          out_length = width; 
        } 
        TextOut(ps.hdc, 
                0, 
                yChar * position, 
                display_buffer + buffer_offset, 
                out_length); 
        buffer_offset += out_length; 
        position++; 
      } 
 
      /******************************************************************STAT*/ 
      /* Convert current status into display string                     *STAT*/ 
      /******************************************************************STAT*/ 
      GetFmiReturnCode(last_status,                                    /*STAT*/ 
                       (unsigned short) 0xffff,                        /*STAT*/ 
                       (unsigned short) 80, status_buff);              /*STAT*/ 
 
      /***********************************************************************/ 
/* Now fill in the status line                                         */ 
      /***********************************************************************/ 
      out_length  = wsprintf (string, 
                              "%s     %s     %s",                      /*STAT*/ 
                   (UCHAR FAR *)((send_state == BETB) ? "BETB" : "INB"), 
                   (UCHAR FAR *)((lu_session)         ? "LU"   : "SSCP"), 
                   (UCHAR FAR *)status_buff);                         /*STAT*/ 
      TextOut(ps.hdc, 
              0, 
              (UINT) (yChar * (height + 2)), 
              string, 
              out_length); 
      /***********************************************************************/ 
      /* Now write the input line.  Only in NO_WRITE state, o.w.  data is in */ 
      /* EBCDIC                                                              */ 
      /***********************************************************************/ 
      if (write_state == NO_WRITE) 
      { 
        TextOut(ps.hdc, 
                0, 
                (UINT) (yChar * (height+1)), 
                write_data, 
                data_offset); 
      } 
      EndPaint(hWnd, &ps); 
      break; 
 
    case WM_CLOSE: 
      if (!terminating) 
      { 
        /*********************************************************************/ 
        /* Tell the RUI we are going                                         */ 
        /*********************************************************************/ 
        terminating = TRUE; 
        WinRUICleanup(); 
      } 
      break; 
 
    case WM_DESTROY: 
      PostQuitMessage(0); 
      return 0l; 
      break; 
 
    default: 
      break; 
  } 
  return (DefWindowProc(hWnd, message, wParam, lParam)); 
} 
 
/**PROC+**********************************************************************/ 
/* Name:      verb_complete_proc                                             */ 
/*                                                                           */ 
/* Purpose:   deal with verb completion                                      */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    IN verb - pointer to completed verb                            */ 
/*                                                                           */ 
/* Operation: Determine which verb has completed and perform the appropriate */ 
/* action                                                                    */ 
/**PROC-**********************************************************************/ 
VOID verb_complete_proc (verb) 
 
LUA_VERB_RECORD FAR * verb; 
{ 
 
  switch (verb->common.lua_opcode) 
  { 
    case LUA_OPCODE_RUI_INIT: 
      /***********************************************************************/ 
      /* Received ACTLU.  Save the SID for use on other verbs, flag init     */ 
      /* done so that we can write data, and issue first read                */ 
      /***********************************************************************/ 
      sid = other_verb.common.lua_sid; 
      init_done = TRUE; 
      issue_read(); 
      break; 
 
    case LUA_OPCODE_RUI_READ: 
      /***********************************************************************/ 
      /* Read completed.  Call read dne processor to display data and        */ 
      /* determine if a response is required.                                */ 
      /* If no response is required issue a new read                         */ 
      /* if a response is required issue the response if we can              */ 
      /***********************************************************************/ 
      read_done (verb); 
      if (terminating == TRUE) 
        break; 
      if (read_state == NO_READ) 
      { 
        /*********************************************************************/ 
        /* No work to do, issue a new read verb                              */ 
        /*********************************************************************/ 
        read_state = READ_OUTSTANDING; 
        issue_read(); 
      } 
      else if ((read_state  == RSP_QUEUED) && 
               (write_state != WRITE_OUTSTANDING) && 
               (rpq_state   != RPQ_OUTSTANDING)) 
      { 
        /*********************************************************************/ 
        /* We need to send a response to the RU we have just received.  The  */ 
        /* write flow is free, so send it                                    */ 
        /*********************************************************************/ 
        read_state = RSP_OUTSTANDING; 
        issue_rsp (sense); 
      } 
 
      if ((rpq_state   == RPQ_QUEUED) && 
          (write_state != WRITE_OUTSTANDING) && 
          (read_state  != RSP_OUTSTANDING)) 
      { 
        /*********************************************************************/ 
        /* We need to send a read partition query response and we can, so do */ 
        /* it.                                                               */ 
        /*********************************************************************/ 
        if (issue_rpq()) 
        { 
          rpq_state = RPQ_OUTSTANDING; 
        } 
      } 
      break; 
 
    case LUA_OPCODE_RUI_WRITE: 
      /***********************************************************************/ 
      /* Determine what kind of RUI_WRITE completed                          */ 
      /* either                                                              */ 
      /* -  writing user data                                                */ 
      /* -  writing a RPQ response                                           */ 
      /* -  writing a RSP to host data                                       */ 
      /***********************************************************************/ 
      if (write_state == WRITE_OUTSTANDING) 
      { 
        write_state = NO_WRITE; 
        write_data[0] = '\0'; 
      } 
      else if (rpq_state == RPQ_OUTSTANDING) 
      { 
        rpq_state = NO_RPQ; 
      } 
      else if (read_state == RSP_OUTSTANDING) 
      { 
        read_state = NO_READ; 
        issue_read(); 
      } 
      /***********************************************************************/ 
      /* Perform the next action depending on what work their is to do.      */ 
      /***********************************************************************/ 
      if (read_state == RSP_QUEUED) 
      { 
        /*********************************************************************/ 
        /* We need to issue a RSP to an RU we have received.  Do it          */ 
        /*********************************************************************/ 
        read_state = RSP_OUTSTANDING; 
        issue_rsp (sense); 
      } 
      else if (rpq_state == RPQ_QUEUED) 
      { 
        /*********************************************************************/ 
        /* We need to issue a response to a read partion query.  Send it if  */ 
        /* the bracket state allows.                                         */ 
        /*********************************************************************/ 
        if (issue_rpq()) 
        { 
          rpq_state = RPQ_OUTSTANDING; 
        } 
      } 
      else if (write_state == WRITE_QUEUED) 
      { 
        /*********************************************************************/ 
        /* We have user data to send to the Host.  Send it if the bracket    */ 
        /* state allows                                                      */ 
        /*********************************************************************/ 
        if (do_write()) 
        { 
          write_state = WRITE_OUTSTANDING; 
        } 
      } 
      break; 
 
    default: 
      break; 
  } 
}  /* verb_complete_proc                                                     */ 
 
/**PROC+**********************************************************************/ 
/* Name:      csv_init                                                       */ 
/*                                                                           */ 
/* Purpose:   set up CSV convert verbs                                       */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    none                                                           */ 
/*                                                                           */ 
/* Operation: sets uup two CSV convert verbs, one in each direction.  Only   */ 
/* the length needs to be set when the verb is called                        */ 
/**PROC-**********************************************************************/ 
void csv_init (void) 
{ 
  convert_to_asc.opcode       = SV_CONVERT; 
  convert_to_asc.direction    = SV_EBCDIC_TO_ASCII; 
  convert_to_asc.char_set     = SV_G; 
  convert_to_asc.source       = read_data; 
  convert_to_asc.target       = read_data; 
 
  convert_to_ebc.opcode       = SV_CONVERT; 
  convert_to_ebc.direction    = SV_ASCII_TO_EBCDIC; 
  convert_to_ebc.char_set     = SV_G; 
  convert_to_ebc.source       = write_data; 
  convert_to_ebc.target       = write_data; 
}  /* csv_init                                                               */ 
 
 
/**PROC+**********************************************************************/ 
/* Name:      issue_init                                                     */ 
/*                                                                           */ 
/* Purpose:   build a verb and send it                                       */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    None                                                           */ 
/*                                                                           */ 
/* Operation: Build an INIT verb and issue it.                               */ 
/**PROC-**********************************************************************/ 
void issue_init(void) 
{ 
  memset(&other_verb, 0, sizeof(other_verb)); 
  other_verb.common.lua_verb             = LUA_VERB_RUI; 
  other_verb.common.lua_verb_length      = sizeof(other_verb); 
  other_verb.common.lua_opcode           = LUA_OPCODE_RUI_INIT; 
  memcpy(other_verb.common.lua_luname, lu_name, 8); 
 
  WinRUI(hWnd, (LUA_VERB_RECORD FAR *) &other_verb); 
 
  /***************************************************************************/ 
  /* The sid is valid immediately.  Save it now.                             */ 
  /***************************************************************************/ 
  sid = other_verb.common.lua_sid; 
 
  last_status = WinRUIGetLastInitStatus(0, hWnd, WLUA_NTFY_MSG_SID, 0);/*STAT*/ 
 
  if (!other_verb.common.lua_flag2.async) 
  { 
    /*************************************************************************/ 
    /* Verb completed immediately.  Post our own completion message          */ 
    /*************************************************************************/ 
    PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&other_verb); 
  } 
 
}  /* issue_init                                                             */ 
 
 
/**PROC+**********************************************************************/ 
/* Name:      issue_read                                                     */ 
/*                                                                           */ 
/* Purpose:   build a read verb and send it                                  */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    none                                                           */ 
/*                                                                           */ 
/* Operation: Build a read verb for all flows and issue it                   */ 
/**PROC-**********************************************************************/ 
void issue_read (void) 
{ 
  memset(&read_verb, 0, sizeof(read_verb)); 
  memset(read_data, 0, DATASIZE); 
  read_verb.common.lua_verb             = LUA_VERB_RUI; 
  read_verb.common.lua_verb_length      = sizeof(read_verb); 
  read_verb.common.lua_opcode           = LUA_OPCODE_RUI_READ; 
  read_verb.common.lua_sid              = sid; 
  read_verb.common.lua_max_length       = DATASIZE; 
  read_verb.common.lua_data_ptr         = (char FAR *) read_data; 
  read_verb.common.lua_flag1.lu_norm    = 1; 
  read_verb.common.lua_flag1.lu_exp     = 1; 
  read_verb.common.lua_flag1.sscp_norm  = 1; 
  read_verb.common.lua_flag1.sscp_exp   = 1; 
  WinRUI(hWnd, (LUA_VERB_RECORD FAR *)&(read_verb)); 
  if (!read_verb.common.lua_flag2.async) 
  { 
    /*************************************************************************/ 
    /* Verb completed immediately.  Post our own completion message          */ 
    /*************************************************************************/ 
    PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&read_verb); 
  } 
 
}  /* issue_read                                                             */ 
 
 
 
 
/**PROC+**********************************************************************/ 
/* Name:      read_done                                                      */ 
/*                                                                           */ 
/* Purpose:   handle completed read verb                                     */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    IN verb - completed read verb                                  */ 
/*                                                                           */ 
/* Operation: If the completed verb contains data, first parse it and then   */ 
/*            display it.                                                    */ 
/*            If message is a BIND or an UNBIND, set the LU-LU session state */ 
/*            accordingly                                                    */ 
/*            Also check for EB, CD and change session state flags           */ 
/**PROC-**********************************************************************/ 
void read_done(verb) 
LUA_VERB_RECORD FAR * verb; 
{ 
  BOOL           rsp_required = FALSE; /* is a resonse required              */ 
 
  sense = 0l; 
 
  if (verb->common.lua_prim_rc == LUA_OK) 
  { 
    if ((verb->common.lua_message_type == LUA_MESSAGE_TYPE_LU_DATA)   || 
        (verb->common.lua_message_type == LUA_MESSAGE_TYPE_SSCP_DATA)) 
    { 
      if (verb->common.lua_data_length > 0) 
      { 
        /*********************************************************************/ 
        /* We now have to parse the data.  For the moment we only look for   */ 
        /* RPQ requests.                                                     */ 
        /*********************************************************************/ 
        parse_data (read_data, (USHORT) (verb->common.lua_data_length)); 
 
        /*********************************************************************/ 
        /* Display outbound SSCP or LU data.                                 */ 
        /*********************************************************************/ 
        convert_to_asc.len = (unsigned short) verb->common.lua_data_length; 
        ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_asc)); 
        add_to_display_buffer (read_data); 
      } 
 
      /***********************************************************************/ 
      /* Set session state.                                                  */ 
      /***********************************************************************/ 
      if (verb->common.lua_rh.ebi) 
      { 
        send_state = BETB; 
      } 
      else if (verb->common.lua_rh.cdi) 
      { 
        send_state = SEND; 
      } 
      else 
      { 
        send_state = RECV; 
      } 
      InvalidateRect (hWnd, NULL, TRUE); 
    } 
    /*************************************************************************/ 
    /* Handle BIND or UNBIND as a special case.                              */ 
    /*************************************************************************/ 
    else if (verb->common.lua_message_type == LUA_MESSAGE_TYPE_BIND) 
    { 
      if (((read_data[6] & 0x20) == 0x20)  &&      /* Brackets used and BETB */ 
          ((read_data[7] & 0xF0) == 0x80)  &&      /* HDX-FF, sec con winner */ 
          ( read_data[14]        == 0x02))         /* LU type 2              */ 
      { 
        InvalidateRect (hWnd, NULL, TRUE); 
        send_state = BETB; 
        lu_session = TRUE; 
      } 
      else 
      { 
        sense = LUA_INVALID_SESSION_PARAMETERS; 
      } 
    } 
    else if (verb->common.lua_message_type == LUA_MESSAGE_TYPE_UNBIND) 
    { 
      send_state = BETB; 
      lu_session = FALSE; 
      InvalidateRect (hWnd, NULL, TRUE); 
    } 
 
    /*************************************************************************/ 
    /* Respond to any RQD request.                                           */ 
    /*************************************************************************/ 
    if ((verb->common.lua_message_type != LUA_MESSAGE_TYPE_RSP)  && 
        (verb->common.lua_rh.ri == 0))                  /* definite response */ 
    { 
      rsp_required = TRUE; 
    } 
  } 
  else         /* primary rc not OK - read failed - stop now */ 
  { 
    closedown(); 
  } 
 
  /***************************************************************************/ 
  /* Continue processing with either another read or a write positive rsp.   */ 
  /* (The callback from issuing response will then issue another read) If    */ 
  /* we've already gone into closedown, stop here                            */ 
  /***************************************************************************/ 
  if (!terminating) 
  { 
    if (rsp_required) 
    { 
      read_state = RSP_QUEUED; 
    } 
    else 
    { 
      read_state = NO_READ; 
    } 
  } 
}  /* read_done                                                              */ 
 
 
/**PROC+**********************************************************************/ 
/* Name:      issue_rsp                                                      */ 
/*                                                                           */ 
/* Purpose:   issue a response for a request from the host                   */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    IN sense - sense code for the response                         */ 
/*                                                                           */ 
/* Operation: Build a response and write it out.  Uses the read verb control */ 
/*            block because it has the necessary information.                */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
void issue_rsp(sense) 
unsigned long sense; 
{ 
  read_verb.common.lua_opcode           = LUA_OPCODE_RUI_WRITE; 
  read_verb.common.lua_max_length       = 0; 
  read_verb.common.lua_rh.rri           = 1;       /* response             */ 
  read_verb.common.lua_flag1.lu_norm    = 0; 
  read_verb.common.lua_flag1.lu_exp     = 0; 
  read_verb.common.lua_flag1.sscp_norm  = 0; 
  read_verb.common.lua_flag1.sscp_exp   = 0; 
 
  /***************************************************************************/ 
  /* If we have been given a sense code this must be a negative response     */ 
  /***************************************************************************/ 
  if (sense) 
  { 
    read_verb.common.lua_data_length      = 4; 
    memcpy(read_data, &sense, 4); 
    read_verb.common.lua_rh.ri            = 1;       /* negative rsp         */ 
  } 
  else 
  { 
    read_verb.common.lua_data_length      = 0; 
    read_verb.common.lua_rh.ri            = 0;       /* positive rsp         */ 
  } 
  /***************************************************************************/ 
  /* Send the response back on the flow from which the request came          */ 
  /***************************************************************************/ 
  if (read_verb.common.lua_flag2.lu_norm) 
  { 
    read_verb.common.lua_flag1.lu_norm = 1; 
  } 
  else if (read_verb.common.lua_flag2.lu_exp) 
  { 
    read_verb.common.lua_flag1.lu_exp = 1; 
  } 
  else if (read_verb.common.lua_flag2.sscp_norm) 
  { 
    read_verb.common.lua_flag1.sscp_norm = 1; 
  } 
  else if (read_verb.common.lua_flag2.sscp_exp) 
  { 
    read_verb.common.lua_flag1.sscp_exp = 1; 
  } 
  /***************************************************************************/ 
  /* Send out the verb                                                       */ 
  /***************************************************************************/ 
  WinRUI(hWnd, (LUA_VERB_RECORD FAR *)&read_verb);     /* write the response */ 
  if (!read_verb.common.lua_flag2.async) 
  { 
    /*************************************************************************/ 
    /* Verb completed immediately.  Post our own completion message          */ 
    /*************************************************************************/ 
    PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&read_verb); 
  } 
}  /* issue_rsp                                                              */ 
 
 
/**PROC+**********************************************************************/ 
/* Name:      rsp_done                                                       */ 
/*                                                                           */ 
/* Purpose:   handle completion of RUI_WRITE, when RUI_WRITE has written a   */ 
/*            response                                                       */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    IN verb - completed verb                                       */ 
/*                                                                           */ 
/* Operation: If verb did not complete OK terminate                          */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
void rsp_done (verb) 
LUA_VERB_RECORD FAR * verb; 
{ 
  if (verb->common.lua_prim_rc != LUA_OK)   /* failed to write the response */ 
  {                                         /* so stop here                 */ 
    closedown(); 
  } 
}  /* rsp_done                                                               */ 
 
 
/**PROC+**********************************************************************/ 
/* Name:      closedown                                                      */ 
/*                                                                           */ 
/* Purpose:   terminate the application cleanly                              */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    none                                                           */ 
/*                                                                           */ 
/* Operation: Issue a WinRUICleanup() to tell RUI the we are about to go,    */ 
/* and then post a close message so that we do.                              */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
void closedown (void) 
{ 
  if (!terminating)                /* check we haven't already got here from */ 
  {                                /* another section of the code            */ 
    terminating = TRUE;            /* then make sure we can't get here again */ 
    WinRUICleanup(); 
    PostMessage (hWnd, WM_CLOSE, 0, 0l); 
  } 
}  /* closedown                                                              */ 
 
 
 
/**PROC+**********************************************************************/ 
/* Name:      do_keyboard_stuff                                              */ 
/*                                                                           */ 
/* Purpose:   poll keyboard for data                                         */ 
/*                                                                           */ 
/* Returns:   BOOL - TRUE => we have data to send                            */ 
/*                                                                           */ 
/* Params:    none                                                           */ 
/*                                                                           */ 
/* Operation: Look for Alt-1 to Alt-9 and ascii chars.                       */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
BOOL do_keyboard_stuff (type, key) 
 
UINT  type; 
UCHAR key; 
 
{ 
  BOOL   data_to_send;             /* do we have data to send?               */ 
 
  data_to_send = FALSE; 
 
  if (type == WM_SYSCHAR) 
  { 
    /*************************************************************************/ 
    /* Alt key pressed                                                       */ 
    /*************************************************************************/ 
    if ((key >= '1') && 
        (key <= '9')) 
    { 
      /***********************************************************************/ 
      /* ALT-1 to ALT-9 0xF1 is the AID code for PF1.  Follow this with the  */ 
      /* cursor address                                                      */ 
      /***********************************************************************/ 
      *write_data = 0xF1 + key - '1'; 
      *(write_data + 1) = 0x40; 
      *(write_data + 2) = 0x40; 
      write_len = 3; 
      data_to_send = TRUE; 
    } 
  } 
  else 
  { 
    /*************************************************************************/ 
    /* Ordinary ASCII char                                                   */ 
    /*************************************************************************/ 
    if (key == SWITKEY) 
    { 
      /***********************************************************************/ 
      /* Hit key to switch between sessions                                  */ 
      /***********************************************************************/ 
      if (lu_session) 
      { 
        lu_session = FALSE; 
      } 
      else 
      { 
        lu_session = TRUE; 
      } 
      InvalidateRect (hWnd, NULL, TRUE); 
    } 
    else 
    { 
      /***********************************************************************/ 
      /* Key should be real data.  Add it to the string                      */ 
      /***********************************************************************/ 
      if (key == 13) 
      { 
        /*********************************************************************/ 
        /* If user pressed return key then send the data.  Reset data_offset */ 
        /* for next data.                                                    */ 
        /*********************************************************************/ 
        write_data[data_offset++] = '\0'; 
        data_to_send = TRUE; 
        data_offset  = 0; 
 
        /*********************************************************************/ 
        /* Convert data to EBCDIC                                            */ 
        /*********************************************************************/ 
        convert_to_ebc.len = (unsigned short) (strlen(write_data) ); 
        if (convert_to_ebc.len > 0) 
        { 
          ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_ebc)); 
        } 
        write_len = convert_to_ebc.len; 
 
        /*********************************************************************/ 
        /* Allow for ENTER AID if necessary                                  */ 
        /*********************************************************************/ 
        if (lu_session) 
        { 
          write_data -= WRITE_EXTRA; 
          write_len  += WRITE_EXTRA; 
        } 
      } 
      else if (key == 8) 
      { 
        /*********************************************************************/ 
        /* Backspace.  Delete last char                                      */ 
        /*********************************************************************/ 
        if (data_offset > 0) 
        { 
          data_offset--; 
        } 
      } 
      else if (key != 0) 
      { 
        /*********************************************************************/ 
        /* ASCII char.  Add it to the data buffer                            */ 
        /*********************************************************************/ 
write_data[data_offset++] = (UCHAR) key; 
 
      } 
      /***********************************************************************/ 
      /* Invalidate our window so that the new data is displayed             */ 
      /***********************************************************************/ 
      InvalidateRect (hWnd, NULL, TRUE); 
    } 
  } 
 
 
  return(data_to_send); 
}  /* do_keyboard_stuff                                                      */ 
 
 
 
/**PROC+**********************************************************************/ 
/* Name:      do_write                                                       */ 
/*                                                                           */ 
/* Purpose:   issue a write verb                                             */ 
/*                                                                           */ 
/* Returns:   BOOL - TRUE => data sent OK                                    */ 
/*                                                                           */ 
/* Params:    none                                                           */ 
/*                                                                           */ 
/* Operation: convert data to EBCDIC and send it on the right session        */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
BOOL do_write (void) 
 
{ 
  BOOL ok; 
 
  ok = TRUE; 
 
 
  /***************************************************************************/ 
  /* Set up the vcb                                                          */ 
  /***************************************************************************/ 
  memset(&other_verb, 0, sizeof(other_verb)); 
  other_verb.common.lua_verb             = LUA_VERB_RUI; 
  other_verb.common.lua_verb_length      = sizeof(read_verb); 
  other_verb.common.lua_opcode           = LUA_OPCODE_RUI_WRITE; 
  other_verb.common.lua_sid              = sid; 
  other_verb.common.lua_data_length      = write_len; 
  other_verb.common.lua_data_ptr         = (char far *) write_data; 
  other_verb.common.lua_rh.bci           = 1; 
  other_verb.common.lua_rh.eci           = 1; 
  other_verb.common.lua_rh.dr1i          = 1; 
 
  if (lu_session) 
  { 
    /*************************************************************************/ 
    /* On the LU session we must add the <enter> key prefix.  All inbound    */ 
    /* requests flow RQE with the BBI and CDI flags set depending on the     */ 
    /* current session state.                                                */ 
    /*************************************************************************/ 
    other_verb.common.lua_flag1.lu_norm  = 1; 
    other_verb.common.lua_rh.ri          = 1; 
    if (send_state == BETB) 
    { 
      /***********************************************************************/ 
      /* Between bracket, so open bracket and give direction.  Note that we  */ 
      /* can do this since we will always be contention winner.              */ 
      /***********************************************************************/ 
      other_verb.common.lua_rh.bbi         = 1; 
      other_verb.common.lua_rh.cdi         = 1; 
      send_state = RECV; 
    } 
    else if (send_state = SEND) 
    { 
      /***********************************************************************/ 
      /* In bracket and we have direction, so simply give direction.         */ 
      /***********************************************************************/ 
      other_verb.common.lua_rh.cdi         = 1; 
      send_state = RECV; 
    } 
    else 
    { 
      /***********************************************************************/ 
      /* In bracket and we do not have direction, so do not send.            */ 
      /***********************************************************************/ 
      ok = FALSE; 
    } 
  } 
  else 
  { 
    /*************************************************************************/ 
    /* On the SSCP session things are straightforward.                       */ 
    /*************************************************************************/ 
    other_verb.common.lua_flag1.sscp_norm  = 1; 
  } 
 
  if (ok) 
  { 
    /*************************************************************************/ 
    /* Issue write verb                                                      */ 
    /*************************************************************************/ 
    WinRUI(hWnd, (LUA_VERB_RECORD FAR *) &other_verb); 
    if (!other_verb.common.lua_flag2.async) 
    { 
      /***********************************************************************/ 
      /* Verb completed immediately.  Post our own completion message        */ 
      /***********************************************************************/ 
      PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&other_verb); 
    } 
 
    /*************************************************************************/ 
    /* Reset write_data to point to correct point in write_array             */ 
    /*************************************************************************/ 
    write_data = write_array + WRITE_EXTRA; 
  } 
 
  return(ok); 
}  /* do_write ()                                                            */ 
 
 
 
/**PROC+**********************************************************************/ 
/* Name:      parse_data                                                     */ 
/*                                                                           */ 
/* Purpose:   parse data from the host                                       */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    IN  data - pointer to data                                     */ 
/*                                                                           */ 
/* Operation: Looks through data for read partition query from host.  Could  */ 
/* be expanded to format data from host                                      */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
void parse_data (data, length) 
 
UCHAR FAR * data; 
USHORT      length; 
{ 
  USHORT  field_length; 
 
  switch (*(data++)) 
  { 
    case 0xF3:                       /* write structured field               */ 
      /***********************************************************************/ 
      /* Next byte is the WCC - ignore                                       */ 
      /***********************************************************************/ 
      data++; 
      length -= 2; 
 
      while (length > 0) 
      { 
        /*********************************************************************/ 
        /* We're just looking for a Read Partion query                       */ 
        /*********************************************************************/ 
        field_length = (((USHORT) *data) << 8) || ((USHORT) *(data + 1)); 
        if ((*(data+2) == 0x01) &&   /* Read partition                       */ 
            (*(data+3) == 0xFF) &&   /* Query                                */ 
            (*(data+4) == 0x02))     /* not a list                           */ 
        { 
          /*******************************************************************/ 
          /* Build an RPQ and flag it to be sent                             */ 
          /*******************************************************************/ 
          rpq_state = RPQ_QUEUED; 
        } 
        data   += field_length; 
        length -= field_length; 
      } 
 
 
      break; 
 
    default: 
      break; 
 
  } 
}  /* parse_data                                                             */ 
 
 
 
/**PROC+**********************************************************************/ 
/* Name:      issue_rpq                                                      */ 
/*                                                                           */ 
/* Purpose:   issue a response to a Read partition query                     */ 
/*                                                                           */ 
/* Returns:   BOOL - TRUE => sent OK                                         */ 
/*                                                                           */ 
/* Params:    none                                                           */ 
/*                                                                           */ 
/* Operation: Builds and sends an RPQ reesponse                              */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
BOOL issue_rpq (void) 
 
{ 
  BOOL issue_rpq; 
 
  issue_rpq = TRUE; 
  /***************************************************************************/ 
  /* Set up the vcb                                                          */ 
  /***************************************************************************/ 
  memset(&rpq_verb, 0, sizeof(rpq_verb)); 
  rpq_verb.common.lua_verb             = LUA_VERB_RUI; 
  rpq_verb.common.lua_verb_length      = sizeof(rpq_verb); 
  rpq_verb.common.lua_opcode           = LUA_OPCODE_RUI_WRITE; 
  rpq_verb.common.lua_sid              = sid; 
  rpq_verb.common.lua_data_length      = RPQ_LENGTH; 
  rpq_verb.common.lua_data_ptr         = (char far *) rpq_data; 
  rpq_verb.common.lua_rh.bci           = 1; 
  rpq_verb.common.lua_rh.eci           = 1; 
  rpq_verb.common.lua_rh.dr1i          = 1; 
 
  /***************************************************************************/ 
  /* All inbound requests flow RQD with the BBI and CDI flags set depending  */ 
  /* on the current session state.                                           */ 
  /***************************************************************************/ 
  rpq_verb.common.lua_flag1.lu_norm  = 1; 
  rpq_verb.common.lua_rh.ri          = 1; 
  if (send_state == BETB) 
  { 
    /*************************************************************************/ 
    /* Between bracket, so open bracket and give direction.  Note that we    */ 
    /* can do this since we will always be contention winner.                */ 
    /*************************************************************************/ 
    rpq_verb.common.lua_rh.bbi         = 1; 
    rpq_verb.common.lua_rh.cdi         = 1; 
    send_state = RECV; 
  } 
  else if (send_state = SEND) 
  { 
    /*************************************************************************/ 
    /* In bracket and we have direction, so simply give direction.           */ 
    /*************************************************************************/ 
    rpq_verb.common.lua_rh.cdi         = 1; 
    send_state = RECV; 
  } 
  else 
  { 
    /*************************************************************************/ 
    /* In bracket and we do not have direction, so do not send.              */ 
    /*************************************************************************/ 
    issue_rpq = FALSE; 
  } 
 
  if (issue_rpq) 
  { 
    WinRUI(hWnd, (LUA_VERB_RECORD FAR *) &rpq_verb); 
    if (!rpq_verb.common.lua_flag2.async) 
    { 
      /***********************************************************************/ 
      /* Verb completed immediately.  Post our own completion message        */ 
      /***********************************************************************/ 
      PostMessage (hWnd, verb_complete, 0, (LPARAM) (VOID FAR *)&rpq_verb); 
    } 
  } 
 
  return(issue_rpq); 
}  /* issue_rpq                                                              */ 
 
/**PROC+**********************************************************************/ 
/* Name:      add_to_display_buffer                                          */ 
/*                                                                           */ 
/* Purpose:   add data to the display buffer                                 */ 
/*                                                                           */ 
/* Returns:   void                                                           */ 
/*                                                                           */ 
/* Params:    IN data - data to be displayed                                 */ 
/*                                                                           */ 
/* Operation: Add the zero terminated data string to the circular display    */ 
/* buffer.  Cope with wrapping                                               */ 
/*                                                                           */ 
/**PROC-**********************************************************************/ 
void add_to_display_buffer (data) 
 
UCHAR FAR * data; 
{ 
  UINT data_length;         /* length of new data to display                 */ 
  BOOL need_to_wrap;        /* do we need to wrap to the start of the buffer */ 
  UINT copy_length;         /* length of data to copy                        */ 
 
 
  data_length = _fstrlen (data); 
 
  /***************************************************************************/ 
  /* Work out whether the data will go over the end of the dispaly buffer.   */ 
  /* If it will, wrap it back over the start of the buffer.                  */ 
  /***************************************************************************/ 
  need_to_wrap = (buffer_end + data_length > DISPLAY_BUFFER_SIZE); 
 
  if (need_to_wrap) 
  { 
    copy_length = DISPLAY_BUFFER_SIZE - buffer_end; 
    wrapped = TRUE; 
  } 
  else 
  { 
    copy_length = data_length; 
  } 
 
  /***************************************************************************/ 
  /* Copy as much data as will fit into the buffer                           */ 
  /***************************************************************************/ 
  _fmemcpy ((UCHAR FAR *) (display_buffer + buffer_end), 
            data, 
            copy_length); 
 
  /***************************************************************************/ 
  /* If there is more data to copy, copy it to the start of the buffer       */ 
  /* Set up the new end point.                                               */ 
  /***************************************************************************/ 
  if (need_to_wrap) 
  { 
    _fmemcpy ((UCHAR FAR *)display_buffer, 
              data + copy_length, 
              data_length - copy_length); 
 
    buffer_end   = data_length - copy_length; 
  } 
  else 
  { 
    buffer_end   += data_length; 
  } 
 
  /***************************************************************************/ 
  /* Cause the window to be re-painted                                       */ 
  /***************************************************************************/ 
  InvalidateRect (hWnd, NULL, TRUE); 
 
}  /* add_to_display_buffer                                                  */