//
//**************************************************************************
//
// BOleHelp.cpp -- Implements message hooks for catching F1 in the dialogs
//
// Copyright (c) 1993,94 by Borland International, Inc. All rights reserved
//
//**************************************************************************

#include "BOle.h"
#include "BOleSvc.h"
extern "C" {
#include "Ole2UI.h"
#include "Common.h"
}

















// GetBOleHook -- Examine the parameters to our hook proc and determine if 
//                it's a message we should handle. If so, return the hook 
//                out of the window properties
//
HHOOK GetBOleHook (int code, WPARAM wParam, LPARAM lParam)
{
	HHOOK hHook = NULL;

	// Make sure the message is one we should handle
	//
	if (code != MSGF_DIALOGBOX                 || 
		((LPMSG) lParam)->message != WM_KEYDOWN ||
		((LPMSG) lParam)->wParam != VK_F1)
		 return hHook; 

	// The window property "Structure" contains the private part of the
	// dialog struct (INSERTOBJECT is private, OLEUIINSERTOBJECT is public)
	//
	HWND hwnd = GetParent (((LPMSG) lParam)->hwnd);
	HANDLE hOleUIStd = GetProp (hwnd, TEXT(STRUCTUREPROP));
	if (!hOleUIStd)
		return hHook;

	// The data model in OLE2UI is limiting here. If we want to get the
	// pointer to the public part of a dialog struct, there's nothing to
	// cast this pointer to. OleUIStandard doesn't have the pointer in the
	// beginning like the private declarations of the dialog box structs!
	//
	LPOLEUISTANDARD pOleUIStd = (LPOLEUISTANDARD) ((LPLONG) GlobalLock (hOleUIStd))[0];
	if (!pOleUIStd)
		return hHook;

	// If we're a system-wide hook, make sure this hook was installed in
	// this task before returning it.
	//

	hHook = pOleUIStd->hHook;
	
	GlobalUnlock (hOleUIStd);
	return hHook;
}

// MyHookProc is a MessageProc callback for SetWindowsHookEx which allows
// us to catch messages during our dialog boxes. We're looking for F1
// keystrokes which would otherwise be eaten by the control with focus.
//
extern "C" LRESULT _loadds CALLBACK MyHookProc (int code, WPARAM wParam, LPARAM lParam)
{
	HHOOK hHook = GetBOleHook (code, wParam, lParam);
	if (hHook) {

		// The window which really gets the message is the control, so the
		// dialog is its parent
		//
		HWND w = GetParent (((LPMSG) lParam)->hwnd);
#ifdef ANSI
		::PostMessageA(w, RegisterWindowMessageA(HELPMSGSTRINGA), 0, 0);
#else
		::PostMessage(w, RegisterWindowMessage(HELPMSGSTRING), 0, 0);
#endif
		return ::CallNextHookEx (hHook, code, wParam, lParam);
	}




	return 0; 
}

// EnterBOleDialog has two basic jobs:
// 1. Install and remove the Windows hook which allows us to catch
//    F1 keystrokes while we're running a BOleUI dialog box.
// 2. Make sure we do the right enabling of modeless dialogs around
//    the system
//
void _IFUNC BOleService::EnterBOleDialog (BOOL fEnter, HHOOK& hHook, HTASK& hTask)
{
	// If we're closing this dialog box, remove the Windows hook 
	//
	if (!fEnter) {
		::UnhookWindowsHook (WH_MSGFILTER, MyHookProc);

		OnModalDialog (FALSE);
		return;
	}

	BOOL fHookSuccess = TRUE;

	// Find the address of the callback for the Windows hook
	//
	HOOKPROC hookProc = (HOOKPROC)MyHookProc; //
	if (!hookProc) 
		fHookSuccess = FALSE;

	// Install the Windows hook
	//
	if (fHookSuccess) {
#ifndef WIN32
		hHook = ::SetWindowsHook (WH_MSGFILTER, hookProc);

#else
#ifdef ANSI
		hHook = ::SetWindowsHookExA(WH_MSGFILTER, hookProc, NULL, GetCurrentThreadId() );
#else
		hHook = ::SetWindowsHookEx(WH_MSGFILTER, hookProc, NULL, GetCurrentThreadId() );
#endif
#endif
		if (!hHook) 
			fHookSuccess = FALSE;

		// Pass back the current "task"
		//
#ifndef	WIN32
		hTask = GetCurrentTask();
#else
		hTask = (HTASK)GetCurrentThread();
#endif
	}

	// Use the same thing Bolero clients do to en/disable modeless dialogs
	//
	OnModalDialog (TRUE);
}

// BOleHelpNotify is a C function which is exposed to the OLE2UI dialog
// boxes (but not to other DLLs) for them to call back to get help from 
// the application.
//
// 2 minor hacks are used here to solve the language differences between
// the Bolero header files (C++ only) and OLE2UI (C, and I don't have the 
// time to convert it to C++)
//
// 1. We're using the resource IDs of the dialog boxes to identify which 
//    dialog box to provide help on since OLE2UI can't compile the 
//    BOleDialogHelp enum.
//
// 2. The pCastToApp parameter is used because OLE2UI can't compile the
//    class definition for IBApplication.
//
extern "C" void BOleHelpNotify (DWORD pCastToApp, int dialogResId)
{
	BOleDialogHelp helpCode;
	switch (dialogResId) {
		case IDD_INSERTOBJECT : helpCode = BOLE_HELP_BROWSE;          break;
		case IDD_PASTESPECIAL : helpCode = BOLE_HELP_BROWSECLIPBOARD; break;
		case IDD_CONVERT      : helpCode = BOLE_HELP_CONVERT;         break;
		case IDD_EDITLINKS    : helpCode = BOLE_HELP_BROWSELINKS;     break;
		case IDD_CHANGEICON   : helpCode = BOLE_HELP_CHANGEICON;      break;
		case IDD_INSERTFILEBROWSE
		                      : helpCode = BOLE_HELP_FILEOPEN;        break;
		case IDD_CHANGESOURCE : helpCode = BOLE_HELP_SOURCESET;       break;
		case IDD_CHANGEICONBROWSE
		                      : helpCode = BOLE_HELP_ICONFILEOPEN;    break;
		default               : return;
	}

	PIBApplication pIApp = (PIBApplication) pCastToApp;
	pIApp->DialogHelpNotify (helpCode);
}



