/******************************************************************************
 *
 * 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.
 *
 *
 *	Primitive.cpp
 *
 *****************************************************************************/

// SOL++2000

#include <sol\Application.h>
#include <sol\Primitive.h>
#include <sol\ClientDC.h>

Arg Primitive::styles[] = {
	{XmNgroup,	     WS_GROUP},
	{XmNdisabled,	     WS_DISABLED},
	{XmNtabStop,         WS_TABSTOP},
	{XmNborderWidth,     WS_BORDER},
};


//<added date="2000.02.10"/>
Primitive::Primitive()
:View()
{
	newProc = NULL;
	oldProc = NULL;
}

Primitive::Primitive(View* parent, HWND hwnd)
	:View(parent)
{
	newProc = NULL;
	oldProc = NULL;
	setWindow(hwnd);
	Application::add(hwnd, this);	
	setDestructable(FALSE);
}

Primitive::Primitive(View* parent, const char* name, Args& args)
	:View(parent, name,
			args.set(styles, XtNumber(styles))
			    .set(XmNstyle, (ulong)WS_CHILD|WS_VISIBLE))
{
	newProc = NULL;
	oldProc = NULL;
}


Primitive::~Primitive()
{
}


//<added date="2000.02.10">
Boolean Primitive::create(View* parent, const char* name, Args& args)
{
	return View::create(parent, name,
				args.set(styles, XtNumber(styles))
			        .set(XmNstyle, (ulong)WS_CHILD|WS_VISIBLE));
}
//</added>


LRESULT Primitive::defaultProc(Event& event)
{
	if(oldProc) {
#ifdef STRICT
		return ::CallWindowProc(oldProc, 
#else
		return ::CallWindowProc((FARPROC)oldProc, 
#endif
				     getWindow(), 
			         event.getMessage(), 
				     event.getWParam(),
				     event.getLParam());
	}
	return View::defaultProc(event);
}


LRESULT Primitive::discardInput(Event& event)
{
	View* view = getParent();
	if(view) {
		HWND parent = view -> getWindow();

		POINT p;
		::GetCursorPos(&p);
		::ScreenToClient(parent, &p);

		switch(event.getMessage()) {

		case WM_KEYDOWN:
		case WM_KEYUP:
		case WM_SETFOCUS:
		case WM_CHAR:
			return 0L;

		case WM_MOUSEMOVE:
		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_LBUTTONDBLCLK:
			return view -> send(event.getMessage(), 0,
					MAKELONG(p.x, p.y));

		default:
			break;
		}
	}
	return Primitive::defaultProc(event);
}


void Primitive::layout(int x, int y, int w, int h)
{
	reshape(x, y, w, h);
}

 
void Primitive::replaceWindowProc()
{
	WNDPROC proc   = (WNDPROC)getWindowLong(GWL_WNDPROC);
	HINSTANCE hins = Application::getInstance();
			
	if(newProc == NULL) {
		newProc = (WNDPROC)View::procedure;

		oldProc = proc;
		setWindowLong(GWL_WNDPROC, (LPARAM)newProc);
	}
}


void Primitive::resize(const char* label)
{
// SOL++ 1.2
	if(label && strlen(label)) {
		ClientDC cdc(this);
		HFONT hfont = null;
		Font* font = getFont();
		if (font) {
			hfont = cdc.select(font);
		}
		SIZE size;
		cdc.getTextExtent(label, strlen(label), &size);
		int w = size.cx;
		int h = size.cy;
		int x, y;
		getLocation(x, y);
		h = cdc.getTextHeight();
		reshape(x, y, w+h*2, h+10);//h*7/4);
		if (hfont) cdc.select(hfont);
	}
}


void Primitive::restoreWindowProc()
{
	if(oldProc) {
		setWindowLong(GWL_WNDPROC, (LONG)oldProc);
		oldProc = NULL;
		if(newProc) {
			newProc = NULL;
		}
	}
}

