
#include "c4d_gui.h"
#include "c4d_listview.h"
#include "c4d_basecontainer.h"
#include "c4d_resource.h"
#include "customgui_base.h"
#include "c4d_customguiplugin.h"
#include "c4d_colors.h"

#ifndef __API_INTERN__
	#include "c4d_memory.h"
	#include "c4d_basebitmap.h"
	#include "c4d_general.h"
	#include "c4d_tools.h"
	#include "c4d_basedocument.h"

	enum
	{
		CM_DISABLED													= 'disb',
		CM_TYPE_BUTTON											= 'bttn',
			CM_TYPE_STRING											= 'strg',
				CM_STRING													= 'strg',
			CM_TYPE_DATA												= 'vdat',
			CM_TYPE_INT													= 'vint',
			CM_TYPE_FLOAT												= 'vflt',
				CM_VALUE_VAL											= 'valu',	// necessary
				CM_VALUE_MIN											= 'mini',	// unnecessary
				CM_VALUE_MAX											= 'maxi',	// unnecessary
				CM_VALUE_MIN2											= 'min2', // for second range of slider with ints
				CM_VALUE_MAX2											= 'max2', // for second range of slider with ints
				CM_VALUE_STEP											= 'step',	// unnecessary
				CM_VALUE_FORMAT										= 'frmt',	// unnecessary
				CM_VALUE_QUADSCALE								= 'quad',	// quadscale of the slider
				CM_VALUE_TRISTATE									= 'tris',	// 0 == off, 1 == enabled/even values 2 == enabled/different values
				CM_VALUE_FPS											= 'ffps'	// for FORMAT_FRAMES, FORMAT_SECONDS, FORMAT_SMPTE
	};

#else
	#include "basereq.h"
	#include "basevar.h"
	#include "gui_coredefs.h"
	#include "ge_basebitmap.h"
	#include "basedocument.h"
	#include "world.h"
	#include "ge_event.h"

#define StopAllThreads StopEditorThreads

#endif

LONG CDialogCallBack(CDialog *cd, CUserArea *cu, BaseContainer *msg)
{
	LONG res = 0;
	BaseContainer result;
	if (cu)
	{
		// UserAreaMessage
		GeUserArea *usr = (GeUserArea*)C4DOS.Cu->GetUserData(cu); if (!usr) return FALSE;
		if (usr) res = usr->Message(*msg,result);
	}
	else
	{
		// DialogMessage
		GeDialog *dlg = (GeDialog*)C4DOS.Cd->GetUserData(cd); if (!dlg) return FALSE;
		res = dlg->Message(*msg,result);
	}

	if (result.GetId()!=NOTOK)
		C4DOS.Cd->SetMessageResult(cd,&result);

	return res;
}

LONG GeDialog::Message(const BaseContainer &msg,BaseContainer &result)
{
	LONG id;
	LONG res;

	switch (msg.GetId())
	{
		case BFM_INTERACTSTART: // interact stop
			StopAllThreads();
			break;

		case BFM_INIT:
			if (createlayout) return TRUE;
			createlayout = TRUE;
			return CreateLayout();

		case BFM_DESTROY:
			DestroyWindow();
			createlayout = FALSE;
			break;

		case BFM_INITVALUES:
			return InitValues();

		case BFM_SYNC_MESSAGE:
			id = msg.GetLong(BFM_CORE_ID);
			return CoreMessage(id,msg);

		case BFM_CORE_MESSAGE:
			id = msg.GetLong(BFM_CORE_ID);
			return CoreMessage(id,msg);

		case BFM_ACTION:
			id = msg.GetLong(BFM_ACTION_ID);
			res = Command(id,msg);
			return res;

		case BFM_CHECKCLOSE:
			return AskClose();
			break;

		case BFM_TIMER_MESSAGE:
			Timer(msg);
			return TRUE;

		case BFM_COMMANDNOTIFY:
			return CommandNotify(msg.GetLong(BFM_CMD_ID),msg);

		case BFM_COMMAND:
			return Command(msg.GetLong(BFM_CMD_ID),msg);
	}
	return FALSE;
}

GeDialog::GeDialog(void)
{
	cd = C4DOS.Cd->Alloc(CDialogCallBack,this);
	createlayout = FALSE;
#ifdef __API_INTERN__
	dontfree = FALSE;
#endif
}

GeDialog::~GeDialog(void)
{
#ifdef __API_INTERN__
	if (!dontfree)
#endif
	if (cd) C4DOS.Cd->Free(cd);
	cd = NULL;
}

#ifdef __API_INTERN__
	void GeDialog::Set(CDialog* set)
	{
		if (cd && !dontfree)
			C4DOS.Cd->Free(cd);
			
		cd = set; 
		dontfree = TRUE;
	}
#endif

void *GeDialog::GetWindowHandle()
{
	return C4DOS.Cd->CBF_GetWindowHandle((CBaseFrame*)cd);	
}

Bool GeDialog::SendParentMessage(const BaseContainer &msg)
{
	return C4DOS.Cd->SendParentMessage(cd,&msg);
}

LONG GeDialog::GetId(void)
{
	return C4DOS.Cd->GetID(Get());
}

Bool GeDialog::IsOpen()
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_ISOPEN,0,NULL,0,0,0,0,NULL,NULL);
}

void *GeDialog::FindCustomGui(LONG id,LONG pluginid)
{
	return C4DOS.Cd->FindCustomGui(Get(),id);
}

void* GeDialog::AddCustomGui(LONG id,LONG pluginid,const String &name,LONG flags,LONG minw,LONG minh,const BaseContainer &t_customdata)
{
	BaseContainer customdata = t_customdata;
	customdata.SetLong(DROLDWIN_SDK,pluginid);
	void *r = NULL;
	C4DOS.Cd->AddGadget(Get(),DIALOG_SDK,id,&name,flags,minw,minh,0,&customdata,&r);
	return r;
}

Bool GeDialog::ReleaseLink()
{
	return C4DOS.Cd->ReleaseLink(Get());
}

Bool GeDialog::Open(Bool async,LONG pluginid,LONG xpos,LONG ypos,LONG defaultw,LONG defaulth,LONG subid)
{
	if (!cd) return FALSE;
	C4DOS.Cd->AddGadget(cd,DIALOG_SETIDS,pluginid,NULL,subid,0,0,0,NULL,NULL);
	return C4DOS.Cd->Open(cd,async,NULL,xpos,ypos,defaultw,defaulth);
}

Bool GeDialog::Close(void)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->Close(cd);
}

Bool GeDialog::SendMessage(const GadgetPtr &id,const BaseContainer &msg)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->SendUserAreaMessage(cd,id.Id(),(BaseContainer*)&msg,id.Ptr());
}

void GeDialog::SetTimer(LONG timer)
{
	C4DOS.Cd->SetTimer(cd,timer);
}

void GeDialog::SetTitle(const String &title)
{
	if (!cd) return;
	C4DOS.Cd->AddGadget(cd,DIALOG_SETTITLE,0,(String*)&title,0,0,0,0,NULL,NULL);
}

Bool GeDialog::Enable(const GadgetPtr &id, Bool enabled)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->Enable(cd,id.Id(),enabled,id.Ptr());
}

Bool GeDialog::SetPopup(const GadgetPtr &id,const BaseContainer &bc)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->SetPopup(cd,id.Id(),(BaseContainer*)&bc,id.Ptr());
}

Bool GeDialog::Local2Global(LONG *x,LONG *y)
{
	if (!cd) return FALSE;
	*x = - (*x);
	*y = - (*y);
	Bool ok = C4DOS.Cu->Global2Local((CBaseFrame*)cd,x,y);
	*x = - (*x);
	*y = - (*y);
	return ok;
}

Bool GeDialog::Global2Local(LONG *x,LONG *y)
{
	if (!cd) return FALSE;
	return C4DOS.Cu->Global2Local((CBaseFrame*)cd,x,y);
}

