#ifndef GUIUTILS_H
#define GUIUTILS_H

#include <gtk/gtk.h>


/*
 *	GTK 2 wrappers:
 */
#if (GTK_MAJOR_VERSION >= 2)

#define GTK_WINDOW_DIALOG		GTK_WINDOW_TOPLEVEL

#define gtk_accel_group_add(_a_,_c_,_m_,_f_,_w_,_s_)	\
 gtk_widget_add_accelerator(				\
  (GtkWidget *)(_w_), (_s_), (_a_),			\
  (_c_), (_m_), (_f_)					\
 )



#endif	/* End of GTK 2 wrappers */


/*
 *	Button Numbers:
 */
#ifndef GDK_BUTTON1
# define GDK_BUTTON1		1
#endif
#ifndef GDK_BUTTON2
# define GDK_BUTTON2		2
#endif
#ifndef GDK_BUTTON3
# define GDK_BUTTON3		3
#endif
#ifndef GDK_BUTTON4
# define GDK_BUTTON4		4
#endif
#ifndef GDK_BUTTON5
# define GDK_BUTTON5		5
#endif


/*
 *	Geometry Flags:
 */
typedef enum {
	GDK_GEOMETRY_X				= (1 << 0),
	GDK_GEOMETRY_Y				= (1 << 1),
	GDK_GEOMETRY_WIDTH			= (1 << 2),
	GDK_GEOMETRY_HEIGHT			= (1 << 3)
} GdkGeometryFlags;

/*
 *	String Bounds:
 */
typedef struct _GdkTextBounds		GdkTextBounds;
struct _GdkTextBounds {
	gint		lbearing,
			rbearing,
			width,
			ascent,
			descent;
};

/*
 *	Button default sizes:
 */
#define GUI_BUTTON_HLABEL_WIDTH			95
#define GUI_BUTTON_HLABEL_HEIGHT		-1

#define GUI_BUTTON_VLABEL_WIDTH			60
#define GUI_BUTTON_VLABEL_HEIGHT		50

/* With GTK_CAN_DEFAULT border */
#define GUI_BUTTON_HLABEL_WIDTH_DEF		(100 + (2 * 3))
#define GUI_BUTTON_HLABEL_HEIGHT_DEF		(30 + (2 * 3))


/*
 *	Menu Item default size:
 */
#define GUI_MENU_ITEM_DEF_WIDTH			-1
#define GUI_MENU_ITEM_DEF_HEIGHT		20

/*
 *	Menu Item types:
 */
typedef enum {
	GUI_MENU_ITEM_TYPE_LABEL,	/* Regular menu item */
	GUI_MENU_ITEM_TYPE_CHECK,	/* Check menu item */
	GUI_MENU_ITEM_TYPE_SEPARATOR,	/* Separator */
	GUI_MENU_ITEM_TYPE_SUBMENU	/* Label that refers to a submenu */
} gui_menu_item_type;

/*
 *	Menu Bar Item alignment:
 */
typedef enum {
	GUI_MENU_BAR_ALIGN_LEFT,
	GUI_MENU_BAR_ALIGN_RIGHT,
	GUI_MENU_BAR_ALIGN_CENTER
} gui_menu_bar_item_alignment;


/*
 *	String Macros:
 */
#define g_strcasepfx(_str_,_pfx_)			\
(!g_strncasecmp((_str_),(_pfx_),strlen(_pfx_)))


/*
 *	Colormap & Color Macros:
 */
#define GDK_COLOR_SET_BYTE(_c_,_r_,_g_,_b_)		\
{ if((_c_) != NULL) {                                   \
 (_c_)->red	= ((gushort)(_r_) << 8) |		\
		  ((gushort)(_r_));			\
 (_c_)->green	= ((gushort)(_g_) << 8) |		\
		  ((gushort)(_g_));			\
 (_c_)->blue	= ((gushort)(_b_) << 8) |		\
		  ((gushort)(_b_));			\
} }
#define GDK_COLOR_SET_COEFF(_c_,_r_,_g_,_b_)		\
{ if((_c_) != NULL) {					\
 const gfloat m = (gfloat)((gushort)-1);		\
 (_c_)->red	= (gushort)((gfloat)(_r_) * m);		\
 (_c_)->green	= (gushort)((gfloat)(_g_) * m);		\
 (_c_)->blue	= (gushort)((gfloat)(_b_) * m);		\
} }

