/****************************************************************************
**
**  Name: wsnet.c
**
**  Description: Routines to support network communication with the emulator.
**
**  $Log:   S:/tbird/mt2_68k/pcnfs/wsnet.c_v  $
** 
**    Rev 1.0   13 Feb 1997 08:59:36   gene
** Initial revision.
** 
**    Rev 1.0   07 Sep 1995 11:00:32   gene
** Initial revision.
** 
**    Rev 1.2   28 Mar 1994 11:18:24   nghia
** Remove StrLib.h include - unused.
** 
**    Rev 1.1   11 Mar 1994 16:08:30   tom
** Cleanup of types, integration with PC-NFS.
** 
**    Rev 1.0   17 Jan 1994 11:49:06   tom
** Initial revision.
**
**  $Header:   S:/tbird/mt2_68k/pcnfs/wsnet.c_v   1.0   13 Feb 1997 08:59:36   gene  $
**
**  Copyright (C) 1991-4 Microtek International.  All rights reserved.
**
*****************************************************************************/

                        /****************************
                         *                          *
                         *       INCLUDE FILES      *
                         *                          *
                         ****************************/

#ifndef _BASEWIND_
#include "basewind.h"
#endif

#include <stdio.h>

#ifndef _WSCOM_
#include "wscom.h"
#endif

#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif

#ifndef _HLPENTRY_
#include "hlpentry.h"
#endif

#include "version.h"

#ifndef _GENERICN_
#include "genericn.h"
#endif


#ifndef _HEAP_
#include "heap.h"
#endif

#include <string.h>

/* use with Borland C++ compiler */
#ifndef _BORLANDC_
#define _BORLANDC_
#endif

                        /****************************
                         *                          *
                         *     LOCAL DEFINITIONS    *
                         *                          *
                         ****************************/
// for retrieving host name from profile
#define COMM_AP_NAME      "Comm"
#define COMM_KEY_NAME     "Type"
#define COMM_LENGTH       32
#define NET_AP_NAME       "Network"
#define NET_KEY_NAME      "Emulators"
#define NET_DEFAULT_NAME  NULL
#define PROFILE_STRING_LENGTH 256
#define POWERVIEWS_INI    "pwrviews.ini"
#define HOST_NAME_LENGTH  256
#define HOST_NAME_MAX     20
#define DELIMITER_SET     ", "

#define COMBO_CONTROL_ID 501  // control ID for dialog

S8 *hostNameList[HOST_NAME_MAX];
S16 hostNameCount;  // number of entries in hostNameList
S8 selectedHostName[HOST_NAME_LENGTH];

U16 timerId;       /* timer ID for SdatInput callback */
U32 connection;    /* connection ID */
HANDLE libInst;    /* handle of the DLL */
HWND theHWnd;      /* save from WSComInit */

// recognize each of the legal network communication types
#define NETWORK_TYPE_COUNT 2
static S8 *networkTypeName[NETWORK_TYPE_COUNT] = {
   "pcnfs",
   "lanserver"
};
                        /****************************
                         *                          *
                         *    EXTERNAL VARIABLES    *
                         *                          *
                         ****************************/

                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/
RETCODE selectHostFromDialog(void);
BOOL EXPORT selectDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lParam);

                        /****************************
                         *                          *
                         *      EXECUTABLE CODE     *
                         *                          *
                         ****************************/
/**************************************************************************
**
**  LibMain
**
**  Description: Main entry point of the DLL.
**
**  Parameters:
**    input:
**       hInstance:     Handle of the library instance
**       wDataSeg:      Value of Data Segment register
**       cbHeapSize:    Heap Size of the heap defined in the DEF
**       lpszCmdLine:   Command Line information (rarely used)
**
**    output:
**
***************************************************************************/
#pragma argsused
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize,
    LPSTR lpszCmdLine) {
    /* the LIBENTRY initializes the local heap by calling LocalInit() and
       then calls LibMain.  The LocalInit() locks the data segment of the
       library when initialize; therefore LibMain needs to unlock */
    if (cbHeapSize != 0) /* the DLL Data segment is MOVEABLE */
       UnlockData(0);
    libInst = hInstance;  /* Save the handle */
    ErrInitDLL(MODULE_WSCOM,"wscom.dll");
    /* initialize successfully */
    return(TRUE);

}

#ifndef _BORLANDC_
/**************************************************************************
**
**  WEP {Windows Exit Procedure}
**
**  Description: DLL exit procedure to perform cleanup for the DLL before it
**              is unloaded. - not to be used with BC++
**
**  Parameters:
**    input:
**       nParam:     Message to indicate whether all of Windows is shutting
**                   down or just the DLL itself.
**
**    output:
**       return a 1 to indicate success
**
***************************************************************************/
VOID FAR PASCAL WEP(int nParam) {

   switch(nParam) {
      case WEP_SYSTEMEXIT:
         /* System shutdown in progress. Respond accordingly */
         break;
      case WEP_FREE_DLL:
         /* The DLL use count is 0 */
         break;
      default:
         /* Undefined value - ignore */
         break;
   }
   return(TRUE);
}