Bool GeDialog::Screen2Local(LONG *x, LONG *y)
{
	if (!cd) return FALSE;
	return C4DOS.Cu->Screen2Local((CBaseFrame*)cd,x,y);
}

Bool GeDialog::Local2Screen(LONG *x, LONG *y)
{
	if (!cd) return FALSE;
	*x = - (*x);
	*y = - (*y);
	Bool ok=C4DOS.Cu->Screen2Local((CBaseFrame*)cd,x,y);
	*x = - (*x);
	*y = - (*y);
	return ok;
}

Bool GeDialog::SetBool(const GadgetPtr &id, Bool value,LONG tristate)
{
	return SetLong(id,value,0,!tristate?1:2,0,tristate);
}

Bool GeDialog::SetLong(const GadgetPtr &id, LONG value,LONG min,LONG max,LONG step,LONG tristate)
{
	BaseContainer msg(CM_TYPE_INT);

	msg.SetLong(CM_VALUE_VAL,value);
	msg.SetLong(CM_VALUE_FORMAT,FORMAT_LONG);
	msg.SetLong(CM_VALUE_MIN,min);
	msg.SetLong(CM_VALUE_MAX,max);
	msg.SetLong(CM_VALUE_STEP,step);
	msg.SetLong(CM_VALUE_TRISTATE,tristate);

	return SendMessage(id,msg);
}

Bool GeDialog::SetReal(const GadgetPtr &id, Real value,Real min,Real max,Real step,LONG format,Real min2,Real max2,Bool quadscale,LONG tristate)
{
	BaseContainer msg(CM_TYPE_FLOAT);

	msg.SetReal(CM_VALUE_VAL,value);
	msg.SetLong(CM_VALUE_FORMAT,format);
	msg.SetReal(CM_VALUE_MIN,min);
	msg.SetReal(CM_VALUE_MAX,max);
	msg.SetReal(CM_VALUE_STEP,step);
	msg.SetLong(CM_VALUE_TRISTATE,tristate);

	if (min2!=0.0 || max2!=0.0)
	{
		msg.SetReal(CM_VALUE_MIN2,min2);
		msg.SetReal(CM_VALUE_MAX2,max2);
	}
	msg.SetLong(CM_VALUE_QUADSCALE,quadscale);

	return SendMessage(id,msg);
}

Bool GeDialog::SetVectorReal(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, const Vector &value, Real min, Real max, Real step,LONG tristate)
{
	return SetReal(id_x,value.x,min,max,step,FORMAT_REAL,0.0,0.0,FALSE,tristate) && SetReal(id_y,value.y,min,max,step,FORMAT_REAL,0.0,0.0,FALSE,tristate) && SetReal(id_z,value.z,min,max,step,FORMAT_REAL,0.0,0.0,FALSE,tristate);
}

Bool GeDialog::SetVectorMeter(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, const Vector &value, Real min, Real max, Real step,LONG tristate)
{
	return SetMeter(id_x,value.x,min,max,step,tristate) && SetMeter(id_y,value.y,min,max,step,tristate) && SetMeter(id_z,value.z,min,max,step,tristate);
}

Bool GeDialog::SetVectorDegree(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, const Vector &value, Real min, Real max, Real step,LONG tristate)
{
	return SetDegree(id_x,value.x,min,max,step,tristate) && SetDegree(id_y,value.y,min,max,step,tristate) && SetDegree(id_z,value.z,min,max,step,tristate);
}

Bool GeDialog::SetVectorPercent(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, const Vector &value, Real min, Real max, Real step,LONG tristate)
{
	return SetPercent(id_x,value.x,min,max,step,tristate) && SetPercent(id_y,value.y,min,max,step,tristate) && SetPercent(id_z,value.z,min,max,step,tristate);
}

Bool GeDialog::SetString(const GadgetPtr &id, const String &text,LONG tristate)
{
	BaseContainer msg(BFM_TITLECHNG);
	msg.SetString(BFM_TITLECHNG,text);
	msg.SetLong(CM_VALUE_TRISTATE,tristate);
	return SendMessage(id,msg);
}

Bool GeDialog::SetFilename(const GadgetPtr &id, const Filename &fn,LONG tristate)
{
	return SetString(id,fn.GetString(),tristate);
}

Bool GeDialog::SetMeter(const GadgetPtr &id, Real value,Real min,Real max,Real step,LONG tristate)
{
	return SetReal(id,value,min,max,step,FORMAT_METER,0.0,0.0,FALSE,tristate);
}

Bool GeDialog::SetDegree(const GadgetPtr &id, Real value,Real min,Real max,Real step,LONG tristate)
{
	return SetReal(id,value,Rad(min),Rad(max),Rad(step),FORMAT_DEGREE,0.0,0.0,FALSE,tristate);
}

Bool GeDialog::SetPercent(const GadgetPtr &id, Real value,Real min,Real max,Real step,LONG tristate)
{
	return SetReal(id,value,min/100.0,max/100.0,step/100.0,FORMAT_PERCENT,0.0,0.0,FALSE,tristate);
}

Bool GeDialog::SetColorField(const GadgetPtr &id, const Vector &color, Real brightness,Real maxbrightness,LONG flags)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->SetColorField(cd,id.Id(),color,brightness,maxbrightness,flags,id.Ptr());
}


Bool GeDialog::GetBool(const GadgetPtr &id, Bool &value)
{
	if (!cd) return FALSE;
	LONG val;
	Bool ok=C4DOS.Cd->GetLong(cd,id.Id(),val,id.Ptr());
	value=val!=0;
	return ok;
}

Bool GeDialog::GetLong(const GadgetPtr &id, LONG &value)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GetLong(cd,id.Id(),value,id.Ptr());
}

Bool GeDialog::GetReal(const GadgetPtr &id, Real &value)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GetReal(cd,id.Id(),value,id.Ptr());
}

Bool GeDialog::GetVector(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, Vector &value)
{
	if (!GetReal(id_x,value.x)) return FALSE;
	if (!GetReal(id_y,value.y)) return FALSE;
	if (!GetReal(id_z,value.z)) return FALSE;
	return TRUE;
}

Bool GeDialog::GetString(const GadgetPtr &id, String &text)
{
	if (!cd) return FALSE;
	String *str = &text;
	Bool res = C4DOS.Cd->GetString(cd,id.Id(),str,id.Ptr());
	if (res && str)
	{
		text = *str;
		gDelete(str);
	}
	return res;
}

Bool GeDialog::GetFilename(const GadgetPtr &id, Filename &fn)
{
	String str;
	Bool res = GetString(id,str);
	if (!res) return FALSE;
	fn.SetString(str);
	return res;
}

Bool GeDialog::GetColorField(const GadgetPtr &id, Vector &color, Real &brightness)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GetColorField(cd,id.Id(),color,brightness,id.Ptr());
}

Bool GeDialog::GetBool(const GadgetPtr &id, BaseContainer *bc, LONG bcid)
{
	Bool b;
	Bool ok=GetBool(id,b);
	bc->SetBool(bcid,b);
	return ok;
}

Bool GeDialog::GetLong(const GadgetPtr &id, BaseContainer *bc, LONG bcid)
{
	LONG b;
	Bool ok=GetLong(id,b);
	bc->SetLong(bcid,b);
	return ok;
}

Bool GeDialog::GetReal(const GadgetPtr &id, BaseContainer *bc, LONG bcid)
{
	Real b;
	Bool ok=GetReal(id,b);
	bc->SetReal(bcid,b);
	return ok;
}

Bool GeDialog::GetVector(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, BaseContainer *bc, LONG bcid)
{
	Vector v;
	if (!GetReal(id_x,v.x)) return FALSE;
	if (!GetReal(id_y,v.y)) return FALSE;
	if (!GetReal(id_z,v.z)) return FALSE;
	bc->SetVector(bcid,v);
	return TRUE;
}

Bool GeDialog::GetString(const GadgetPtr &id, BaseContainer *bc, LONG bcid)
{
	String b;
	Bool   ok=GetString(id,b);
	bc->SetString(bcid,b);
	return ok;
}