#define GDK_COLORMAP_UNREF(_cmap_)	\
{ if((_cmap_) != NULL) gdk_colormap_unref(_cmap_); }
#define GDK_COLORMAP_ALLOC_COLOR(_cmap_,_c_)	\
{ if(((_cmap_) != NULL) && ((_c_) != NULL))	\
 gdk_colormap_alloc_color((_cmap_), (_c_), TRUE, TRUE); \
}
#define GDK_COLORMAP_ALLOC_COLORS(_cmap_,_c_,_n_)\
{ if(((_cmap_) != NULL) && ((_c_) != NULL) &&	\
     ((_n_) > 0)) {				\
 gboolean status;				\
 gdk_colormap_alloc_colors(			\
  (_cmap_), (_c_), (_n_), TRUE, TRUE, &status	\
 );						\
} }

#define GDK_COLORMAP_FREE_COLOR(_cmap_,_c_)	\
{ if(((_cmap_) != NULL) && ((_c_) != NULL))	\
 gdk_colormap_free_colors((_cmap_), (_c_), 1);	\
}
#define GDK_COLORMAP_FREE_COLORS(_cmap_,_c_,_n_)	\
{ if(((_cmap_) != NULL) && ((_c_) != NULL))		\
 gdk_colormap_free_colors((_cmap_), (_c_), (_n_));	\
}

/*
 *	GdkFont, GdkBitmap, GdkPixmap, GdkCursor, and GdkGC
 *	Macros:
 */
#define GDK_FONT_UNREF(_p_)	\
{ if((_p_) != NULL) gdk_font_unref(_p_); }
#define GDK_BITMAP_UNREF(_p_)	\
{ if((_p_) != NULL) gdk_bitmap_unref(_p_); }
#define GDK_PIXMAP_UNREF(_p_)	\
{ if((_p_) != NULL) gdk_pixmap_unref(_p_); }
#define GDK_CURSOR_DESTROY(_p_)	\
{ if((_p_) != NULL) gdk_cursor_destroy(_p_); }
#define GDK_GC_UNREF(_p_)		\
{ if((_p_) != NULL) gdk_gc_unref(_p_); }


/*
 *	GtkObject Macros:
 */
#define GTK_OBJECT_UNREF(_o_)			\
{ if((_o_) != NULL) gtk_object_unref(GTK_OBJECT(_o_)); }
#define GTK_OBJECT_GET_DATA(_o_,_k_)		\
 (((_o_) != NULL) ? gtk_object_get_data((GtkObject *)(_o_), (_k_)) : NULL)

/*
 *	GtkSignal Macros:
 */
#define GTK_SIGNAL_DISCONNECT(_o_,_i_)		\
{ if(((_o_) != NULL) && ((_i_) > 0)) {		\
 GtkSignalQuery *q = gtk_signal_query(_i_);	\
 if(q != NULL) {				\
  g_free(q);					\
  gtk_signal_disconnect(GTK_OBJECT(_o_), (_i_));\
 }						\
} }
#define GTK_TIMEOUT_REMOVE(_i_)			\
{ if((_i_) > 0)					\
 gtk_timeout_remove(_i_);			\
}
#define GTK_IDLE_REMOVE(_i_)			\
{ if((_i_) > 0)					\
 gtk_idle_remove(_i_);				\
}



/*
 *	GtkStyle & GtkRcStyle Macros:
 */
#define GTK_RC_STYLE_UNREF(_s_)		\
{ if((_s_) != NULL) gtk_rc_style_unref(_s_); }
#define GTK_STYLE_UNREF(_s_)		\
{ if((_s_) != NULL) gtk_style_unref(_s_); }

