/*************************************************************************/
/*                                                                       */
/* ITSC Redbook OS/2 v2.0 Sample Program                                 */
/*                                                                       */
/*                                                                       */
/* RECORD.C  -  This is the C implementation of a WPS transient          */
/*              Record class                                             */
/*                                                                       */
/*************************************************************************/

/*
 * This file was generated by the SOM Compiler.
 * FileName: record.c.
 * Generated using:
 *     SOM Precompiler spc: 1.21
 *     SOM Emitter emitc: 1.23
 */

#define INCL_DOS
#define INCL_WIN
#include <os2.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stddef.h>
#include <process.h>
#include <memory.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <bsememf.h>

#include "res.h"      /* resource definitions */
#include "msgs.h"     /* Message and data passing definitions */

#define Record_Class_Source
#include "record.ih"

#define DebugBox(title, text)  WinMessageBox(HWND_DESKTOP,HWND_DESKTOP, \
                               (PSZ) text , (PSZ) title, 0, \
                               MB_OK | MB_INFORMATION )


/*************************************************************/
/* Define the new record view OPEN_CONTENTS to OPEN_TREE are */
/* reserved by the shell user views begin at OPEN_USER this  */
/* is similar to the WM_USER concept for messages            */
/*************************************************************/
#define OPEN_RECORD (OPEN_USER+1)

/******************************************************************/
/*                           Class Data                           */
/******************************************************************/

/* Store the class pointer itself to save time getting hold of it */
SOMAny  *ThisClass;

/* module handle - this can be used by all instances of this class */
HMODULE  ThisClasshmodule;

/* default title when created without a title */
PSZ ThisClassDefaultTitle = "Record";

/* default icon for record objects */
HPOINTER    ThisClassDefaultIcon;

/* Handle to requester object window - all methods go via this */
/* to send messages to the sever process                       */
HWND hwndRequester;

/******************************************************************/
/*                           Structures                           */
/******************************************************************/

#define RECORD_BUFFER_SIZE 500

/* Structure needed for views of records */
typedef struct _RECORDVIEW {
  SOMAny   *Record;
  USEITEM  UseItem;
  VIEWITEM ViewItem;
} RECORDVIEW;
typedef RECORDVIEW *PRECORDVIEW;

/* Buffer to hold record text */
typedef struct _RECORDVIEWDATA {
  SOMAny   *Record;
  CHAR     Data[RECORD_BUFFER_SIZE];
} RECORDVIEWDATA;
typedef RECORDVIEWDATA *PRECORDVIEWDATA;

/******************************************************************/
/*                           Functions                            */
/******************************************************************/
MRESULT EXPENTRY MLEFrameWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
HWND CreateViewWindow( SOMAny *somSelf );
void DeleteViewWindow( HWND hwnd );


/****************************************************************************/
/*                 Required for the object window requester                 */
/****************************************************************************/

typedef struct {
        HWND hwndServer;
        PID  pidServer;
} REQ_DATA, *PREQ_DATA;

MRESULT EXPENTRY IpcRequesterObjectWinProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );

VOID  IpcRequesterObjectThread (VOID *p);
VOID  IpcStartServerProg(PSZ Args);
BOOL  IpcServerWinCheck(HWND hwnd);
PVOID IpcGetMessageMem(ULONG ObjectSize);

#define STACKSIZE 9000

/****************************************************************************/
/* Start of Methods section                                                 */


/*
 *
 *  METHOD:   SetRecordInfo                               PUBLIC
 *
 *  PURPOSE:  Copy the szData string in to the
 *            Record objects text buffer
 *
 */

#undef SOM_CurrentClass
#define SOM_CurrentClass SOMInstance
SOM_Scope BOOL   SOMLINK record_SetRecordInfo(Record *somSelf,
                PSZ szData)
{
    RecordData *somThis = RecordGetData(somSelf);
    RecordMethodDebug("Record","record_SetRecordInfo");

    strcpy ( _pRecordData, szData);
    return (BOOL) 0;
}

/*
 *
 *  METHOD:   GetRecordInfo                               PUBLIC
 *
 *  PURPOSE:  Copy the  Record objects text buffer
 *            in to the szData string
 *
 */

SOM_Scope BOOL   SOMLINK record_GetRecordInfo(Record *somSelf,
                PSZ szData)
{
    RecordData *somThis = RecordGetData(somSelf);
    RecordMethodDebug("Record","record_GetRecordInfo");

    strcpy ( szData, _pRecordData);

    return (BOOL) 0;
}

