
#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"
	#include "lib_description.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
	#undef Lock
	
#endif

static 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;
		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:
			if (!createlayout) return TRUE;
			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;
	}
	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);
}

Bool GeDialog::IsVisible()
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_ISVISIBLE,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(DLG_TYPE dlgtype,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,dlgtype,NULL,xpos,ypos,defaultw,defaulth);
}

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

Bool GeDialog::Close(Bool dummy)
{
	return Close();
}

GeData 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::IsEnabled(const GadgetPtr &id)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->IsEnabled(cd,id.Id(),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;
	return C4DOS.Cu->Local2Global((CBaseFrame*)cd,x,y);
}

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;
	return C4DOS.Cu->Local2Screen((CBaseFrame*)cd,x,y);
}

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,LONG min2,LONG max2)
{
	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);
	if (min2!=MINLONGl || max2!=MAXLONGl)
	{
		msg.SetLong(CM_VALUE_MIN2,min2);
		msg.SetLong(CM_VALUE_MAX2,max2);
	}

	return SendMessage(id,msg).GetLong();
}

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).GetLong();
}

Bool GeDialog::SetMultiLinePos(const GadgetPtr &id, LONG line, LONG pos)
{
	BaseContainer msg(BFM_SPECIALSETRANGE);
	msg.SetData(1,line);
	msg.SetData(2,pos);
	return SendMessage(id,msg).GetLong();
}

Bool GeDialog::SetMultiLineMode(const GadgetPtr &id, SCRIPTMODE mode)
{
	BaseContainer msg(BFM_SPECIALMODE);
	msg.SetLong(1,mode);
	return SendMessage(id,msg).GetLong();
}

Bool GeDialog::SetMultiLineLock(const GadgetPtr &id, Bool lock)
{	
	BaseContainer msg(lock?BFM_SETSPECIALMULTI:BFM_SETSPECIALMULTID);
	msg.SetLong(msg.GetId(),DR_MULTILINE_READONLY);
	return SendMessage(id,msg).GetLong();
}

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

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 radians_value,Real min,Real max,Real step,LONG tristate)
{
	return SetReal(id,radians_value, min == MINREALr ? min : Rad(min), max == MAXREALr ? max : 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/RCO 100.0,max/RCO 100.0,step/RCO 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) const
{
	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) const
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GetLong(cd,id.Id(),value,id.Ptr());
}

Bool GeDialog::GetReal(const GadgetPtr &id, Real &value) const
{
	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) const
{
	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) const
{
	if (!cd) return FALSE;
	String *str = NULL;
	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) const
{
	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) const
{
	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) const
{
	Bool b=FALSE;
	Bool ok=GetBool(id,b);
	bc->SetBool(bcid,b);
	return ok;
}

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

Bool GeDialog::GetReal(const GadgetPtr &id, BaseContainer *bc, LONG bcid) const
{
	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) const
{
	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) const
{
	String b;
	Bool   ok=GetString(id,b);
	bc->SetString(bcid,b);
	return ok;
}

Bool GeDialog::GetFilename(const GadgetPtr &id, BaseContainer *bc, LONG bcid) const
{
	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) const
{
	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, const BaseContainer *bc, LONG bcid)
{
	return SetBool(id,bc->GetBool(bcid));
}

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

Bool GeDialog::SetReal(const GadgetPtr &id, const 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, const 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, const 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, const BaseContainer *bc, LONG bcid,Real min,Real max,Real step)
{
	return SetPercent(id,bc->GetReal(bcid),min,max,step);
}

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

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

Bool GeDialog::SetColorField(const GadgetPtr &id, const 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, const 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.GetNumerator()*fps)/Floor(value.GetDenominator()));
	msg.SetLong(CM_VALUE_FORMAT,FORMAT_FRAMES);
	msg.SetReal(CM_VALUE_MIN,Floor(min.GetNumerator()*fps)/Floor(min.GetDenominator()));
	msg.SetReal(CM_VALUE_MAX,Floor(max.GetNumerator()*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).GetLong();
}

