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

// Give ZafMSWindowsApp access to protected data.
#define OSWindow ZafMSWindowsApp
#define OSWindowObject ZafMSWindowsApp
#include <w_app.hpp>
#include <z_win.hpp>

//??? Development Only
#if defined(ZAF_DEBUG)
FILE *debug = NULL;
#endif

// ----- ZafMSWindowsApp ---------------------------------------------------------

// Allocate/Initialize static member variables.
ZafWindowsPlatform ZafMSWindowsApp::windowsPlatform;
int ZafMSWindowsApp::windowsVersion;
HINSTANCE ZafMSWindowsApp::hInstance = 0;
#if defined(ZAF_WIN32)
bool ZafMSWindowsApp::commonControlsAvailable = false;
#else
#	if defined(__WATCOMC__)
char *ZafMSWindowsApp::objectLowWord = "zafObjectLow";
char *ZafMSWindowsApp::objectHighWord = "zafObjectHigh";
#	else
ATOM ZafMSWindowsApp::objectLowWord = 0;
ATOM ZafMSWindowsApp::objectHighWord = 0;
#	endif
#endif
bool ZafMSWindowsApp::convertText = false;
bool ZafMSWindowsApp::dragTest = false;
#if defined(ZAF_WIN32)
POINTS ZafMSWindowsApp::dragStartPosition;
#else
POINT ZAF_FARDATA ZafMSWindowsApp::dragStartPosition;
#endif
#if defined(ZAF_MSWINDOWS_3D)
bool ZafMSWindowsApp::native3D = false;
bool ZafMSWindowsApp::available3D = false;
#endif
UINT ZafMSWindowsApp::mouseTimerID = 0;
HWND ZafMSWindowsApp::dropDownCombo = 0;

HMODULE ZafMSWindowsApp::ctl3dModule = 0;
BOOL (WINAPI *ZafMSWindowsApp::Ctl3dRegister)(HINSTANCE) = 0;
BOOL (WINAPI *ZafMSWindowsApp::Ctl3dEnabled)(void) = 0;
BOOL (WINAPI *ZafMSWindowsApp::Ctl3dAutoSubclass)(HINSTANCE) = 0;
BOOL (WINAPI *ZafMSWindowsApp::Ctl3dUnregister)(HINSTANCE) = 0;
BOOL (WINAPI *ZafMSWindowsApp::Ctl3dSubclassCtl)(HWND) = 0;


ZafMSWindowsApp::ZafMSWindowsApp(HINSTANCE tHInstance)
{
	// Save the instance handle.
	hInstance = tHInstance;

	// Get Windows version information.
#if defined(ZAF_WIN32)
#if defined(ZAF_UNICODE)
	OSVERSIONINFOA versionInfo;
	versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
	GetVersionExA(&versionInfo);
#else
	OSVERSIONINFO versionInfo;
	versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
	GetVersionEx(&versionInfo);
#endif
	windowsVersion = versionInfo.dwMajorVersion * 100 + versionInfo.dwMinorVersion % 100;
	if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32s)
		windowsPlatform = ZAF_WIN32S;
	else if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
		windowsPlatform = ZAF_WIN32_WINDOWS;
	else if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
		windowsPlatform = ZAF_WIN32_NT;
#else
	DWORD versionInfo = GetVersion();
	windowsVersion = LOBYTE(LOWORD(versionInfo)) * 100 + HIBYTE(LOWORD(versionInfo)) % 100;
	if (windowsVersion == 395)
		windowsPlatform = ZAF_WIN32_WINDOWS;
	else if (windowsVersion == 310)
	{
		if (GetWinFlags() & WF_WINNT)
			windowsPlatform = ZAF_WIN32_NT;
		else
			windowsPlatform = ZAF_WIN16;
	}
	else
		windowsPlatform = ZAF_WIN16;
#endif

