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


// SOL++2000


#include <sol\CallbackEntry.h>
#include <sol\TextField.h>
#include <sol\Font.h>
#include <sol\ClientDC.h>


static const int  ENTER = 13;

static const long STYLE = WS_BORDER|ES_LEFT|ES_AUTOHSCROLL;


TextField::TextField(View* parent, const char* name, Args& args)
	:Text(parent, name, 
			args.set(XmNstyle, (ulong)STYLE))
{
	enterCallback = NULL;
	keyInCallback = NULL;

	limitText(LINE_LENGTH);
	replaceWindowProc();
	addEventHandler(WM_CHAR, this,
	        (Handler)&TextField::charIn, NULL);
	addEventHandler(WM_COMMAND, this,
	        (Handler)&TextField::charIn, NULL);

	resize(name);		// Added
	dataType = T_STRING;
	setValues(args);
}

TextField::~TextField() 
{ 
	delete enterCallback; 
	delete keyInCallback;
}



void TextField::addCallback(const char* name, Object* object,
		Callback proc, void* data)
{
	if(name == XmNactivateCallback) {
		if(enterCallback) {
			delete enterCallback;
		}
		enterCallback = new CallbackEntry(name, NULL, object,
				proc, data);
	}
	if(name == XmNkeyInCallback) {
		if(keyInCallback) {
			delete keyInCallback;
		}		
		keyInCallback = new CallbackEntry(name, NULL, object,
				proc, data);
	}
}



Boolean TextField::create(View* parent, const char* name, Args& args)
{
	Boolean rc = Text::create(parent, name, 
			args.set(XmNstyle, (ulong)STYLE));

	enterCallback = NULL;
	keyInCallback = NULL;

	limitText(LINE_LENGTH);
	replaceWindowProc();
	addEventHandler(WM_CHAR, this,
	        (Handler)&TextField::charIn, NULL);
	addEventHandler(WM_COMMAND, this,
	        (Handler)&TextField::charIn, NULL);

	resize(name);		// Added
	dataType = T_STRING;
	setValues(args);

	return rc;
}

long TextField::charIn(Event& event)
{
	char line[LINE_LENGTH];
	WORD word = event.getWParam();
	if(keyInCallback) {
		Action action(NULL, event);
		keyInCallback -> call(action); 
	}

	if(dataType == T_BOOLEAN) {
		if((word >= '0' && word <='1') || 
		    (word == VK_BACK)) {
			return defaultProc(event);
		}
		if(word != ENTER)
		return 0L;
	}
	if(dataType == T_INTEGER) {
		if((word >= '0' && word <='9') || 
		    (word == VK_BACK)) {
			return defaultProc(event);
		}
		if(word != ENTER)
		return 0L;
    }

	if(word == ENTER) {
		if(enterCallback) {
        	::GetWindowText(getWindow(), line, LINE_LENGTH);
			Action action(NULL, event);
        	enterCallback -> setData(line);
        	enterCallback -> call(action);
		}
        return 0L;
	}

	return defaultProc(event);
}


void TextField::getPreferredSize(Dimension& d)
{
	ClientDC cdc(this);
	HFONT hfont = null;
	Font* font = getFont();
	if (font) {
		hfont = cdc.select(font);
	}
//	SIZE size;
	int h = cdc.getTextHeight();
	int x, y, ww, hh;

	getGeometry(x, y, ww, hh);
	reshape(x, y, ww, h+8);
	if (hfont) cdc.select(hfont);
	
	d.set(ww, h+8);
}

void TextField::getValues(Args& args)
{
	Text::getValues(args);

	ulong* val = (ulong*)args.get(XmNdataType);
	if(val) {
		*val = dataType;
	}
}


void TextField::setValues(Args& args)
{
	Text::setValues(args);

	ulong  val;
	if (args.get(XmNdataType, &val)) {
		dataType = val;
		// Limit text length.
		if(dataType == T_STRING) {
			limitText(LINE_LENGTH);
		}
		if(dataType == T_BOOLEAN) {
			limitText(1);
		}
		if(dataType == T_INTEGER) {
			limitText(6);
		}
	}
}