/*
 *	GtkAccelGroup Macros:
 */
#define GTK_ACCEL_GROUP_UNREF(_a_)	\
{ if((_a_) != NULL) gtk_accel_group_unref(_a_); }

/*
 *      GtkAdjustment Macros:
 */
#define GTK_ADJUSTMENT_GET_VALUE(_a_)   (((_a_) != NULL) ? \
 ((GtkAdjustment *)(_a_))->value : 0.0f)

/*
 *      GtkWidget Macros:
 */
#define GTK_WIDGET_SET_SENSITIVE(_w_,_b_)	\
{ if((_w_) != NULL) gtk_widget_set_sensitive((_w_), (_b_)); }
#define GTK_WIDGET_DESTROY(_w_)			\
{ if((_w_) != NULL) gtk_widget_destroy(_w_); }

/*
 *	GtkToggleButton Macros:
 */
#define GTK_TOGGLE_BUTTON_GET_ACTIVE(_w_)	\
 (((_w_) != NULL) ? GTK_TOGGLE_BUTTON(_w_)->active : FALSE)
#define GTK_TOGGLE_BUTTON_SET_ACTIVE(_w_,_b_)	\
{ if((_w_) != NULL)				\
 gtk_toggle_button_set_active(			\
  GTK_TOGGLE_BUTTON(_w_), (_b_)			\
 );						\
}

/*
 *	GtkCheckMenuItem Macros:
 */
#define GTK_CHECK_MENU_ITEM_GET_ACTIVE(_w_)	\
 (((_w_) != NULL) ? GTK_CHECK_MENU_ITEM(_w_)->active : FALSE)
#define GTK_CHECK_MENU_ITEM_SET_ACTIVE(_w_,_b_)	\
{ if((_w_) != NULL)				\
 gtk_check_menu_item_set_active(		\
  GTK_CHECK_MENU_ITEM(_w_), (_b_)		\
 );						\
}

/*
 *	GtkRange Macros:
 */
#define GTK_RANGE_GET_ADJUSTMENT(_w_)		\
 (((_w_) != NULL) ? gtk_range_get_adjustment(GTK_RANGE(_w_)) : NULL)

/*
 *	GtkEntry Macros:
 */
#define GTK_ENTRY_GET_TEXT(_w_)			\
 (((_w_) != NULL) ? gtk_entry_get_text(GTK_ENTRY(_w_)) : NULL)
#define GTK_ENTRY_GET_VALUE	GTK_ENTRY_GET_TEXT
#define GTK_ENTRY_GET_VALUEI(_w_)		\
 (((_w_) != NULL) ? atoi(gtk_entry_get_text(GTK_ENTRY(_w_))) : 0)
#define GTK_ENTRY_GET_VALUEL(_w_)		\
 (((_w_) != NULL) ? atol(gtk_entry_get_text(GTK_ENTRY(_w_))) : 0.0f)
#define GTK_ENTRY_GET_VALUEF(_w_)		\
 (((_w_) != NULL) ? atof(gtk_entry_get_text(GTK_ENTRY(_w_))) : 0.0f)


/* Block/Unblock Input */
extern void GUIBlockInput(GtkWidget *w, gboolean block);


/* GtkRcStyle Utilities */
#if (GTK_MAJOR_VERSION == 1)
# define gtk_rc_style_copy	GUIRCStyleCopy
#endif
extern GtkRcStyle *GUIRCStyleCopy(const GtkRcStyle *rcstyle);
#define gtk_widget_modify_style_recursive	GUIRCStyleSetRecursive
extern void GUIRCStyleSetRecursive(GtkWidget *w, GtkRcStyle *rcstyle);


/* Geometry Utilities */
#define gdk_parse_geometry	GUIParseGeometry
extern GdkGeometryFlags GUIParseGeometry(
	const gchar *s,
	gint *x, gint *y, gint *width, gint *height
);
#define gtk_clist_get_cell_geometry	GUICListGetCellGeometry
extern gboolean GUICListGetCellGeometry(
	GtkCList *clist, gint column, gint row,
	gint *x, gint *y, gint *width, gint *height
);
#define gtk_ctree_get_node_row_index	GUICTreeNodeRow
extern gint GUICTreeNodeRow(GtkCTree *ctree, GtkCTreeNode *node);