#if defined(ZAF_WIN32)
	// See if "common controls" are available.
	if ((windowsPlatform == ZAF_WIN32_WINDOWS) ||
		(windowsPlatform == ZAF_WIN32_NT && windowsVersion >= 351) ||
		(windowsPlatform == ZAF_WIN32S && windowsVersion >= 103))
			commonControlsAvailable = true;
	else
		commonControlsAvailable = false;
#endif

#if defined(ZAF_MSWINDOWS_3D)
	if ((windowsPlatform == ZAF_WIN32_WINDOWS) ||
		(windowsPlatform == ZAF_WIN32_NT && windowsVersion >= 351) ||
		(windowsPlatform == ZAF_WIN32S && windowsVersion >= 103))
			native3D = true;
	else
		native3D = false;

	if (native3D)
		available3D = true;
	else
	{
#if defined(ZAF_WIN32)
		ctl3dModule = LoadLibraryA("ctl3d32.dll");
		if (ctl3dModule)
#else
		ctl3dModule = LoadLibrary("ctl3dv2.dll");
		if (ctl3dModule > HINSTANCE_ERROR)
#endif
		{
			Ctl3dRegister = (BOOL (WINAPI *)(HINSTANCE))GetProcAddress(ctl3dModule, (LPCSTR)12);
			Ctl3dEnabled = (BOOL (WINAPI *)(void))GetProcAddress(ctl3dModule, (LPCSTR)5);
			Ctl3dAutoSubclass = (BOOL (WINAPI *)(HINSTANCE))GetProcAddress(ctl3dModule, (LPCSTR)16);
			Ctl3dUnregister = (BOOL (WINAPI *)(HINSTANCE))GetProcAddress(ctl3dModule, (LPCSTR)13);
			Ctl3dSubclassCtl = (BOOL (WINAPI *)(HWND))GetProcAddress(ctl3dModule, (LPCSTR)3);

			Ctl3dRegister(hInstance);
			if (Ctl3dEnabled())
			{
				available3D = true;
				Ctl3dAutoSubclass(hInstance);
			}
			else
				available3D = false;
		}
		else
			available3D = false;
	}
#endif

#if !defined(ZAF_WIN32)
	// Create atoms for quickly retrieving object pointers from 
	// windows' properties.
#	if !defined(__WATCOMC__)
	objectLowWord = GlobalAddAtom("zafObjectLow");
	objectHighWord = GlobalAddAtom("zafObjectHigh");
#	endif
#endif

	// See if the text storage format is the same for the OS and for ZAF
	// or if text must be converted when calling OS API's.
#if defined(ZAF_UNICODE)
#	if defined(ZAF_WIN32)
	// See if the unicode OS API's are available.
	if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
		convertText = false;
	else
		convertText = true;
#	else
	convertText = true;
#	endif
#elif defined(ZAF_ISO8859_1)
	convertText = false;
#else
	convertText = false;
#endif

	InitializeWrappers();

	// Register Zinc's window classes.
#if defined(ZAF_WIN32)
	if (convertText)
	{
		WNDCLASSA wndClass;
		wndClass.style = CS_DBLCLKS;
		wndClass.lpfnWndProc = DefWindowProc;
		wndClass.cbClsExtra = 0;
		wndClass.cbWndExtra = 0;
		wndClass.hInstance = hInstance;
		wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
		wndClass.hCursor = LoadCursor(NULL, (LPCSTR)IDC_ARROW);
		wndClass.hbrBackground = 0;
		wndClass.lpszMenuName = 0;
		wndClass.lpszClassName = ZAF_WINDOW_CLASSA;
		RegisterClassA(&wndClass);
		wndClass.lpfnWndProc = MDIFrameJumpProc;
		wndClass.lpszClassName = ZAF_MDI_FRAME_CLASSA;
		RegisterClassA(&wndClass);
		wndClass.lpfnWndProc = MDIChildJumpProc;
		wndClass.lpszClassName = ZAF_MDI_CHILD_CLASSA;
		RegisterClassA(&wndClass);
	}
	else
	{
		WNDCLASS wndClass;
		wndClass.style = CS_DBLCLKS;
		wndClass.lpfnWndProc = DefWindowProc;
		wndClass.cbClsExtra = 0;
		wndClass.cbWndExtra = 0;
		wndClass.hInstance = hInstance;
		wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
		wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
		wndClass.hbrBackground = 0;
		wndClass.lpszMenuName = 0;
		wndClass.lpszClassName = ZAF_WINDOW_CLASS;
		RegisterClass(&wndClass);
		wndClass.lpfnWndProc = MDIFrameJumpProc;
		wndClass.lpszClassName = ZAF_MDI_FRAME_CLASS;
		RegisterClass(&wndClass);
		wndClass.lpfnWndProc = MDIChildJumpProc;
		wndClass.lpszClassName = ZAF_MDI_CHILD_CLASS;
		RegisterClass(&wndClass);
	}
