/* $Id: e2_fileview.h 874 2008-05-07 14:47:27Z tpgww $

Copyright (C) 2004-2008 tooar <tooar@gmx.net>

This file is part of emelFM2.
emelFM2 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 3, or (at your option)
any later version.

emelFM2 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 emelFM2; see the file GPL. If not, contact the Free Software
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef __E2_FILEVIEW_H__
#define __E2_FILEVIEW_H__

#include "emelfm2.h"

//these are in same order as ascii <, =, >
typedef enum { LT, EQ, GT } Operator;
typedef enum { E2_REFRESH, E2_RECREATE, E2_CHANGE } E2_RefreshType;
typedef enum { CD_NOTFINISHED, CD_TIMEOUT, CD_SUCCESS } E2_CDType;
//filelist treestore column-number enumerator
enum { FILENAME = 0, SIZE, PERM, OWNER, GROUP, MODIFIED, ACCESSED, CHANGED, MAX_COLUMNS };
//directory-read failure codes
enum
{
	E2DREAD_ENOENT,	//empty dir (not really an error)
	E2DREAD_NS,		//stat dir failed
	E2DREAD_DNR,	//dir not opened
	E2DREAD_DNCH,	//cannot cd into dir to poll its contents
	E2DREAD_DNF,	//read cancelled by user after timeout
	E2DREAD_ENOTH,	//failed to create thread when doing timed read
	E2DREAD_ENOMEM,	//not enough memory for storing data about read item
	E2DREAD_ELAST	//just an enumerator
};
#define E2DREAD_FAILED(ptr) (!(ptr == NULL || (gpointer)ptr > GUINT_TO_POINTER (E2DREAD_ENOMEM)))

typedef enum
{
	E2FSCASE_UNKNOWN,
	E2FSCASE_SENSITIVE,
	E2FSCASE_ANY,	//insensitive
	E2FSCASE_NEVER,	//tried to discover, but unable to do so
	E2FSCASE_VIRTUAL,
	E2FSCASE_NOCACHE = 16,	//a bitfag set for removable devices
	E2FSCASE_SENSITIVENOW,	//values corresponding to fixed devices
	E2FSCASE_ANYNOW,
	E2FSCASE_NOTNOW,
	E2FSCASE_VIRTUALNOW
} E2_FSSensitive;

typedef struct _E2_Listman
{
	VOLATILE E2_RefreshType refreshtype; //whether a view update is a refresh, recreate or cd
	VOLATILE struct _E2_ViewInfo *view;	//use this when re-starting a cd after timeout
	VOLATILE gchar *newpath;	//stored copy of place to open, non-NULL implies cd requested
	VOLATILE gboolean history;
	VOLATILE gboolean hook;
	VOLATILE gboolean cd_requested;	//TRUE when we can't yet cd using this data
	VOLATILE gboolean cd_working;	//TRUE to prevent re-entrant cd of the same filelist
//	VOLATILE guint timer;	//id of timer running a cd process

	VOLATILE gboolean refresh_requested;	//TRUE when something has proposed that the view be refreshed
	VOLATILE gboolean refresh_working;
	VOLATILE gboolean norefresh;	//flag signalling refresh is disabled (though backend checks are not)

//	VOLATILE gboolean listing ; //TRUE during th "core" part of list re-creation
} E2_Listman;

typedef struct _E2_ViewInfo
{
	VOLATILE GtkListStore *store;
	VOLATILE GtkTreeModel *model;	//may be a filter model or standard
	VOLATILE GtkWidget *treeview;
	VOLATILE GtkTreeSelection *selection;	//pointer to selection for this view's treeview
	VOLATILE GHashTable *selected_names;  //names of selected items (for reselection), or NULL
	gint sort_column;  //copy of current sort column, can be <0
	gboolean extsort;	//TRUE when name-sorting is by extension
	GtkSortType sort_order; //copy of current sort order
	GtkWidget *sort_arrows[MAX_COLUMNS];
	GtkLabel *name_label;	//for showing active pane by changing label content
//	E2_FSType dirtype;	//flags for type of namespace this view belongs to
	E2_FSSensitive case_sensitive_names; //cache, FIXME needs to be cleared when removable device changes
#ifdef E2_VFS
	VOLATILE PlaceInfo *spacedata;	//pointer to extra data for virual namespace, NULL for mounted dir
#endif
	gchar dir[PATH_MAX];	//path shown in this view (utf-8) with vpreface if approprate
	GList *dir_history;  //list of structs with focused line etc for each opened dir in the current namespace
						//FIXME clean list data at end-session
//#ifndef E2_FAM
	time_t dir_mtime;
	time_t dir_ctime;
//#endif
	GtkWidget *check_dirs; //filter sub-menu toggle-widget
	GtkWidget *check_name; //filter sub-menu toggle-widget
	struct
	{
		gchar *patternptr;
		GSList *compiled_patterns;	//list of _E2_SelectPattern's
		gboolean invert_mask;
		gboolean case_sensitive;
		gboolean active;
	} name_filter;
	GtkWidget *check_size;
	struct
	{
		size_t size;
		Operator op;
		gboolean active;
	} size_filter;
	GtkWidget *check_date;
	struct
	{
		time_t time;	//time_t may be int or long int
		Operator op;
		enum {MTIME, ATIME, CTIME} time_type;
		gboolean active;
	} date_filter;

	gboolean filtered_before;	//state of prior call to filter function
	gboolean filter_directories;
	gboolean show_hidden;  //whether to display hidden items in this view
	guint total_items;	//total displayed and undisplayed items in the dir - 2 (to ignore . and ..)
	gint row;	//index of most-recently clicked row in the treeview
	gint drop_row;	//index of most-recently moused row during a drag operation
	gboolean lit;	//TRUE if drop-row is highlighted
//	E2_RefreshType refreshtype; //whether a view update is a refresh, recreate or cd
//	gboolean refresh_requested;	//TRUE when something has proposed that the view be refreshed
//	gboolean norefresh;	//flag signalling refresh is disabled (though backend checks are not)
//	gboolean listing ; //flag to block recursive filelist updates
	E2_Listman listcontrols;
	gchar last_find[NAME_MAX]; //buffer for storing names used in find task
//	GHookList hook_refresh;	//data for functions to run during post-refresh idle-time function
} ViewInfo;

typedef struct _E2_FileInfo
{
	gchar filename[NAME_MAX+1];  //localised string
	struct stat statbuf;
} FileInfo;

typedef struct _E2_SelectedItemInfo
{
	gchar filename[NAME_MAX+1];  //localised string no trailing /
/*	FileInfo info;
	gchar *filename;  //selected item name (except no trailing /), utf-8 string
#ifdef E2_INCLIST
	//use this if the store data is changed on the fly
	GtkTreeRowReference *ref;
#else
	//this is used for un-selecting liststore items on the fly
	GtkTreePath *path;
#endif
*/
} E2_SelectedItemInfo;