Bool GeDialog::GetFilename(const GadgetPtr &id, BaseContainer *bc, LONG bcid)
{
	Filename b;
	Bool   ok = GetFilename(id,b);
	bc->SetFilename(bcid,b);
	return ok;
}

Bool GeDialog::GetColorField(const GadgetPtr &id, BaseContainer *bc, LONG bc_colid, LONG bc_brightnessid)
{
	Vector c;
	Real   b;
	Bool   ok=GetColorField(id,c,b);
	if (bc_colid!=NOTOK) bc->SetVector(bc_colid,c);
	if (bc_brightnessid!=NOTOK) bc->SetReal(bc_brightnessid,b);
	return ok;
}

Bool GeDialog::SetBool(const GadgetPtr &id, BaseContainer *bc, LONG bcid)
{
	return SetBool(id,bc->GetBool(bcid));
}

Bool GeDialog::SetLong(const GadgetPtr &id, BaseContainer *bc, LONG bcid,LONG min,LONG max, LONG step)
{
	return SetLong(id,bc->GetLong(bcid),min,max,step);
}

Bool GeDialog::SetReal(const GadgetPtr &id, BaseContainer *bc, LONG bcid,Real min,Real max, Real step,LONG format,Real min2,Real max2,Bool quadscale)
{
	return SetReal(id,bc->GetReal(bcid),min,max,step,format,min2,max2,quadscale);
}

Bool GeDialog::SetMeter(const GadgetPtr &id, BaseContainer *bc, LONG bcid,Real min,Real max,Real step)
{
	return SetMeter(id,bc->GetReal(bcid),min,max,step);
}

Bool GeDialog::SetDegree(const GadgetPtr &id, BaseContainer *bc, LONG bcid,Real min,Real max,Real step)
{
	return SetDegree(id,bc->GetReal(bcid),min,max,step);
}

Bool GeDialog::SetPercent(const GadgetPtr &id, BaseContainer *bc, LONG bcid,Real min,Real max,Real step)
{
	return SetPercent(id,bc->GetReal(bcid),min,max,step);
}

Bool GeDialog::SetVectorReal(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, BaseContainer *bc, LONG bcid,Real min,Real max, Real step)
{
	return SetVectorReal(id_x,id_y,id_z,bc->GetVector(bcid),min,max,step);
}

Bool GeDialog::SetVectorMeter(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, BaseContainer *bc, LONG bcid,Real min,Real max,Real step)
{
	return SetVectorMeter(id_x,id_y,id_z,bc->GetVector(bcid),min,max,step);
}

Bool GeDialog::SetVectorDegree(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, BaseContainer *bc, LONG bcid,Real min,Real max,Real step)
{
	return SetVectorDegree(id_x,id_y,id_z,bc->GetVector(bcid),min,max,step);
}

Bool GeDialog::SetVectorPercent(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, BaseContainer *bc, LONG bcid,Real min,Real max,Real step)
{
	return SetVectorPercent(id_x,id_y,id_z,bc->GetVector(bcid),min,max,step);
}

Bool GeDialog::SetString(const GadgetPtr &id, BaseContainer *bc, LONG bcid)
{
	return SetString(id,bc->GetString(bcid));
}

Bool GeDialog::SetFilename(const GadgetPtr &id, BaseContainer *bc, LONG bcid)
{
	return SetFilename(id,bc->GetFilename(bcid));
}

Bool GeDialog::SetColorField(const GadgetPtr &id, BaseContainer *bc, LONG bc_colid, LONG bc_brightnessid, Real maxbrightness, LONG flags)
{
	Real bright = 1.0;
	if (bc_brightnessid!=-1) bright = bc->GetReal(bc_brightnessid);
	return SetColorField(id,bc->GetVector(bc_colid),bright,maxbrightness,flags);
}

Bool GeDialog::SetTime(const GadgetPtr &id, BaseDocument *doc, const BaseTime &value,const BaseTime &min, const BaseTime &max, LONG stepframes,LONG tristate)
{
	if (!doc) doc = C4DOS.Ge->GetActiveDocument();
	if (!doc) return FALSE;
#ifndef __API_INTERN__
	LONG fps = doc->GetFps();
#else
	LONG fps = doc->docpref.GetFps();
#endif

	BaseContainer msg(CM_TYPE_FLOAT);

	msg.SetReal(CM_VALUE_VAL,Floor(value.GetNominator()*fps)/Floor(value.GetDenominator()));
	msg.SetLong(CM_VALUE_FORMAT,FORMAT_FRAMES);
	msg.SetReal(CM_VALUE_MIN,Floor(min.GetNominator()*fps)/Floor(min.GetDenominator()));
	msg.SetReal(CM_VALUE_MAX,Floor(max.GetNominator()*fps)/Floor(max.GetDenominator()));
	msg.SetReal(CM_VALUE_STEP,1.0);
	msg.SetLong(CM_VALUE_QUADSCALE,FALSE);
	msg.SetLong(CM_VALUE_FPS,fps);
	msg.SetLong(CM_VALUE_TRISTATE,tristate);
/*
	if (min2.Get()!=0.0 || max2!=0.0)
	{
		msg.SetReal(CM_VALUE_MIN2,min2);
		msg.SetReal(CM_VALUE_MAX2,max2);
	}
*/
	return SendMessage(id,msg);
}

Bool GeDialog::GetTime(const GadgetPtr &id, BaseDocument *doc, BaseTime &time)
{
	if (!doc) doc = C4DOS.Ge->GetActiveDocument();
	if (!doc) return FALSE;
#ifndef __API_INTERN__
	LONG fps = doc->GetFps();
#else
	LONG fps = doc->docpref.GetFps();
#endif

	Real b;
	Bool ok = GetReal(id,b);
	time = BaseTime(b*1000.0,fps*1000.0);
	return ok;
}

Bool GeDialog::SetTime(const GadgetPtr &id, BaseDocument *doc,BaseContainer *bc, LONG bcid, const BaseTime &min, const BaseTime &max, LONG stepframes)
{
	return SetTime(id, doc, bc->GetTime(bcid), min, max, stepframes);
}

Bool GeDialog::GetTime(const GadgetPtr &id, BaseDocument *doc, BaseContainer *bc, LONG bcid)
{
	BaseTime time;
	Bool ok = GetTime(id, doc, time);
	bc->SetTime(bcid,time);
	return ok;
}

Bool GeDialog::CheckTristateChange(const GadgetPtr &id)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->AddGadget(cd,DIALOG_GETTRISTATE,id.Id(),NULL,0,0,0,0,NULL,(void**)id.Ptr());
}

C4DGadget *GeDialog::AddCheckbox(LONG id, LONG flags, LONG initw, LONG inith, const String &name)
{
	if (!cd) return FALSE;
	void *r = NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_CHECKBOX,id,(String*)&name,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

#ifdef __API_INTERN__
Bool GeDialog::MenuSetResource(LONG id)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->AddGadget(cd,DIALOG_MENURESOURCE,id,NULL,0,0,0,0,NULL,NULL);
}
#endif

C4DGadget *GeDialog::AddSeparatorH(LONG initw)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_SEPARATOR,0,NULL,BFH_FIT,initw,0,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddSeparatorV(LONG initw)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_SEPARATOR,0,NULL,BFV_FIT,0,initw,0,NULL,&r);
	return (C4DGadget*)r;
}

Bool GeDialog::AddSubDialog(LONG id,LONG flags,LONG initw,LONG inith)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->AddGadget(cd,DIALOG_SUBDIALOG,id,NULL,flags,initw,inith,0,NULL,NULL);
}

