/*****************************************************************************/
/* The development of this program is partly supported by IPA                */
/* (Information-Technology Promotion Agency, Japan).                         */
/*****************************************************************************/

/*****************************************************************************/
/*  gdavl.h - GUI disk allocation viewer header                              */
/*  Copyright: Copyright (c) Hitachi, Ltd. 2004-2008                         */
/*             Authors: Yumiko Sugita (yumiko.sugita.yf@hitachi.com),        */
/*                      Satoshi Fujiwara (sa-fuji@sdl.hitachi.co.jp)         */
/*                                                                           */
/*  This program is free software; you can redistribute it and/or modify     */
/*  it under the terms of the GNU General Public License as published by     */
/*  the Free Software Foundation; either version 2 of the License, or        */
/*  (at your option) any later version.                                      */
/*                                                                           */
/*  This program is distributed in the hope that it will be useful,          */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
/*  GNU General Public License for more details.                             */
/*                                                                           */
/*  You should have received a copy of the GNU General Public License        */
/*  along with this program; if not, write to the Free Software              */
/*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
/*****************************************************************************/

#define	GDAVL_VER		"1.2.4"
#define	COPYRIGHT		"Copyright (c) Hitachi, Ltd. 2004-2008"

#define	MAX_NAME_LEN		64
#define	OUT_DEFAULT_LEN		(64 * 1024)
#define	ERR_DEFAULT_LEN		64

#define	BLK_WIDTH		8
#define	BLK_HEIGHT		12
#define	BLKS_PER_LINE		64

#define	MARGIN			5
#define	DIFF_MARGIN_LN		2
#define	DIFF_MARGIN_BN		3

#define	NOTEPAGE_TOTAL		0
#define	NOTEPAGE_FRAG		1
#define	MAX_NOTEPAGE		2

#define	SUMMARIZE_DEFAULT	3
#define	SUMMARIZE_MIN		0
#define	SUMMARIZE_MAX		24

#ifdef	DEBUG
#define	MAX_POPDOWN_CNT		2
#define	MAX_DRAW_PIXEL		0x80
#define	MAX_FFILES_PER_PAGE	4
#else
#define	MAX_POPDOWN_CNT		10
#define	MAX_DRAW_PIXEL		0x7d00
#define	MAX_FFILES_PER_PAGE	1024
#endif

#define	CONTEXT_NAME		"Main"

#define	TAG_RESULT_START	"------ cdavl result start ------\n"
#define	TAG_FSTYPE		"fstype"
#define	TAG_MOUNT		"mount"
#define	TAG_PERCENT		"f-per"
#define	TAG_BLOCKS		"blocks"
#define	TAG_SBLOCKS		"sblocks"
#define	TAG_XBLOCKS		"xattrs"
#define	TAG_FBLOCKS		"fblocks"
#define	TAG_FRAGS		"frags"
#define	TAG_SFRAGS		"sfrags"
#define	TAG_CFILES		"cfiles"
#define	TAG_FFILES		"ffiles"
#define	TAG_DEPTH		"depth"
#define	TAG_FBSEQ		"fbseq"

#define	GDAVL_FONT		"-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"

#define	DEV_LABEL_STR		"device:"
#define	PATH_LABEL_STR		"path:"
#define	BEFORE_LABEL_STR	"before:"
#define	AFTER_LABEL_STR		"after:"

#define	EXEC_LABEL_STR		"exec"
#define	ABORT_LABEL_STR		"abort"
#define	RESUME_LABEL_STR	"resume"
#define	PAUSE_LABEL_STR		"pause"

#define	EMSG_CDAVL_RESULT_INVALID	"cdavl result invalid format."

#define	TEST_ERR_TAG		"Test Error:"



enum {
	ID_BLOCKS,
	ID_SBLOCKS,
	ID_XBLOCKS,
	ID_FBLOCKS,
	ID_FRAGS,
	ID_SFRAGS,
	ID_CFILES,
	ID_FFILES,
	ID_DEPTH,
};
#define	MAX_ID	(ID_DEPTH + 1)

