/* **********************************************************
   sessutil.c - Session DDE client for variable maintenance

   Placed in public domain by Horizon Technologies Inc. 1990

  ***revision history***
1 SESSUTIL.C 29-Jan-90,13:35:12,`JMH' Base version
2 SESSUTIL.C 28-Feb-90,13:52:26,`JMH' Version as of 3/5/90
3 SESSUTIL.C 6-Mar-90,15:23:10,`JMH' Version as of 3/5/90
4 SESSUTIL.C 19-Jun-90,10:51:20,`JMH' Version as of 6/25/90
5 SESSUTIL.C 25-Jun-90,14:48:08,`JMH' Version as of 6/25/90
6 SESSUTIL.C 17-Sep-90,11:38:30,`JMH' Version 1.3
  ***revision history***
********************************************************** */
#define MAIN
#define NOCOMM

#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "dde.h"
#include "ddelib.h"
#include "sessutil.h"

/* Undocumented windows functions */
int FAR PASCAL lstrlen (LPSTR);
LPSTR FAR PASCAL lstrcpy (LPSTR, LPSTR);
LPSTR FAR PASCAL lstrcat (LPSTR, LPSTR);
int FAR PASCAL lstrcmp (LPSTR, LPSTR);

/* Globals */
static HANDLE ghInstance;
static HWND ghWnd;
static char *gszAppName = "SessUtil";
static DDECALLBACK glpfnUser;
static FARPROC glpfnModify;
static FARPROC glpfnAbout;
static HANDLE ghSession;
static char gszUser[100];

/* Functions */
int PASCAL WinMain (HANDLE, HANDLE, LPSTR, int);
long FAR PASCAL SessutilProc (HWND, unsigned, WORD, LONG);
WORD FAR PASCAL User (HWND, unsigned, LPSTR, HANDLE);
BOOL FAR PASCAL Modify (HWND, unsigned, WORD, LONG);
void Poke (void);
BOOL FAR PASCAL About (HWND, unsigned, WORD, LONG);


int PASCAL WinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
   WNDCLASS wndclass;
   MSG msg;

   ghInstance = hInstance;

   if ( !hPrevInstance )
      {
      wndclass.style = CS_HREDRAW | CS_VREDRAW;
      wndclass.lpfnWndProc = SessutilProc;
      wndclass.cbClsExtra = 0;
      wndclass.cbWndExtra = 0;
      wndclass.hInstance = hInstance;
      wndclass.hIcon = LoadIcon ( hInstance, gszAppName );
      wndclass.hCursor = LoadCursor ( NULL, IDC_ARROW );
      wndclass.hbrBackground = (HBRUSH) GetStockObject ( WHITE_BRUSH );
      wndclass.lpszMenuName = gszAppName;
      wndclass.lpszClassName = gszAppName;

      if ( !RegisterClass ( &wndclass ) )
	 return FALSE;
      }  /* if ! hPrevInstance */

   ghWnd = CreateWindow ( gszAppName, gszAppName, WS_OVERLAPPEDWINDOW,
			  CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
			  hInstance, NULL );

   if ( !ghWnd )
      return ( NULL );

   ShowWindow ( ghWnd, nCmdShow );
   UpdateWindow ( ghWnd );

   while ( GetMessage ( &msg, NULL, NULL, NULL ) )
      {
      TranslateMessage ( &msg );
      DispatchMessage ( &msg );
      }  /* while GetMessage */

   return ( msg.wParam );
}  /* function WinMain */