C4DGadget *GeDialog::AddRadioButton(LONG id, LONG flags, LONG initw, LONG inith, const String &name)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_RADIOBUTTON,id,(String*)&name,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget* GeDialog::AddRadioText(LONG id, LONG flags, LONG initw, LONG inith, const String &name)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_RADIOTEXT,id,(String*)&name,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddButton(LONG id, LONG flags, LONG initw, LONG inith, const String &name)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_BUTTON,id,(String*)&name,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddStaticText(LONG id, LONG flags, LONG initw, LONG inith, const String &name,LONG borderstyle)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_STATICTEXT,id,(String*)&name,flags,initw,inith,borderstyle,NULL,&r);
	return (C4DGadget*)r;
}

Bool GeDialog::AddListView(LONG id, LONG flags, LONG initw, LONG inith)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_LISTVIEW,id,NULL,flags,initw,inith,0,NULL,NULL);
}

C4DGadget *GeDialog::AddArrowButton(LONG id, LONG flags, LONG initw, LONG inith, LONG arrowtype)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_ARROWBUTTON,id,NULL,flags,initw,inith,arrowtype,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddEditText(LONG id, LONG flags, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_EDITTEXT,id,NULL,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddMultiLineEditText(LONG id,LONG flags,LONG initw,LONG inith,LONG style)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_MULTILINEEDITTEXT,id,NULL,flags,initw,inith,style,NULL,&r);
	return (C4DGadget*)r;
}


C4DGadget *GeDialog::AddEditNumber(LONG id, LONG flags, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_EDITNUMBER,id,NULL,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddEditNumberArrows(LONG id, LONG flags, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_EDITNUMBERUD,id,NULL,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddEditSlider(LONG id, LONG flags, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_EDITSLIDER,id,NULL,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddSlider(LONG id, LONG flags, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_SLIDER,id,NULL,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddColorField(LONG id, LONG flags, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_COLORFIELD,id,NULL,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddColorChooser(LONG id, LONG flags, LONG initw, LONG inith,LONG layoutflags)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_COLORCHOOSER,id,NULL,flags,initw,inith,layoutflags,NULL,&r);
	return (C4DGadget*)r;
}

Bool GeDialog::AddRadioGroup(LONG id, LONG flags, LONG columns, LONG rows)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->AddGadget(cd,DIALOG_RADIOGROUP,id,NULL,flags,columns,rows,0,NULL,NULL);
}

C4DGadget *GeDialog::AddComboBox(LONG id, LONG flags, LONG initw, LONG inith,Bool specialalign)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_COMBOBOX,id,NULL,flags,initw,inith,specialalign,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddPopupButton(LONG id, LONG flags, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_POPUPBUTTON,id,NULL,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

Bool GeDialog::AddChild(const GadgetPtr &id, LONG subid,const String &child)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->AddGadget(cd,DIALOG_CHILD,id.Id(),(String*)&child,subid,0,0,0,NULL,(void**)id.Ptr());
}

Bool GeDialog::FreeChilds(const GadgetPtr &id)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->AddGadget(cd,DIALOG_FREECHILDS,id.Id(),NULL,0,0,0,0,NULL,(void**)id.Ptr());
}

C4DGadget *GeDialog::AddUserArea(LONG id, LONG flags, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	void *r = NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_USERAREA,id,NULL,flags,initw,inith,0,NULL,&r);
	return (C4DGadget*)r;
}

Bool GeDialog::TabGroupBegin(LONG id, LONG flags,LONG tabtype)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->TabGroupBegin(cd,id,flags,tabtype);
}

Bool GeDialog::GroupBegin(LONG id, LONG flags,LONG cols,LONG rows,const String &title,LONG groupflags)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GroupBegin(cd,id,flags,cols,rows,(String*)&title,groupflags);
}

Bool GeDialog::GroupEnd(void)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GroupEnd(cd);
}

Bool GeDialog::GroupSpace(LONG spacex,LONG spacey)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GroupSpace(cd,spacex,spacey);
}

Bool GeDialog::GroupBorder(LONG borderstyle)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GroupBorder(cd,borderstyle|BORDER_WITH_TITLE);
}

Bool GeDialog::GroupBorderNoTitle(LONG borderstyle)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GroupBorder(cd,borderstyle);
}

Bool GeDialog::GroupBorderSpace(LONG left, LONG top,LONG right,LONG bottom)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GroupBorderSize(cd,left,top,right,bottom);
}

Bool GeDialog::AttachUserArea(GeUserArea &ua,const GadgetPtr &id,LONG userareaflags)
{
	C4DOS.Cu->Free(ua.cu);
	ua.cu = NULL;
	ua.dlg = this;
	ua.cu  = C4DOS.Cd->AttachUserArea(cd,id.Id(),&ua,userareaflags,id.Ptr());
	return ua.cu!=NULL;
}

Bool GeDialog::AddDlgGroup(LONG type)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->AddGadget(cd,DIALOG_DLGGROUP,0,NULL,type,0,0,0,NULL,NULL);
}

Bool GeDialog::AttachSubDialog(SubDialog *userdlg,LONG id)
{
	if (!userdlg) return FALSE;

	userdlg->createlayout = FALSE;

	return C4DOS.Cd->AttachSubDialog(Get(),id,userdlg->Get());
}

Bool GeDialog::CheckClose(void)
{
	return C4DOS.Cd->AddGadget(Get(),DIALOG_CHECKCLOSE,0,NULL,0,0,0,0,NULL,NULL);
}

Bool GeDialog::LoadDialogResource(LONG id, GeResource *lr, LONG flags)
{
#ifndef __API_INTERN__
	if (!lr) lr=&resource;
	return C4DOS.Cd->LoadDialogResource(cd,id,lr->Get(),flags);
#else
	return C4DOS.Cd->LoadDialogResource(cd,id,NULL,flags);
#endif
}

Bool GeDialog::SetVisibleArea(LONG scrollgroupid,LONG x1,LONG y1,LONG x2,LONG y2)
{
	return C4DOS.Cd->SetVisibleArea(cd,scrollgroupid,x1,y1,x2,y2);
}

Bool GeDialog::GetVisibleArea(LONG scrollgroupid,LONG *x1,LONG *y1,LONG *x2,LONG *y2)
{
	return C4DOS.Cd->GetVisibleArea(cd,scrollgroupid,x1,y1,x2,y2);
}

Bool GeDialog::GetItemDim(const GadgetPtr &id,LONG *x,LONG *y,LONG *w,LONG *h)
{
	return C4DOS.Cd->GetItemDim(cd,id.Id(),x,y,w,h,id.Ptr());
}

Bool GeDialog::LayoutChanged(const GadgetPtr &id)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_LAYOUTCHANGED,id.Id(),NULL,0,0,0,0,NULL,NULL);
}

Bool GeDialog::Activate(const GadgetPtr &id)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_ACTIVATE,id.Id(),NULL,0,0,0,0,NULL,NULL);
}

Bool GeDialog::LayoutFlushGroup(const GadgetPtr &id)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_FLUSHGROUP,id.Id(),NULL,0,0,0,0,NULL,(void**)id.Ptr());
}

Bool GeDialog::RemoveElement(const GadgetPtr &id)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_REMOVEGADGET,id.Id(),NULL,0,0,0,0,NULL,(void**)id.Ptr());
}

Bool GeDialog::ScrollGroupBegin(LONG id, LONG flags,LONG scrollflags,LONG initw,LONG inith)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_SCROLLGROUP,id,NULL,flags,initw,inith,scrollflags,NULL,NULL);
}

Bool GeDialog::RestoreLayout(LONG pluginid,LONG subid,void *secret)
{
	C4DOS.Cd->AddGadget(cd,DIALOG_SETIDS,pluginid,NULL,subid,0,0,0,NULL,NULL);
	return C4DOS.Cd->RestoreLayout(cd,secret);
}

Bool GeDialog::MenuSubBegin(const String &string)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_ADDSUBMENU,0,(String*)&string,0,0,0,0,NULL,NULL);
}

Bool GeDialog::MenuSubEnd(void)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_ENDSUBMENU,0,NULL,0,0,0,0,NULL,NULL);
}

