/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	Application.cpp
 *
 *****************************************************************************/

// SOL++2000
// 1999.08.14 Modified initialize method. 
// 2001/04/01 Added a public static DEFAULT_WIN_CLASS_STYLE variable. You can modify the
//	value for your own application in something like this.
//
//	void Main(int argc, char** argv) {
//	{
//		Application::DEFAULT_WIN_CLASS_STYLE = CS_DBLCLKS
//		//...
//  }

#include <sol\Application.h>
#include <sol\Event.h>
#include <sol\Composite.h>


const char* Application::name    = NULL;
HINSTANCE  	Application::instance    = NULL;
HINSTANCE  	Application::prevInstance= NULL;
HashTable* 	Application::table       = NULL;
char*      	Application::cmdLine	 = NULL;
int	   		Application::cmdShow	 = SW_SHOWNORMAL;
int	   		Application::argc	     = 0;
char**	   	Application::argv	     = NULL;
Composite*  Application::toplevel  = NULL;
HINSTANCE	Application::richEdit    = NULL;

// 2001/04/01
long		Application::DEFAULT_WIN_CLASS_STYLE = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; 

BOOL Application::registerClass(Args& args)
{
	WNDCLASS wc;
	char* className = (char*)args.get(XmNclassName);
	if (::GetClassInfo(instance, className, &wc)) {
		return TRUE;
	}

	if (!prevInstance) {
		memset(&wc, 0, sizeof(WNDCLASS));
		wc.hCursor	 = LoadCursor(NULL, IDC_ARROW);
		wc.hIcon	 = LoadIcon(NULL, IDI_APPLICATION);
		wc.lpszClassName = className;
		wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
		wc.hInstance     = instance;
		wc.style         = DEFAULT_WIN_CLASS_STYLE;
		CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
		wc.lpfnWndProc   = View::procedure;

		ulong val;
		if (args.get(XmNclassStyle, &val)) 
			wc.style      = (int)val;
		if (args.get(XmNclsExtra, &val))
			wc.cbClsExtra = (int)val;
		if (args.get(XmNwndExtra, &val))
			wc.cbWndExtra  = (int)val;
		if (args.get(XmNwndProc, &val))
			wc.lpfnWndProc = (WNDPROC)val;
		if (args.get(XmNbackground, &val))
			wc.hbrBackground = (HBRUSH)val;
		if (args.get(XmNicon, &val))
			wc.hIcon      = (HICON)val;
		if (args.get(XmNcursor, &val))
			wc.hCursor    = (HCURSOR)val;
		return ::RegisterClass(&wc);
	}
	return FALSE;
}


Application::Application(const char* name1, int argc1, char** argv1)
{
	name	 = name1;
	argc	 = argc1;
	argv	 = argv1;
	table    = new HashTable(113);
	toplevel = NULL;
}

// SOL++ 2.1 1996.11.17 to-arai {
#define WINSOCK_VERSION 0x0101		

void Application::initialize(HINSTANCE progIns, HINSTANCE prevIns, 
		char* cmdLine1, int cmdShow1)
{
	name	     = NULL;
	instance     = progIns;
	prevInstance = prevIns;
	cmdLine      = cmdLine1;
	cmdShow	     = cmdShow1;
	table        = NULL;
	toplevel     = NULL;

	::InitCommonControls();	
	
	richEdit = ::LoadLibrary("RICHED32.DLL");
	// 1998.09.05 {
	INITCOMMONCONTROLSEX ic;
	memset(&ic, 0, sizeof(ic));
	ic.dwSize = sizeof(ic);
	ic.dwICC  =
		ICC_LISTVIEW_CLASSES| // listview, header
		ICC_TREEVIEW_CLASSES| // treeview, tooltips
		ICC_BAR_CLASSES     | // toolbar, statusbar, trackbar, tooltips
		ICC_TAB_CLASSES     | // tab, tooltips
		ICC_UPDOWN_CLASS    | // updown
		ICC_PROGRESS_CLASS  | // progress
		ICC_HOTKEY_CLASS    | // hotkey
		ICC_ANIMATE_CLASS   | // animate
		ICC_WIN95_CLASSES   | 
		ICC_DATE_CLASSES    | // month picker, date picker, time picker, updown
		ICC_USEREX_CLASSES  | // comboex
		ICC_INTERNET_CLASSES| // IP address field  1999.08.14
		ICC_COOL_CLASSES;     // rebar (coolbar) control
	::InitCommonControlsEx(&ic);	

	// }

	// For socket library
	WSADATA wsaData;
	if (::WSAStartup(WINSOCK_VERSION, &wsaData)) {
		::MessageBox(NULL, "Could not load Windows Sockets DLL.", 
					"SOL++", MB_OK|MB_ICONSTOP);
	}					
}


Application::~Application()
{
	if(table) {
		delete table;
	}
	::FreeLibrary(richEdit);

	::WSACleanup();
}


int Application::dialogMessage(MSG* msg)
{
	HWND parent = ::GetParent(msg->hwnd);
	if(parent == NULL) return FALSE;

	DWORD style = ::GetWindowLong(parent, GWL_STYLE);
	DWORD exStyle = ::GetWindowLong(parent, GWL_EXSTYLE);

	if(((style & WS_POPUP) || (exStyle & WS_EX_CONTROLPARENT )) && 
		::IsDialogMessage(parent, msg) == TRUE) {
		if(msg->message == WM_KEYDOWN && 
		   msg->wParam  == VK_RETURN) {
			if(exStyle & WS_EX_CONTROLPARENT){
				::DispatchMessage(msg);
			}	
			if(style & WS_POPUP) {
				msg->lParam  = (LPARAM)msg->hwnd;
				msg->message = WM_COMMAND;
				::DispatchMessage(msg);
			}
		}
		return TRUE;
	}
	return FALSE;
}



WPARAM Application::run()
{
	MSG  msg;
	while (::GetMessage(&msg, NULL, 0, 0)) {
		if(dialogMessage(&msg))
			continue;
		if(toplevel && toplevel->translate(&msg))
			continue;
		::TranslateMessage(&msg);
		::DispatchMessage(&msg);
	}
	return msg.wParam;
}