#else
	WNDCLASS wndClass;
	wndClass.style = CS_DBLCLKS;
	wndClass.lpfnWndProc = DefWindowProc;
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hInstance = hInstance;
	wndClass.hIcon = 0;
	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndClass.hbrBackground = 0;
	wndClass.lpszMenuName = 0;
	wndClass.lpszClassName = ZAF_WINDOW_CLASSA;
	RegisterClass(&wndClass);
	wndClass.lpfnWndProc = MDIFrameJumpProc;
	wndClass.lpszClassName = ZAF_MDI_FRAME_CLASSA;
	RegisterClass(&wndClass);
	wndClass.lpfnWndProc = MDIChildJumpProc;
	wndClass.lpszClassName = ZAF_MDI_CHILD_CLASSA;
	RegisterClass(&wndClass);
#endif
}

ZafMSWindowsApp::~ZafMSWindowsApp()
{
	// Clean up.
#if !defined(ZAF_WIN32) && !defined(__WATCOMC__)
	GlobalDeleteAtom(objectLowWord);
	GlobalDeleteAtom(objectHighWord);
#endif
#if defined(ZAF_WIN32) && defined(ZAF_UNICODE)
	UnregisterClassA(ZAF_WINDOW_CLASSA, hInstance);
	UnregisterClassA(ZAF_MDI_FRAME_CLASSA, hInstance);
	UnregisterClassA(ZAF_MDI_CHILD_CLASSA, hInstance);
#else
	UnregisterClass(ZAF_WINDOW_CLASSA, hInstance);
	UnregisterClass(ZAF_MDI_FRAME_CLASSA, hInstance);
	UnregisterClass(ZAF_MDI_CHILD_CLASSA, hInstance);
#endif

#if defined(ZAF_MSWINDOWS_3D)
	if (available3D && !native3D)
	{
		Ctl3dUnregister(hInstance);
		FreeLibrary(ctl3dModule);
	}
#endif
}