Bool GeDialog::MenuAddCommand(LONG cmdid)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_ADDMENUCMD,cmdid,NULL,0,0,0,0,NULL,NULL);
}

Bool GeDialog::MenuAddSeparator(void)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_ADDMENUSEP,0,NULL,0,0,0,0,NULL,NULL);
}

Bool GeDialog::MenuAddString(LONG id,const String &string)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_ADDMENUSTR,id,(String*)&string,0,0,0,0,NULL,NULL);
}

Bool GeDialog::MenuInitString(LONG id,Bool enabled,Bool checked)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_INITMENUSTR,id,NULL,enabled,checked,0,0,NULL,NULL);
}

Bool GeDialog::MenuFlushAll(void)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_FLUSHMENU,0,NULL,0,0,0,0,NULL,NULL);
}

Bool GeDialog::MenuFinished(void)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_SETMENU,0,NULL,0,0,0,0,NULL,NULL);
}

Bool GeDialog::GetDragPosition(const BaseContainer &msg,LONG *x,LONG *y)
{
	if (x) *x = msg.GetLong(BFM_DRAG_SCREENX);
	if (y) *y = msg.GetLong(BFM_DRAG_SCREENY);
	return C4DOS.Cd->Screen2Local(cd,x,y);
}

Bool GeDialog::GetDragObject(const BaseContainer &msg,LONG *type,void **object)
{
	return C4DOS.Cd->GetDragObject(cd,(BaseContainer*)&msg,type,object);
}


Bool GeDialog::CheckValueRanges(void)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_CHECKNUMBERS,0,NULL,0,0,0,0,NULL,NULL);
}


// to overload
Bool GeDialog::CreateLayout(void)
{
	return TRUE;
}

Bool GeDialog::InitValues(void)
{
	return TRUE;
}

void GeDialog::DestroyWindow(void)
{
}

Bool GeDialog::CoreMessage(LONG id,const BaseContainer &msg)
{
	return TRUE;
}

LONG GeDialog::CommandNotify(LONG id,const BaseContainer &msg)
{
	return 0;
}

Bool GeDialog::Command(LONG id,const BaseContainer &msg)
{
	return TRUE;
}

Bool GeDialog::AskClose(void)
{
	return FALSE;
}

void GeDialog::Timer(const BaseContainer &msg)
{
}

#ifdef __API_INTERN__
	Bool GeDialog::OpenPopUpMenu(LONG menuid,LONG localx,LONG localy)
	{
		Bool CDialog_OpenPopUp(CDialog *cd,LONG menuid,LONG localx,LONG localy);
		if (localx!=-1 && localy!=-1)
		{
			localx = -localx;
			localy = -localy;
			C4DOS.Cd->Screen2Local(cd,&localx,&localy);
			localx = -localx;
			localy = -localy;
		}
		return CDialog_OpenPopUp(cd,menuid,localx,localy);
	}

	Bool GeUserArea::OpenPopUpMenu(LONG menuid,LONG localx,LONG localy)
	{
		if (!dlg) return FALSE;
		if (localx!=-1 && localy!=-1)
		{
			localx = -localx;
			localy = -localy;
			C4DOS.Cu->Screen2Local(cu,&localx,&localy);
			localx = -localx;
			localy = -localy;
		}
		Bool CDialog_OpenPopUp(CDialog *cd,LONG menuid,LONG localx,LONG localy);
		return CDialog_OpenPopUp(dlg->cd,menuid,localx,localy);
	}
#endif

GeModalDialog::GeModalDialog(void)
{
	close = TRUE;
	dlg_result = FALSE;
}

GeModalDialog::~GeModalDialog(void)
{
}

Bool GeModalDialog::Open(LONG xpos,LONG ypos)
{
	return GeDialog::Open(FALSE,0,xpos,ypos) && dlg_result;
}

Bool GeModalDialog::Close(Bool result)
{
	dlg_result = result;
	return GeDialog::Close();
}

LONG GeModalDialog::Message(const BaseContainer &msg,BaseContainer &result)
{
	LONG id,res;

	switch (msg.GetId())
	{
		case BFM_INTERACTSTART: // interact stop
			return FALSE;

		case BFM_CHECKCLOSE:
			if (dlg_result && CheckValueRanges())
			{
				dlg_result = FALSE;
				return TRUE;
			}
			return FALSE;

		case BFM_ASKCLOSE:
			if (dlg_result)
			{
				return AskClose();
			}
			return FALSE;

		case BFM_ACTION:
			id = msg.GetLong(BFM_ACTION_ID);
			close = TRUE;
			res = Command(id,msg);

			if (close && id==IDC_OK || id == IDC_CANCEL)
			{
				Close(id==IDC_OK);
			}
			return res;
	}
	return GeDialog::Message(msg,result);
}

void GeModalDialog::CheckLong(LONG id, LONG type, LONG val, LONG x, LONG y)
{
	if (!close) return;
	switch (type)
	{
		case Greater				 : if (val>x) return; break;
		case GreaterOrEqual  : if (val>=x) return; break;
		case Less						 : if (val<x) return; break;
		case LessOrEqual		 : if (val<=x) return; break;
		case Between				 : if (val>x && val<y) return; break;
		case BetweenOrEqual	 : if (val>=x && val<=y) return; break;
		case BetweenOrEqualX : if (val>=x && val<y) return; break;
		case BetweenOrEqualY : if (val>x && val<=y) return; break;
		case Different			 : if (val!=x) return; break;
	}

	Activate(id);
#ifndef __API_INTERN__
	ErrorStringDialog(type,x,y,IS_LONG);
#else
	ErrorStringDialog(NULL,type,x,y,IS_LONG);
#endif
	close=FALSE;
}

void GeModalDialog::CheckReal(LONG id, LONG type, Real val, Real x, Real y, LONG format)
{
	if (!close) return;
	switch (type)
	{
		case Greater				 : if (val>x) return; break;
		case GreaterOrEqual  : if (val>=x) return; break;
		case Less						 : if (val<x) return; break;
		case LessOrEqual		 : if (val<=x) return; break;
		case Between				 : if (val>x && val<y) return; break;
		case BetweenOrEqual	 : if (val>=x && val<=y) return; break;
		case BetweenOrEqualX : if (val>=x && val<y) return; break;
		case BetweenOrEqualY : if (val>x && val<=y) return; break;
		case Different			 : if (val!=x) return; break;
	}

	Activate(id);
#ifndef __API_INTERN__
	ErrorStringDialog(type,x,y,format);
#else
	ErrorStringDialog(NULL,type,x,y,format);
#endif
	close=FALSE;
}

void GeModalDialog::CheckMeter(LONG id, LONG type, Real val, Real x, Real y)
{
	CheckReal(id,type,val,x,y,IS_METER);
}

void GeModalDialog::CheckPercent(LONG id, LONG type, Real val, Real x, Real y)
{
	CheckReal(id,type,val,x,y,IS_PERCENT);
}

void GeModalDialog::CheckDegree(LONG id, LONG type, Real val, Real x, Real y)
{
	CheckReal(id,type,val,x,y,IS_DEGREE);
}

GeUserArea::GeUserArea(void)
{
	dlg   = NULL;
	cu    = NULL;
	owncu = FALSE;
}

GeUserArea::~GeUserArea(void)
{
	if (!owncu)
		C4DOS.Cu->Free(cu);

	dlg = NULL;
	cu  = NULL;
}

Bool GeUserArea::SetDragDestination(LONG cursor)
{
	return C4DOS.Cu->SetDragDestination(cu,cursor);
}

Bool GeDialog::SetDragDestination(LONG cursor,LONG gadgetid)
{
	if (gadgetid)
	{
		CBaseFrame *cbf = C4DOS.Cd->CBF_FindBaseFrame(Get(),gadgetid);
		return C4DOS.Cd->CBF_SetDragDestination(cbf,cursor);
	}
	return C4DOS.Cd->SetDragDestination(cd,cursor);
}