#endif

/*****************************************************************************
**
**  WSComInit
**
**  Description:  Establish the network connection to the emulator.
**
**  Parameters:
**    hWnd (in): Windows handle.
**    cIndx (not used): for compatability with serial interface.
**
**  Side Effect:
**    static variable "connection" receives connection descriptor.
**
**
*****************************************************************************/
#pragma argsused
BOOL FAR PASCAL
WSComInit(HWND hWnd, LPWORD cIndx)
{
   int i;
   S16 ret;
   RETCODE err, status;
   LPSTR stringPointer;
   char commType[COMM_LENGTH];    // receives comm type from profile
   char hostProfileString[PROFILE_STRING_LENGTH];
   char *hostNamePointer;

   theHWnd = hWnd;

   // make sure pwrviews.ini indicates ethernet
   if (!(GetPrivateProfileString(COMM_AP_NAME, COMM_KEY_NAME,
         "", commType, sizeof(commType), POWERVIEWS_INI)))
   {
      ErrDisplayError(ER_NET_PROFILE_MISSING, FORCE_POPUP);
      return(FALSE);
   }

   /* reject if not a known network type */
   for (i = 0; i < NETWORK_TYPE_COUNT; ++i) {
      if (!(strncmpi(networkTypeName[i], commType, strlen(networkTypeName[i]))))
         break;
   }
   if (i == NETWORK_TYPE_COUNT) {
      ErrDisplayError(ER_NET_NOT_NETWORK, FORCE_POPUP);
      return(FALSE);
   }

   // get emulator host name from profile; 0 returned if no match
   if (!(GetPrivateProfileString(NET_AP_NAME, NET_KEY_NAME,
         NET_DEFAULT_NAME, hostProfileString, sizeof(hostProfileString),
         POWERVIEWS_INI)))
   {
      ErrDisplayError(ER_NET_HOST_NAMES_NOT_FOUND, FORCE_POPUP);
      return(FALSE);
   }

   // parse host name(s) into list
   hostNamePointer = strtok(hostProfileString, DELIMITER_SET);
   for (hostNameCount = 0;
      hostNamePointer && (hostNameCount < HOST_NAME_MAX);
      ++hostNameCount)
   {
      hostNameList[hostNameCount] = hostNamePointer;
      hostNamePointer = strtok(NULL, DELIMITER_SET);
   }

   // adjust count if needed
   if (hostNamePointer)
      ++hostNameCount;

   // if exactly one name in profile, use that as host name
   if (hostNameCount == 1) {
      strcpy(selectedHostName, hostNameList[0]);
   }
   // if zero or more than one hosts, bring up dialog & let user pick
   else {
      selectHostFromDialog();
   }

   /* keep retrying as long as the user is willing */
   while ((err =
      genericNetworkConnect((U8 *)selectedHostName, &connection)) != GOOD)
   {

      // allow retry if this is a warning; otherwise return.
      if ((err & E_SEVERITY_MASK) == E_WARNING) {

         // display dialog with retry/cancel; get user response.
         if ((stringPointer = TMalloc(E_ERRSIZE)) == NULL) {
            ErrDisplayError(ER_OUT_OF_MEMORY, FORCE_POPUP);
            return(FALSE);
         }
         if (ErrGetErrorText(err, stringPointer) != GOOD)
            return(FALSE);

         ret = MessageBox(hWnd, stringPointer,
            VERSION, MB_ICONSTOP | MB_RETRYCANCEL);

         // free allocated memory
         if (status = TFree(stringPointer) != GOOD) {
            ErrDisplayError(status, FORCE_POPUP);
            return(FALSE);
         }

         // return if user selected cancel
         if (ret == IDCANCEL)
            return(FALSE);
      }
      else {

         // display fatal error, return
         ErrDisplayError(err, FORCE_POPUP);
         return(FALSE);
      }
   }

   return(TRUE);
}  /* WSComInit */

/*****************************************************************************
**
**  WSComConfig
**
**  Description:  This is a no-op for ethernet.
**
**  Parameters:  Don't care.
**
*****************************************************************************/
#pragma argsused
BOOL FAR PASCAL WSComConfig(HWND hWnd, WORD cIndx, BOOLEAN useDTRHandshake) {
   return(TRUE);
}

/*****************************************************************************
**
**  WSComAckRequired
**
**  ACK not required for ethernet.
**
*****************************************************************************/
BOOL FAR PASCAL WSComAckRequired(VOID) {
    return(FALSE);
}

/*****************************************************************************
**
**  WSComRecvTimer
**
*****************************************************************************/
BOOL FAR PASCAL WSComRecvTimer(WORD timeEllapse, FARPROC lpfnAppRecv)
{
   /* Set timer to run and register callback function to receive data */
   if (!(timerId = SetTimer(NULL, 0, timeEllapse, lpfnAppRecv))) {
      /*
      ErrDisplayError(ER_NO_TIMER_AVAIL, FORCE_POPUP);
      */
      return(FALSE);
   }
   return(TRUE);
}