/*
 *
 *  METHOD:   clsQueryDatabase                            PUBLIC
 *
 *  PURPOSE:  Search the record database for all entries
 *            that match the patern in the search string.
 *            This results in the creation of new objects
 *            in the Folder specified
 *
 */

#undef SOM_CurrentClass
#define SOM_CurrentClass SOMMeta
SOM_Scope BOOL   SOMLINK recordcls_clsQueryDatabase(M_Record *somSelf,
                PSZ szSearch,
                WPObject *Folder)
{
    PQUERY_DATA pQuery;

    /* M_RecordData *somThis = M_RecordGetData(somSelf); */
    M_RecordMethodDebug("M_Record","recordcls_clsQueryDatabase");

    pQuery = (PQUERY_DATA) IpcGetMessageMem( sizeof(QUERY_DATA) );

    pQuery->folder = (ULONG)Folder;
    strcpy( pQuery->szSearch, szSearch );

    /* Ask the server to perform the search */
    WinPostMsg(hwndRequester,
               WMP_SEND_MSG_TO_SERVER,
               (MPARAM) WMP_SEARCH_DATABASE,
               (MPARAM) pQuery );

    return (BOOL) 0;
}

/*
 *
 *  METHOD:   clsRestartServer                            PUBLIC
 *
 *  PURPOSE:  Restarts the server program.
 *
 */

SOM_Scope BOOL   SOMLINK recordcls_clsRestartServer(M_Record *somSelf)
{
    /* M_RecordData *somThis = M_RecordGetData(somSelf); */
    M_RecordMethodDebug("M_Record","recordcls_clsRestartServer");

    WinPostMsg(hwndRequester, WMP_START_SERVER_PROGRAM, (MPARAM)0, (MPARAM)0 );
    return (BOOL) 0;
}

/*
 *
 *  METHOD:   wpInitData                    OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Initialise the object memory for
 *            the record text buffer
 *
 */

#undef SOM_CurrentClass
#define SOM_CurrentClass SOMInstance
SOM_Scope void   SOMLINK record_wpInitData(Record *somSelf)
{
    SOMAny   *RecordClass;
    RecordData *somThis = RecordGetData(somSelf);
    RecordMethodDebug("Record","record_wpInitData");

    /* Allocate storage for record text buffer */
    _pRecordData = (PSZ) _wpAllocMem(somSelf, RECORD_BUFFER_SIZE, NULL);

    /* Initialise the buffer */
    strcpy( _pRecordData, "<Empty Record>");
    parent_wpInitData(somSelf);
}

/*
 *
 *  METHOD:   wpUnInitData                   OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Free the object memory for
 *            the record text buffer
 *
 */

SOM_Scope void   SOMLINK record_wpUnInitData(Record *somSelf)
{
    RecordData *somThis = RecordGetData(somSelf);
    RecordMethodDebug("Record","record_wpUnInitData");

    /* Free storage for record buffer */
    _wpFreeMem(somSelf, _pRecordData );

    parent_wpUnInitData(somSelf);
}

/*
 *
 *  METHOD:   wpModifyPopupMenu             OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Add any new options for the records
 *            context menu
 *
 */

SOM_Scope BOOL   SOMLINK record_wpModifyPopupMenu(Record *somSelf,
                HWND hwndMenu,
                HWND hwndCnr,
                ULONG iPosition)
{
    RecordData *somThis = RecordGetData(somSelf);
    RecordMethodDebug("Record","record_wpModifyPopupMenu");
    /* Reserved for future use */
    return (parent_wpModifyPopupMenu(somSelf,hwndMenu,hwndCnr,iPosition));
}

/*
 *
 *  METHOD:   wpMenuItemSelected            OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Processing for record objects menu
 *
 */

SOM_Scope ULONG  SOMLINK record_wpMenuItemSelected(Record *somSelf,
                HWND hwndFrame,
                ULONG MenuId)
{
    RecordData *somThis = RecordGetData(somSelf);
    RecordMethodDebug("Record","record_wpMenuItemSelected");
    /* Reserved for future use */
    return parent_wpMenuItemSelected(somSelf,hwndFrame,MenuId);
}

