/*
				Manual Page Editor
 */

#ifndef EDITOR_H
#define EDITOR_H

#include <gtk/gtk.h>
#include "medit_types.h"


typedef struct _editor_struct		editor_struct;
#define EDITOR(p)			((editor_struct *)(p))
typedef struct _editor_item_struct	editor_item_struct;
#define EDITOR_ITEM(p)			((editor_item_struct *)(p))
typedef struct _editor_fip_struct	editor_fip_struct;
#define EDITOR_FIP(p)			((editor_fip_struct *)(p))


/*
 *	Editor Item Types:
 */
typedef enum {
	EditorItemTypeFile,		/* Main trunk */
	EditorItemTypeHeader,
	EditorItemTypeSection
} editor_item_type;


/*
 *	Editor:
 */
struct _editor_struct {

	GtkWidget	*toplevel;
	gint		freeze_count,
			busy_count;
	gboolean	syntax_highlighting;

	medit_core_struct	*core;
	gint		viewer_num;	/* Index of spawned manual page viewer
					 * (can be -1 for none) */

	GtkWidget	*main_vbox,

			*menu_bar_dock,
			*menu_bar,
			*tool_bar_dock,
			*tool_bar,

			*layout_ctree;

	/* List of trunk branch nodes on the layout ctree, these may
	 * not be in any particular order and not in sync on the
	 * ctree
	 *
	 * These should all have user item data type set to
	 * EditorItemTypeFile, which implies the number of files loaded
	 */
	GtkCTreeNode	**layout_trunk;
	gint		total_layout_trunks;

	GtkCTreeNode	*selected_branch;	/* Can be NULL for none */

	/* Right pane editing widgets parent, note the type
	 * corresponds to EditorItemType* and maximum is
	 * MEDIT_EDIT_PANEL_MAX which must be one greater than
	 * the highest EditorItemType* code
	 */
#define MEDIT_EDIT_PANEL_MAX	3
	GtkWidget	*edit_panel_vbox[MEDIT_EDIT_PANEL_MAX];

	GtkWidget	*header_name_entry,
			*header_section_number_entry,
			*header_version_entry,
			*header_author_entry,
			*header_catagory_entry,
			*header_text;	/* For comments */

	GtkWidget	*section_name_entry,
			*section_text;

	/* Syntax highlight timeout callback values */
	guint		synhl_timeout_cb_id;	/* None if (guint)(-1) */
	gint		synhl_timeout_cb_cursor_pos;
	gint		synhl_timeout_cb_start_pos;
	gint		synhl_timeout_cb_end_pos;

	/* Important menu items */
	GtkWidget	*file_mh,
			*new_mi,
			*new_from_template_mi,
			*open_mi,
			*save_mi,
			*save_as_mi,
			*revert_mi,
			*close_manual_mi,
			*close_mi,
			*exit_mi,

			*edit_mh,
			*undo_mi,
			*undo_milabel,
			*redo_mi,
			*redo_milabel,
			*cut_mi,
			*copy_mi,
			*paste_mi,
			*select_all_mi,
			*unselect_all_mi,
			*find_in_pages_mi,

			*view_mh,
			*preview_mi,
			*syntax_highlight_cmi,

			*layout_mh,
			*add_header_mi,
			*add_section_mi,
			*remove_mi,
			*properties_mi,

			*fmt_mh,
			*fmt_pl_mi,
			*fmt_pr_mi,
			*fmt_pi_mi,
			*fmt_li_mi,
			*fmt_b_mi,
			*fmt_u_mi,
			*fmt_br_mi,
			*fmt_amp_mi,
			*fmt_lt_mi,
			*fmt_gt_mi,
			*fmt_strip_tags_mi,

			*windows_mh,
			*windows_new_editor,
			*windows_new_viewer;

	/* Tool bar buttons */
	GtkWidget	*new_btn,
			*new_btn_new_menu,
			*new_btn_new_mi,
			*new_btn_new_from_template_mi,
			*open_btn,
			*save_btn,
			*save_as_btn,
			*close_btn,