Bool GeDialog::GetTime(const GadgetPtr &id, const BaseDocument *doc, BaseTime &time) const
{
	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*RCO 1000.0,fps*RCO 1000.0);
	return ok;
}

Bool GeDialog::SetTime(const GadgetPtr &id, const BaseDocument *doc, const 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, const BaseDocument *doc, BaseContainer *bc, LONG bcid) const
{
	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;
}

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

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

C4DGadget *GeDialog::AddSeparatorV(LONG initw,LONG flags)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_SEPARATOR,0,NULL,flags,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::AddEditShortcut(LONG id, LONG flags, LONG initw, LONG inith, LONG shortcutflags)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_EDITSHORTCUT,id,NULL,flags,initw,inith,shortcutflags,NULL,&r);
	return (C4DGadget*)r;
}

C4DGadget *GeDialog::AddEditText(LONG id, LONG flags, LONG initw, LONG inith, LONG editflags)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_EDITTEXT,id,NULL,flags,initw,inith,editflags,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, LONG colorflags)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_COLORFIELD,id,NULL,flags,initw,inith,colorflags,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::AddComboButton(LONG id, LONG flags, LONG initw, LONG inith,Bool specialalign)
{
	if (!cd) return FALSE;
	void *r=NULL;
	C4DOS.Cd->AddGadget(cd,DIALOG_COMBOBUTTON,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::AddChildren(const GadgetPtr &id, const BaseContainer &bc)
{
	BrowseContainer br(&bc);
	LONG sid;
	GeData *dat;
	while (br.GetNext(&sid, &dat))
	{
		if (!dat) continue;
		if (!AddChild(id, sid, dat->GetString()))
			return FALSE;
	}
	return TRUE;
}

Bool GeDialog::FreeChildren(const GadgetPtr &id)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->AddGadget(cd,DIALOG_FREECHILDREN,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, LONG initw, LONG inith)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GroupBegin(cd,id,flags,cols,rows,(String*)&title,groupflags,initw,inith);
}

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(ULONG borderstyle)
{
	if (!cd) return FALSE;
	return C4DOS.Cd->GroupBorder(cd,borderstyle|BORDER_WITH_TITLE);
}

Bool GeDialog::GroupBorderNoTitle(ULONG 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,USERAREAFLAGS 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::LayoutChangedNoRedraw(const GadgetPtr &id)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_LAYOUTCHANGED,id.Id(),NULL,TRUE,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::GroupWeightsSave(const GadgetPtr &id,BaseContainer &weights)
{
	BaseContainer storehere;
	Bool ret = C4DOS.Cd->AddGadget(cd,DIALOG_SAVEWEIGHTS,id.Id(),NULL,0,0,0,0,&storehere,(void**)id.Ptr());
	if (ret) weights = storehere;
	return ret;
}

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

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::HideElement(const GadgetPtr &id, Bool hide)
{
	return C4DOS.Cd->AddGadget(cd,DIALOG_HIDEELEMENT,id.Id(),NULL,hide,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 override
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;
}

Bool GeDialog::Command(LONG id,const BaseContainer &msg)
{
	// esc when focus in userareas did not worked!
	return FALSE;
}

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

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

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

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

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

GeModalDialog::~GeModalDialog(void)
{
}

Bool GeModalDialog::Open(LONG xpos,LONG ypos,LONG defaultw,LONG defaulth, Bool resizable)
{
	dlg_result = FALSE;
	return GeDialog::Open(resizable?DLG_TYPE_MODAL_RESIZEABLE:DLG_TYPE_MODAL,0,xpos,ypos,defaultw,defaulth) && 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, CHECKVALUERANGE type, LONG val, LONG x, LONG y)
{
	if (!close) return;
	switch (type)
	{
		case CHECKVALUERANGE_GREATER				 : if (val>x) return; break;
		case CHECKVALUERANGE_GREATEROREQUAL  : if (val>=x) return; break;
		case CHECKVALUERANGE_LESS						 : if (val<x) return; break;
		case CHECKVALUERANGE_LESSOREQUAL		 : if (val<=x) return; break;
		case CHECKVALUERANGE_BETWEEN				 : if (val>x && val<y) return; break;
		case CHECKVALUERANGE_BETWEENOREQUAL	 : if (val>=x && val<=y) return; break;
		case CHECKVALUERANGE_BETWEENOREQUALX : if (val>=x && val<y) return; break;
		case CHECKVALUERANGE_BETWEENOREQUALY : if (val>x && val<=y) return; break;
		case CHECKVALUERANGE_DIFFERENT			 : if (val!=x) return; break;
	}

	Activate(id);
	ErrorStringDialog(type,(Real)x,(Real)y,CHECKVALUEFORMAT_LONG);
	close=FALSE;
}

void GeModalDialog::CheckReal(LONG id, CHECKVALUERANGE type, Real val, Real x, Real y, CHECKVALUEFORMAT format)
{
	if (!close) return;
	switch (type)
	{
		case CHECKVALUERANGE_GREATER				 : if (val>x) return; break;
		case CHECKVALUERANGE_GREATEROREQUAL  : if (val>=x) return; break;
		case CHECKVALUERANGE_LESS						 : if (val<x) return; break;
		case CHECKVALUERANGE_LESSOREQUAL		 : if (val<=x) return; break;
		case CHECKVALUERANGE_BETWEEN				 : if (val>x && val<y) return; break;
		case CHECKVALUERANGE_BETWEENOREQUAL	 : if (val>=x && val<=y) return; break;
		case CHECKVALUERANGE_BETWEENOREQUALX : if (val>=x && val<y) return; break;
		case CHECKVALUERANGE_BETWEENOREQUALY : if (val>x && val<=y) return; break;
		case CHECKVALUERANGE_DIFFERENT			 : if (val!=x) return; break;
	}

	Activate(id);
	ErrorStringDialog(type,x,y,format);
	close=FALSE;
}

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

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

void GeModalDialog::CheckDegree(LONG id, CHECKVALUERANGE type, Real val, Real x, Real y)
{
	CheckReal(id,type,val,x,y,CHECKVALUEFORMAT_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::DrawBezier(Real sx, Real sy, Real *p, LONG count, Bool closed, Bool filled)
{
	C4DOS.Cu->DrawBezier(cu,sx,sy,p,count,closed,filled);
}

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 GeData &d)
{
	if (d.GetType() == DA_VECTOR)
		DrawSetPen(d.GetVector());
	else if (d.GetType() == DA_LONG)
		DrawSetPen(d.GetLong());
	else
		GeBoom();
}

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

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

Bool GeUserArea::GetColorRGB(LONG colorid, LONG &r, LONG &g, LONG &b)
{
	return C4DOS.Cd->CBF_GetColorRGB((CBaseFrame*)cu,colorid,r,g,b);
}

void GeUserArea::ActivateFading(LONG milliseconds)
{
	C4DOS.Cd->CBF_ActivateFading((CBaseFrame*)cu,milliseconds);
}

void GeUserArea::AdjustColor(LONG colorid, LONG highlightid, Real percent)
{
	C4DOS.Cd->CBF_AdjustColor((CBaseFrame*)cu, colorid, highlightid, percent);
}

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::DrawGetTextWidth_ListNodeName(BaseList2D *node, LONG fontid)
{
	return C4DOS.Cu->DrawGetTextWidth_ListNodeName(cu,node,fontid);
}

void GeUserArea::DrawSetTextRotation(Real textrotation)
{
	C4DOS.Cu->DrawSetTextRotation(cu,textrotation);
}

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

LONG GeUserArea::DrawGetFontBaseLine()
{
	return C4DOS.Cu->DrawGetFontBaseLine(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::DrawSetTextCol(const GeData& fg, const GeData& bg)
{
	if (fg.GetType() == DA_VECTOR)
	{
		if (bg.GetType() == DA_VECTOR)
			C4DOS.Cu->DrawSetTextColVV(cu,fg.GetVector(),bg.GetVector());
		else if (bg.GetType() == DA_LONG)
			C4DOS.Cu->DrawSetTextColVI(cu,fg.GetVector(),bg.GetLong());
		else
			GeBoom();
	}
	else if (fg.GetType() == DA_LONG)
	{
		if (bg.GetType() == DA_VECTOR)
			C4DOS.Cu->DrawSetTextColIV(cu,fg.GetLong(),bg.GetVector());
		else if (bg.GetType() == DA_LONG)
			C4DOS.Cu->DrawSetTextColII(cu,fg.GetLong(),bg.GetLong());
		else
			GeBoom();
	}
	else
		GeBoom();
}

void GeUserArea::DrawText(const String &txt,LONG x,LONG y,LONG flags)
{
	C4DOS.Cu->DrawText(cu,txt,x,y,flags);
}

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);
}

Bool GeUserArea::OffScreenOn(LONG x, LONG y, LONG w, LONG h)
{
	return C4DOS.Cu->OffScreenOnRect(cu,x,y,w,h);
}

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)
{
	return C4DOS.Cu->Local2Global((CBaseFrame*)cu,x,y);
}

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

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,MOUSEDRAGFLAGS flag)
{
	C4DOS.Cu->MouseDragStart(cu,button,mx,my,flag);
}

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

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

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

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

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

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

void GeUserArea::DrawMsg(LONG x1,LONG y1,LONG x2,LONG y2,const BaseContainer &msg)
{
	Draw(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,LONG dragflags)
{
	return C4DOS.Cu->HandleMouseDrag(cu,&msg,type,data,dragflags);
}

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);
				DrawMsg(xr1,yr1,xr2,yr2,msg);
				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, LONG *res_mainid)
{
	return C4DOS.Ge->ShowPopupMenu(parent,screenx,screeny,(BaseContainer*)&bc,flags,res_mainid);
}

Bool RemoveLastCursorInfo(LASTCURSORINFOFUNC func)
{
	return C4DOS.Cd->RemoveLastCursorInfo(func);
}

String Shortcut2String(LONG shortqual,LONG shortkey)
{
	return C4DOS.Cd->Shortcut2String(shortqual,shortkey);
}

String Shortcut2String(const BaseContainer &sc)
{
	String t;
	LONG i;
	for (i=0;TRUE;i++)
	{
		LONG qual = sc.GetLong(i*10+0);
		LONG key  = sc.GetLong(i*10+1);
		if (!key) break;
		if (i>0) 
			t += "~";
		t += Shortcut2String(qual,key);
	}
	return t;
}

#ifndef __API_INTERN__
	Bool GetIconCoordInfo(LONG &id, const CHAR* ident)
	{
		return C4DOS.Cd->GetIconCoordInfo(id, ident);
	}

	Bool GetInterfaceIcon(LONG type, LONG id_x, LONG id_y, LONG id_w, LONG id_h, IconData &d)
	{
		return C4DOS.Cd->GetInterfaceIcon(type, id_x, id_y, id_w, id_h, d);
	}

	GeClipMap *GetInterfaceScheme(LONG type)
	{
		return C4DOS.Cd->GetInterfaceScheme(type);
	}

	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,LONG min2,LONG max2)
{
	return SetLong(id,tri.GetValue(),min,max,step,tri.GetTri(),min2,max2);
}

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, const 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::SetString(const GadgetPtr &id, const TriState<String> &tri, LONG flags)
{
	return SetString(id,tri.GetValue(),tri.GetTri(),flags);
}

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 *ownlastcoremsg)
{
	LONG *storage = ownlastcoremsg;
	if (!storage) storage = &t_lastcoremsg;

	LONG coremsg = msg.GetLong(BFM_CORE_UNIQUEID);
	if (!coremsg) return TRUE;
	if (coremsg==*storage) return FALSE;
	if (coremsg==msg.GetLong(BFM_CORE_ID) && (((VULONG)msg.GetVoid(BFM_CORE_PAR1))&EVENT_GLHACK)) return FALSE;
	*storage = coremsg;
	return TRUE;
}