/*
 *
 *  METHOD:   wpOpen                        OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Open a view of the object ( see also
 *            wpclsQueryDefaultView )
 *
 */

SOM_Scope HWND   SOMLINK record_wpOpen(Record *somSelf,
                HWND hwndCnr,
                ULONG ulView,
                ULONG param)
{
    RecordData *somThis = RecordGetData(somSelf);
    RecordMethodDebug("Record","record_wpOpen");

    /********************************************************************/
    /* Note that double clicking on an icon sends the object a message  */
    /* with OPEN_DEFAULT as the parameter. The Normal processing of     */
    /* this is the find out what the default is with wpQueryDefaultView */
    /* and then send a wpOpen message with whatever was returned.       */
    /********************************************************************/

    if (ulView==OPEN_RECORD)
    {
       /***************************************************************/
       /* Try and switch to an open view of the object. If this fails */
       /* it means that the view has yet to be created                */
       /***************************************************************/
       if ( !_wpSwitchTo(somSelf,OPEN_RECORD) )
       {
          /*****************************************************************/
          /* Here we wanted to get the sever process to show the view      */
          /* for our object. However WPS needs to subclass the view frame  */
          /* window in order manipulate the title bar mini icon, and       */
          /* since subclassing does not work across processes it presents  */
          /* a problem. If you did not care to have the Mini icon feature  */
          /* for the view of your object then creating the frame in the    */
          /* second process is ok.                                         */
          /* Another approach would be to start a new program whose        */
          /* sole purpose would be to represent the view to the object,    */
          /* See the WinStartApp API.                                      */
          /*****************************************************************/

          HWND  hwndView;
          hwndView = CreateViewWindow( somSelf );

          if(! WinIsWindow( (HAB)0, hwndView) )
          {
             /****************************************/
             /* If unsuccessful do parent processing */
             /****************************************/
             return (parent_wpOpen(somSelf,hwndCnr,ulView,param));
          }
          else
          {
             /***************************************************************/
             /* Post a message to the view frame to display the record data */
             /***************************************************************/
             WinPostMsg( hwndView, WMP_INSERT_DATA_INTO_VIEW, (MPARAM) _pRecordData, (MPARAM)0 );
             return( hwndView );
          }
       }
       else
       {
          return (parent_wpOpen(somSelf,hwndCnr,ulView,param));
       }
    }
    else
    {
       return (parent_wpOpen(somSelf,hwndCnr,ulView,param));
    }

}

/*
 *
 *  METHOD:   wpSetup                       OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Process the records Setup strings
 *
 */

SOM_Scope BOOL   SOMLINK record_wpSetup(Record *somSelf,
                PSZ pszSetupString)
{
    RecordData *somThis = RecordGetData(somSelf);
    RecordMethodDebug("Record","record_wpSetup");
    /* Reserved for future use */
    return (parent_wpSetup(somSelf,pszSetupString));
}

/*
 *
 *  METHOD:   wpclsFindObjects                            PUBLIC
 *
 *  PURPOSE:  Shell entry to finding record objects
 *
 */

#undef SOM_CurrentClass
#define SOM_CurrentClass SOMMeta
SOM_Scope BOOL   SOMLINK recordcls_wpclsFindObjectFirst(M_Record *somSelf,
                PCLASS pClassList,
                PHFIND phFind,
                PSZ pszTitle,
                WPFolder *Folder,
                BOOL fSubfolders,
                PVOID pExtendedCriteria,
                POBJECT pBuffer,
                PULONG pCount)
{
    /* M_RecordData *somThis = M_RecordGetData(somSelf); */
    M_RecordMethodDebug("M_Record","recordcls_wpclsFindObjectFirst");

    return (parent_wpclsFindObjectFirst(somSelf,pClassList,phFind,pszTitle,Folder,fSubfolders,pExtendedCriteria,pBuffer,pCount));
}

/*
 *
 *  METHOD:   wpclsInitData                 OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Initialises the Class
 *            This involves :
 *               Initialising class variables
 *               Loading class resources
 *               Starting the IPC requester thread
 *               Registering the Viewing window PM Class
 *
 */