extern gint GUICTreeNodeDeltaRows(
	GtkCTree *ctree,
	GtkCTreeNode *start,    /* Use NULL for first/toplevel node */
	GtkCTreeNode *end
);
#define gdk_window_get_root_position	GUIGetWindowRootPosition
extern void GUIGetWindowRootPosition(
	GdkWindow *window, gint *x, gint *y
);
extern void GUIGetPositionRoot(
	GdkWindow *w, gint x, gint y, gint *rx, gint *ry
);


/* String Utilities */
#define gdk_text_bounds		GUIGetTextBounds
extern void GUIGetTextBounds(
	GdkFont *font, const gchar *text, gint text_length,
	GdkTextBounds *bounds
);
#define gdk_string_bounds	GUIGetStringBounds
extern void GUIGetStringBounds(
	GdkFont *font, const gchar *string,
	GdkTextBounds *bounds
);


/* GdkGC utilities */
extern GdkGC *GDK_GC_NEW(void);


/* GdkWindow utilities */
#define gdk_window_get_ref_count	GUIWindowGetRefCount
extern gint GUIWindowGetRefCount(GdkWindow *window);


/* WM Utilities */
extern void GUISetWMIcon(GdkWindow *window, guint8 **data);
extern void GUISetWMIconFile(GdkWindow *window, const gchar *filename);


/* GtkWindow Utilities */
#define gtk_window_apply_args GUIWindowApplyArgs
extern void GUIWindowApplyArgs(GtkWindow *w, gint argc, gchar **argv);


/* GtkCTree Utilities */
extern gboolean GUICTreeOptimizeExpandPosition(
	GtkCTree *ctree,
	GtkCTreeNode *node      /* Expanded parent node */
);


/* Bitmap Utilities */
extern GdkBitmap *GUICreateBitmapFromDataRGBA(
	gint width, gint height, gint bpl,
	const guint8 *rgba, guint8 threshold,
	GdkWindow *window
);

/* Pixmap Utilities */
extern GdkPixmap *GDK_PIXMAP_NEW(gint width, gint height);
extern GdkPixmap *GDK_PIXMAP_NEW_FROM_XPM_DATA(
        GdkBitmap **mask_rtn, guint8 **data
); 
extern GdkPixmap *GDK_PIXMAP_NEW_FROM_XPM_FILE(
        GdkBitmap **mask_rtn, const gchar *filename
);
extern GtkWidget *gtk_pixmap_new_from_xpm_d(
	GdkWindow *window, GdkColor *transparent_color,            
	guint8 **data
);
extern GtkWidget *GUICreateMenuItemIcon(guint8 **icon_data);


/* Widget & Window Mapping */
#define gtk_widget_show_raise   GUIWidgetMapRaise
extern void GUIWidgetMapRaise(GtkWidget *w);
#define gtk_window_minimize     GUIWindowMinimize
extern void GUIWindowMinimize(GtkWindow *window);


/* Tool Tips */
extern void GUISetWidgetTip(GtkWidget *w, const gchar *tip);
extern void GUIShowTipsNow(GtkWidget *w);
extern void GUISetGlobalTipsState(gboolean state);


/* Buttons Modifying */
extern void GUIButtonChangeLayout(
	GtkWidget *w, gboolean show_pixmap, gboolean show_label
);
extern void GUIButtonLabelUnderline(GtkWidget *w, guint c);
extern void GUIButtonPixmapUpdate(
	GtkWidget *w, guint8 **icon, const gchar *label
);
extern void GUIButtonArrowUpdate(
	GtkWidget *w,
	GtkArrowType arrow_type, gint arrow_width, gint arrow_height,
	const gchar *label
);
extern GtkWidget *GUIButtonGetMainBox(GtkWidget *w);
extern GtkWidget *GUIButtonGetLabel(GtkWidget *w);
extern GtkWidget *GUIButtonGetPixmap(GtkWidget *w);
extern GtkWidget *GUIButtonGetArrow(GtkWidget *w);
extern gchar *GUIButtonGetLabelText(GtkWidget *w);

