/////////////////////////////////////////////////////////////
// CINEMA 4D SDK                                           //
/////////////////////////////////////////////////////////////
// (c) 1989-2004 MAXON Computer GmbH, all rights reserved  //
/////////////////////////////////////////////////////////////

#ifndef __C4DGENERAL_H
#define __C4DGENERAL_H

#include "c4d_string.h"
#include "operatingsystem.h"

class Filename;
class GeDialog;
class GeUserArea;
class GeListHead;
class BaseList2D;

#define UNIT_NONE	0
#define UNIT_KM		1
#define UNIT_M		2
#define UNIT_CM		3
#define UNIT_MM		4
#define UNIT_UM		5
#define UNIT_NM		6
#define UNIT_MILE	7
#define UNIT_YARD	8
#define UNIT_FEET	9
#define UNIT_INCH	10

#define ANGLE_DEG	0
#define ANGLE_RAD 1

enum Result 
{
	RES_FALSE  =0, // function result not ok
	RES_TRUE   =1, // function result ok
	RES_MEM_ERR=2, // memory error
	RES_STOP   =3, // stop execution (e.g. user break) but no mem error

	RES_DUM
};

class Parser
{
	private:
		Parser();
		~Parser();
	public:
		Bool AddVar(const String &str, Real *value);
		Bool Eval(const String &str, LONG *error, Real *res, LONG unit, LONG angletype, LONG basis);
		Bool AddVarLong(const String &str, LONG *value);
		Bool EvalLong(const String &str, LONG *error, LONG *res, LONG unit, LONG basis);

		static Parser *Alloc(void);
		static void Free(Parser *&pr);
};

struct SerialInfo
{
	String nr,name,organization,street,city,country;
};

void GeGetSerialInfo(LONG type, SerialInfo *si);
LONG GeGetVersionType(void);
LONG GeGetSystemInfo(void);
void GeShowMouse(LONG v);
void GeGetSysTime(LONG *year, LONG *month, LONG *day, LONG *hour, LONG *minute, LONG *second);
inline LONG GeGetTimer(void) { return C4DOS.Ge->GetTimer(); }
String GeGetLineEnd(void);
LONG GeGetDefaultFPS(void);
LONG GeOutString(const String &str, LONG flags);
LONG GeGetCurrentOS(void);
LONG GeGetByteOrder(void);
void GeGetGray(LONG *r, LONG *g, LONG *b);
Bool GeChooseColor(Vector *col);
Bool GeOpenHTML(const String &webaddress);
Bool GeChooseFont(BaseContainer *bc);
Bool GeRegisterPlugin(LONG type, LONG id, const String &str, void *data, LONG datasize);
void GePrint(const String &str);
void GeConsoleOut(const String &str);
Bool GeGetMovieInfo(const Filename &fn, LONG *frames, Real *fps);
Bool RenameDialog(String *str);
inline LONG GetC4DVersion(void) { return C4DOS.version; }
String GeGetDegreeChar();
String GeGetPercentChar();

inline void lSwap (void *adr, VLONG cnt=1) { C4DOS.Ge->lSwap(adr,cnt); }
inline void wSwap (void *adr, VLONG cnt=1) { C4DOS.Ge->wSwap(adr,cnt); }
inline void lIntel(void *adr, VLONG cnt=1) { C4DOS.Ge->lIntel(adr,cnt); }
inline void wIntel(void *adr, VLONG cnt=1) { C4DOS.Ge->wIntel(adr,cnt); }
inline void lMotor(void *adr, VLONG cnt=1) { C4DOS.Ge->lMotor(adr,cnt); }
inline void wMotor(void *adr, VLONG cnt=1) { C4DOS.Ge->wMotor(adr,cnt); }
inline void llSwap (void *adr, VLONG cnt=1) { C4DOS.Ge->llSwap(adr,cnt); }
inline void llIntel(void *adr, VLONG cnt=1) { C4DOS.Ge->llIntel(adr,cnt); }
inline void llMotor(void *adr, VLONG cnt=1) { C4DOS.Ge->llMotor(adr,cnt); }

inline void vlSwap (void *adr, LONG cnt=1)
{
	#ifdef __C4D_64BIT
	C4DOS.Ge->llSwap(adr,cnt);
	#else
	C4DOS.Ge->lSwap(adr,cnt);
	#endif
}

inline void vlIntel(void *adr, LONG cnt=1)
{
	#ifdef __C4D_64BIT
	C4DOS.Ge->llIntel(adr,cnt);
	#else
	C4DOS.Ge->lIntel(adr,cnt);
	#endif
}

