/*
				   Hex View
 */

#ifndef HVIEW_H
#define HVIEW_H

#include <gtk/gtk.h>


/*
 *	Edit Modes:
 */
typedef enum {
	HVIEW_EDIT_MODE_HEX,
	HVIEW_EDIT_MODE_ASCII
} hview_edit_mode;


/*
 *	Hex View:
 */
typedef struct _hview_struct		hview_struct;
struct _hview_struct {

	GtkWidget 	*toplevel;
	gboolean	map_state;
	gint		freeze_count,
			busy_count;
	GdkCursor	*busy_cur,
			*text_cur,
			*translate_cur;
	GdkFont 	*font;
	GdkColormap	*colormap;
	GdkGC		*gc;

	gboolean	dragging_selection, dragging_scroll;
	gint		last_motion_x, last_motion_y;

	gint		cell_width, cell_height, cells_per_row;

	/* Column positions */
	gint		address_x, hex_x, ascii_x;

	GtkAdjustment	*vadj;
	GtkWidget	*heading_toplevel,
			*view_da,
			*vscrollbar,
			*status_bar_toplevel,
			*status_bar_label;
	GdkPixmap	*view_pm;
	guint		scroll_toid,
			draw_idle_id;

	/* Right click menu */
	GtkWidget	*menu,
			*cut_mi,
			*copy_mi,
			*paste_mi,
			*insert_mi,
			*delete_mi,
			*select_all_mi,
			*unselect_all_mi,
			*edit_mode_msep,
			*edit_mode_hex_mi,
			*edit_mode_ascii_mi;

	/* Loaded data */
	guint8		*buf;		/* Buffer */
	gint		buf_len,
			buf_pos;
	gint		buf_sel_start,	/* Selection */
			buf_sel_end;

	gboolean	read_only;	/* Not editable if TRUE */

	/* Edit mode */
	hview_edit_mode	edit_mode;

	/* If not 0, indicates the hex is being edited. When this is
	 * 1 then it means the user pressed one key to indicate the
	 * first character of the hex value, pressing another key
	 * finishes the editing
	 */
	gint		buf_hex_edit;
	/* Tempory buffer for holding the user typed hex characters */
	gchar		buf_hex_edit_buf[3];


	gboolean	modified;

	/* Changed callback */
	void		(*changed_cb)(
		hview_struct *hv,		/* Hex View */
		gpointer			/* Data */
	);
	gpointer	changed_data;

};
#define HVIEW(p)	((hview_struct *)(p))

/* Returns TRUE if the buffer is selected (not nessisarly has selection)
 * or FALSE if the buffer is not selected
 */
#define HVIEW_IS_BUF_SELECTED(_h_)	(			\
 ((_h_) != NULL) ?						\
  (((_h_)->buf_sel_start > -1) && ((_h_)->buf_sel_end > -1)) :	\
  FALSE								\
)

/* Returns TRUE if the position i is in bounds */
#define HVIEW_IS_BUF_POS_VALID(_h_,_i_)	(			\
 ((_h_) != NULL) ?						\
  (((_h_)->buf != NULL) && ((_i_) >= 0) && ((_i_) < (_h_)->buf_len)) : \
  FALSE								\
)


extern gint HViewPositionXYToBuffer(hview_struct *hv, gint x, gint y);
extern void HViewScrollTo(hview_struct *hv, gint pos, gfloat ycoeff);
extern GtkVisibility HViewIsBufferPositionVisible(
	hview_struct *hv, gint i
);

extern gint HViewOpenFile(hview_struct *hv, const gchar *path);
extern gint HViewSaveFile(hview_struct *hv, const gchar *path);
extern gint HViewOpenData(hview_struct *hv, const guint8 *data, gint data_len);
extern void HViewClear(hview_struct *hv);

extern void HViewSetEditMode(hview_struct *hv, hview_edit_mode edit_mode);
extern void HViewSetSelected(hview_struct *hv, guint8 v);
extern void HViewSetPosition(hview_struct *hv, gint pos);
extern void HViewSelect(
	hview_struct *hv, gint start_pos, gint end_pos
);
extern void HViewCut(hview_struct *hv);
extern void HViewCopy(hview_struct *hv);
extern void HViewPaste(hview_struct *hv);
extern void HViewInsert(hview_struct *hv);
extern void HViewDeleteSelected(hview_struct *hv);
extern gint HViewFind(
	hview_struct *hv, const guint8 *needle, gint needle_len,
	gint start_pos, gboolean case_sensitive
);

extern gboolean HViewToplevelIsWindow(hview_struct *hv);
extern GtkWidget *HViewGetToplevelWidget(hview_struct *hv);
extern GtkDrawingArea *HViewGetViewWidget(hview_struct *hv);
extern GtkMenu *HViewGetMenuWidget(hview_struct *hv);

extern hview_struct *HViewNew(GtkWidget *parent);
extern hview_struct *HViewNewWithToplevel(
	gint width, gint height
);
extern void HViewShowHeading(hview_struct *hv, gboolean show);
extern void HViewShowStatusBar(hview_struct *hv, gboolean show);
extern void HViewSetReadOnly(hview_struct *hv, gboolean read_only);
extern void HViewSetChangedCB(
	hview_struct *hv,
	void (*changed_cb)(hview_struct *, gpointer),
	gpointer data
);
extern void HViewUpdate(hview_struct *hv);
extern void HViewDraw(hview_struct *hv);
extern void HViewQueueDraw(hview_struct *hv);
extern void HViewSetStatusMessage(
	hview_struct *hv, const gchar *mesg,
	gboolean allow_gtk_iteration
);
extern void HViewSetBusy(hview_struct *hv, gboolean is_busy);
extern void HViewMap(hview_struct *hv);
extern void HViewUnmap(hview_struct *hv);
extern void HViewDelete(hview_struct *hv);


#endif	/* HVIEW_H */