/* Buttons With Icon & Label */
extern GtkWidget *GUIButtonPixmap(guint8 **icon);
extern GtkWidget *GUIButtonPixmapLabelH(
	guint8 **icon, const gchar *label, GtkWidget **label_rtn
);
extern GtkWidget *GUIButtonPixmapLabelV(
	guint8 **icon, const gchar *label, GtkWidget **label_rtn
);

/* Buttons With Arrow & Label */
extern GtkWidget *GUIButtonArrowLabelH(
	GtkArrowType arrow_type, gint arrow_width, gint arrow_height,
	const gchar *label, GtkWidget **label_rtn
);
extern GtkWidget *GUIButtonArrowLabelV(
	GtkArrowType arrow_type, gint arrow_width, gint arrow_height,
	const gchar *label, GtkWidget **label_rtn
);
extern GtkWidget *GUIButtonArrow(
	GtkArrowType arrow_type, gint arrow_width, gint arrow_height
);

/* Toggle Buttons With Icon & Label */
extern GtkWidget *GUIToggleButtonPixmap(guint8 **icon);
extern GtkWidget *GUIToggleButtonPixmapLabelH(
	guint8 **icon, const gchar *label, GtkWidget **label_rtn
);
extern GtkWidget *GUIToggleButtonPixmapLabelV(
	guint8 **icon, const gchar *label, GtkWidget **label_rtn
);


/* Prompts With Icon, Label, Entry, and Browse */
extern GtkWidget *GUIPromptBarWithBrowse(
	guint8 **icon, const gchar *label,
	gpointer *label_rtn, gpointer *entry_rtn, gpointer *browse_rtn,
	gpointer browse_data, void (*browse_cb)(GtkWidget *, gpointer)
);
extern GtkWidget *GUIPromptBar(
	guint8 **icon, const gchar *label,
	gpointer *label_rtn, gpointer *entry_rtn
);


/* Dynamic Data Exchange */
extern void GUIDDESetBinary(
	GtkWidget *w,			/* Owner widget */
	GdkAtom selection_atom,		/* Selection */
	gulong t,			/* Time */
	const guint8 *data, gint length
);
extern guint8 *GUIDDEGetBinary(
	GtkWidget *w,			/* Widget making request */
	GdkAtom selection_atom,		/* Can be GDK_NONE */
	gulong t,			/* Time */
	gint *length
);
extern void GUIDDESetString(
	GtkWidget *w,			/* Owner widget */
	GdkAtom selection_atom,		/* Selection */
	gulong t,			/* Time */
	const gchar *data
);
extern gchar *GUIDDEGetString(
	GtkWidget *w,			/* Widget making request */
	GdkAtom selection_atom,		/* Can be GDK_NONE */
	gulong t			/* Time */
);


/* Drag & Drop Utilities */
extern void GUIDNDSetSrc(
	void *w, const void *drag_type, int ndrag_types,
	unsigned int actions, unsigned int buttons,
	void (*begin_cb)(GtkWidget *, GdkDragContext *, gpointer),
	void (*request_data_cb)(GtkWidget *, GdkDragContext *,
		GtkSelectionData *, guint, guint, gpointer),
	void (*delete_data_cb)(GtkWidget *, GdkDragContext *, gpointer),
	void (*end_cb)(GtkWidget *, GdkDragContext *, gpointer),
	gpointer client_data
);
extern void GUIDNDSetTar(
	void *w, const void *drag_type, int ndrag_types,
	unsigned int actions, unsigned int default_action_same,
	unsigned int default_action,
	void (*recieved_data_cb)(GtkWidget *, GdkDragContext *,
		gint, gint, GtkSelectionData *, guint, guint,
		gpointer  
	),
	gpointer client_data
);
extern void GUIDNDSetDragIcon(
	GdkPixmap *pixmap, GdkBitmap *mask, gint hot_x, gint hot_y
);