void GeDialog::HandleHelpString(const BaseContainer &msg, BaseContainer &result, const String &sym)
{
	const BaseContainer *bc = msg.GetContainerInstance(BFM_GETCURSORINFO);
	if (bc && bc->GetDataPointer(RESULT_HELP1)!=NULL) return;
	result = msg.GetContainer(BFM_GETCURSORINFO);
	if (result.GetId()==-1 || result.GetId()==0) result.SetId(BFM_GETCURSORINFO);
	result.SetString(RESULT_HELP1,sym);
}

Bool GeDialog::GetColorRGB(LONG colorid, LONG &r, LONG &g, LONG &b)
{
	return C4DOS.Cd->CBF_GetColorRGB((CBaseFrame*)Get(),colorid,r,g,b);
}

void GeDialog::SetDefaultColor(const GadgetPtr &id, LONG colorid, LONG mapid)
{
	C4DOS.Cd->AddGadget(cd,DIALOG_SETDEFAULTCOLOR,id.Id(),NULL,colorid,mapid,0,0,NULL,(void**)id.Ptr());
}

void GeDialog::SetDefaultColor(const GadgetPtr &id, LONG colorid, const Vector &color)
{
	C4DOS.Cd->AddGadget(cd,DIALOG_SETDEFAULTCOLOR,id.Id(),NULL,colorid,NOTOK,0,0,(BaseContainer*)&color,(void**)id.Ptr());
}


