/* **********************************************************
   accexcel.c - Access to Excell demo program

   Placed in public domain by Horizon Technologies Inc. 1990

  ***revision history***
1 ACCEXCEL.C 19-Jun-90,10:51:06,`JMH' Base version
2 ACCEXCEL.C 25-Jun-90,14:47:50,`JMH' Version as of 6/25/90
3 ACCEXCEL.C 15-Sep-90,16:36:10,`JMH' Version 1.3
  ***revision history***
********************************************************** */
#define MAIN
#define NOCOMM

#include "windows.h"
#include "dde.h"
#include "ddelib.h"
#include "string.h"
#include "accexcel.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 char *gszAppName = "accexcel";
static char gszApp[40] = "excel";
static char gszTopic[40] = "sheet1";
static char gszItem[40] = "r1c1";
static char gszData[80] = "7";
static char gszCommand[80] = "[open(\"sheet2\")]";
static int gcfFormat;
static int fDeferUpd = FALSE;
static int fAckReq = TRUE;
static FARPROC glpfnCallBack;

/* Functions */
int PASCAL WinMain (HANDLE, HANDLE, LPSTR, int);
long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL Initiate (HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL Advise (HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL Unadvise (HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL Request (HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL Poke (HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL Execute (HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL About (HWND, unsigned, WORD, LONG);
WORD FAR PASCAL CallBack (HWND, unsigned, LPSTR, HANDLE);


int PASCAL WinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
   WNDCLASS wndclass;
   MSG msg;
   HWND hWnd;

   ghInstance = hInstance;

   if ( !hPrevInstance )
      {
      wndclass.style = CS_HREDRAW | CS_VREDRAW;
      wndclass.lpfnWndProc = WndProc;
      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 */

   hWnd = CreateWindow ( gszAppName, gszAppName, WS_OVERLAPPEDWINDOW,
			 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
			 hInstance, NULL );

   if ( !hWnd )
      return ( NULL );

   ShowWindow ( hWnd, nCmdShow );
   UpdateWindow ( hWnd );

   gcfFormat = RegisterClipboardFormat ( "csv" );
   glpfnCallBack = MakeProcInstance ( CallBack, ghInstance );

   while ( GetMessage ( &msg, NULL, NULL, NULL ) )
      {
      TranslateMessage ( &msg );
      DispatchMessage ( &msg );
      }  /* while GetMessage */

   FreeProcInstance ( glpfnCallBack );

   return ( msg.wParam );
}  /* function WinMain */


long FAR PASCAL WndProc (hWnd, iMessage, wParam, lParam)
HWND hWnd;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   static HWND hClient = NULL;
   FARPROC lpfnFunc;
   DDEACK wAck;
   HANDLE hCommand;
   HANDLE hPoke;
   LPSTR lpCommand;
   LPDDEPOKE lpPoke;
   DDEADVISE ddeAdvise;
   int iRet;

   switch ( iMessage )
      {
      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDM_EXIT:
	       SendMessage ( hWnd, WM_CLOSE, 0, 0L );
	       break;

	    case IDM_ABOUT:
	       lpfnFunc = MakeProcInstance ( About, ghInstance );
	       DialogBox ( ghInstance, "About", hWnd, lpfnFunc );
	       FreeProcInstance ( lpfnFunc );
	       break;

	    case IDM_INITIATE:
	       if ( hClient )
		  {
		  DDETerminate ( hClient );
		  hClient = NULL;
		  }  /* if hClient */

	       lpfnFunc = MakeProcInstance ( Initiate, ghInstance );
	       iRet = DialogBox ( ghInstance, "Initiate", hWnd, lpfnFunc );
	       FreeProcInstance ( lpfnFunc );

	       if ( iRet == IDOK )
		  {
		  hClient = DDEInitiate ( hWnd, gszApp, gszTopic );

		  MessageBox ( hWnd, hClient ? "Session established" :
			       "Initiate failed", "Initiate", MB_OK );
		  }  /* if iRet */
	       break;

	    case IDM_ADVISE:
	       if ( !hClient )
		  break;

	       lpfnFunc = MakeProcInstance ( Advise, ghInstance );
	       iRet = DialogBox ( ghInstance, "Advise", hWnd, lpfnFunc );
	       FreeProcInstance ( lpfnFunc );

	       if ( iRet == IDOK )
		  {
		  /* Fill in the advise structure */
		  ddeAdvise.reserved = 0;
		  ddeAdvise.fDeferUpd = fDeferUpd;
		  ddeAdvise.fAckReq = fAckReq;
		  ddeAdvise.cfFormat = gcfFormat;

		  *(WORD *) &wAck = DDEAdvise ( hClient, gszItem, &ddeAdvise,
						glpfnCallBack );

		  MessageBox ( hWnd, wAck.fAck ? "Advise succeeded" :
			       "Advise failed", "Advise", MB_OK );
		  }  /* if iRet */
	       break;

	    case IDM_UNADVISE:
	       if ( !hClient )
		  break;

	       lpfnFunc = MakeProcInstance ( Unadvise, ghInstance );
	       iRet = DialogBox ( ghInstance, "Unadvise", hWnd, lpfnFunc );
	       FreeProcInstance ( lpfnFunc );

	       if ( iRet == IDOK )
		  {
		  *(WORD *) &wAck = DDEUnadvise ( hClient, gszItem );

		  MessageBox ( hWnd, wAck.fAck ? "Unadvise succeeded" :
			       "Unadvise failed", "Unadvise", MB_OK );
		  }  /* if iRet */
	       break;

	    case IDM_REQUEST:
	       if ( !hClient )
		  break;

	       lpfnFunc = MakeProcInstance ( Request, ghInstance );
	       iRet = DialogBox ( ghInstance, "Request", hWnd, lpfnFunc );
	       FreeProcInstance ( lpfnFunc );

	       if ( iRet == IDOK )
		  {
		  *(WORD *) &wAck = DDERequest ( hClient, gszItem, gcfFormat,
						 glpfnCallBack );

		  MessageBox ( hWnd, wAck.fAck ? "Request succeeded" :
			       "Request failed", "Request", MB_OK );
		  }  /* if iRet */
	       break;

	    case IDM_POKE:
	       if ( !hClient )
		  break;

	       lpfnFunc = MakeProcInstance ( Poke, ghInstance );
	       iRet = DialogBox ( ghInstance, "Poke", hWnd, lpfnFunc );
	       FreeProcInstance ( lpfnFunc );

	       if ( iRet == IDOK )
		  {
		  hPoke = GlobalAlloc ( GHND | GMEM_DDESHARE, (DWORD) sizeof
					( DDEPOKE ) + strlen ( gszData ) );

		  /* Fill in the poke structure */
		  lpPoke = (LPDDEPOKE) GlobalLock ( hPoke );
		  lpPoke->fRelease = TRUE;
		  lpPoke->cfFormat = gcfFormat;
		  lstrcpy ( lpPoke->Value, gszData );
		  GlobalUnlock ( hPoke );

		  *(WORD *) &wAck = DDEPoke ( hClient, gszItem, hPoke );

		  MessageBox ( hWnd, wAck.fAck ? "Poke succeeded" :
			       "Poke failed", "Poke", MB_OK );
		  }  /* if iRet */
	       break;

	    case IDM_EXECUTE:
	       if ( !hClient )
		  break;

	       lpfnFunc = MakeProcInstance ( Execute, ghInstance );
	       iRet = DialogBox ( ghInstance, "Execute", hWnd, lpfnFunc );
	       FreeProcInstance ( lpfnFunc );

	       if ( iRet == IDOK )
		  {
		  hCommand = GlobalAlloc ( GHND | GMEM_DDESHARE, (DWORD)
					   strlen ( gszCommand ) );

		  /* Fill in the poke structure */
		  lpCommand = (LPSTR) GlobalLock ( hCommand );
		  lstrcpy ( lpCommand, gszCommand );
		  GlobalUnlock ( hCommand );

		  *(WORD *) &wAck = DDEExecute ( hClient, hCommand );

		  MessageBox ( hWnd, wAck.fAck ? "Execute succeeded" :
			       "Execute failed", "Execute", MB_OK );
		  }  /* if iRet */
	       break;

	    case IDM_TERMINATE:
	       if ( hClient )
		  {
		  DDETerminate ( hClient );
		  hClient = NULL;
		  }  /* if hClient */
	       break;
	    }  /* switch wParam */
	 break;

      case WM_DESTROY:
	 if ( hClient )
	    {
	    DDETerminate ( hClient );
	    hClient = NULL;
	    }  /* if hClient */
	 PostQuitMessage ( 0 );
	 break;

      default:
	 return DefWindowProc ( hWnd, iMessage, wParam, lParam );
      }  /* switch iMessage */

   return 0L;
}  /* function WndProc */


/* Initiate box */
BOOL FAR PASCAL Initiate (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   switch ( iMessage )
      {
      case WM_INITDIALOG:
	 SetDlgItemText ( hDlg, IDD_APP, gszApp );
	 SetDlgItemText ( hDlg, IDD_TOPIC, gszTopic );
	 break;

      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDOK:
	       GetDlgItemText ( hDlg, IDD_APP, gszApp, sizeof ( gszApp ) );
	       GetDlgItemText ( hDlg, IDD_TOPIC, gszTopic, sizeof ( gszTopic
				) );
	       EndDialog ( hDlg, wParam );
	       break;

	    case IDCANCEL:
	       EndDialog ( hDlg, wParam );
	       break;
	    }  /* switch wParam */
	 break;

      default:
	 return FALSE;
      }  /* switch iMessage */
   return TRUE;
}  /* function Initiate */


/* Advise box */
BOOL FAR PASCAL Advise (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   switch ( iMessage )
      {
      case WM_INITDIALOG:
	 SetDlgItemText ( hDlg, IDD_ITEM, gszItem );
	 break;

      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDOK:
	       GetDlgItemText ( hDlg, IDD_ITEM, gszItem, sizeof ( gszItem ) );
	       EndDialog ( hDlg, wParam );
	       break;

	    case IDCANCEL:
	       EndDialog ( hDlg, wParam );
	       break;
	    }  /* switch wParam */
	 break;

      default:
	 return FALSE;
      }  /* switch iMessage */
   return TRUE;
}  /* function Advise */


/* Unadvise box */
BOOL FAR PASCAL Unadvise (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   switch ( iMessage )
      {
      case WM_INITDIALOG:
	 SetDlgItemText ( hDlg, IDD_ITEM, gszItem );
	 break;

      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDOK:
	       GetDlgItemText ( hDlg, IDD_ITEM, gszItem, sizeof ( gszItem ) );
	       EndDialog ( hDlg, wParam );
	       break;

	    case IDCANCEL:
	       EndDialog ( hDlg, wParam );
	       break;
	    }  /* switch wParam */
	 break;

      default:
	 return FALSE;
      }  /* switch iMessage */
   return TRUE;
}  /* function Unadvise */


/* Request box */
BOOL FAR PASCAL Request (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   switch ( iMessage )
      {
      case WM_INITDIALOG:
	 SetDlgItemText ( hDlg, IDD_ITEM, gszItem );
	 break;

      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDOK:
	       GetDlgItemText ( hDlg, IDD_ITEM, gszItem, sizeof ( gszItem ) );
	       EndDialog ( hDlg, wParam );
	       break;

	    case IDCANCEL:
	       EndDialog ( hDlg, wParam );
	       break;
	    }  /* switch wParam */
	 break;

      default:
	 return FALSE;
      }  /* switch iMessage */
   return TRUE;
}  /* function Request */