LONG GeUserArea::GetWidth(void)
{
	return C4DOS.Cu->GetWidth(cu);
}

LONG GeUserArea::GetHeight(void)
{
	return C4DOS.Cu->GetHeight(cu);
}

LONG GeUserArea::GetId(void)
{
	return C4DOS.Cu->GetID(cu);
}

Bool GeUserArea::IsEnabled(void)
{
	return C4DOS.Cu->IsEnabled(cu);
}

Bool GeUserArea::HasFocus(void)
{
	return C4DOS.Cu->HasFocus(cu);
}

void GeUserArea::DrawLine(LONG x1,LONG y1,LONG x2,LONG y2)
{
	C4DOS.Cu->DrawLine(cu,x1,y1,x2,y2);
}

void GeUserArea::DrawRectangle(LONG x1,LONG y1,LONG x2,LONG y2)
{
	C4DOS.Cu->DrawRectangle(cu,x1,y1,x2,y2);
}

void GeUserArea::DrawSetPen(const Vector &color)
{
	C4DOS.Cu->DrawSetPenV(cu,color);
}

void GeUserArea::DrawSetPen(LONG id)
{
	C4DOS.Cu->DrawSetPenI(cu,id);
}

Bool GeUserArea::IsHotkeyDown(LONG id)
{
	return C4DOS.Cu->IsHotkeyDown(cu,id);
}

void GeUserArea::GetBorderSize(LONG type,LONG *l,LONG *t,LONG *r,LONG *b)
{
	C4DOS.Cu->GetBorderSize(cu,type,l,t,r,b);
}

void GeUserArea::DrawBorder(LONG type,LONG x1,LONG y1,LONG x2,LONG y2)
{
	C4DOS.Cu->DrawBorder(cu,type,x1,y1,x2,y2);
}

void GeUserArea::SetTimer(LONG timer)
{
	C4DOS.Cu->SetTimer(cu,timer);
}

Bool GeUserArea::GetInputState(LONG askdevice,LONG askchannel,BaseContainer &res)
{
	return C4DOS.Cu->GetInputState((CBaseFrame*)cu,askdevice,askchannel,&res);
}

Bool GeUserArea::GetInputEvent(LONG askdevice,BaseContainer &res)
{
	return C4DOS.Cu->GetInputEvent((CBaseFrame*)cu,askdevice,&res);
}

void GeUserArea::KillEvents(void)
{
	C4DOS.Cu->KillEvents((CBaseFrame*)cu);
}

Bool GeUserArea::CheckDropArea(const BaseContainer &msg,Bool horiz,Bool vert)
{
	LONG x=0,y=0,w,h,dx,dy;

	dlg->GetDragPosition(msg,&dx,&dy);
	dlg->GetItemDim(GetId(),&x,&y,&w,&h);

	if (horiz && vert)
		return dx>x && dx<x+w && dy>y && dy<y+h;
	else if (vert)
		return dy>y && dy<y+h;
	return dx>x && dx<x+w;
}

void GeUserArea::DrawSetFont(LONG fontid)
{
	C4DOS.Cu->DrawSetFont(cu,fontid);
}

LONG GeUserArea::DrawGetTextWidth(const String &text)
{
	return C4DOS.Cu->DrawGetTextWidth(cu,(String*)&text);
}

LONG GeUserArea::DrawGetFontHeight()
{
	return C4DOS.Cu->DrawGetFontHeight(cu);
}

void GeUserArea::DrawSetTextCol(LONG fg,LONG bg)
{
	C4DOS.Cu->DrawSetTextColII(cu,fg,bg);
}

void GeUserArea::DrawSetTextCol(const Vector &fg,LONG bg)
{
	C4DOS.Cu->DrawSetTextColVI(cu,fg,bg);
}

void GeUserArea::DrawSetTextCol(LONG fg,const Vector &bg)
{
	C4DOS.Cu->DrawSetTextColIV(cu,fg,bg);
}

void GeUserArea::DrawSetTextCol(const Vector &fg,const Vector &bg)
{
	C4DOS.Cu->DrawSetTextColVV(cu,fg,bg);
}

void GeUserArea::DrawText(const String &txt,LONG x,LONG y)
{
	if (!txt.Content()) return;
	C4DOS.Cu->DrawText(cu,(String *)&txt,x,y);
}

void GeUserArea::DrawBitmap(BaseBitmap *bmp,LONG wx,LONG wy,LONG ww,LONG wh,LONG x,LONG y,LONG w,LONG h,LONG mode)
{
	C4DOS.Cu->DrawBitmap(cu,bmp,wx,wy,ww,wh,x,y,w,h,mode);
}

void GeUserArea::SetClippingRegion(LONG x,LONG y,LONG w,LONG h)
{
	C4DOS.Cu->SetClippingRegion(cu,x,y,w,h);
}

void GeUserArea::ClearClippingRegion(void)
{
	C4DOS.Cu->ClearClippingRegion(cu);
}

Bool GeUserArea::OffScreenOn()
{
	return C4DOS.Cu->OffScreenOn(cu);
}

void GeUserArea::ScrollArea(LONG xdiff,LONG ydiff,LONG x,LONG y,LONG w,LONG h)
{
	C4DOS.Cu->ScrollArea(cu,xdiff,ydiff,x,y,w,h);
}

Bool GeUserArea::Global2Local(LONG *x,LONG *y)
{
	return C4DOS.Cu->Global2Local((CBaseFrame*)cu,x,y);
}

Bool GeUserArea::Local2Global(LONG *x,LONG *y)
{
	if (x) *x=-*x;
	if (y) *y=-*y;
	Bool res = C4DOS.Cu->Global2Local((CBaseFrame*)cu,x,y);
	if (x) *x=-*x;
	if (y) *y=-*y;
	return res;
}

Bool GeUserArea::Local2Screen(LONG *x,LONG *y)
{
	if (x) *x=-*x;
	if (y) *y=-*y;
	Bool res = C4DOS.Cu->Screen2Local((CBaseFrame*)cu,x,y);
	if (x) *x=-*x;
	if (y) *y=-*y;
	return res;
}

Bool GeUserArea::Screen2Local(LONG *x,LONG *y)
{
	return C4DOS.Cu->Screen2Local((CBaseFrame*)cu,x,y);
}

void GeUserArea::Redraw(Bool threaded)
{
	if (dlg)
	{
		if (threaded)
		{
			C4DOS.Cd->SendRedrawThread(dlg->Get(),GetId());
		}
		else
		{
			dlg->SendMessage(GetId(),BaseContainer(BFM_DRAW));
		}
	}
}

Bool GeUserArea::SendParentMessage(const BaseContainer &msg)
{
	C4DOS.Cu->SendParentMessage(cu,(BaseContainer*)&msg);
	return TRUE;
}

void GeUserArea::MouseDragStart(LONG button,Real mx,Real my,LONG flag)
{
	C4DOS.Cu->MouseDragStart(cu,button,mx,my,flag);
}

LONG GeUserArea::MouseDrag(Real *mx,Real *my,BaseContainer *channels)
{
	return C4DOS.Cu->MouseDrag(cu,mx,my,channels);
}

LONG GeUserArea::MouseDragEnd(void)
{
	return C4DOS.Cu->MouseDragEnd(cu);
}


Bool GeUserArea::Init(void)
{
	return TRUE;
}

Bool GeUserArea::InitValues(void)
{
	return TRUE;
}

void GeUserArea::Draw(LONG x1,LONG y1,LONG x2,LONG y2)
{
	DrawSetPen(COLOR_BG);
	DrawRectangle(x1,y1,x2,y2);
}

Bool GeUserArea::CoreMessage(LONG id,const BaseContainer &msg)
{
	return TRUE;
}

Bool GeUserArea::GetMinSize(LONG &w,LONG &h)
{
	return FALSE;
}

void GeUserArea::Sized(LONG w,LONG h)
{
}

Bool GeUserArea::InputEvent(const BaseContainer &msg)
{
	return FALSE;
}

