//	Zinc Application Framework - W_APP.HPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#ifndef W_APP_HPP
#define W_APP_HPP

#include <z_env.hpp>

#define ZAF_WINDOW_CLASSA		"ZafWindow"
#define ZAF_MDI_FRAME_CLASSA	"ZafMDIFrame"
#define ZAF_MDI_CHILD_CLASSA	"ZafMDIChild"
#define ZAF_WINDOW_CLASSW		L"ZafWindow"
#define ZAF_MDI_FRAME_CLASSW	L"ZafMDIFrame"
#define ZAF_MDI_CHILD_CLASSW	L"ZafMDIChild"
#if defined(ZAF_UNICODE)
#	define ZAF_WINDOW_CLASS		ZAF_WINDOW_CLASSW
#	define ZAF_MDI_FRAME_CLASS	ZAF_MDI_FRAME_CLASSW
#	define ZAF_MDI_CHILD_CLASS	ZAF_MDI_CHILD_CLASSW
#else
#	define ZAF_WINDOW_CLASS		ZAF_WINDOW_CLASSA
#	define ZAF_MDI_FRAME_CLASS	ZAF_MDI_FRAME_CLASSA
#	define ZAF_MDI_CHILD_CLASS	ZAF_MDI_CHILD_CLASSA
#endif

// Unique timer identifiers.
#define ZAF_BUTTON_TIMER_ID			1
#define ZAF_DEVICE_TIMER_ID			2
#define ZAF_MOUSE_TIMER_ID			3

// Special constants.
#define ZAF_MOUSE_TEST_INTERVAL		500

// Special flag set by the GetWinFlags API under NT.
#define WF_WINNT	0x4000

enum ZafWindowsPlatform
{
	ZAF_WIN16,
	ZAF_WIN32S,
	ZAF_WIN32_WINDOWS,
	ZAF_WIN32_NT
};

/*
//??? How much overhead does this macro have?!
#define DefaultCallback(event) ((GetClassLong(event.osEvent.hwnd, \
	GCL_WNDPROC)) ? (ZafEventType)CallWindowProc(\
	(WINDOWSPROC)GetClassLong(event.osEvent.hwnd, GCL_WNDPROC),\
	event.osEvent.hwnd, event.osEvent.message, event.osEvent.wParam,\
	event.osEvent.lParam) : 0)
*/
struct ZafEventStruct;
ZafEventType DefaultCallback(const ZafEventStruct &event);

class ZAF_EXPORT ZafWindowObject;
class ZAF_EXPORT ZafMSWindowsApp
{
public:
	static ZafWindowsPlatform windowsPlatform;
	static int windowsVersion;
#if defined(ZAF_WIN32)
#else
#	if !defined(__WATCOMC__)
	static ATOM objectLowWord;
	static ATOM objectHighWord;
#	else
	static char *objectLowWord;
	static char *objectHighWord;
#	endif
#endif
#if defined(ZAF_WIN32)
	static bool commonControlsAvailable;
#endif
#if defined(ZAF_MSWINDOWS_3D)
	static bool native3D;
	static bool available3D;
#endif
	static HINSTANCE hInstance;
	static bool convertText;
	static bool dragTest;
#if defined(ZAF_WIN32)
	static POINTS dragStartPosition;
#else
	static POINT ZAF_FARDATA dragStartPosition;
#endif
	static UINT mouseTimerID;
	static HWND dropDownCombo;