			*undo_btn,
			*redo_btn,

			*cut_btn,
			*copy_btn,
			*paste_btn,

			*add_header_btn,
			*add_section_btn,
			*remove_btn,
			*properties_btn,

			*preview_btn;

	/* Formatting bar buttons */
	GtkWidget	*fmt_bar_dock,
			*fmt_bar,
			*fmt_pl_btn,
			*fmt_pr_btn,
			*fmt_pi_btn,
			*fmt_li_btn,
			*fmt_b_btn,
			*fmt_u_btn,
			*fmt_br_btn,
			*fmt_amp_btn,
			*fmt_lt_btn,
			*fmt_gt_btn,
			*fmt_strip_tags_btn;

	/* Search bar */
	GtkWidget	*find_bar_dock,
			*find_bar,
			*find_combo,
			*find_btn,
			*replace_combo,
			*replace_btn,
			*replace_all_btn;

	/* Find bar button find menu */
	GtkWidget	*find_bar_find_menu,
			*find_bar_find_in_pages_mi;

	/* Find bar button replace menu */
	GtkWidget       *find_bar_replace_menu,
			*find_bar_replace_entire_page_mi;

	/* Right-click menus */
	GtkWidget *layout_menu, *edit_panel_menu;

	/* Important menu items on right-click menus */
	GtkWidget	*layout_menu_expand_mi,
			*layout_menu_preview_mi,
			*layout_menu_add_header_mi,
			*layout_menu_add_section_mi,
			*layout_menu_remove_mi,
			*layout_menu_properties_mi,
			*layout_menu_new_manual_mi,
			*layout_menu_new_from_template_mi,
			*layout_menu_open_mi,
			*layout_menu_save_mi,
			*layout_menu_save_as_mi,
			*layout_menu_revert_mi,
			*layout_menu_close_manual_mi;

	GtkWidget	*edit_panel_undo_mi,
			*edit_panel_undo_milabel,
			*edit_panel_redo_mi,
			*edit_panel_redo_milabel,
			*edit_panel_cut_mi,
			*edit_panel_copy_mi,
			*edit_panel_paste_mi,
			*edit_panel_select_all_mi,
			*edit_panel_unselect_all_mi;
	/* Format submenu on edit panel menu */
	GtkWidget	*edit_panel_fmt_sub_menu,
			*edit_panel_fmt_pl_mi,
			*edit_panel_fmt_pr_mi,
			*edit_panel_fmt_pi_mi,
			*edit_panel_fmt_li_mi,
			*edit_panel_fmt_b_mi,
			*edit_panel_fmt_u_mi,
			*edit_panel_fmt_br_mi,
			*edit_panel_fmt_amp_mi,
			*edit_panel_fmt_lt_mi,
			*edit_panel_fmt_gt_mi,
			*edit_panel_fmt_strip_tags_mi;

	/* Status bar */
	GtkWidget	*status_bar_dock,
			*status_bar_toplevel,	/* An hbox */
			*status_bar_progress,
			*status_bar_label,
			*status_bar_cursor_label;

	/* Last progress position value from 0.0 to 1.0 */
	gfloat		status_bar_progress_pos_last;

	/* Undo/redo structures */
	gpointer	*undo;
	gint		total_undos;

	gpointer	*redo;
	gint		total_redos;

	gint		max_undos;	/* Maximum undos and maximum redos */


	/* Last open file path */
	gchar		*last_open_path;

	/* Last save as file path */
	gchar		*last_save_as_path;


	/* Editor Find In Pages dialog */
	editor_fip_struct *fip_dlg;

};

#define EDITOR_TOPLEVEL(p)		(((p) != NULL) ? \
 (EDITOR(p)->toplevel) : NULL)
#define EDITOR_LAYOUT_CTREE(p)		(((p) != NULL) ? \
 (EDITOR(p)->layout_ctree) : NULL)