#undef SOM_CurrentClass
#define SOM_CurrentClass SOMMeta
SOM_Scope void   SOMLINK recordcls_wpclsInitData(M_Record *somSelf)
{
    CHAR  ErrorBuffer[100];

    /* M_RecordData *somThis = M_RecordGetData(somSelf); */
    M_RecordMethodDebug("M_Record","recordcls_wpclsInitData");

    DosLoadModule((PSZ) ErrorBuffer,
                  sizeof(ErrorBuffer),
                  "RECORD", &ThisClasshmodule);

    ThisClassDefaultIcon = WinLoadPointer( HWND_DESKTOP, ThisClasshmodule, ID_RECORDICON );

    /* Initialise the pointer to this class */
    ThisClass = somSelf;

    /* Start the requester */
    _beginthread( IpcRequesterObjectThread, NULL, STACKSIZE, NULL);

    /* Register the viewing window class */
    if (!WinRegisterClass( (HAB)0, (PSZ)"MLEFrameWindow",
                          (PFNWP)MLEFrameWindowProc,
                          CS_SIZEREDRAW, sizeof( HWND ) ))
    {
       DebugBox("Fatal Error","Register View Frame Class Failed");
    }

    parent_wpclsInitData(somSelf);
}

/*
 *
 *  METHOD:   wpclsUnInitData               OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Free Class resources
 *
 */

SOM_Scope void   SOMLINK recordcls_wpclsUnInitData(M_Record *somSelf)
{
    /* M_RecordData *somThis = M_RecordGetData(somSelf); */
    M_RecordMethodDebug("M_Record","recordcls_wpclsUnInitData");

    /* Close down the Server */
    WinPostMsg(hwndRequester, WMP_IPC_END, (MPARAM) 0, (MPARAM) 0 );

    DosFreeModule(ThisClasshmodule); /* Free the resources */

    parent_wpclsUnInitData(somSelf);
}

/*
 *
 *  METHOD:   wpclsQueryTitle               OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Return the string "Record" as the default
 *            title for new record objects
 *
 */

SOM_Scope PSZ   SOMLINK recordcls_wpclsQueryTitle(M_Record *somSelf)
{
    /* M_RecordData *somThis = M_RecordGetData(somSelf); */
    M_RecordMethodDebug("M_Record","recordcls_wpclsQueryTitle");

    return ( ThisClassDefaultTitle );
}

/*
 *
 *  METHOD:   wpclsQueryIcon                OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Returns the default record icon pointer.
 *
 */

SOM_Scope HPOINTER   SOMLINK recordcls_wpclsQueryIcon(M_Record *somSelf)
{
    /* M_RecordData *somThis = M_RecordGetData(somSelf); */
    M_RecordMethodDebug("M_Record","recordcls_wpclsQueryIcon");

    if ( ThisClassDefaultIcon )
    {
       return( ThisClassDefaultIcon );
    }
    else
    {
       return( parent_wpclsQueryIcon(somSelf) );
    }
}

/*
 *
 *  METHOD:   wpclsQueryDefaultView         OVERRIDE      PUBLIC
 *
 *  PURPOSE:  Returns the default view for a
 *            new instance of the record object.
 *
 */

SOM_Scope ULONG   SOMLINK recordcls_wpclsQueryDefaultView(M_Record *somSelf)
{
    /* M_RecordData *somThis = M_RecordGetData(somSelf); */
    M_RecordMethodDebug("M_Record","recordcls_wpclsQueryDefaultView");

    return (OPEN_RECORD);
}

/* End of Methods                                                         */
/**************************************************************************/