// This function extends the Windows CreateWindowEx API by subclassing the
// window and setting attributes to conform to ZAF architecture.
HWND ZafMSWindowsApp::CreateSubclassedWindow(ZafWindowObject *object, const ZafIChar *lpClassName,
	DWORD dwStyle, const ZafIChar *text, HWND hwndParent, DWORD dwExStyle, HINSTANCE dataSegment,
	LPVOID lpvParam)
{
//	ZafIChar *wcDialog = (ZafIChar *)WC_DIALOG;
	bool isDialog = (lpClassName == (ZafIChar *)WC_DIALOG);

	// Generate defaults.
	if (!lpClassName)
    	lpClassName = ZAF_WINDOW_CLASS;
	if (!hwndParent && object->parent)
	{
		if (object->SupportObject())
			hwndParent = object->parent->OSScreenID(ZAF_FRAMEID);
		else
			hwndParent = object->parent->screenID;
	}
	if (!dataSegment)
		dataSegment = hInstance;
//	HMENU hMenu = hwndParent ? (HMENU)object->NumberID() : 0;
	HMENU hMenu = object->parent ? (HMENU)object->NumberID() : 0;

	// Create the window.
	HWND hwnd;
	if (convertText && !isDialog)
	{
		char *osClassName = ZafConvertToOSString(lpClassName, ZAF_NULLP(char), false);
		char *osText = ZafConvertToOSString(text);
#if defined(ZAF_WIN32) && defined(ZAF_UNICODE)
		hwnd = CreateWindowExA(dwExStyle, osClassName, osText, dwStyle,
			0, 0, 0, 0, hwndParent, hMenu, dataSegment, lpvParam);
#else
		hwnd = CreateWindowEx(dwExStyle, osClassName, osText, dwStyle,
			0, 0, 0, 0, hwndParent, hMenu, dataSegment, lpvParam);
#endif
		delete []osText;
	}
	else if (isDialog)
	{
		char *osText = ZafConvertToOSString(text);
#if defined(ZAF_WIN32)
		if (convertText)
			hwnd = CreateWindowExA(dwExStyle, (char *)lpClassName, osText, dwStyle,
				0, 0, 0, 0, hwndParent, hMenu, dataSegment, lpvParam);
		else
#endif
#if defined(ZAF_WIN32)
			hwnd = CreateWindowEx(dwExStyle, lpClassName, text, dwStyle,
				0, 0, 0, 0, hwndParent, hMenu, dataSegment, lpvParam);
#else
			hwnd = CreateWindowEx(dwExStyle, (char *)lpClassName, (char *)text, dwStyle,
				0, 0, 0, 0, hwndParent, hMenu, dataSegment, lpvParam);
#endif
		delete []osText;
	}
#if defined(ZAF_WIN32) || !defined(ZAF_UNICODE)
	else
		hwnd = CreateWindowEx(dwExStyle, lpClassName, text, dwStyle,
			0, 0, 0, 0, hwndParent, hMenu, dataSegment, lpvParam);
#endif

	// Set the objects "z-order."
	if (object->Next() && object->Next()->screenID)
	{
		HWND hwndPrevious = HWND_TOP;
		ZafWindowObject *prevObject = object->Previous();
		while (prevObject && !prevObject->SystemObject())
			prevObject = prevObject->Previous();
		if (prevObject && prevObject->screenID)
			hwndPrevious = object->Previous()->OSScreenID(ZAF_FRAMEID);
		SetWindowPos(hwnd, hwndPrevious, 0, 0, 0, 0,
			SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOACTIVATE);
	}

	// Subclass the window.
#if defined(ZAF_WIN32)
	SetWindowLong(hwnd, GWL_USERDATA, (LONG)object);
#else
	SetProp(hwnd, (LPCSTR)objectLowWord, (HANDLE)LOWORD(object));
	SetProp(hwnd, (LPCSTR)objectHighWord, (HANDLE)HIWORD(object));
#endif
	SetWindowLong(hwnd, GWL_WNDPROC, (LONG)JumpProc);

#if defined(ZAF_MSWINDOWS_3D)
	//??? Should this be in OSRegisterObject()?
	if (available3D && !native3D && (object->Bordered() || object->IsA(ID_ZAF_BUTTON)))
		Ctl3dSubclassCtl(hwnd);
#endif

	return (hwnd);
}

// All windows created by ZAF are subclassed to use this window procedure.
// This procedure packages Windows messages into ZAF events and routes
// them to the destination objects.
LRESULT CALLBACK ZafMSWindowsApp::JumpProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
	// Get a pointer to the object to which the message is being sent.
	ZafWindowObject *object = ObjectFromHandle(hwnd);

	// Create the Zinc event.
	ZafEventStruct event(E_MSWINDOWS);
	event.osEvent.hwnd = hwnd;
	event.osEvent.message = wMsg;
	event.osEvent.wParam = wParam;
	event.osEvent.lParam = lParam;

	// Route the event. (Keyboard events are routed top-down.)