/* Poke box */
BOOL FAR PASCAL Poke (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   switch ( iMessage )
      {
      case WM_INITDIALOG:
	 SetDlgItemText ( hDlg, IDD_ITEM, gszItem );
	 SetDlgItemText ( hDlg, IDD_DATA, gszData );
	 break;

      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDOK:
	       GetDlgItemText ( hDlg, IDD_ITEM, gszItem, sizeof ( gszItem ) );
	       GetDlgItemText ( hDlg, IDD_DATA, gszData, sizeof ( gszData ) );
	       EndDialog ( hDlg, wParam );
	       break;

	    case IDCANCEL:
	       EndDialog ( hDlg, wParam );
	       break;
	    }  /* switch wParam */
	 break;

      default:
	 return FALSE;
      }  /* switch iMessage */
   return TRUE;
}  /* function Poke */


/* Execute box */
BOOL FAR PASCAL Execute (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
   switch ( iMessage )
      {
      case WM_INITDIALOG:
	 SetDlgItemText ( hDlg, IDD_COMMAND, gszCommand );
	 break;

      case WM_COMMAND:
	 switch ( wParam )
	    {
	    case IDOK:
	       GetDlgItemText ( hDlg, IDD_COMMAND, gszCommand,
				sizeof ( gszCommand ) );
	       EndDialog ( hDlg, wParam );
	       break;

	    case IDCANCEL:
	       EndDialog ( hDlg, wParam );
	       break;
	    }  /* switch wParam */
	 break;

      default:
	 return FALSE;
      }  /* switch iMessage */
   return TRUE;
}  /* function Execute */


/* 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 */


/* Callback routine for advise circuit */
WORD FAR PASCAL CallBack (hSession, iMessage, lpszItem, hData)
HWND hSession;
unsigned iMessage;
LPSTR lpszItem;
HANDLE hData;
{
   LPDDEDATA lpData;


   switch ( iMessage )
      {
      case DDE_ACK:
	 break;

      case DDE_DATA:
	 /* Show the data */
	 lpData = (LPDDEDATA) GlobalLock ( hData );
	 MessageBox ( NULL, lpData->Value, lpszItem, MB_OK );
	 GlobalUnlock ( hData );
	 break;

      case DDE_TERMINATE:
	 break;
      }

   return NULL;
}  /* function CallBack */