Bool GeDialog::GroupBeginInMenuLine()
{
	return C4DOS.Cd->AddGadget(Get(),DIALOG_MENUGROUPBEGIN,0,NULL,0,0,0,0,NULL,NULL);
}

#if !defined( __LINUX ) && !( defined( __MAC ) && __LP64__)
template <> void TriState<Bool>::Add(BaseContainer *bc,LONG id)
{
	Bool val;
	val = bc->GetBool(id);
	Add(val);
}
#endif

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

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

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

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

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


#if !defined( __LINUX ) && !( defined( __MAC ) && __LP64__)
template <> 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;
}
#endif

template <> 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;
}

template <> 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;
}

template <> 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;
}

template <> 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;
}

template <> 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, 10/*EDITH*/);
}

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()
{
}

//-------------------------------------------------------------------------------------------------
#define ID_MESSAGE_PROGRESS_STOP  100004837 // (defined in newman)

const CHAR* ProgressThread::GetThreadName(void) { return "Progress Thread"; }

void ProgressThread::Main(void)
{
	dlg->SetPercent(0.0);
	dlg->Main(this);
	SpecialEventAdd(ID_MESSAGE_PROGRESS_STOP);
}

void ProgressDialog::SetPercent(Real p) { percent=p; }

#define IDC_CACHE_TEXT 1000
#define IDC_CACHE_AREA 1001