HWND CreateViewWindow( SOMAny *somSelf )
{
   HWND        hwndView;
   ULONG       flViewCreate;
   PRECORDVIEW pRecView;

   flViewCreate = FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER | FCF_MINMAX | FCF_SHELLPOSITION ;

   hwndView = WinCreateStdWindow( HWND_DESKTOP, 0,
                                  &flViewCreate, "MLEFrameWindow",
                                  "", 0, (HMODULE)0L, 0, NULL);

   WinSendMsg(hwndView, WM_SETICON, MPFROMP(ThisClassDefaultIcon), NULL);

   WinSetWindowPos( hwndView,  HWND_TOP, 0,0, 400, 180,
                    SWP_ZORDER | SWP_SIZE | SWP_ACTIVATE | SWP_SHOW);

   /*******************************************************************/
   /* Allocate memory for the objects viewitem and useitem structures */
   /*                                                                 */
   /* A viewitem should always be the next thing in memory after      */
   /* a useitem (this is what WPS expects). So will allocate a        */
   /* structure which guarantees this:                                */
   /*                                                                 */
   /*        RECORDVIEW                                               */
   /*           SOMAny   *Record                                      */
   /*           USEITEM  UseItem                                      */
   /*           VIEWITEM ViewItem                                     */
   /*                                                                 */
   /* The useitems form a linked-list, one for each open view         */
   /* of a particular object. The WPS scans this list in the          */
   /* _wpSwitchTo method and then uses the information in the         */
   /* adjacent viewitem to switch to the view.                        */
   /*******************************************************************/

   pRecView = (PRECORDVIEW) _wpAllocMem(somSelf, sizeof(RECORDVIEW) , NULL);

   /********************************/
   /* Fill out the item structures */
   /********************************/
   pRecView->Record          = somSelf;
   pRecView->UseItem.type    = USAGE_OPENVIEW;
   pRecView->ViewItem.view   = OPEN_RECORD;
   pRecView->ViewItem.handle = hwndView;

   WinSetWindowULong(hwndView, QWL_USER, (ULONG) pRecView);

   /********************************************************/
   /* Add the object to the use list, if this is the first */
   /* time this is done then the Shell draws the in use    */
   /* hash lines around the icon                           */
   /********************************************************/
   _wpAddToObjUseList(somSelf, &pRecView->UseItem);

   /********************************************************/
   /* Registering the view with the shell will cause the   */
   /* frame to be subclassed and the shell will take over  */
   /* the system menu processing                           */
   /********************************************************/
   _wpRegisterView(somSelf, hwndView, "Person Details");

   return( hwndView );
}

void DeleteViewWindow( HWND hwnd )
{
   HWND         hwndFrame;
   PRECORDVIEW  pRecView;

   hwndFrame = WinQueryWindow(hwnd, QW_PARENT);

   /* Get the record view structure from the frames QWL_USER WW */
   pRecView  = (PRECORDVIEW)WinQueryWindowULong(hwndFrame,QWL_USER);

   /**********************************************************/
   /* Delete from use list. This will remove the in-use hash */
   /* lines from around the icon                             */
   /**********************************************************/
   _wpDeleteFromObjUseList(pRecView->Record, &pRecView->UseItem);

   /* Free the view structure memory */
   _wpFreeMem(pRecView->Record,(PBYTE)pRecView);

}

void IpcRequesterObjectThread (void *p)
{
  HMQ  hmq;
  QMSG qmsg;
  HAB  hab;

  hab = WinInitialize(0);

  hmq = WinCreateMsgQueue( hab, 0 );

  if ( !WinRegisterClass( hab, (PSZ)"IpcRequesterObjectWin",
                          (PFNWP)IpcRequesterObjectWinProc,
                          0L, sizeof(PREQ_DATA) )             )
  {
     DebugBox("IPC Fatal Error","Register Requester Class Failed");
  }

  hwndRequester = WinCreateWindow(HWND_OBJECT,
                                  "IpcRequesterObjectWin",
                                  "", 0L, 0,0,0,0,
                                  (HWND)0, HWND_TOP, 0L, NULL, NULL);

  while( WinGetMsg( hab, &qmsg, 0L, 0, 0 ) )
     WinDispatchMsg( hab, &qmsg );


  WinDestroyWindow(hwndRequester);
  WinDestroyMsgQueue( hmq );
  WinTerminate( hab );
}


