/*
 *	spComponentDefs.h
 */

#ifndef __SPCOMPONENTDEFS_H
#define __SPCOMPONENTDEFS_H

#include <sp/spDefs.h>
#include <sp/spOption.h>
#include <sp/spKeySym.h>

#ifdef __cplusplus
extern "C" {
#endif

#define SPC_VERSION_STRING	"0.6.23"
#define SPC_VERSION 		0
#define SPC_REVISION		6
#define SPC_UPDATE_LEVEL	23
#define SPC_VERSION_ID		(SPC_VERSION * 1000 + SPC_REVISION)
    
#define SPC_CHECK_VERSION(version, revision, update) \
    (SPC_VERSION > (version) || \
     (SPC_VERSION == (version) && SPC_REVISION > (revision)) || \
     (SPC_VERSION == (version) && SPC_REVISION == (revision) && SPC_UPDATE_LEVEL >= (update)))

#if defined(ANDROID)
typedef struct _spAndroidClassRef *spAndroidClassRef;
#endif
    
#define SP_MAX_COLORNAME 32 
#define SP_MAX_FONTNAME 256
    
typedef unsigned long spMask;
typedef char *spString;
typedef char **spStrings;
typedef void *spPointer;

typedef struct _spCallback spCallback;
typedef struct _spCallbackList spCallbackList;
    
typedef unsigned long spKeySym;

typedef unsigned short spModifierMask;

/* Don't use SP_CONTROL_MASK, SP_ALT_MASK and SP_OPTION_MASK directly.
 * Use SP_*_MODIFIER_MASK instead. */
#define SP_SHIFT_MASK (1<<0)
#define SP_LOCK_MASK (1<<1)
#define SP_CONTROL_MASK (1<<2)
#define SP_ALT_MASK (1<<3)	/* Command key on Mac OS */
#define SP_OPTION_MASK (1<<4)	/* Option key on Mac OS */
#define SP_LBUTTON_MASK (1<<8)
#define SP_MBUTTON_MASK (1<<9)
#define SP_RBUTTON_MASK (1<<10)

/*
 * SP_COMMAND_MODIFIER_MASK: another command will be emitted by clicking left button with this key
 *
 * the following sets can be used
 * 	{SP_COMMAND_MODIFIER_MASK, SP_MIDDLE_MODIFIER_MASK,
 *		SP_RIGHT_MODIFIER_MASK (0 on some systems), SP_EXTEND_MODIFIER_MASK}
 * 	{SP_COMMAND_MODIFIER_MASK, SP_OPTION_MODIFIER_MASK, SP_EXTEND_MODIFIER_MASK}
 * 	{SP_COPY_MODIFIER_MASK, SP_MOVE_MODIFIER_MASK, SP_PASTE_MODIFIER_MASK}
 * 	{SP_COPY_MODIFIER_MASK, SP_PASTE_MODIFIER_MASK, SP_EXTEND_MODIFIER_MASK}
 * 	{SP_SELECT_MODIFIER_MASK, SP_EXTEND_MODIFIER_MASK, SP_PASTE_MODIFIER_MASK}
 * 	{SP_COMMAND_MODIFIER_MASK, SP_EXTEND_MODIFIER_MASK, SP_PASTE_MODIFIER_MASK}
 */
#ifdef MACOS
#define SP_COMMAND_MODIFIER_MASK SP_ALT_MASK
#define SP_OPTION_MODIFIER_MASK SP_OPTION_MASK
#define SP_MIDDLE_MODIFIER_MASK SP_OPTION_MASK
#define SP_RIGHT_MODIFIER_MASK SP_CONTROL_MASK
    
#define SP_COPY_MODIFIER_MASK SP_OPTION_MASK
#define SP_PASTE_MODIFIER_MASK SP_CONTROL_MASK
#define SP_SELECT_MODIFIER_MASK SP_ALT_MASK	/* multiple selection */
#else
#define SP_COMMAND_MODIFIER_MASK SP_CONTROL_MASK
#define SP_OPTION_MODIFIER_MASK SP_ALT_MASK
#define SP_MIDDLE_MODIFIER_MASK SP_ALT_MASK
#define SP_RIGHT_MODIFIER_MASK 0
    
#define SP_COPY_MODIFIER_MASK SP_CONTROL_MASK
#define SP_PASTE_MODIFIER_MASK SP_ALT_MASK
#define SP_SELECT_MODIFIER_MASK SP_CONTROL_MASK	/* multiple selection */
#endif
    
#define SP_POPUP_MODIFIER_MASK SP_RIGHT_MODIFIER_MASK 	/* popup menu */
#define SP_MOVE_MODIFIER_MASK SP_SHIFT_MASK	/* moving forcedly */
#define SP_EXTEND_MODIFIER_MASK SP_SHIFT_MASK	/* extending selection */

typedef const char *spParam;
#if defined(_WIN64)
typedef __int64 spParamValue;
#elif  defined(__x86_64__) || defined(__ia64__) || defined(__alpha__) || defined(__alpha) || defined(CRAY) || defined(__LP64__)
typedef long long spParamValue;
#else
typedef long spParamValue;
#endif
typedef struct _spParamTable spParamTable;

typedef spOptionType spParamType;
#define SP_TYPE_STRINGS	(SP_TYPE_USER + 1)
#define SP_TYPE_POINTER (SP_TYPE_USER + 2)
#define SP_TYPE_FUNCTION (SP_TYPE_USER + 3)

typedef unsigned short spParamAccess;
#define SP_NO_ACCESS 0
#define SP_CREATE_ACCESS (1L<<0)
#define SP_SET_ACCESS (1L<<1)
#define SP_GET_ACCESS (1L<<2)

struct _spParamTable {
    spParam param;
    spParamAccess param_access;
    int param_offset;
    char *param_default;
};

#define SP_MAX_NUM_ARG 32

typedef struct _spArg {
    spParam param;
    spParamValue value;
} spArg;
    
#define SP_PARAM_VALUE_DOUBLE_WEIGHT 10000.0
    
#define spSetArg(arg, par, val) ((void)((arg).param = (par), (arg).value = (spParamValue)(val)))

#define spGetArgs(argp, args, num_arg) \
{ \
    spParam param; \
    spParamValue value; \
    for (;;) { \
	param = va_arg(argp, spParam); \
	if (spNoParam(param) == SP_TRUE) { \
	    break; \
	} else { \
	    if (spGetParamType(param) == SP_TYPE_BOOL) { \
                value = (spParamValue)va_arg(argp, spBool); \
            } else if (spGetParamType(param) == SP_TYPE_INT) { \
                value = (spParamValue)va_arg(argp, int); \
            } else if (spGetParamType(param) == SP_TYPE_LONG) { \
                value = (spParamValue)va_arg(argp, long); \
            } else if (spGetParamType(param) == SP_TYPE_DOUBLE) { \
                value = (spParamValue)(SP_PARAM_VALUE_DOUBLE_WEIGHT*va_arg(argp, double)); \
            } else if (spGetParamType(param) == SP_TYPE_STRING) { \
                value = (spParamValue)va_arg(argp, char*); \
            } else if (spGetParamType(param) == SP_TYPE_STRING_A) { \
                value = (spParamValue)va_arg(argp, char*); \
            } else if (spGetParamType(param) == SP_TYPE_STRINGS) { \
                value = (spParamValue)va_arg(argp, char**); \
            } else if (spGetParamType(param) == SP_TYPE_POINTER) { \
                value = (spParamValue)va_arg(argp, void*); \
            } else if (spGetParamType(param) == SP_TYPE_FUNCTION) { \
                value = (spParamValue)va_arg(argp, void*); \
	    } else { \
		break; \
	    } \
	    spSetArg(args[num_arg], param, value); num_arg++; \
	} \
    } \
}

#define spGetArgsForOutput(argp, args, num_arg) \
{ \
    spParam param; \
    spParamValue value; \
    for (;;) { \
	param = va_arg(argp, spParam); \
	if (spNoParam(param) == SP_TRUE) { \
	    break; \
	} else { \
	    if (spGetParamType(param) == SP_TYPE_BOOL) { \
                value = (spParamValue)va_arg(argp, spBool*); \
            } else if (spGetParamType(param) == SP_TYPE_INT) { \
                value = (spParamValue)va_arg(argp, int*); \
            } else if (spGetParamType(param) == SP_TYPE_LONG) { \
                value = (spParamValue)va_arg(argp, long*); \
            } else if (spGetParamType(param) == SP_TYPE_DOUBLE) { \
                value = (spParamValue)va_arg(argp, double*); \
            } else if (spGetParamType(param) == SP_TYPE_STRING) { \
                value = (spParamValue)va_arg(argp, char**); \
            } else if (spGetParamType(param) == SP_TYPE_STRING_A) { \
                value = (spParamValue)va_arg(argp, char*); \
            } else if (spGetParamType(param) == SP_TYPE_STRINGS) { \
                value = (spParamValue)va_arg(argp, char***); \
            } else if (spGetParamType(param) == SP_TYPE_POINTER) { \
                value = (spParamValue)va_arg(argp, void**); \
            } else if (spGetParamType(param) == SP_TYPE_FUNCTION) { \
                value = (spParamValue)va_arg(argp, void**); \
	    } else { \
		break; \
	    } \
	    spSetArg(args[num_arg], param, value); num_arg++; \
	} \
    } \
}
    
#define spGetArgsExceptFirst(first_param, argp, args, num_arg) \
{ \
    int i; \
    spParam param; \
    spParamValue value; \
    for (i = 0;; i++) { \
        if (i == 0) { param = first_param; } else { param = va_arg(argp, spParam); } \
	if (spNoParam(param) == SP_TRUE) { \
	    break; \
	} else { \
	    if (spGetParamType(param) == SP_TYPE_BOOL) { \
                value = (spParamValue)va_arg(argp, spBool); \
            } else if (spGetParamType(param) == SP_TYPE_INT) { \
                value = (spParamValue)va_arg(argp, int); \
            } else if (spGetParamType(param) == SP_TYPE_LONG) { \
                value = (spParamValue)va_arg(argp, long); \
            } else if (spGetParamType(param) == SP_TYPE_DOUBLE) { \
                value = (spParamValue)(SP_PARAM_VALUE_DOUBLE_WEIGHT*va_arg(argp, double)); \
            } else if (spGetParamType(param) == SP_TYPE_STRING) { \
                value = (spParamValue)va_arg(argp, char*); \
            } else if (spGetParamType(param) == SP_TYPE_STRING_A) { \
                value = (spParamValue)va_arg(argp, char*); \
            } else if (spGetParamType(param) == SP_TYPE_STRINGS) { \
                value = (spParamValue)va_arg(argp, char**); \
            } else if (spGetParamType(param) == SP_TYPE_POINTER) { \
                value = (spParamValue)va_arg(argp, void*); \
            } else if (spGetParamType(param) == SP_TYPE_FUNCTION) { \
                value = (spParamValue)va_arg(argp, void*); \
	    } else { \
		break; \
	    } \
	    spSetArg(args[num_arg], param, value); num_arg++; \
	} \
    } \
}

#define spGetArgsExceptFirstForOutput(first_param, argp, args, num_arg)  \
{ \
    int i; \
    spParam param; \
    spParamValue value; \
    for (i = 0;; i++) { \
        if (i == 0) { param = first_param; } else { param = va_arg(argp, spParam); } \
	if (spNoParam(param) == SP_TRUE) { \
	    break; \
	} else { \
	    if (spGetParamType(param) == SP_TYPE_BOOL) { \
                value = (spParamValue)va_arg(argp, spBool*); \
            } else if (spGetParamType(param) == SP_TYPE_INT) { \
                value = (spParamValue)va_arg(argp, int*); \
            } else if (spGetParamType(param) == SP_TYPE_LONG) { \
                value = (spParamValue)va_arg(argp, long*); \
            } else if (spGetParamType(param) == SP_TYPE_DOUBLE) { \
                value = (spParamValue)va_arg(argp, double*); \
            } else if (spGetParamType(param) == SP_TYPE_STRING) { \
                value = (spParamValue)va_arg(argp, char**); \
            } else if (spGetParamType(param) == SP_TYPE_STRING_A) { \
                value = (spParamValue)va_arg(argp, char*); \
            } else if (spGetParamType(param) == SP_TYPE_STRINGS) { \
                value = (spParamValue)va_arg(argp, char***); \
            } else if (spGetParamType(param) == SP_TYPE_POINTER) { \
                value = (spParamValue)va_arg(argp, void**); \
            } else if (spGetParamType(param) == SP_TYPE_FUNCTION) { \
                value = (spParamValue)va_arg(argp, void**); \
	    } else { \
		break; \
	    } \
	    spSetArg(args[num_arg], param, value); num_arg++; \
	} \
    } \
}
    
/*  parameter prefix
 *	'b': bool, 'i': int,
 *	'l': long, 'd': double, 'e': enum,
 *	'S': string, 'A': string array,
 *	'P': pointer, 'F': function, 'L': strings
 */
#define SppNone NULL
#define SppBackground "SBackground" /* CSG */
#define SppForeground "SForeground" /* CSG */
#define SppDestroyCallback "FDestroyCallback" /* internal use */
#define SppCloseCallback "FCloseCallback" /* internal use */
#define SppFontName "SFontName" /* CSG; only for spGraphics and spText */
#define SppZoomCallback "FZoomCallback" /* internal use */
#define SppWheelCallback "FWheelCallback" /* internal use */

typedef unsigned long spCallbackType;
#define SP_NO_CALLBACK 0
#define SP_KEY_PRESS_CALLBACK (1L<<0)
#define SP_KEY_RELEASE_CALLBACK (1L<<1)
#define SP_BUTTON_PRESS_CALLBACK (1L<<2)
#define SP_BUTTON_RELEASE_CALLBACK (1L<<3)
#define SP_POINTER_MOTION_CALLBACK (1L<<4)
#define SP_BUTTON_MOTION_CALLBACK (1L<<5)
#define SP_ENTER_WINDOW_CALLBACK (1L<<6)	/* not implemented yet */
#define SP_LEAVE_WINDOW_CALLBACK (1L<<7) 	/* not implemented yet */
#define SP_WHEEL_CALLBACK (1L<<8)		/* +0.6.13 */

#define SP_ACTIVATE_CALLBACK (1L<<9)
#define SP_VALUE_CHANGED_CALLBACK (1L<<10)
#define SP_EXPOSE_CALLBACK (1L<<11) 
#define SP_RESIZE_CALLBACK (1L<<12)
#define SP_MAP_CALLBACK (1L<<13) 		/* not implemented yet */
#define SP_UNMAP_CALLBACK (1L<<14) 		/* not implemented yet */

#define SP_OK_CALLBACK (1L<<15)
#define SP_CANCEL_CALLBACK (1L<<16)
#define SP_HELP_CALLBACK (1L<<17)
#define SP_APPLY_CALLBACK (1L<<18)
#define SP_TASK_TRAY_CALLBACK (1L<<19)
#define SP_CLOSE_CALLBACK (1L<<20)
#define SP_DESTROY_CALLBACK (1L<<21)
#define SP_CLOSE_BUTTON_CALLBACK (1L<<22)
#define SP_SIMPLIFY_CALLBACK (1L<<23)
    
#define SP_SCROLL_CALLBACK (1L<<24)		/* +0.6.13 */
#define SP_ZOOM_CALLBACK (1L<<25)		/* +0.6.13 */
#define SP_FOCUS_CALLBACK (1L<<26)		/* +0.6.13; not implemented yet */
    
#define SP_USER1_CALLBACK (1L<<27)
#define SP_USER2_CALLBACK (1L<<28)
#define SP_USER3_CALLBACK (1L<<29)
#define SP_USER4_CALLBACK (1L<<30)
#define SP_NUM_CALLBACK_TYPE 31

typedef enum {
    SP_CR_NONE = -1,
    SP_CR_UNKNOWN = 0,
    SP_CR_KEY_PRESS = 1,
    SP_CR_KEY_RELEASE = 2,
    SP_CR_LBUTTON_PRESS = 3,
    SP_CR_RBUTTON_PRESS = 4,
    SP_CR_MBUTTON_PRESS = 5,
    SP_CR_LBUTTON_RELEASE = 6,
    SP_CR_RBUTTON_RELEASE = 7,
    SP_CR_MBUTTON_RELEASE = 8,
    SP_CR_POINTER_MOTION = 9,
    SP_CR_LBUTTON_MOTION = 10,
    SP_CR_RBUTTON_MOTION = 11,
    SP_CR_MBUTTON_MOTION = 12,
    SP_CR_ENTER_WINDOW = 13,	/* not implemented yet */
    SP_CR_LEAVE_WINDOW = 14,	/* not implemented yet */

    SP_CR_WHEEL = 15,
	
    SP_CR_ACTIVATE = 20,
    SP_CR_VALUE_CHANGED = 21,
    SP_CR_EXPOSE = 22,
    SP_CR_RESIZE = 23,
    SP_CR_MAP = 24,		/* not implemented yet */
    SP_CR_UNMAP = 25,		/* not implemented yet */

    SP_CR_OK = 30,
    SP_CR_CANCEL = 31,
    SP_CR_YES = 32,
    SP_CR_NO = 33,
    SP_CR_RETRY = 34,
    SP_CR_APPLY = 35,
    SP_CR_HELP = 36,

    SP_CR_CLOSE = 40,
    SP_CR_DESTROY = 41,
    SP_CR_CLOSE_BUTTON = 42,
    
    SP_CR_SIMPLIFY = 45,
    
    SP_CR_SCROLL = 46,		/* +0.6.13 */
    SP_CR_ZOOM = 47,		/* +0.6.13 */
    SP_CR_FOCUS_IN = 48,	/* +0.6.13 */
    SP_CR_FOCUS_OUT = 49,	/* +0.6.13 */

    SP_CR_USER_EVENT = 19,	/* +0.6.17 */
	
    SP_CR_USER1 = 50,
    SP_CR_USER2 = 51,
    SP_CR_USER3 = 52,
    SP_CR_USER4 = 53,
} spCallbackReason;

#define SP_CR_BUTTON_PRESS SP_CR_LBUTTON_PRESS
#define SP_CR_BUTTON_RELEASE SP_CR_LBUTTON_RELEASE

typedef char *spComponentType;
#define SpComponentNone ""
#define SpSeparator "Separator"
#define SpToolBar "ToolBar"
#define SpToolItem "ToolItem"
#define SpSpinBox "SpinBox"

typedef enum {
    SP_DYNAMIC = -1,
    SP_HORIZONTAL = 0,
    SP_VERTICAL = 1,
} spOrientation;

#define SP_DYNAMIC_STRING "-1"
#define SP_HORIZONTAL_STRING "0"
#define SP_VERTICAL_STRING "1"

typedef enum {
    SP_UNKNOWN_BUTTON = -1,
    SP_LBUTTON = 0,
    SP_RBUTTON = 1,
    SP_MBUTTON = 2,
} spMouseButton;

#define SP_LBUTTON_STRING "0"
#define SP_RBUTTON_STRING "1"
#define SP_MBUTTON_STRING "2"

typedef enum {
    SP_GM_COPY = 0,
    SP_GM_XOR = 1,
    SP_GM_INVERT = 2,
    SP_GM_AND = 3,
    SP_GM_OR = 4,
	
    SP_GM_SOURCE_OVER = 5,
    SP_GM_SOURCE_IN = 6,
    SP_GM_SOURCE_OUT = 7,
    SP_GM_SOURCE_ATOP = 8,
    SP_GM_DEST_OVER = 9,
    SP_GM_DEST_IN = 10,
    SP_GM_DEST_OUT = 11,
    SP_GM_DEST_ATOP = 12,
    SP_GM_PORTER_DUFF_XOR = 13,
    SP_GM_PLUS_DARKER = 14,
    SP_GM_PLUS_LIGHTER = 15,
    SP_GM_SATURATE = 16,

    SP_GM_MULTIPLY = 17,
    SP_GM_SCREEN = 18,
    SP_GM_OVERLAY = 19,
    SP_GM_DARKEN = 20,
    SP_GM_LIGHTEN = 21,
    SP_GM_COLOR_DODGE = 22,
    SP_GM_COLOR_BURN = 23,
    SP_GM_HARD_LIGHT = 24,
    SP_GM_SOFT_LIGHT = 25,
    SP_GM_DIFFERENCE = 26,
    SP_GM_EXCLUSION = 27,
	
    SP_GM_HSL_HUE = 28,
    SP_GM_HSL_SATURATION = 29,
    SP_GM_HSL_COLOR = 30,
    SP_GM_HSL_LUMINOSITY = 31,
} spGraphicsMode;

#define SP_GM_COPY_STRING "0"
#define SP_GM_XOR_STRING "1"
#define SP_GM_INVERT_STRING "2"
#define SP_GM_AND_STRING "3"
#define SP_GM_OR_STRING "4"
#define SP_GM_SOURCE_OVER_STRING "12"
#define SP_GM_SOURCE_IN_STRING "13"
#define SP_GM_SOURCE_OUT_STRING "14"
#define SP_GM_SOURCE_ATOP_STRING "15"
#define SP_GM_DEST_OVER_STRING "16"
#define SP_GM_DEST_IN_STRING "17"
#define SP_GM_DEST_OUT_STRING "18"
#define SP_GM_DEST_ATOP_STRING "19"
#define SP_GM_PORTER_DUFF_XOR_STRING "20"
#define SP_GM_PLUS_DARKER_STRING "21"
#define SP_GM_PLUS_LIGHTER_STRING "22"

typedef enum {
    SP_CURSOR_UNKNOWN = -1,
    SP_CURSOR_ARROW = 0,
    SP_CURSOR_TEXT = 1,
    SP_CURSOR_WAIT = 2,
    SP_CURSOR_CROSS = 3,
    SP_CURSOR_HAND = 4,
    SP_CURSOR_MOVE = 5,
    SP_CURSOR_SIZE = 6,
    
    SP_CURSOR_SW_RESIZE = 7,
    SP_CURSOR_SE_RESIZE = 8,
    SP_CURSOR_NW_RESIZE = 9,
    SP_CURSOR_NE_RESIZE = 10,
    SP_CURSOR_N_RESIZE = 11,
    SP_CURSOR_S_RESIZE = 12,
    SP_CURSOR_W_RESIZE = 13,
    SP_CURSOR_E_RESIZE = 14,
} spCursorType;

#define SP_CURSOR_DEFAULT SP_CURSOR_ARROW

typedef unsigned long spEventType;
#define SP_EVENT_NONE 0
#define SP_EVENT_UPDATE 1
#define SP_EVENT_USER 16384

typedef void *spTimerId;
#define SP_TIMER_ID_NONE NULL
    
typedef struct _spUserEventDefaultRec spUserEventDefaultRec, *spUserEventDefault;
    
#ifdef __cplusplus
}  /* Close scope of 'extern "C"' declaration */
#endif

#endif /* __SPCOMPONENTDEFS_H */