Bool ProgressDialog::CreateLayout(void)
{
	SetTitle(GetTitle());

	GroupBegin(0,BFH_SCALEFIT|BFV_SCALEFIT,2,0,String(),0);
		if (!AddStaticText(IDC_CACHE_TEXT,BFH_LEFT,SizePix(40),0,String(),BORDER_NONE)) return FALSE;
		GroupBegin(0,BFH_SCALEFIT,0,0,String(),0);
			GroupBorderNoTitle(BORDER_THIN_IN);
			AddCustomGui(IDC_CACHE_AREA,CUSTOMGUI_PROGRESSBAR,String(),BFH_SCALEFIT|BFV_FIT,SizePix(300),SizePix(12),BaseContainer());
		GroupEnd();
	GroupEnd();

	AddDlgGroup(DLG_CANCEL);

	thread.dlg = this;
	
	GeShowMouse(MOUSE_BUSY);
	return TRUE;
}

Bool ProgressDialog::InitValues(void)
{
	thread.End();

	callback = NULL;
	callback_context = NULL;
	callback_result = NULL;
	percent=0.0;
	SetTimer(200);
	SetString(IDC_CACHE_TEXT,"0%");	

	return thread.Start();
}

C4DThread	*ProgressDialog::GetThread( void )
{
	return &thread;
}