MRESULT EXPENTRY IpcRequesterObjectWinProc( HWND hwnd,
                                         ULONG msg,
                                         MPARAM mp1,
                                         MPARAM mp2 )
{

  MRESULT mr;
  REQ_DATA *pRequesterData;

  mr = (MRESULT)FALSE;


  switch( msg )
  {
     case WM_CREATE:

         WinPostMsg(hwnd, WMP_INITIALISE_REQUESTER, (MPARAM)0, (MPARAM)0 );
         mr = WinDefWindowProc( hwnd, msg, mp1, mp2 );
         break;

     case WMP_INITIALISE_REQUESTER:

         pRequesterData = (REQ_DATA *)malloc( sizeof(REQ_DATA) );
         pRequesterData->hwndServer = (HWND)0;
         pRequesterData->pidServer  = 0;
         WinSetWindowPtr(hwnd,0,pRequesterData);
         WinPostMsg(hwnd, WMP_START_SERVER_PROGRAM, (MPARAM)0, (MPARAM)0 );
         break;

    case WMP_START_SERVER_PROGRAM:
         {
            pRequesterData = (REQ_DATA *)WinQueryWindowPtr(hwnd,0);

            if( WinIsWindow( (HAB)0, pRequesterData->hwndServer) )
            {
               DosBeep(500,500);
               DebugBox("Record Class Warning", "Server is already running. " \
                        "Request to re-start has been discarded" );
            }
            else
            {
               CHAR  Args[80];
               sprintf(Args,"%s@ %ul @",SERVER_PROGRAM, (ULONG)hwnd);
               IpcStartServerProg(Args);
            }
         }
         break;


    case WMP_SERVER_READY:
         {
            PID pid;
            TID tid;

            pRequesterData = (REQ_DATA *)WinQueryWindowPtr(hwnd,0);
            pRequesterData->hwndServer = (HWND)mp1;
            WinQueryWindowProcess((HWND)mp1,&pid,&tid);
            pRequesterData->pidServer  = pid;
         }
         break;

    case WMP_SERVER_TERMINATED:
         {
            pRequesterData = (REQ_DATA *)WinQueryWindowPtr(hwnd,0);

            pRequesterData->hwndServer = (HWND)0;
            pRequesterData->pidServer  = 0;

            DebugBox("Record Class Error", "Server Disconnected." \
                     "Server must be restarted to perform record queries" );
         }
         break;

    case WMP_IPC_END:
         {
            pRequesterData = (REQ_DATA *)WinQueryWindowPtr(hwnd,0);

            WinPostMsg(pRequesterData->hwndServer, WM_CLOSE, (MPARAM)0, (MPARAM)0 );

            /* Exit this object window - end this thread */
            WinPostMsg(hwnd, WM_CLOSE, (MPARAM)0, (MPARAM)0 );

         }
         break;

    case WMP_RESULTS_FROM_SEARCH:
         {
            PRESULTS_DATA pResults;
            PPERSON_DATA  pPerson;
            APIRET rc;
            USHORT i;
            CHAR szTemp[500];
            SOMAny *NewObj = NULL;

            pResults = (PRESULTS_DATA) mp1;
            pPerson  = (PPERSON_DATA) ( (ULONG)mp1 + (ULONG)sizeof(RESULTS_DATA) );

            if(pResults->cRecords == 0)
            {
               /* This is temporary */
               DebugBox("Query Results",(CHAR *)pPerson );
            }
            else
            {
               for(i=0; i<pResults->cRecords; i++)
               {
                  sprintf( szTemp,
                           "\nName: %s\nAddress: %s\nTel: %s\n",
                           pPerson->szName,
                           pPerson->szAddress,
                           pPerson->szTelepnone );

                  NewObj = _wpclsNew(ThisClass,
                                     pPerson->szName,
                                     "", (SOMAny *)pResults->folder,
                                     TRUE);

                  _SetRecordInfo( NewObj, szTemp);
                  pPerson++;
               }
            }

            rc = DosFreeMem( (PVOID)mp1 );
            if (rc)
            {
                DebugBox("Error","DosFreeMem Failed");
            }
         }
         break;


    case WMP_SEND_MSG_TO_SERVER:      /* mp1 = message                  */
         {                            /* mp2 = pointer to shared memory */
            ULONG ServerMsg;
            PVOID pMsgData;
            ULONG rc;

            ServerMsg = (ULONG) mp1;
            pMsgData  = (PVOID) mp2;

            pRequesterData = (REQ_DATA *)WinQueryWindowPtr(hwnd,0);

            if( IpcServerWinCheck(pRequesterData->hwndServer) )
            {
               rc = DosGiveSharedMem( pMsgData,
                                      pRequesterData->pidServer,
                                      PAG_WRITE | PAG_READ);

               if (rc)
               {
                   DebugBox("Error","DosGiveSharedMem Failed");
               }
               else
               {
                  mr = WinSendMsg(pRequesterData->hwndServer, ServerMsg, (MPARAM)pMsgData, (MPARAM)0 );
                  rc = DosFreeMem( pMsgData );
                  if (rc)
                  {
                      DebugBox("Error","DosFreeMem Failed");
                  }
                  return(mr);
               }
            }
            else
            {
               rc = DosFreeMem( pMsgData );
               if (rc)
               {
                   DebugBox("Error","DosFreeMem Failed");
               }
            }
         }
         break;

    default:
      mr = WinDefWindowProc( hwnd, msg, mp1, mp2 );
  }
  return mr;
}