/* Banners */
extern GtkWidget *GUIBannerCreate(
	const gchar *label,
	const gchar *font_name,
	GdkColor color_fg,
	GdkColor color_bg,
	GtkJustification justify,	/* One of GTK_JUSTIFY_* */
	gboolean expand
);
extern void GUIBannerDraw(GtkWidget *w);


/* Combo With Label, Combo, Initial Value, and Initial List */
extern GtkWidget *GUIComboCreate(
	const gchar *label,	/* Label */
	const gchar *text,	/* Entry Value */
	GList *list,		/* Combo List */
	gint max_items,		/* Maximum Items In Combo List */
	gpointer *combo_rtn,	/* GtkCombo Return */
	gpointer data,
	void (*func_cb)(GtkWidget *w, gpointer),
	void (*list_change_cb)(GtkWidget *, gpointer, GList *)
);
extern void GUIComboActivateValue(GtkWidget *w, const gchar *value);
extern void GUIComboAddItem(GtkWidget *w, const gchar *value);
extern GList *GUIComboGetList(GtkWidget *w);
extern void GUIComboSetList(GtkWidget *w, GList *list);
extern void GUIComboClearAll(GtkWidget *w);


/* Menu Bar & Menu Items */
extern GtkWidget *GUIMenuBarCreate(GtkAccelGroup **accelgrp_rtn);
extern GtkWidget *GUIMenuCreateTearOff(void);
extern GtkWidget *GUIMenuCreate(void);
extern GtkWidget *GUIMenuItemCreate(
	GtkWidget *menu,
	gui_menu_item_type type,	/* One of GUI_MENU_ITEM_TYPE_* */
	GtkAccelGroup *accelgrp,
	guint8 **icon, const gchar *label,
	guint accel_key, guint accel_mods,
	gpointer *functional_widget_rtn,
	gpointer data,
	void (*func_cb)(GtkWidget *w, void *)
);
extern void GUISetMenuItemDefault(GtkWidget *w);
extern void GUISetMenuItemCrossingCB(
	GtkWidget *w,
	gint (*enter_cb)(GtkWidget *, GdkEvent *, gpointer),
	gpointer enter_data,
	gint (*leave_cb)(GtkWidget *, GdkEvent *, gpointer),
	gpointer leave_data
);
extern GtkWidget *GUIMenuAddToMenuBar(
	GtkWidget *menu_bar, GtkWidget *menu,
	const gchar *label,
	gui_menu_bar_item_alignment align	/* One of GUI_MENU_BAR_ALIGN_* */
);
extern void GUIMenuItemSetLabel(GtkWidget *menu_item, const gchar *label);
extern void GUIMenuItemSetPixmap(GtkWidget *menu_item, guint8 **icon_data);
extern GtkWidget *GUIMenuAddToMenuBarPixmapH(
	GtkWidget *menu_bar, GtkWidget *menu,
	const gchar *label, guint8 **icon_data,
	gui_menu_bar_item_alignment align	/* One of GUI_MENU_BAR_ALIGN_* */
);
extern void GUIMenuItemSetSubMenu(
	GtkWidget *menu_item, GtkWidget *sub_menu
);


/* Pull Out Window */
extern void *GUIPullOutCreateH(
	void *parent_box,
	int homogeneous, int spacing,           /* Of client vbox */
	int expand, int fill, int padding,      /* Of holder hbox */
	int toplevel_width, int toplevel_height,
	void *pull_out_client_data,
	void (*pull_out_cb)(void *, void *),
	void *push_in_client_data,
	void (*push_in_cb)(void *, void *)
);
extern void *GUIPullOutGetToplevelWindow(
	void *client_box,
	int *x, int *y, int *width, int *height
);
extern void GUIPullOutPullOut(void *client_box);
extern void GUIPullOutPushIn(void *client_box);


#endif	/* GUIUTILS_H */