void GeUserArea::Timer(const BaseContainer &msg)
{
}

Bool GeUserArea::HandleMouseDrag(const BaseContainer &msg,LONG type,void *data,Bool privateframe)
{
	return C4DOS.Cu->HandleMouseDrag(cu,&msg,type,data,privateframe);
}

Bool GeUserArea::GetDragObject(const BaseContainer &msg,LONG *type,void **object)
{
	return dlg->GetDragObject(msg,type,object);
}

Bool GeUserArea::GetDragPosition(const BaseContainer &msg,LONG *x,LONG *y)
{
	if (x) *x = msg.GetLong(BFM_DRAG_SCREENX);
	if (y) *y = msg.GetLong(BFM_DRAG_SCREENY);
	return C4DOS.Cu->Screen2Local((CBaseFrame*)cu,x,y);
}

LONG GeUserArea::Message(const BaseContainer &msg,BaseContainer &result)
{
	LONG id;
	LONG res = 0;

	switch (msg.GetId())
	{
		case BFM_INIT:
			Init();
			res = TRUE;
			break;

		case BFM_INITVALUES:
			InitValues();
			res = TRUE;
			break;

		case BFM_CALCSIZE:
			{
				LONG w=0,h=0;
				if (GetMinSize(w,h))
					C4DOS.Cu->SetMinSize(cu,w,h);
				res = TRUE;
			}
			break;

		case BFM_SIZED:
			Sized(GetWidth(),GetHeight());
			res = TRUE;
			break;

		case BFM_DRAW:
			{
				LONG xr1 = msg.GetLong(BFM_DRAW_LEFT);
				LONG yr1 = msg.GetLong(BFM_DRAW_TOP);
				LONG xr2 = msg.GetLong(BFM_DRAW_RIGHT);
				LONG yr2 = msg.GetLong(BFM_DRAW_BOTTOM);
				Draw(xr1,yr1,xr2,yr2);
				res = TRUE;
			}
			break;

		case BFM_INPUT:
			return InputEvent(msg);

		case BFM_TIMER_MESSAGE:
			Timer(msg);
			res = TRUE;
			break;

		case BFM_SYNC_MESSAGE:
		case BFM_CORE_MESSAGE:
			id = msg.GetLong(BFM_CORE_ID);
			return CoreMessage(id,msg);
	}
	return res;
}

void GeUserArea::FillBitmapBackground(BaseBitmap *bmp,LONG offsetx,LONG offsety)
{
	DrawBitmap(bmp,-0x12345,-0x12345,-0x12345,-0x12345,offsetx,offsety,-0x12345,-0x12345,-0x12345);
}

void GeUserArea::LayoutChanged(void)
{
	SendParentMessage(BaseContainer(BFM_LAYOUT_CHANGED));
}

SubDialog::SubDialog(void)
{
	dlg_result = TRUE;
}

SubDialog::~SubDialog(void)
{
}

LONG SubDialog::Message(const BaseContainer &msg,BaseContainer &result)
{
	switch (msg.GetId())
	{
		case BFM_CHECKCLOSE:
			dlg_result = TRUE;
			if (CheckValueRanges())
			{
				dlg_result = FALSE;
				return TRUE;
			}
			return FALSE;

		case BFM_ASKCLOSE:
			if (dlg_result)
			{
				return AskClose();
			}
			return FALSE;
	}
	return GeDialog::Message(msg,result);
}

LONG ShowPopupMenu(CDialog *parent,LONG screenx,LONG screeny,const BaseContainer &bc,LONG flags)
{
	return C4DOS.Ge->ShowPopupMenu(parent,screenx,screeny,(BaseContainer*)&bc,flags);
}


#ifndef __API_INTERN__
	void MessageDialog(const String &str)
	{
		GeOutString(str,GEMB_OK+GEMB_ICONEXCLAMATION);
	}

	void MessageDialog(LONG id)
	{
		GeOutString(GeLoadString(id),GEMB_OK+GEMB_ICONEXCLAMATION);
	}

	void MessageDialog(LONG id, const String &p1)
	{
		GeOutString(GeLoadString(id,p1),GEMB_OK+GEMB_ICONEXCLAMATION);
	}

	void MessageDialog(LONG id, const String &p1, const String &p2)
	{
		GeOutString(GeLoadString(id,p1,p2),GEMB_OK+GEMB_ICONEXCLAMATION);
	}

	Bool QuestionDialog(const String &str)
	{
		return GeOutString(str,GEMB_YESNO+GEMB_ICONQUESTION)==GEMB_R_YES;
	}

	Bool QuestionDialog(LONG id)
	{
		return GeOutString(GeLoadString(id),GEMB_YESNO+GEMB_ICONQUESTION)==GEMB_R_YES;
	}

	Bool QuestionDialog(LONG id, const String &p1)
	{
		return GeOutString(GeLoadString(id,p1),GEMB_YESNO+GEMB_ICONQUESTION)==GEMB_R_YES;
	}

	Bool QuestionDialog(LONG id, const String &p1, const String &p2)
	{
		return GeOutString(GeLoadString(id,p1,p2),GEMB_YESNO+GEMB_ICONQUESTION)==GEMB_R_YES;
	}

	Bool GetInputEvent(LONG askdevice,BaseContainer &res)
	{
		return C4DOS.Ge->EwBfGetInputEvent(NULL,askdevice,&res);
	}

	Bool GetInputState(LONG askdevice,LONG askchannel,BaseContainer &res)
	{
		return C4DOS.Ge->EwBfGetInputState(NULL,askdevice,askchannel,&res);
	}
#endif



Bool GeDialog::GetInputState(LONG askdevice,LONG askchannel,BaseContainer &res)
{
	return C4DOS.Cu->GetInputState((CBaseFrame*)cd,askdevice,askchannel,&res);
}

Bool GeDialog::GetInputEvent(LONG askdevice,BaseContainer &res)
{
	return C4DOS.Cu->GetInputEvent((CBaseFrame*)cd,askdevice,&res);
}

void GeDialog::KillEvents(void)
{
	C4DOS.Cu->KillEvents((CBaseFrame*)cd);
}

// Tristate functions
Bool GeDialog::SetBool(const GadgetPtr &id, const TriState<Bool> &tri)
{
	Bool v = tri.GetValue();
	Bool t = tri.GetTri();
	if (t) v = 2;
	return SetBool(id,v,t);
}

Bool GeDialog::SetLong(const GadgetPtr &id, const TriState<LONG> &tri,LONG min,LONG max,LONG step)
{
	return SetLong(id,tri.GetValue(),min,max,step,tri.GetTri());
}

Bool GeDialog::SetReal(const GadgetPtr &id, const TriState<Real> &tri,Real min,Real max,Real step,LONG format,Real min2,Real max2,Bool quadscale)
{
	return SetReal(id,tri.GetValue(),min,max,step,format,min2,max2,quadscale,tri.GetTri());
}

Bool GeDialog::SetMeter(const GadgetPtr &id, const TriState<Real> &tri,Real min,Real max,Real step)
{
	return SetMeter(id,tri.GetValue(),min,max,step,tri.GetTri());
}

Bool GeDialog::SetDegree(const GadgetPtr &id, const TriState<Real> &tri,Real min,Real max,Real step)
{
	return SetDegree(id,tri.GetValue(),min,max,step,tri.GetTri());
}

Bool GeDialog::SetPercent(const GadgetPtr &id, const TriState<Real> &tri,Real min,Real max,Real step)
{
	return SetPercent(id,tri.GetValue(),min,max,step,tri.GetTri());
}

Bool GeDialog::SetTime(const GadgetPtr &id, BaseDocument *doc, const TriState<BaseTime> &tri,const BaseTime &min, const BaseTime &max,LONG stepframes)
{
	return SetTime(id, doc, tri.GetValue(),min,max,stepframes,tri.GetTri());
}