PVOID IpcGetMessageMem(ULONG ObjectSize)
{
    PVOID   pData;
    ULONG   AttributeFlags;
    APIRET  rc;

    AttributeFlags =  OBJ_GIVEABLE | PAG_WRITE | PAG_READ | PAG_COMMIT;

    rc = DosAllocSharedMem(&pData, NULL, ObjectSize,AttributeFlags);
    if (rc)
    {
       /* This should never happen */

       DebugBox("IPC Fatal Error","DosAllocSharedMem failed");
       return(NULL);
    }
    else
    {
       return(pData);
    }
}


VOID IpcStartServerProg(PSZ Args )
{
   CHAR        LoadError[100];
   RESULTCODES ReturnCodes;
   ULONG       rc;
   CHAR        *sptr;

   sptr = Args;
   while(*sptr != '\0')
   {
      if(*sptr == '@')
          *sptr = '\0';
      sptr++;
   }

   rc = DosExecPgm(LoadError, sizeof(LoadError),
                   EXEC_BACKGROUND, Args,
                   "", &ReturnCodes,
                   SERVER_PROGRAM);

   if (rc)
   {
        DebugBox("IPC Fatal Error", "Sever Program could not be started");
   }
}

BOOL IpcServerWinCheck(HWND hwnd)
{
   if(! WinIsWindow( (HAB)0, hwnd) )
   {
      DosBeep(500,500);
      DebugBox("IPC Fatal Error", "Cannot Access Server - Request discarded");
      return(FALSE);
   }
   else
      return(TRUE);
}

/***************************************************************************/
/*                          MLE in a Frame window                          */
/***************************************************************************/

MRESULT EXPENTRY MLEFrameWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
  MRESULT mr;

  mr = (MRESULT)FALSE;

  switch( msg )
  {
     case WM_CREATE:
        {
            HWND  hwndMLEWindow;

            /* Create MLE window */
            hwndMLEWindow = WinCreateWindow(hwnd, WC_MLE,
                                            "", MLS_VSCROLL | MLS_HSCROLL | MLS_BORDER,
                                            0,0,0,0, hwnd, HWND_TOP, 0, NULL, NULL);

            /* Store the MLE hwnd in WW 0 */
            WinSetWindowPtr(hwnd, 0, (PVOID) hwndMLEWindow);

            mr = WinDefWindowProc( hwnd, msg, mp1, mp2 );
        }
        break;

     case WMP_INSERT_DATA_INTO_VIEW:  /* mp1 = pointer to text buffer */
        {
            HWND    hwndMLEWindow;

            hwndMLEWindow = (HWND)WinQueryWindowPtr(hwnd, 0);
            WinSendMsg(hwndMLEWindow, MLM_INSERT, (MPARAM)mp1, (MPARAM)0 );
        }
        break;

     case WM_SIZE:
        {
            RECTL   rc;
            HWND    hwndMLEWindow;

            /* Get the MLE hwnd from WW 0 */
            hwndMLEWindow = (HWND)WinQueryWindowPtr(hwnd, 0);

            WinQueryWindowRect(hwnd,&rc);

            WinSetWindowPos( hwndMLEWindow,  HWND_TOP,
                             rc.xLeft,
                             rc.yBottom,
                             rc.xRight,
                             rc.yTop,
                             SWP_SIZE | SWP_MOVE | SWP_SHOW);

            mr = WinDefWindowProc( hwnd, msg, mp1, mp2 );
        }
        break;

    case WM_PAINT:
        {
           HPS    hps;
           RECTL  rc;
           hps = WinBeginPaint( hwnd, 0L, &rc );
           WinFillRect(hps, &rc, CLR_WHITE);
           WinEndPaint( hps );
        }
        break;

     case WM_CLOSE:
        {
           /************************************/
           /* Tell WPS that this view has gone */
           /************************************/
           DeleteViewWindow( hwnd );

           WinPostMsg( hwnd, WM_QUIT, (MPARAM)0, (MPARAM)0 );
           WinDestroyWindow( WinQueryWindow(hwnd, QW_PARENT) );
        }
        break;

    default:
        mr = WinDefWindowProc( hwnd, msg, mp1, mp2 );
        break;
  }
  return mr;
}