enum {
	UBLK,
	SBLK,
	XBLK,
	CBLK,
	FBLK,
	FBLK_LF,
	FBLK_LSF,
};
#define	MAX_BLK_ID	(FBLK_LSF + 1)

enum {
	EV_START,		/* click exec button */
	EV_TOTAL_PAGE,		/* click total/file-block prev/next button */
	EV_FFILE_PAGE,		/* click fragmented file list prev/next btn */
	EV_FRAG_VIEW,		/* select fragmented file */
	EV_FRAG_PAGE,		/* click fragmented file-block prev/next btn */
	EV_SWITCH_TAB,		/* switch note tab */
	EV_FBVIEW,		/* change total/file-block view */
	EV_SUMMARY,		/* change summary */
};

enum {
	FFI_PERCENT,		/* fragmented blocks percentage */
	FFI_TOTAL,		/* total block count */
	FFI_FRAGS,		/* fragmented block count  */
	FFI_SFRAGS,		/* fragment by sys-block count */
};
#define	FFILE_INFO_CNT		(FFI_SFRAGS + 1)


#define	ARRAY_SIZE(ary)		(sizeof(ary) / sizeof (ary[0]))

#define	CHK_POINTER(p, p_max)						\
	do {								\
		if ((p) == NULL || (p) >= (p_max)) {			\
			display_err_dialog(EMSG_CDAVL_RESULT_INVALID);	\
			goto ERR_RETURN;				\
		}							\
	} while (0)



typedef struct {
	GtkWidget	*label;
	GtkWidget	*widget;
	gchar		*s;
	GList		*list;		/* popdown strings */
}	t_combo;

typedef struct {
	/* all t_text common */
	GdkFont		*font;

	/* each t_text individual */
	GtkWidget	*widget;
	GtkAdjustment	*adjust;
}	t_text;

typedef struct {
	GtkWidget	*widget;
	gint		cnt;
}	t_spin;

typedef struct {
	gint		page;
	gint		page_max;
	gint		ln_per_page;

	gint		ln_all;
	gint		ln_1st;
	guint		start_bn;
	guint		start_bn_2nd;

	GtkWidget	*box;
	GtkWidget	*prev;
	GtkWidget	*next;
	GtkWidget	*info;

}	t_page;

typedef struct {
	GtkWidget	*widget;
	t_page		page;
}	t_clist;

typedef struct {
	/* all t_draw common */
	GdkFont		*font;
	GdkPixmap	*xpm[MAX_BLK_ID * 2];

	/* each t_draw individual */
	GtkWidget	*widget;
	GdkPixmap	*pixmap;
	gint		bnum_width;
	gint		width;
	gint		height;
	GtkWidget	*scrl_win;
	gint		summary_cnt;

	/* page support */
	t_page		page;

}	t_draw;

typedef struct {
	GtkWidget	*widget;
	guint		cid;
}	t_sbar;

typedef struct {
	GIOChannel	*ch;
	GString		*s;
}	t_io_info;

typedef struct {
	struct timeval	start;
	struct timeval	cdavl_end;
	struct timeval	end;
}	t_time_info;

typedef struct {
	gint		interval;
	gboolean	is_exec;
	gchar		**fpaths;
	gint		cnt;
	gint		id;
	struct timeval	exec_time;
}	t_anim;

typedef struct {
	GtkMenuItem	*normal;
	GtkMenuItem	*diff;
}	t_menu;

typedef struct {
	GtkWidget	*exec;
	GtkWidget	*abort;
	t_menu		menu;
	gboolean	is_normal;
	t_combo		dev;
	t_combo		path;
	t_combo		after;
	GtkWidget	*fbview[MAX_NOTEPAGE];
	t_text		text;
	t_draw		note;
	t_clist		ffrag;
	t_draw		blks[MAX_NOTEPAGE];
	t_sbar		sbar;
	gint		tab_page;
	gboolean	is_abort;
	t_spin		summary;
	t_anim		anim;
	gint		not_use_devdrv;
	pid_t		cdavl_pid;
	t_io_info	out;
	t_io_info	out_B;
	t_io_info	err;
	t_time_info	time;
	GtkWidget	*version_dlg;
}	t_app_status;