/****************************************************************************
**
**  WSComRead
**
**  Description: Read bytes from the network connection with the emulator.
**
**  Parameters:
**    rxBuff(in):  Buffer from caller for read data
**    numBytes(in/out):  in: number of bytes to read;
**                       out: number of bytes read.
**
**  Returns:  status of network-specific operation.
**
*****************************************************************************/
RETCODE FAR PASCAL WSComRead(U8 FAR *rxBuff, U16 FAR *numBytes) {
    return(genericNetworkRead(connection, rxBuff, numBytes));
}

/****************************************************************************
**
**  WSComWrite
**
**  Description:  Write bytes to the emulator via the network connection.
**
**  Parameters:
**     txBuff(in):  Bytes to be sent to the emulator over the network.
**     numBytes(in/out):  in: number of bytes to write;
**                        out: number of bytes written.
**
**  Returns: status of network specific write operation.
**
*****************************************************************************/
RETCODE FAR PASCAL WSComWrite(U8 FAR *txBuff, U16 *numBytes)
{
    return(genericNetworkWrite(connection, txBuff, numBytes));
}

/************************************************************************
**
**  WSComClose
**
************************************************************************/
BOOL FAR PASCAL
WSComClose(VOID)
{
    RETCODE ret;

    KillTimer(NULL,timerId);
    ret = genericNetworkClose(connection);
    if (ret != GOOD)
        return(FALSE);
    else
        return(TRUE);
}

/**************************************************************************
**
**  WSComFlush
**
***************************************************************************/
RETCODE FAR PASCAL WSComFlush(VOID)
{
   return(genericNetworkFlush(connection));
}

/*****************************************************************************
**
**  selectHostFromDialog
**
**  Description:  Create dialog for user selection of network emulator.
**
**  Parameters:
**    <none>
**
*****************************************************************************/
RETCODE selectHostFromDialog(void)
{
   FARPROC lpfnSelectDlgProc;
   int dialogStatus;

   lpfnSelectDlgProc = MakeProcInstance(selectDlgProc, libInst);
   if (lpfnSelectDlgProc == NULL) {
      return(ER_NET_HOST_SELECT_DIALOG);
   }

   dialogStatus = DialogBox(libInst, "SELECT_EMULATOR", theHWnd,
      lpfnSelectDlgProc);
   FreeProcInstance(lpfnSelectDlgProc);

   if (dialogStatus == -1) return(ER_NET_HOST_SELECT_DIALOG);

   return(GOOD);
}

/*****************************************************************************
**
**  selectDlgProc
**
**  Description:  Handle network emulator selection dialog.
**
**  Parameters:
**    <standard dialog parameters>
**
**  Side Effect:
**    - initial combo box entries are stored in hostNameList, count of same
**      in hostNameCount.
**    - if user makes a selection, host name text placed in selectedHostName.
**
*****************************************************************************/
BOOL EXPORT selectDlgProc(HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
   S16 index;
   HWND hwndList;

   hwndList = GetDlgItem(hDlg, COMBO_CONTROL_ID);

   switch(message) {
      case WM_INITDIALOG:
         strcpy(selectedHostName, "");  // initialize receiver string
         for (index = 0; index < hostNameCount; ++index) {
            SendMessage(hwndList, CB_ADDSTRING, NULL,
               (LPSTR)hostNameList[index]);
         }
         SendMessage(hwndList, CB_SETCURSEL, 0, 0);  // highlight first line
         SendMessage(hwndList, CB_SHOWDROPDOWN, 0, 0); // hide drop-down
         SetFocus(hwndList);
         return(FALSE);

      case WM_COMMAND:
         switch(wParam) {
            case IDOK:
               GetDlgItemText(hDlg, COMBO_CONTROL_ID, (LPSTR)selectedHostName,
                  HOST_NAME_LENGTH);
               EndDialog(hDlg, GOOD);
               return(TRUE);

            case IDCANCEL:
               EndDialog(hDlg, GOOD);
               return(TRUE);

            case IDHELP:
               WinHelp(hDlg, "PWRVIEWS.HLP", HELP_CONTEXT,
		  HE_HOST_SELECTION_DLG);
               return(TRUE);

            default:
               return(FALSE);
         } /* end of switch(wParam) */
   }
   return(FALSE);
}

/****************************************************************************
**
** WSComUploadPacketSize
**
*****************************************************************************/
RETCODE FAR PASCAL WSComUploadPacketSize(U32 *packetSize)
{
   *packetSize = 256L;
#ifdef PC_NFS
   *packetSize = 0L;
#endif
#ifdef OS2_LAN_SERVER
   *packetSize = 500L;
#endif
   return(GOOD);
}

/******************************** E O F ***********************************/