inline void vlMotor(void *adr, LONG cnt=1)
{
	#ifdef __C4D_64BIT
	C4DOS.Ge->llMotor(adr,cnt);
	#else
	C4DOS.Ge->lMotor(adr,cnt);
	#endif
}

void GeAddBackgroundHandler(BackgroundHandler *handler, void *tdata, LONG typeclass, LONG priority);
Bool GeRemoveBackgroundHandler(void *tdata, LONG typeclass);
void GeStopBackgroundThreads(LONG typeclass, LONG flags);
Bool GeCheckBackgroundThreadsRunning(LONG typeclass, Bool all);
void GeProcessBackgroundThreads(LONG typeclass);

void SetMousePointer(LONG);
Bool ShowBitmap(const Filename &fn);
Bool ShowBitmap(BaseBitmap *bm);
void StopAllThreads(void);
void StatusClear(void);
void StatusSetSpin(void);
void StatusSetBar(LONG p);
void StatusSetText(const String &str);
void SpecialEventAdd(LONG messageid, VULONG p1=0, VULONG p2=0);
void EventAdd(LONG flags=0);
Bool GeSyncMessage(LONG messageid, LONG destid=0, VULONG p1=0, VULONG p2=0);
Bool DrawViews(LONG flags,BaseDraw *bd=NULL);
Bool SendModelingCommand(LONG command, ModelingCommandData &data);
Filename GetGlobalTexturePath(LONG i);
void SetGlobalTexturePath(LONG i, const Filename &fn);
Bool GenerateTexturePath(const Filename &docpath, const Filename &srcname, const Filename &suggestedfolder, Filename *dstname);
Bool IsInSearchPath(const Filename &texfilename, const Filename &docpath);
void FlushTexture(const Filename &docpath, const String &name, const Filename &suggestedfolder);
void FlushUnusedTextures(void);
BaseContainer GetWorldContainer(void);
BaseContainer *GetWorldContainerInstance(void);
void SetWorldContainer(const BaseContainer &bc);
Vector GetViewColor(LONG colid);
void SetViewColor(LONG colid, const Vector &col);
#define GetWorldColor	GetViewColor
void ErrorStringDialog(LONG type, Real x, Real y, LONG is);
Bool ReadPluginInfo(LONG pluginid, void *buffer, LONG size);
Bool WritePluginInfo(LONG pluginid, void *buffer, LONG size);
BaseContainer *GetWorldPluginData(LONG id);
Bool SetWorldPluginData(LONG id, const BaseContainer &bc, Bool add=TRUE);
BaseContainer *GetToolPluginData(BaseDocument *doc, LONG id);
Bool GeIsActiveToolEnabled(void);
Bool GeGetLanguage(LONG index, String *extension, String *name, Bool *default_language);
LONG GeIdentifyFile(const Filename &name, UCHAR *probe, LONG probesize, LONG recognition, BasePlugin **bp);

GeListHead *GetScriptHead(LONG type);
LONG GetDynamicScriptID(BaseList2D *bl);
Bool GetCommandLineArgs(C4DPL_CommandLineArgs &args);

String GetObjectName(LONG type);
String GetTagName(LONG type);
LONG GetObjectType(const String &name);
LONG GetTagType(const String &name);

class Registry
{
	private:
		Registry();
		~Registry();
	public:
		LONG GetMainID(void);
		LONG GetSubID(void);
		void *GetData(void);
};

Bool GeRegistryAdd(LONG sub_id, LONG main_id, void *data);
Bool GeRegistryRemove(LONG sub_id, LONG main_id);
Registry *GeRegistryFind(LONG sub_id, LONG main_id);
Registry *GeRegistryFindLast(LONG main_id);
Registry *GeRegistryFindFirst(LONG main_id);
Registry *GeRegistryFindPrev(Registry *last);
Registry *GeRegistryFindNext(Registry *last);
Bool GeRegistryGetAutoID(LONG *id);
Bool GePluginMessage(LONG id, void *data);

Bool CheckIsRunning(LONG type);

String GeGetDefaultFilename(LONG id);

void FindInManager(BaseList2D *bl);
void GeSleep(LONG milliseconds);

Bool GeIsMainThread(void);

#ifndef GeAssert
	#if defined _DEBUG && !defined __LINUX
		#define GeAssert(a) if (!(a)) { GeDebugOut("%s(%d): %s", __FILE__, __LINE__, #a); GeBoom(); }
	#else
		#define GeAssert(a) { }
	#endif
#endif