/* START BLOCK COMMENT
**		ZafEventType inputType = event.InputType();
**		if (object->editMode && inputType == E_MOUSE)
**			return (object->ZafWindowObject::Event(event));
**		else if (inputType == E_KEY)
END BLOCK COMMENT */
	if (event.InputType() == E_KEY)
	{
		// Route the event to the root window to be processed top-down.
		// (The event has already been passed to the window manager.)
		event.route = object;
		// Make Sure we go all the way to the root of a MDI heirarchy.
		ZafWindowObject *root = object->RootObject();
		if (root->parent)
			root = root->parent->RootObject();
		return (root->Event(event));
	}
	else
		return (object->Event(event));
}

// --- Utilities ------------------------------------------------------------

ZafIChar *ZafMSWindowsApp::HotKeyText(const ZafIChar *text, int hotKeyIndex)
{
	if (!text)
		return (ZAF_NULLP(ZafIChar));

	// Count the '&' characters.
	int numAmpersands = 0;
	const ZafIChar *ampersand = strchr(text, '&');
	while (ampersand)
	{
		numAmpersands++;
		ampersand = strchr(ampersand + 1, '&');
	}

	ZafIChar *hotKeyText = new ZafIChar[strlen(text) + numAmpersands + 2];

	int sourceIndex = 0, destIndex = 0;
	while (text[sourceIndex])
	{
		if (sourceIndex == hotKeyIndex)
			hotKeyText[destIndex++] = '&';
		if (text[sourceIndex] == '&')
			hotKeyText[destIndex++] = '&';
		hotKeyText[destIndex++] = text[sourceIndex++];
	}
	hotKeyText[destIndex] = 0;

	return (hotKeyText);
}

/* START BLOCK COMMENT
**	
**	// This function allows the simulation of a key press, including modifiers.
**	void ZafMSWindowsApp::SendKeyDown(HWND hwnd, WPARAM virtualKey, unsigned int modifiers)
**	{
**		BYTE keyboardState[256], shiftState, controlState;
**	
**		// Set keyboard state.
**		GetKeyboardState((LPBYTE)&keyboardState);
**		shiftState = keyboardState[VK_SHIFT];
**		controlState = keyboardState[VK_CONTROL];
**		if (modifiers & S_SHIFT)
**			keyboardState[VK_SHIFT] |= 0x80;
**		if (modifiers & S_CTRL)
**			keyboardState[VK_CONTROL] |= 0x80;
**		SetKeyboardState((LPBYTE)&keyboardState);
**	
**		// Send character.
**		SendMessage(hwnd, WM_KEYDOWN, (WPARAM)virtualKey, (LPARAM)1);
**	
**		// Restore keyboard state.
**		keyboardState[VK_SHIFT] = shiftState;
**		keyboardState[VK_CONTROL] = controlState;
**		SetKeyboardState((LPBYTE)&keyboardState);
**	}
END BLOCK COMMENT */

/* START BLOCK COMMENT
**	#if defined(ZAF_WIN32)
**	// --- Unicode Support ------------------------------------------------------
**	
**	#	if defined(ZAF_UNICODE)
**	char *ZafMSWindowsApp::UnicodeToAPIString(const ZafIChar *unicodeString)
**	{
**		int i = WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, unicodeString, -1, NULL, 0, NULL, NULL);
**		char *apiString = new OSAPIChar[i+1];
**		WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, unicodeString, -1, apiString, i+1, NULL, NULL);
**		return apiString;
**	}
**	
**	ZafIChar *ZafMSWindowsApp::APIToUnicodeString(const char *apiString)
**	{
**		int i = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, apiString, -1, NULL, 0);
**		ZafIChar *unicodeString = new ZafIChar[i + 1];
**		MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, apiString, -1, unicodeString, i + 1);
**		return unicodeString;
**	}
**	#	endif
**	#endif
END BLOCK COMMENT */