#define EDITOR_HEADER_TEXT(p)		(((p) != NULL) ? \
 (EDITOR(p)->header_text) : NULL)
#define EDITOR_SECTION_TEXT(p)		(((p) != NULL) ? \
 (EDITOR(p)->section_text) : NULL)
#define EDITOR_LAST_OPEN_PATH(p)	(((p) != NULL) ? \
 (EDITOR(p)->last_open_path) : NULL)
#define EDITOR_LAST_SAVE_AS_PATH(p)	(((p) != NULL) ? \
 (EDITOR(p)->last_save_as_path) : NULL)


/*
 *	Editor Item:
 *
 *	Used as row data on the layout_ctree.
 *
 *	When adding new members be sure to update functions
 *	EditorItemNew(), EditorItemDup(), and EditorItemDelete()
 *	so that they properly allocate, duplicate, and delete the
 *	new members.
 */
struct _editor_item_struct {

	editor_item_type	type;
	editor_struct	*editor;
	gboolean	has_changes;

	GtkCTree	*ctree;		/* Layout GtkCTree */
	GtkCTreeNode	*parent;	/* Parent branch */
	GtkCTreeNode	*this_branch;	/* This branch */
	gboolean	is_leaf;

	/* Members for type EditorItemTypeFile */
	gchar		*name;		/* File name without path */
	gchar		*full_path;	/* If NULL then implies it has
					 * never been saved before */

	/* Members for type EditorItemTypeHeader */
	gchar		*header_name;
	gchar		*header_section_number;
	gchar		*header_version;
	gchar		*header_author;
	gchar		*header_catagory;

	/* Members for type EditorItemTypeSection */
	gchar		*section_name;

	/* Common members */
	gchar		**line;
	gint		total_lines;

};


extern editor_item_struct *EditorItemNew(
	editor_item_type type,
	editor_struct *editor,
	GtkCTree *ctree,
	GtkCTreeNode *parent,
	GtkCTreeNode *this_branch,
	gboolean is_leaf,
	gchar **line,		/* Transfered, not copied */
	gint total_lines
);
extern editor_item_struct *EditorItemDup(editor_item_struct *item);
extern void EditorItemDelete(editor_item_struct *item);

extern void EditorLayoutTrunkDeleteAll(editor_struct *editor);

extern void EditorBranchSelect(
	editor_struct *editor, GtkCTreeNode *branch
);

extern void EditorBranchSetData(
	GtkCTree *ctree, GtkCTreeNode *branch,
	editor_item_struct *item, GtkDestroyNotify destroy
);
extern editor_item_struct *EditorBranchGetData(
	GtkCTree *ctree, GtkCTreeNode *branch
);
extern void EditorItemSetToplevelHasChanges(
	editor_struct *editor, GtkCTreeNode *branch, gboolean has_changes
);

extern GtkCTreeNode *EditorItemGetFirstToplevel(editor_struct *editor);
extern GtkCTreeNode *EditorItemGetParent(
	editor_struct *editor, GtkCTreeNode *branch
);
extern GtkCTreeNode *EditorItemGetToplevel(
	editor_struct *editor, GtkCTreeNode *branch
);

extern void EditorSetBusy(editor_struct *editor);
extern void EditorSetReady(editor_struct *editor);

extern editor_struct *EditorNew(gpointer core_ptr);
extern void EditorUpdateMenus(editor_struct *editor);
extern void EditorSetStatusPosition(editor_struct *editor, gint row, gint column);
extern void EditorSetStatusMessage(editor_struct *editor, const gchar *mesg);
extern void EditorSetStatusProgress(editor_struct *editor, gfloat percent);
extern void EditorRecordPositions(editor_struct *editor);
extern void EditorResetUndos(editor_struct *editor);
extern void EditorReset(editor_struct *editor, const gboolean need_unmap);
extern void EditorMap(editor_struct *editor);
extern void EditorUnmap(editor_struct *editor);
extern void EditorDelete(editor_struct *editor);


#endif	/* EDITOR_H */