	static LRESULT FrameProc(LRESULT (DefaultProc)(HWND, UINT,
		WPARAM, LPARAM), HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
	static LRESULT CALLBACK JumpProc(HWND hwnd, UINT wMsg,
		WPARAM wParam, LPARAM lParam);
	static LRESULT CALLBACK FrameJumpProc(HWND hwnd, UINT wMsg,
		WPARAM wParam, LPARAM lParam);
	static LRESULT CALLBACK MDIFrameJumpProc(HWND hwnd, UINT wMsg,
		WPARAM wParam, LPARAM lParam);
	static LRESULT CALLBACK MDIChildJumpProc(HWND hwnd, UINT wMsg,
		WPARAM wParam, LPARAM lParam);
	static ZafWindowObject *ObjectFromHandle(HWND hwnd);

//??? parameter order. (Text is usually set after creation.)
	static HWND CreateSubclassedWindow(ZafWindowObject *object, const ZafIChar *lpClassName,
		DWORD dwStyle, const ZafIChar *text = NULL,	HWND hwndParent = 0,
		DWORD dwExStyle = WS_EX_NOPARENTNOTIFY,	HINSTANCE dataSegment = 0,
		LPVOID lpvParam = 0);
	static ZafIChar *HotKeyText(const ZafIChar *text, int hotKeyIndex);

	// CTL3D functions (for non-native 3D support)
	// Resolved by loading ctl3d32.dll (32-bit) or ctl3dv2 (16 bit)
	static HMODULE ctl3dModule;
	static BOOL (WINAPI *Ctl3dRegister)(HINSTANCE);
	static BOOL (WINAPI *Ctl3dEnabled)(void);
	static BOOL (WINAPI *Ctl3dAutoSubclass)(HINSTANCE);
	static BOOL (WINAPI *Ctl3dUnregister)(HINSTANCE);
	static BOOL (WINAPI *Ctl3dSubclassCtl)(HWND);

	ZafMSWindowsApp(HINSTANCE hInstance);
	virtual ~ZafMSWindowsApp(void);

	// Unicode support for Windows 95.
	void InitializeWrappers(void);
};

// Unicode support.
#if defined(ZAF_WIN32) && defined(ZAF_UNICODE)
extern LRESULT (__stdcall *ZafCallWindowProc)(WINDOWSPROC lpPrevWndFunc, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern LRESULT (__stdcall *ZafDefFrameProc)(HWND hwnd, HWND hWndMDIClient, UINT msg, WPARAM wParam, LPARAM lParam);
extern LRESULT (__stdcall *ZafDefWindowProc)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern LRESULT (__stdcall *ZafDefMDIChildProc)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern LONG (__stdcall *ZafDispatchMessage)(CONST MSG *lpmsg);
extern DWORD (__stdcall *ZafGetClassLong)(HWND hwnd, int nIndex);
extern BOOL (__stdcall *ZafGetMessage)(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
extern BOOL (__stdcall *ZafPeekMessage)(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);
extern BOOL (__stdcall *ZafPostMessage)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern LRESULT (__stdcall *ZafSendMessage)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern int (__stdcall *ZafGetObject)(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
extern LONG (__stdcall *ZafGetWindowLong)(HWND hwnd, int index);
extern LONG (__stdcall *ZafSetWindowLong)(HWND hwnd, int index, long dwNewLong);

HWND ZafCreateWindowEx(DWORD dwExStyle, LPCSTR lpClassName,
	LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight,
	HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
HWND ZafCreateWindowEx(DWORD dwExStyle, LPCWSTR lpClassName,
	LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight,
	HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);

int ZafDrawText(HDC hDC, LPCSTR lpString, int nCount, LPRECT lpRect,
	UINT uFormat);
int ZafDrawText(HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect,
	UINT uFormat);

BOOL ZafAppendMenu(HMENU hMenu, UINT uFlags, UINT uIDNewItem, LPCSTR lpNewItem);
BOOL ZafAppendMenu(HMENU hMenu, UINT uFlags, UINT uIDNewItem, LPCWSTR lpNewItem);

BOOL ZafModifyMenu(HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, LPCSTR lpNewItem);
BOOL ZafModifyMenu(HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, LPCWSTR lpNewItem);

HCURSOR ZafLoadCursor(HINSTANCE hInstance, LPCSTR lpCursorName);
HCURSOR ZafLoadCursor(HINSTANCE hInstance, LPCWSTR lpCursorName);

DWORD ZafGetProfileString(LPCSTR lpAppName, LPCSTR lpKeyName,
	LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize);

DWORD ZafGetProfileString(LPCWSTR lpAppName, LPCWSTR lpKeyName,
	LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize);

UINT ZafGetProfileInt(LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault);

UINT ZafGetProfileInt(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault);


#endif

inline ZafWindowObject *ZafMSWindowsApp::ObjectFromHandle(HWND hwnd)
{
#if defined(ZAF_WIN32)
	return ((ZafWindowObject *)GetWindowLong(hwnd, GWL_USERDATA));
#else
	return ((ZafWindowObject *)MAKELONG(GetProp(hwnd, (LPCSTR)objectLowWord),
		GetProp(hwnd, (LPCSTR)objectHighWord)));
#endif
}

#endif