void _GeDebugBreak(LONG line, const CHAR *file); // Break
#define GeBreak() _GeDebugBreak(__LINE__, __FILE__)
#define GeBoom() _GeDebugBreak(__LINE__, __FILE__)

void GeDebugOut(const CHAR* s,...);		// Warning to Console

class LassoSelection
{
	private:
		LassoSelection();
		~LassoSelection();
	public:
		Bool	Start(GeDialog &dlg, LONG mode, LONG start_x=NOTOK, LONG start_y=NOTOK, LONG start_button=NOTOK,LONG sx1=NOTOK, LONG sy1=NOTOK, LONG sx2=NOTOK, LONG sy2=NOTOK);
		Bool  Start(GeUserArea &ua, LONG mode, LONG start_x=NOTOK, LONG start_y=NOTOK, LONG start_button=NOTOK,LONG sx1=NOTOK, LONG sy1=NOTOK, LONG sx2=NOTOK, LONG sy2=NOTOK);
		Bool  Start(EditorWindow *win, LONG mode, LONG start_x=NOTOK, LONG start_y=NOTOK, LONG start_button=NOTOK,LONG sx1=NOTOK, LONG sy1=NOTOK, LONG sx2=NOTOK, LONG sy2=NOTOK);

		Bool	CheckSingleClick();
		Bool	Test(LONG x, LONG y);
		Bool	TestPolygon(const Vector &pa, const Vector &pb, const Vector &pc, const Vector &pd);
		LONG	GetMode();
		Bool  GetRectangle(Real &x1, Real &y1, Real &x2, Real &y2);

		static LassoSelection *Alloc();
		static void Free(LassoSelection *&ls);
};

GeData SendCoreMessage(LONG coreid, const BaseContainer &msg, LONG eventid=0);
#define COREMSG_CINEMA												'CMci'	// request to C4D core

BaseContainer GetMachineFeatures();
#define COREMSG_CINEMA_GETMACHINEFEATURES			'gOGL'
	#define OPENGL_SUPPORT_DUALPLANE_ARB									1001
	#define OPENGL_SUPPORT_DUALPLANE_KTX									1002
	#define OPENGL_EXTENSION_STRING												1003
	#define OPENGL_SUPPORT_GL_EXT_SEPARATE_SPECULAR_COLOR	1004
	#define OPENGL_SUPPORT_ENHANCED												1005
	#define OPENGL_RENDERER_NAME													1006
	#define OPENGL_VERSION_STRING													1007
	#define OPENGL_VENDOR_NUM															1008
		#define OPENGL_VENDOR_UNKNOWN												0
		#define OPENGL_VENDOR_NVIDIA												1
		#define OPENGL_VENDOR_ATI														2
	#define OPENGL_VENDOR_NAME														1009
	#define OPENGL_SHADING_LANGUAGE_VERSION								1010
	#define OPENGL_VERTEXBUFFER_OBJECT										1011
	#define OPENGL_FRAMEBUFFER_OBJECT											1012
	#define OPENGL_MULTITEXTURE														1013
	#define OPENGL_MAX_2DTEXTURE_SIZE											1014
	#define OPENGL_MAX_3DTEXTURE_SIZE											1015
	#define OPENGL_MAX_TEXCOORD														1016
	#define OPENGL_MAX_TEX_IMAGE_UNITS_VERTEX							1017
	#define OPENGL_MAX_TEX_IMAGE_UNITS_FRAGMENT						1018
	#define OPENGL_MAX_VP_INSTRUCTIONS										1019
	#define OPENGL_MAX_FP_INSTRUCTIONS										1020
	#define OPENGL_FLOATINGPOINT_TEXTURE									1021
	#define OPENGL_NONPOWEROF2_TEXTURE										1022
	#define OPENGL_DEPTH_TEXTURE													1023
	#define OPENGL_CG_TOOLKIT															1024
	#define OPENGL_MAX_TEXTURE_INDIRECTIONS								1025
	#define OPENGL_CG_LATEST_VERTEX_PROFILE								1026
	#define OPENGL_CG_LATEST_FRAGMENT_PROFILE							1027
	#define OPENGL_CG_LATEST_VERTEX_PROFILE_NAME					1028
	#define OPENGL_CG_LATEST_FRAGMENT_PROFILE_NAME				1029
	#define OPENGL_DRIVER_VERSION_STRING									1030 // only supported on Windows
	#define OPENGL_CG_VERSION_STRING											1031
	
	#define MACHINEINFO_OSTYPE														2000
	#define MACHINEINFO_OSVERSION													2001
	#define MACHINEINFO_PROCESSORTYPE											2002
	#define MACHINEINFO_PROCESSORNAME											2003
	#define MACHINEINFO_PROCESSORFEATURES									2004
	#define MACHINEINFO_NUMBEROFPROCESSORS								2005
	#define MACHINEINFO_MACHINEMODEL											2006

	#define MACHINEINFO_LOADEDPLUGINS											3000