typedef struct {
	gint		type;
	guint		n;
}	t_bseq_dt;

typedef struct {
	gchar		*s;		/* string for parse*/
	GArray		*dts;		/* GArray of type-blocks(t_bseq_dt) */
	gdouble		fper;		/* fragment blocks percentage */
	guint		total;		/* total block count */
	guint		frags;		/* fragmented block count */
	guint		sfrags;		/* fragment by sys-block count */
	guint		bcnt;
}	t_tcnts;

typedef struct {
	gchar		*path;
	gboolean	is_diff;
	t_tcnts		tcnts;
	t_tcnts		tcnts_B;
}	t_frag_info;

typedef struct {
	gchar		*fstype;	/* ext2/ext3 */
	gchar		*mount_st;	/* mount status */
	gchar		*f_per;		/* fragmented blocks percentage */
	guint		values[MAX_ID];
	guint		start;
	t_tcnts		fsys_tcnts;	/* type-blocks (file system) data */
	t_tcnts		fb_tcnts;	/* type-blocks (file blocks) data */
	GSList		*frag_info;	/* list of fragment info(t_frag_info) */
	GMemChunk	*finfo_mem_chunk;
	gint		ffile_row;
}	t_result;

typedef struct {
	t_app_status	*app;
	t_result	*result;
	t_result	*result_B;
}	t_all_data;

typedef void (*t_page_func)(gpointer, gint);





/* proto type */
GtkWidget* create_window(t_all_data* all);
gint draw_note(t_draw *note);

gint on_expose_note(GtkWidget *w, GdkEventExpose *event, gpointer tmp);
gint on_expose_total_blocks(GtkWidget *w, GdkEventExpose *event, gpointer tmp);
gint on_expose_frag_blocks(GtkWidget *w, GdkEventExpose *event, gpointer tmp);
void on_switch_tab(GtkNotebook *w, GtkNotebookPage *page,
		   gint pnum, gpointer tmp);
gint on_fbview_toggled(GtkWidget *w, gpointer tmp);
guint on_input_from_out(GIOChannel *c, GIOCondition condition, gpointer tmp);
guint on_input_from_err(GIOChannel *c, GIOCondition condition, gpointer tmp);
gint on_exec_clicked(GtkWidget *w, gpointer tmp);
gint on_abort_clicked(GtkWidget *w, gpointer tmp);
gint on_total_prev_clicked(GtkWidget *w, gpointer tmp);
gint on_total_next_clicked(GtkWidget *w, gpointer tmp);
gint on_frag_prev_clicked(GtkWidget *w, gpointer tmp);
gint on_frag_next_clicked(GtkWidget *w, gpointer tmp);
gint on_ffile_prev_clicked(GtkWidget *w, gpointer tmp);
gint on_ffile_next_clicked(GtkWidget *w, gpointer tmp);
void on_delete(GtkWidget *w, GdkEvent *event, gpointer tmp);
gint on_device_changed(GtkWidget *w, gpointer tmp);
gint on_path_changed(GtkWidget *w, gpointer tmp);
gint on_after_changed(GtkWidget *w, gpointer tmp);
gint on_summary_changed(GtkWidget *w, gpointer tmp);
gint on_select_ffile(GtkWidget *w, gint row, gint column,
		     GdkEventButton *event, gpointer tmp);
gint on_unselect_ffile(GtkWidget *w, gint row, gint column,
		       GdkEventButton *event, gpointer tmp);
gint on_ffiles_click_column(GtkWidget *w, gint column, gpointer tmp);
void on_menu_normal(GtkWidget *w, gpointer tmp);
void on_menu_diff(GtkWidget *w, gpointer tmp);
void on_menu_quit(GtkWidget *w, gpointer tmp);
void on_menu_version(GtkWidget *w, gpointer tmp);