/* START BLOCK COMMENT
**	LRESULT (__stdcall *ZafCallWindowProc)(WINDOWSPROC lpPrevWndFunc, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
**	LRESULT (__stdcall *ZafDefFrameProc)(HWND hwnd, HWND hWndMDIClient, UINT msg, WPARAM wParam, LPARAM lParam);
**	LRESULT (__stdcall *ZafDefWindowProc)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
**	LRESULT (__stdcall *ZafDefMDIChildProc)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
**	LONG (__stdcall *ZafDispatchMessage)(CONST MSG *lpmsg);
**	DWORD (__stdcall *ZafGetClassLong)(HWND hwnd, int nIndex);
**	BOOL (__stdcall *ZafGetMessage)(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
**	BOOL (__stdcall *ZafPeekMessage)(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);
**	BOOL (__stdcall *ZafPostMessage)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
**	LRESULT (__stdcall *ZafSendMessage)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
**	int (__stdcall *ZafGetObject)(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
**	LONG (__stdcall *ZafGetWindowLong)(HWND hwnd, int index);
**	LONG (__stdcall *ZafSetWindowLong)(HWND hwnd, int index, long dwNewLong);
END BLOCK COMMENT */

#if defined(ZAF_WIN32)
#	define ZAF_LNK_CONV __stdcall
#else
#	define ZAF_LNK_CONV
#endif

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

void ZafMSWindowsApp::InitializeWrappers(void)
{
#if defined(ZAF_WIN32)
#	if defined(ZAF_UNICODE)
	if (convertText)
#	endif
	{
		ZafCallWindowProc = CallWindowProcA;
		ZafDefFrameProc = DefFrameProcA;
		ZafDefWindowProc = DefWindowProcA;
		ZafDefMDIChildProc = DefMDIChildProcA;

		ZafGetMessage = GetMessageA;
		ZafPeekMessage = PeekMessageA;
		ZafPostMessage = PostMessageA;
		ZafSendMessage = SendMessageA;
		ZafDispatchMessage = DispatchMessageA;

		ZafGetObject = GetObjectA;
		ZafGetClassLong = GetClassLongA;
		ZafGetWindowLong = GetWindowLongA;
		ZafSetWindowLong = SetWindowLongA;
	}
#	if defined(ZAF_UNICODE)
	else
	{
		ZafCallWindowProc = CallWindowProcW;
		ZafDefFrameProc = DefFrameProcW;
		ZafDefWindowProc = DefWindowProcW;
		ZafDefMDIChildProc = DefMDIChildProcW;

		ZafGetMessage = GetMessageW;
		ZafPeekMessage = PeekMessageW;
		ZafPostMessage = PostMessageW;
		ZafSendMessage = SendMessageW;
		ZafDispatchMessage = DispatchMessageW;

		ZafGetObject = GetObjectW;
		ZafGetClassLong = GetClassLongW;
		ZafGetWindowLong = GetWindowLongW;
		ZafSetWindowLong = SetWindowLongW;
	}
#	endif
#endif
}

ZafEventType DefaultCallback(const ZafEventStruct &event)
{
	WINDOWSPROC proc = (WINDOWSPROC)GetClassLong(event.osEvent.hwnd, 
		GCL_WNDPROC);

	return (proc ? (ZafEventType)CallWindowProc(proc, event.osEvent.hwnd, 
		event.osEvent.message, event.osEvent.wParam, event.osEvent.lParam) : 0);
}