Bool GeGetMemoryStat(BaseContainer &stat);
#define C4D_MEMORY_STAT_MEMORY_INUSE								1	// LONG: bytes
#define C4D_MEMORY_STAT_MEMORY_PEAK									2	// LONG: bytes
#define C4D_MEMORY_STAT_NO_OF_ALLOCATIONS_TOTAL			3	// LONG: count
#define C4D_MEMORY_STAT_NO_OF_ALLOCATIONS_CURRENT		4 // LONG: count


#define POPUPEDITTEXTCALLBACK_TEXTCHANGED		1
#define POPUPEDITTEXTCALLBACK_CLOSED				2
#define POPUPEDITTEXTCALLBACK_CANCELED			3
#define POPUPEDITTEXTCALLBACK_CURSOR_UP			4
#define POPUPEDITTEXTCALLBACK_CURSOR_DOWN		5

Bool PopupEditText(LONG screenx,LONG screeny, LONG width, LONG height,const String &changeme,LONG flags,PopupEditTextCallback *func, void *userdata);

void StartEditorRender(Bool active_only, Bool raybrush, LONG x1, LONG y1, LONG x2, LONG y2, BaseThread *bt, BaseDraw *bd, Bool newthread);
String FormatNumber(const GeData &val, LONG format, LONG fps, Bool bUnit=TRUE);
GeData StringToNumber(const String &text, LONG format, LONG fps);

void CallCommand(LONG id, LONG subid=0);
String GetCommandName(LONG id);
Bool IsCommandEnabled(LONG id);
Bool IsCommandChecked(LONG id);

IpConnection*	GeIpOpenListener(ULONG ipAddr, LONG port, BaseThread* thread, LONG timeout, Bool dontwait, LONG* ferr);
IpConnection* GeIpOpenOutgoing(const CHAR* hostname, BaseThread* thread, LONG initial_timeout, LONG timeout, Bool dontwait, LONG* ferr);
IpConnection*	GeIpWaitForIncoming(IpConnection* listener, BaseThread* connection, LONG *ferr);
void	GeIpCloseConnection(IpConnection *&ipc);
void	GeIpKillConnection(IpConnection *ipc);
LONG	GeIpBytesInInputBuffer(IpConnection* ipc);
LONG	GeIpReadBytes(IpConnection* ipc, void* buf, LONG size);
LONG	GeIpSendBytes(IpConnection* ipc, const void* buf, LONG size);
void	GeIpGetHostAddr(IpConnection* ipc, CHAR *buf, LONG bufsize);
void	GeIpGetRemoteAddr(IpConnection* ipc, CHAR *buf, LONG bufsize);

Bool SendMailAvailable();
Bool SendMail(const String &t_subject, const String *t_to, const String *t_cc, const String *t_bcc, Filename *t_attachments,const String &t_body, LONG flags);
#define SENDMAIL_SENDDIRECTLY		1

Bool GetSystemEnvironmentVariable(const String &varname, String &result);

void SystemCoffeeGuiPrefsChanged();

class DebugTimer
{
		LONG m_lasttime;
		CHAR *m_str;

	public:
		DebugTimer(CHAR *str)
		{
			m_lasttime = GeGetTimer();
			m_str = str;
		}
		~DebugTimer()
		{
			if (m_lasttime!=0)
				GeDebugOut(m_str,GeGetTimer()-m_lasttime);
		}
};

#define SHORTCUT_PLUGINID 1000
#define SHORTCUT_ADDRESS  1001

LONG GetShortcutCount();
BaseContainer GetShortcut(LONG index);
Bool AddShortcut(const BaseContainer &bc);
Bool RemoveShortcut(LONG index);
Bool LoadShortcutSet(const Filename &fn, Bool add);
Bool SaveShortcutSet(const Filename &fn);
LONG FindShortcutsFromID(LONG pluginid, LONG *indexarray, LONG maxarrayelements);
LONG FindShortcuts(const BaseContainer &scut, LONG *idarray, LONG maxarrayelements);

void InsertCreateObject(BaseDocument *doc, BaseObject *op, BaseObject *activeobj=NULL);

void CopyToClipboard(const String &text);

#endif
