/*
	WINDOWS.CPP - (C) 1990 by Joachim Kainz 'On a mission from Bhudda'
*/
	#include "windows.hpp"
	#include <string.h>

	WORD	 WINDOW::wCount	        = 0;
	FARPROC2 WINDOW::lpFnOOPWndProc = (FARPROC2) NULL;
	MSGLOOP  WINDOW::msg;

	static BOOL RegisterClass (
					WORD	 wStyle,
					HICON	 hCursor,
					HCURSOR  hIcon,
					HBRUSH	 hBackground,
					WORD	 wClsExtra,
					WORD	 wWndExtra,
					LPSTR	 lpClass,
					FARPROC2 lpFnProc
				);

	EXPORT WINDOW::WINDOW (
				WORD		wStyle,
				HCURSOR		hCursor,
				HICON		hIcon,
				HBRUSH		hBackground,
				WORD		wClsExtra,
				WORD		wWndExtra,
				LPSTR		lpClass,
				FARPROC2	lpFnProc
	) {
		hWnd = NULL;

		RegisterClass (
			wStyle,
			hCursor,
			hIcon,
			hBackground,
			wClsExtra,
			wWndExtra,
			lpClass,
			lpFnProc
		);
	}

	EXPORT WINDOW::WINDOW (
				int			nCmdShow,
				int			x,
				int			y,
				int			cx,
				int			cy,
				long		lStyle,
				LPSTR   	lpName,
				HANDLE		hMenu,
				HANDLE		hParent,
				long		lExStyle,
				WORD		wStyle,
				HCURSOR		hCursor,
				HICON		hIcon,
				HBRUSH		hBackground,
				WORD		wClsExtra,
				WORD		wWndExtra,
				LPSTR		lpParam,
				LPSTR		lpClass,
				FARPROC2	lpFnProc
	) {
		hWnd = NULL;

		if (
			!RegisterClass (
				wStyle,
				hCursor,
				hIcon,
				hBackground,
				wClsExtra,
				wWndExtra,
				lpClass,
				lpFnProc
			 )
		)
			return;

		CREATESTRUCT cs;

		cs.lpCreateParams	= lpParam;
		cs.hInstance		= GetInstance ();
		cs.hMenu			= hMenu;
		cs.hwndParent		= hParent;
		cs.cy				= cy;
		cs.cx				= cx;
		cs.y				= y;
		cs.x				= x;
		cs.style			= lStyle;
		cs.lpszName			= lpName;
		cs.lpszClass		= lpClass;
		cs.dwExStyle		= lExStyle;

		hWnd = CreateWindowEx (
					cs.dwExStyle,
					cs.lpszClass,
					cs.lpszName,
					cs.style,
					cs.x,
					cs.y,
					cs.cx,
					cs.cy,
					cs.hwndParent,
					cs.hMenu,
					cs.hInstance,
					cs.lpCreateParams
			   );

		SetWindowLong (GetWindowHandle (), 0, (long) this);

		lpDefWndProc =
				(FARPROC2) SetWindowLong (
								GetWindowHandle (),
								GWL_WNDPROC,
								(long) GetOOPWndProc ()
						   );
		SendMessage	(self, WM_CREATE, NULL, (long) &cs);

		if (nCmdShow != SW_HIDE)
			ShowWindow(GetWindowHandle (), nCmdShow);
	}

	BOOL RegisterClass (
			WORD	 wStyle,
			HICON	 hCursor,
			HCURSOR  hIcon,
			HBRUSH	 hBackground,
			WORD	 wClsExtra,
			WORD	 wWndExtra,
			LPSTR	 lpClass,
			FARPROC2 lpFnProc
		 )
	{
		WNDCLASS wc;

		if (GetClassInfo (GetInstance (), lpClass, &wc))
			return TRUE;

		wc.style		= wStyle;
		wc.lpfnWndProc	= lpFnProc;
		wc.cbClsExtra	= wClsExtra;
		wc.cbWndExtra	= wWndExtra+sizeof (long); // Room for Pointer to
		wc.hInstance	= GetInstance ();		   // the instance
		wc.hIcon		= hIcon;
		wc.hCursor		= hCursor;
		wc.hbrBackground= hBackground;
		wc.lpszMenuName	= NULL;
		wc.lpszClassName= lpClass;

		return RegisterClass (&wc);
	}

	EXPORT WINDOW::~WINDOW()
	{
		if(!GetWindowHandle ())
			if(IsWindow(GetWindowHandle ()))
				DestroyWindow(GetWindowHandle ());

		if (!GetCount ())
			FreeProcInstance ((FARPROC) GetOOPWndProc ());
	}

	int EXPORT MsgLoop (const WINDOW & wnd)
	{
		return wnd.msg.Loop ();
	}

	FARPROC2 WINDOW::GetOOPWndProc () const
	{
		if (!lpFnOOPWndProc)
			 lpFnOOPWndProc = (FARPROC2) MakeProcInstance (
											(FARPROC) DefOOPWndProc,
											GetInstance ()
										 );

		return lpFnOOPWndProc;
	}

	void EXPORT ShowWindow  (const WINDOW &wnd, int nShow)
	{
		::ShowWindow (wnd.GetWindowHandle (), nShow);
	}

	BOOL EXPORT IsWindow (const WINDOW &wnd)
	{
		if (!wnd.GetWindowHandle ())
			return FALSE;

		return IsWindow (wnd.GetWindowHandle ());
	}

	long EXPORT SendMessage (
				 const WINDOW &wnd,
				 WORD 		  wMsg,
				 WORD 		  wParam,
				 LONG 		  lParam
				)
	{
		return SendMessage (
				wnd.GetWindowHandle (),
				wMsg,
				wParam,
				lParam
			   );
	}

	long EXPORT PostMessage (
					const WINDOW &wnd,
					WORD 		  wMsg,
					WORD 		  wParam,
					LONG 		  lParam
				)
	{
		return PostMessage (
				wnd.GetWindowHandle (),
				wMsg,
				wParam,
				lParam
			   );
	}

	void EXPORT SetWindowText (const WINDOW &wnd, LPSTR lpText)
	{
		if (HIWORD (lpText)) {

			SetWindowText (
				wnd.GetWindowHandle (),
				lpText
			);

			return;

		}

		PSTR pText;

		for (WORD wLen=64;; wLen*=2) {

			pText = new char [wLen];

			if (
				LoadString (
					GetInstance (),
					LOWORD (lpText),
					pText,
					wLen
				) < wLen-1
			)
				break;

			delete pText;

		}

		SetWindowText (wnd.GetWindowHandle (), pText);

		delete pText;
	}