// in case you have to invoke code from your progress thread that _has_ to run in the main thread (QuickTime)
void	*ProgressDialog::CallFromMainThread( void *(*fn)( void *context ), void *context )
{
	void	*result = NULL;
	
	while ( 1 )
	{
		while ( callback )																			// this shouldn't happen
		{
			GeBoom();
			GeSleep( 10 );
			if ( thread.TestBreak())															// stop thread?
				return NULL;
		}

		callback_lock.Lock();
		if ( callback == NULL )
		{
			callback_context = context;
			callback = fn;
			callback_lock.Unlock();

			while ( callback )
			{
				GeSleep( 10 );																			// wait for completion of callback
				if ( thread.TestBreak())														// stop thread?
					return NULL;
			}
			
			callback_lock.Lock();
			result = callback_result;															// get callback result
			callback_result = NULL;
			callback_lock.Unlock();

			break;
		}
		else																										// this shouldn't happen either
		{
			GeBoom();
			callback_lock.Unlock();
		}
	}
	return result;
}

void ProgressDialog::Timer(const BaseContainer& msg)
{
	SetString(IDC_CACHE_TEXT,LongToString(LONG(percent*100.0))+"%");	

	BaseContainer m(BFM_SETSTATUSBAR);
	m.SetBool(BFM_STATUSBAR_PROGRESSON,TRUE);
	m.SetReal(BFM_STATUSBAR_PROGRESS,percent);
	SendMessage(IDC_CACHE_AREA,m);

	if ( callback )																						// is there a one-time callback that should be called from the main thread
	{
		callback_lock.Lock();
		if ( callback )
		{
			callback_result = callback( callback_context );
			callback_context = NULL;
			callback = NULL;																			// clear the callback pointer (callback has been executed)
		}
		else
			GeBoom();
		callback_lock.Unlock();
	}
}

LONG ProgressDialog::Message(const BaseContainer &msg,BaseContainer &result)
{
	switch (msg.GetId())
	{
		case BFM_GETCURSORINFO:
			result = BaseContainer(1);
			result.SetLong(RESULT_CURSOR,MOUSE_BUSY);
			return TRUE;
		break;

		case BFM_CHECKCLOSE:
			if (!AskClose())
				return FALSE;

			return TRUE;
		break;
			
		case BFM_CORE_MESSAGE:
		{
			switch(msg.GetLong(BFM_CORE_ID))
			{
				case ID_MESSAGE_PROGRESS_STOP:
					{
						BaseContainer m(BFM_SETSTATUSBAR);
						m.SetBool(BFM_STATUSBAR_PROGRESSON,FALSE);
						SendMessage(IDC_CACHE_AREA,m);
					}
					Close(TRUE);
				break;
			}
		}
		break;
	}
	return GeModalDialog::Message(msg,result);
}

Bool ProgressDialog::Command(LONG id, const BaseContainer &msg)
{
	switch (id)
	{
		case IDC_CANCEL:
			thread.End();
			GeShowMouse(MOUSE_NORMAL);
			Close(FALSE);
			return TRUE;
		break;
	}

	return GeDialog::Command(id,msg);
}

Bool ProgressDialog::AskClose()
{
	// thread MUST be killed
	thread.End();
	GeShowMouse(MOUSE_NORMAL);
	return FALSE;
}	