Bool GeDialog::SetVectorReal(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, const TriState<Vector> &tri, Real min, Real max, Real step)
{
	return SetVectorReal(id_x,id_y,id_z,tri.GetValue(),min,max,step,tri.GetTri());
}

Bool GeDialog::SetVectorMeter(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, const TriState<Vector> &tri, Real min, Real max, Real step)
{
	return SetVectorMeter(id_x,id_y,id_z,tri.GetValue(),min,max,step,tri.GetTri());
}

Bool GeDialog::SetVectorDegree(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, const TriState<Vector> &tri, Real min, Real max, Real step)
{
	return SetVectorDegree(id_x,id_y,id_z,tri.GetValue(),min,max,step,tri.GetTri());
}

Bool GeDialog::SetVectorPercent(const GadgetPtr &id_x, const GadgetPtr &id_y, const GadgetPtr &id_z, const TriState<Vector> &tri, Real min, Real max, Real step)
{
	return SetVectorPercent(id_x,id_y,id_z,tri.GetValue(),min,max,step,tri.GetTri());
}

Bool GeDialog::SetString(const GadgetPtr &id, const TriState<String> &tri)
{
	return SetString(id,tri.GetValue(),tri.GetTri());
}

Bool GeDialog::SetColorField(const GadgetPtr &id, const TriState<Vector> &tri, Real brightness, Real maxbrightness, LONG flags)
{
	return SetColorField(id,tri.GetValue(),brightness,maxbrightness,flags);
}

Bool GeDialog::CheckDropArea(const GadgetPtr &id,const BaseContainer &msg,Bool horiz,Bool vert)
{
	LONG x,y,w,h,dx,dy;
	GetDragPosition(msg,&dx,&dy);
	GetItemDim(id,&x,&y,&w,&h);
	if (horiz && vert)
		return dx>x && dx<x+w && dy>y && dy<y+h;
	else if (vert)
		return dy>y && dy<y+h;
	return dx>x && dx<x+w;
}

Bool GeDialog::CheckCoreMessage(const BaseContainer &msg)
{
	LONG coremsg = msg.GetLong(BFM_CORE_UNIQUEID);
	if (!coremsg) return TRUE;
	if (coremsg==lastcoremsg) return FALSE;
	if (coremsg==msg.GetLong(BFM_CORE_ID) && (msg.GetLong(BFM_CORE_PAR1)&EVENT_GLHACK)) return FALSE;
	lastcoremsg = coremsg;
	return TRUE;
}

void TriState<Bool>::Add(BaseContainer *bc,LONG id)
{
	Bool val;
	val = bc->GetBool(id);
	Add(val);
}

void TriState<LONG>::Add(BaseContainer *bc,LONG id)
{
	LONG val;
	val = bc->GetLong(id);
	Add(val);
}

void TriState<Real>::Add(BaseContainer *bc,LONG id)
{
	Real val;
	val = bc->GetReal(id);
	Add(val);
}

void TriState<Vector>::Add(BaseContainer *bc,LONG id)
{
	Vector val;
	val = bc->GetVector(id);
	Add(val);
}

void TriState<BaseTime>::Add(BaseContainer *bc,LONG id)
{
	BaseTime val;
	val = bc->GetTime(id);
	Add(val);
}

void TriState<String>::Add(BaseContainer *bc,LONG id)
{
	String val;
	val = bc->GetString(id);
	Add(val);
}



LONG TriState<Bool>::Check(GeDialog *dlg,const BaseContainer &msg,LONG cid,LONG gid)
{
	if (cid!=gid || msg.GetLong(BFM_ACTION_STRCHG) || msg.GetLong(BFM_ACTION_INDRAG)) return 0;
	Bool val = FALSE;
	if (!dlg->GetBool(cid,val)) return 0;
	Add(val);
	return 1;
}

LONG TriState<LONG>::Check(GeDialog *dlg,const BaseContainer &msg,LONG cid,LONG gid)
{
	if (cid!=gid || msg.GetLong(BFM_ACTION_STRCHG) || msg.GetLong(BFM_ACTION_INDRAG)) return 0;
	LONG val = 0;
	if (!dlg->GetLong(cid,val)) return 0;
	Add(val);
	return 1;
}

LONG TriState<Real>::Check(GeDialog *dlg,const BaseContainer &msg,LONG cid,LONG gid)
{
	if (cid!=gid || msg.GetLong(BFM_ACTION_STRCHG) || msg.GetLong(BFM_ACTION_INDRAG)) return 0;
	Real val = 0.0;
	if (!dlg->GetReal(cid,val)) return 0;
	Add(val);
	return 1;
}

LONG TriState<Vector>::CheckVector(GeDialog *dlg,const BaseContainer &msg,LONG cid,LONG gidx,LONG gidy,LONG gidz)
{
	if (cid!=gidx && cid!=gidy && cid!=gidz) return 0;
	if (msg.GetLong(BFM_ACTION_STRCHG) || msg.GetLong(BFM_ACTION_INDRAG)) return 0;

	Vector val = 0.0;
	if (!dlg->GetVector(gidx,gidy,gidz,val)) return 0;
	Add(val);
	return TRUE;
}

LONG TriState<BaseTime>::CheckBaseTime(GeDialog *dlg,const BaseContainer &msg,BaseDocument *doc,LONG cid,LONG gid)
{
	if (cid!=gid || msg.GetLong(BFM_ACTION_STRCHG) || msg.GetLong(BFM_ACTION_INDRAG)) return 0;
	BaseTime val;
	if (!dlg->GetTime(cid,doc,val)) return 0;
	Add(val);
	return TRUE;
}

LONG TriState<String>::Check(GeDialog *dlg,const BaseContainer &msg,LONG cid,LONG gid)
{
	if (cid!=gid || msg.GetLong(BFM_ACTION_STRCHG) || msg.GetLong(BFM_ACTION_INDRAG)) return 0;
	String val;
	if (!dlg->GetString(cid,val)) return 0;
	Add(val);
	return TRUE;
}


iCustomGui::iCustomGui(const BaseContainer &settings,CUSTOMGUIPLUGIN *t_plugin)
{
	plugin = t_plugin;

	layoutmode = settings.GetLong(CUSTOMGUI_LAYOUTMODE);
	if (layoutmode!=LAYOUTMODE_MINIMIZED && layoutmode!=LAYOUTMODE_MAXIMIZED)
		layoutmode = LAYOUTMODE_NONE;

	editheight = settings.GetLong(CUSTOMGUI_DEFAULTEDITHEIGHT);
}

LONG iCustomGui::Message(const BaseContainer &msg,BaseContainer &result)
{
	switch (msg.GetId())
	{
		case BFM_DESTROY:
			ReleaseLink();
			DestroyWindow();
			return TRUE;
	}
	return SubDialog::Message(msg,result);
}

LONG iCustomGui::CustomGuiWidth()
{
	return 0;
}

LONG iCustomGui::CustomGuiHeight()
{
	return 0;
}

void iCustomGui::CustomGuiRedraw()
{
}

Bool iCustomGui::CustomGuiLayoutChanged()
{
	return FALSE;
}

Bool iCustomGui::CustomGuiActivate()
{
	return FALSE;
}

Bool iCustomGui::SetDefaultForResEdit()
{
	return FALSE;
}

Bool iCustomGui::SetData(const TriState<GeData> &tristate)
{
	return FALSE;
}

TriState<GeData> iCustomGui::GetData()
{
	TriState<GeData> tri;
	return tri;
}

void iCustomGui::SetLayoutMode(LONG mode)
{
	if (SupportLayoutSwitch() && layoutmode != mode)
	{
		layoutmode = mode;
		LayoutModeChanged();
	}
}

LONG iCustomGui::GetLayoutMode()
{
	return layoutmode;
}

Bool iCustomGui::SupportLayoutSwitch()
{
	if (!plugin) return FALSE;
	return (plugin->info & CUSTOMGUI_SUPPORT_LAYOUTSWITCH)!=0;
}

void iCustomGui::LayoutModeChanged()
{
}