typedef struct _E2_CDwatch
{
	ViewInfo *view;	//data for view being changed (can't use E2_PaneRuntime due to circular includes)
	gchar *newpath;	//place to be opened, utf8 with trailing separator
	gint repeats;	//current retry counter
//	guint watchtimer_id; //id of timer that is watching for completion
	E2_CDType *completed_flag;	//store for flag to set when completion detected
} E2_CDwatch;

typedef struct _E2_DRead
{
	pthread_t aid;	//read thread ID, 0 when stopped
	pthread_t mid;	//monitor thread ID, 0 when stopped
	GtkWidget *dialog;	//too-slow dialog widget, or NULL
} E2_DRead;

typedef struct _E2_SelectPattern
{
	GPatternSpec *pspec;
	gboolean negated;
} E2_SelectPattern;

gint e2_fileview_ext_sort (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b,
	GtkSortType *direction);
gboolean e2_fileview_sort_column (gint colnum, ViewInfo *view);
void e2_fileview_refilter_list (ViewInfo *view);
void e2_fileview_filter_dirs_cb (GtkWidget *widget, ViewInfo *view);
void e2_fileview_remove_filters_cb (GtkWidget *widget, ViewInfo *view);
void e2_fileview_initialize_filters (ViewInfo *view);

void e2_fileview_set_menu_position (GtkMenu *menu,
	gint *x, gint *y, gboolean *push_in, GtkWidget *treeview);
void e2_fileview_focus_row (ViewInfo *view, gint row,
	gboolean select_row, gboolean clear_selection,
	gboolean center, gboolean grab_focus);
//void e2_fileview_select_row_by_filename (ViewInfo *view, gchar *filename); unused
GHashTable *e2_fileview_log_selected_names (ViewInfo *view);
void e2_fileview_reselect_names (ViewInfo *view);
void e2_fileview_translate_cols_array (gint *src_array,
	gint *dest_array, gint size);
void e2_fileview_switch_views (void);
//void e2_fileview_switch_views_simple (void);
void e2_fileview_set_font (void);
void e2_fileview_set_row_background (ViewInfo *view,
	GtkTreeIter *iter, GdkColor *color);
void e2_fileview_clear_row_background (ViewInfo *view,
	GtkTreeIter *iter);
void e2_fileview_update_col_cachedata (void);
void e2_fileview_get_scroll_data (ViewInfo *view, gint *leftcol, gint *toprow);
void e2_fileview_scroll_to_position (ViewInfo *view, gint leftcol, gint toprow);
//gint e2_fileview_find_name_col (ViewInfo *view); unused
gboolean e2_fileview_prepare_list (ViewInfo *view);
void e2_fileview_scroll_list (GThread *viewthread);
gpointer e2_fileview_refresh_list (ViewInfo *view);
gboolean e2_fileview_treehash_free (GHashTable *data);
gboolean e2_fileview_cd_watch (E2_CDwatch *data);
gboolean e2_fileview_cd_manage (E2_Listman *data);
GtkWidget *e2_fileview_create_list (ViewInfo *view);
void e2_fileview_select_all (GtkWidget *widget, ViewInfo *view);
void e2_fileview_clean_selected (GPtrArray *selected);
void e2_fileview_clean_history (GList **history);
GPtrArray *e2_fileview_get_selected (ViewInfo *view);
GList *e2_fileview_get_selected_local (ViewInfo *view);
FileInfo *e2_fileview_get_selected_first_local (ViewInfo *view, gboolean updir);
gchar *e2_fileview_get_row_name (ViewInfo *view, gint row);

#endif //ndef __E2_FILEVIEW_H__