long FAR PASCAL SessutilProc (hWnd, iMessage, wParam, lParam)
HWND hWnd;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   DDEADVISE ddeAdvise;
   PAINTSTRUCT ps;

   switch ( iMessage )
      {
      case WM_CREATE:
	 /* Provide callback addresses for DDE callback function */
	 glpfnUser = (DDECALLBACK) MakeProcInstance ( (FARPROC) User,
						      ghInstance );

	 /* Inititate a DDE Session with SESSION */
	 if ( !( ghSession = DDEInitiate ( hWnd, "Session", "Variables" ) ) )
	    break;

	 /* Ask to be advised everytime the User variable changes */
	 ddeAdvise.reserved = 0xABC;
	 ddeAdvise.fDeferUpd = FALSE;
	 ddeAdvise.fAckReq = TRUE;
	 ddeAdvise.cfFormat = CF_TEXT;
	 DDEAdvise ( ghSession, "User", &ddeAdvise, glpfnUser );
	 break;

      case WM_PAINT:
	 BeginPaint ( hWnd, &ps );
	 TextOut ( ps.hdc, 0, 0, gszUser, strlen ( gszUser ) );
	 EndPaint ( hWnd, &ps );
	 break;

      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDM_MODIFY:
	       glpfnModify = MakeProcInstance ( Modify, ghInstance );
	       if ( DialogBox ( ghInstance, "Modify", hWnd, glpfnModify ) )
		  Poke ();
	       FreeProcInstance ( glpfnModify );
	       break;

	    case IDM_EXIT:
	       SendMessage ( hWnd, WM_CLOSE, 0, 0L );
	       break;

	    case IDM_ABOUT:
	       glpfnAbout = MakeProcInstance ( About, ghInstance );
	       DialogBox ( ghInstance, "About", hWnd, glpfnAbout );
	       FreeProcInstance ( glpfnAbout );
	       break;
	    }  /* switch wParam */
	 break;

      case WM_DESTROY:
	 /* Cancel the advise circuit for User */
	 DDEUnadvise ( ghSession, "User" );

	 /* End the session with SESSION */
	 DDETerminate ( ghSession );

	 PostQuitMessage ( 0 );
	 break;

      default:
	 return DefWindowProc ( hWnd, iMessage, wParam, lParam );
      }  /* switch iMessage */

   return 0L;
}  /* function SessutilProc */


/* Callback routine to notify when the User variable changes */
WORD FAR PASCAL User (hSession, iMessage, lpszItem, hData)
HWND hSession;
unsigned iMessage;
LPSTR lpszItem;
HANDLE hData;
{
   LPDDEDATA lpData;

   switch ( iMessage )
      {
      case DDE_ACK:
	 break;

      case DDE_DATA:
	 /* Move data to the current user string */
	 lpData = (LPDDEDATA) GlobalLock ( hData );
	 lstrcpy ( gszUser, lpData->Value );
	 GlobalUnlock ( hData );

	 /* Force a repaint */
	 InvalidateRect ( ghWnd, NULL, TRUE );
	 break;

      case DDE_TERMINATE:
	 break;
      }

   return NULL;
}  /* function User */


/* Modify User variable dialog box */
BOOL FAR PASCAL Modify (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   switch ( iMessage )
      {
      case WM_INITDIALOG:
	 /* Initialize the value */
	 SetDlgItemText ( hDlg, IDD_USER, gszUser );
	 break;

      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDOK:
	       /* Get the new value */
	       GetDlgItemText ( hDlg, IDD_USER, gszUser, sizeof ( gszUser ) )
	    ;

	       EndDialog ( hDlg, TRUE );
	       break;

	    case IDCANCEL:
	       EndDialog ( hDlg, FALSE );
	       break;
	    }  /* switch wParam */
	 break;

      default:
	 return FALSE;
      }  /* switch iMessage */
   return TRUE;
}  /* function Modify */


/* Modify User variable dialog box */
void Poke ()
{
   HANDLE hPoke;
   LPDDEPOKE lpPoke;

   /* Create a poke structure */
   hPoke = GlobalAlloc ( GHND | GMEM_DDESHARE, (DWORD) sizeof ( DDEPOKE ) +
			 strlen ( gszUser ) );

   /* Fill in the poke structure */
   lpPoke = (LPDDEPOKE) GlobalLock ( hPoke );
   lpPoke->fRelease = TRUE;
   lpPoke->cfFormat = CF_TEXT;
   lstrcpy ( lpPoke->Value, gszUser );
   GlobalUnlock ( hPoke );

   DDEPoke ( ghSession, "User", hPoke );
}  /* function Poke */


/* About box */
BOOL FAR PASCAL About (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   switch ( iMessage )
      {
      case WM_INITDIALOG:
	 break;

      case WM_COMMAND:
	 EndDialog ( hDlg, FALSE );
	 break;

      default:
	 return FALSE;
      }  /* switch iMessage */
   return TRUE;
}  /* function About */