#if defined(ZAF_WIN32) && defined(ZAF_UNICODE)
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)
{
	return CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y,
		nWidth, nHeight, hWndParent, hMenu, hInstance, 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)
{
	HWND retValue;

	if (ZafMSWindowsApp::convertText)
	{
		char *osClassName = ZafConvertToOSString(lpClassName, ZAF_NULLP(char), false);
		char *osText = ZafConvertToOSString(lpWindowName);
		retValue = CreateWindowExA(dwExStyle, osClassName, osText, dwStyle, X, Y,
			nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
		delete []osText;
	}
	else
		retValue = CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y,
			nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
	return retValue;
}

int ZafDrawText(HDC hDC, LPCSTR lpString, int nCount, LPRECT lpRect,
	UINT uFormat)
{
	return DrawTextA(hDC, lpString, nCount, lpRect, uFormat);
}

int ZafDrawText(HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect,
	UINT uFormat)
{
/* START BLOCK COMMENT
**		if (ZafMSWindowsApp::convertText)
**		{
**		 	// Not done yet
**		}
**		else
END BLOCK COMMENT */
		return DrawTextW(hDC, lpString, nCount, lpRect, uFormat);
}

BOOL ZafAppendMenu(HMENU hMenu, UINT uFlags, UINT uIDNewItem, LPCSTR lpNewItem)
{
	return AppendMenuA(hMenu, uFlags, uIDNewItem, lpNewItem);
}

BOOL ZafAppendMenu(HMENU hMenu, UINT uFlags, UINT uIDNewItem, LPCWSTR lpNewItem)
{
/* START BLOCK COMMENT
**		if (ZafMSWindowsApp::convertText)
**		{
**		 	// Not done yet
**		}
**		else
END BLOCK COMMENT */
		return AppendMenuW(hMenu, uFlags, uIDNewItem, lpNewItem);
}

BOOL ZafModifyMenu(HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, LPCSTR lpNewItem)
{
	return ModifyMenuA(hMnu, uPosition, uFlags, uIDNewItem, lpNewItem);
}

BOOL ZafModifyMenu(HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, LPCWSTR lpNewItem)
{
/* START BLOCK COMMENT
**		if (ZafMSWindowsApp::convertText)
**		{
**	
**		}
**		else
END BLOCK COMMENT */
		return ModifyMenuW(hMnu, uPosition, uFlags, uIDNewItem, lpNewItem);
}

HCURSOR ZafLoadCursor(HINSTANCE hInstance, LPCSTR lpCursorName)
{
	return LoadCursorA(hInstance, lpCursorName);
}

HCURSOR ZafLoadCursor(HINSTANCE hInstance, LPCWSTR lpCursorName)
{
	HCURSOR retValue;
//	ZafInt32 value = (ZafInt32)lpCursorName;

	if (ZafMSWindowsApp::convertText)
	{
/* START BLOCK COMMENT
**			if (value & 0xff00)
**			{
**				char *cursorName = ZafConvertToOSString(lpCursorName, 0, false);
**				retValue = LoadCursorA(hInstance, cursorName);
**			}
**			else
END BLOCK COMMENT */
			retValue = LoadCursorA(hInstance, (LPCSTR)lpCursorName);
	}
	else
		retValue = LoadCursorW(hInstance, lpCursorName);

	return retValue;
}

DWORD ZafGetProfileString(LPCSTR lpAppName, LPCSTR lpKeyName,
	LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize)
{
	return GetProfileStringA(lpAppName, lpKeyName, lpDefault, lpReturnedString,
		nSize);
}

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

	if (ZafMSWindowsApp::convertText)
	{
		char *appName = ZafConvertToOSString(lpAppName, 0);
		char *keyName = ZafConvertToOSString(lpKeyName, 0);
		char *defaultVal = ZafConvertToOSString(lpDefault, 0);
		char *returnString = new char[nSize];

		GetProfileStringA(appName, keyName, defaultVal, returnString, nSize);

		delete []appName;
		delete []keyName;
		delete []defaultVal;
		ZafConvertToZafString(returnString, lpReturnedString, false);
		delete []returnString;
	}
	else
		retValue = GetProfileStringW(lpAppName, lpKeyName, lpDefault,
			lpReturnedString, nSize);

		return (retValue);
}

UINT ZafGetProfileInt(LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault)
{
	return GetProfileIntA(lpAppName, lpKeyName, nDefault);
}

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

	if (ZafMSWindowsApp::convertText)
	{
		char *appName = ZafConvertToOSString(lpAppName, 0);
		char *keyName = ZafConvertToOSString(lpKeyName, 0);

		retVal = GetProfileIntA(appName, keyName, nDefault);

		delete []appName;
		delete []keyName;
	}
	else
		retVal = GetProfileIntW(lpAppName, lpKeyName, nDefault);

	return (retVal);
}

#endif
