#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "../include/string.h"

#include "guiutils.h"
#include "fb.h"

#include "editor.h"
#include "editorfip.h"
#include "editorundo.h"
#include "editorcb.h"
#include "editordnd.h"
#include "viewerdnd.h"
#include "pref.h"
#include "manedit.h"
#include "maneditcb.h"
#include "maneditop.h"
#include "messages.h"
#include "config.h"

#include "images/manedit_48x48.xpm"
#include "images/manedit_16x16.xpm"
#include "images/manedit_20x20.xpm"
#include "images/mp_viewer_16x16.xpm"
#include "images/mp_viewer_20x20.xpm"

#include "images/icon_new_20x20.xpm"
#include "images/icon_open_20x20.xpm"
#include "images/icon_save_20x20.xpm"
#include "images/icon_save_as_20x20.xpm"
#include "images/icon_revert_20x20.xpm"
#include "images/icon_close_20x20.xpm"
#include "images/icon_exit_20x20.xpm"

#include "images/icon_undo_20x20.xpm"
#include "images/icon_redo_20x20.xpm"
#include "images/icon_cut_20x20.xpm"
#include "images/icon_copy_20x20.xpm"
#include "images/icon_paste_20x20.xpm"
#include "images/icon_options_20x20.xpm"

#include "images/icon_add_20x20.xpm"
#include "images/icon_remove_20x20.xpm"
#include "images/icon_properties2_20x20.xpm"

#include "images/icon_manpage_heading_20x20.xpm"
#include "images/icon_manpage_section_20x20.xpm"
/* #include "images/icon_help_20x20.xpm" */

#include "images/icon_paragraphi_20x20.xpm"
#include "images/icon_paragraphl_20x20.xpm"
#include "images/icon_paragraphr_20x20.xpm"
#include "images/icon_listitems_20x20.xpm"

#include "images/icon_bold_20x20.xpm"
#include "images/icon_underline_20x20.xpm"

#include "images/icon_break_20x20.xpm"

#include "images/icon_amp_20x20.xpm"
#include "images/icon_lessthan_20x20.xpm"
#include "images/icon_greaterthan_20x20.xpm"

#include "images/icon_strip_tags_20x20.xpm"

#include "images/icon_search_20x20.xpm"
#include "images/icon_replace_20x20.xpm"
#include "images/icon_replace_all_20x20.xpm"


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

void EditorLayoutTrunkDeleteAll(editor_struct *editor);

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

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

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

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

static void EditorCreateMenuBar(editor_struct *editor, GtkWidget *parent);
static void EditorCreateToolBar(editor_struct *editor, GtkWidget *parent);
static void EditorCreateStatusBar(editor_struct *editor, GtkWidget *parent);

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


#define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
#define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s)       (((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define STRLEN(s)       (((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)   (((s) != NULL) ? (*(s) == '\0') : TRUE)


/*
 *	Creates a new Editor Item.
 *
 *	The list of strings line will be transtered, not coppied. The
 *	calling function must not reference them again after this call.
 */
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 coppied */
	gint total_lines
)
{
	editor_item_struct *item = EDITOR_ITEM(g_malloc0(
	    sizeof(editor_item_struct)
	));
	if(item == NULL)
	{
	    g_strfreev(line);
	    return(NULL);
	}

	item->type = type;
	item->editor = editor;
	item->ctree = ctree;
	item->parent = parent;
	item->this_branch = this_branch;
	item->is_leaf = is_leaf;
	if(total_lines > 0)
	{
	    item->line = (gchar **)g_realloc(
		line,
		(total_lines + 1) * sizeof(gchar *)
	    );
	    if(item->line != NULL)
	    {
		item->line[total_lines] = '\0';
		item->total_lines = total_lines;
	    }
	    else
	    {
		item->line = NULL;
		item->total_lines = 0;
	    }
	}
	else
	{
	    item->line = NULL;
	    item->total_lines = 0;
	}

	return(item);
}

/*
 *	Makes a duplicate of the given item including all its
 *	allocated sub structures.
 */
editor_item_struct *EditorItemDup(editor_item_struct *item)
{
	editor_item_struct *new_item, *src_item = item;

	if(src_item == NULL)
	    return(NULL);

	new_item = EDITOR_ITEM(g_malloc0(
	    sizeof(editor_item_struct)
	));
	if(new_item != NULL)
	{
	    /* First copy value */
	    memcpy(new_item, src_item, sizeof(editor_item_struct));


	    /* Copy allocated substructures */

	    /* File names */
	    new_item->name = STRDUP(src_item->name);
	    new_item->full_path = STRDUP(src_item->full_path);

	    /* Header title heading values */
	    new_item->header_name = STRDUP(src_item->header_name);
	    new_item->header_section_number = STRDUP(
		src_item->header_section_number
	    );
	    new_item->header_version = STRDUP(src_item->header_version);
	    new_item->header_author = STRDUP(src_item->header_author);
	    new_item->header_catagory = STRDUP(src_item->header_catagory);

	    /* Section name */
	    new_item->section_name = STRDUP(src_item->section_name);

	    /* Lines */
	    if(new_item->total_lines > 0)
	    {
		gint i;

		new_item->line = (gchar **)g_malloc(
		    (new_item->total_lines + 1) * sizeof(gchar *)
		);
		if(new_item->line != NULL)
		{
		    for(i = 0; i < new_item->total_lines; i++)
			new_item->line[i] = STRDUP(src_item->line[i]);
		    new_item->line[new_item->total_lines] = NULL;
		}
		else
		{
		    new_item->total_lines = 0;
		}
	    }
	    else
	    {
		new_item->line = NULL;
	    }
	}

	return(new_item);
}

/*
 *	Deletes the item and all its allocated resources.
 */
void EditorItemDelete(editor_item_struct *item)
{
	if(item == NULL)
	    return;

	g_free(item->name);
	g_free(item->full_path);

	g_free(item->header_name);
	g_free(item->header_section_number);
	g_free(item->header_version);
	g_free(item->header_author);
	g_free(item->header_catagory);

	g_free(item->section_name);

	g_strfreev(item->line);

	g_free(item);
}


/*
 *	Selects the given branch on the editor's layout ctree.
 *
 *	Expands the parent branches if any and as needed.
 *
 *	Will call expand, select, and unselect callbacks.
 */
void EditorBranchSelect(
	editor_struct *editor, GtkCTreeNode *branch  
)
{
	GtkCTreeNode *parent;
	GtkCTreeRow *branch_row;
	GtkCTree *ctree;

	if((editor == NULL) || (branch == NULL))
	    return;

	ctree = GTK_CTREE(editor->layout_ctree);

	/* Get the parent of the specified branch */
	branch_row = GTK_CTREE_ROW(branch);
	parent = (branch_row != NULL) ?
	    branch_row->parent : NULL;
	/* Get row of parent branch (if it is not NULL) */
	branch_row = (parent != NULL) ?
	    GTK_CTREE_ROW(parent) : NULL;

	/* Is parent branch expanded? */
	if((branch_row != NULL) ? !branch_row->expanded : FALSE)
	{
	    /* Expand all parent branches */
	    while(parent != NULL)
	    {
		/* Expand parent branch (this will generate an expand
		 * signal which will be handled).
		 */
		gtk_ctree_expand(ctree, parent);

		/* Get parent of parent branch */
		branch_row = GTK_CTREE_ROW(parent);
		parent = ((branch_row == NULL) ?
		    NULL : branch_row->parent
		);
	    }
	}

/*	gtk_ctree_node_moveto(ctree, branch, 0, 0, 0); */

	/* Select the branch, this will call the unselect and then
	 * select callbacks */
	gtk_ctree_select(ctree, branch);
}


/*
 *	Deletes all layout trunk branches on the specified editor.
 */
void EditorLayoutTrunkDeleteAll(editor_struct *editor)
{
	gint i, total;
	GtkCList *clist;
	GtkCTree *ctree;
	GtkCTreeNode **list;

	if(editor == NULL)
	    return;

	ctree = GTK_CTREE(editor->layout_ctree);
	clist = GTK_CLIST(ctree);

	/* We need to create a tempory list of layout trunks since the one
	 * on the editor will be reduced each time we call
	 * gtk_ctree_remove_node() on a layout trunk
	 */
	total = editor->total_layout_trunks;
	list = (total > 0) ?
	    (GtkCTreeNode **)g_malloc0(
		total * sizeof(GtkCTreeNode *)
	    ) : NULL;
	if(list != NULL)
	    memcpy(list, editor->layout_trunk, total * sizeof(GtkCTreeNode *));
	else
	    total = 0;


	/* Remove each layout trunk branch node using our local
	 * coppied list
	 */
	gtk_clist_freeze(clist);
	for(i = 0; i < total; i++)
	{
	    if(list[i] != NULL)
		gtk_ctree_remove_node(ctree, list[i]);
	}
	gtk_clist_thaw(clist);

	/* Delete both the list of layout trunks on the editor and
	 * our local one. Note that the layout trunks list should have
	 * been deleted by the destroy notify callback when
	 * gtk_ctree_remove_node() was called on it
	 */
	g_free(editor->layout_trunk);
	editor->layout_trunk = NULL;
	editor->total_layout_trunks = 0;

	g_free(list);
}


/*
 *	Sets the data and destroy function for the given GtkCTreeNode 
 *	branch.
 */
void EditorBranchSetData(
	GtkCTree *ctree, GtkCTreeNode *branch,
	editor_item_struct *item, GtkDestroyNotify destroy
)
{
	if((ctree == NULL) || (branch == NULL))
	    return;

	gtk_ctree_node_set_row_data_full(
	    ctree, branch,
	    item, destroy
	);
}

/*
 *	Returns the user set data for the given GtkCTreeNode branch.
 */
editor_item_struct *EditorBranchGetData(
	GtkCTree *ctree, GtkCTreeNode *branch
)
{
	if((ctree == NULL) || (branch == NULL))
	    return(NULL);

	return(EDITOR_ITEM(gtk_ctree_node_get_row_data(
		ctree, branch
	)));
}


/*
 *	Sets the given branch node's item data to the value of
 *	has_changes and the branch node's subsequent parents
 *	(including and espessially the toplevel (trunk) branch node's
 *	item data.
 */
void EditorItemSetToplevelHasChanges(
	editor_struct *editor, GtkCTreeNode *branch, gboolean has_changes
)
{
	editor_item_struct *item;
	GtkCTreeNode *node;
	GtkCTree *ctree;

	if(editor == NULL)
	    return;

	ctree = GTK_CTREE(editor->layout_ctree);

	/* Get toplevel node starting from selected branch node */
	for(
	    node = branch;
	    node != NULL;
	    node = GTK_CTREE_ROW(node)->parent
	)
	{
	    /* Get and set this branch node's item data */
	    item = EditorBranchGetData(ctree, node);
	    if(item != NULL)
		item->has_changes = has_changes;
	}
}


/*
 *	Returns the pointer to the first branch node that is toplevel
 *	on the editor's layout ctree. This is basically getting the
 *	pointer to the branch of the first row since it's gauranteed
 *	to be a toplevel trunk branch and the first one.
 *
 *	Can return NULL on error or if there are no branches.
 */
GtkCTreeNode *EditorItemGetFirstToplevel(editor_struct *editor)
{
	GtkCTree *ctree;


	if(editor == NULL)
	    return(NULL);

	ctree = GTK_CTREE(editor->layout_ctree);
	if(ctree == NULL)
	    return(NULL);

	/* Return the first branch on the ctree */
	return(gtk_ctree_node_nth(ctree, 0));
}

/*
 *	Returns the pointer to the parent branch node of the given branch,
 *	can return NULL if branch is a toplevel trunk or the given branch
 *	itself is NULL.
 */
GtkCTreeNode *EditorItemGetParent(
	editor_struct *editor, GtkCTreeNode *branch
)
{
	GtkCTreeRow *row;


	if((editor == NULL) || (branch == NULL))
	    return(NULL);

	row = GTK_CTREE_ROW(branch);
	if(row == NULL)
	{
	    /* Discontinuity, row data is NULL. Need to return
	     * NULL on error.
	     */
	    return(NULL);
	}

	return(row->parent);
}

/*
 *	Returns the pointer to the toplevel trunk branch for the given
 *	branch node. If given branch node itself is a toplevel trunk
 *	branch then the pointer to the given branch will be returned.
 *
 *	Can return NULL on error.
 */
GtkCTreeNode *EditorItemGetToplevel(
	editor_struct *editor, GtkCTreeNode *branch
)
{
	GtkCTreeNode *parent;


	if((editor == NULL) || (branch == NULL))
	    return(NULL);

	while(branch != NULL)
	{
	    parent = EditorItemGetParent(editor, branch);
	    if(parent == NULL)
		return(branch);
	    else
		branch = parent;
	}

	return(NULL);
}


/*
 *	Marks editor as busy.
 */
void EditorSetBusy(editor_struct *editor)
{ 
	GtkWidget *w;
	GdkCursor *cur;
	medit_core_struct *core;


	if(editor == NULL)
	    return;

	core = (medit_core_struct *)editor->core;
	if(core == NULL)
	    return;

	w = editor->toplevel;
	if(w == NULL)
	    return; 
  
	cur = core->cursors_list.busy;
	if(cur == NULL)
	    return;

	if(GTK_WIDGET_NO_WINDOW(w))
	    return;

	gdk_window_set_cursor(w->window, cur);
	gdk_flush();
}  

/*
 *	Marks editor as ready (opposite affect of EditorSetBusy()).
 */
void EditorSetReady(editor_struct *editor)
{           
	GtkWidget *w;
  
	if(editor == NULL)
	    return;
   
	w = editor->toplevel;
	if(w == NULL)
	    return;
 
	if(GTK_WIDGET_NO_WINDOW(w))
	    return;
 
	gdk_window_set_cursor(w->window, NULL);
	gdk_flush();
}


/*
 *	Creates the menu bar for the editor, this function should be
 *	called by EditorNew().
 *
 *	Given parent is assumed to be a vbox.
 */
static void EditorCreateMenuBar(editor_struct *editor, GtkWidget *parent)
{
	GtkWidget *menu_bar, *parent2, *menu, *w, *fw;
	gint accel_key;
	GtkAccelGroup *accel_grp;
	guint accel_mods;
	gpointer client_data = editor;
	gpointer old_client_data;
	guint8 **icon;
	gchar *label = NULL;
	void (*func_cb)(GtkWidget *w, gpointer);


	/* Create menu bar */
	menu_bar = GUIMenuBarCreate(&accel_grp);
	editor->menu_bar = menu_bar;
	gtk_widget_show(menu_bar);

#define DO_ADD_MENU_ITEM_LABEL		\
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_grp, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  client_data, func_cb \
 ); \
}

#define DO_ADD_MENU_ITEM_SUBMENU	\
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SUBMENU, accel_grp, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  client_data, func_cb \
 ); \
 if(w != NULL) \
  GUIMenuItemSetSubMenu(w, submenu); \
}

#define DO_ADD_MENU_ITEM_CHECK		\
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_CHECK, accel_grp, \
  icon, label, accel_key, accel_mods, (void **)&fw, \
  client_data, func_cb \
 ); \
}

#define DO_ADD_MENU_SEP		\
{ \
 w = GUIMenuItemCreate( \
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL, \
  NULL, NULL, 0, 0, NULL, \
  NULL, NULL \
 ); \
}

	/* Create file menu */
	menu = GUIMenuCreate();
	if(menu != NULL)
	{
	    icon = (guint8 **)icon_new_20x20_xpm;
	    label = "New";
	    accel_key = 'n';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorManualNewCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->new_mi = w;

	    icon = (guint8 **)icon_new_20x20_xpm;
	    label = "New From Template...";
	    accel_key = 't';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorManualNewFromTemplateCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->new_from_template_mi = w;

	    icon = (guint8 **)icon_open_20x20_xpm;
	    label = "Open...";
	    accel_key = 'o';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorManualOpenCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->open_mi = w;

	    icon = (guint8 **)icon_save_20x20_xpm;
	    label = "Save";
	    accel_key = 's';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorManualSaveCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->save_mi = w;

	    icon = (guint8 **)icon_save_as_20x20_xpm;
	    label = "Save As...";
	    accel_key = 'a';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorManualSaveAsCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->save_as_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_close_20x20_xpm;
	    label = "Close Manual";
	    accel_key = 'e';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorManualCloseCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->close_manual_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_revert_20x20_xpm;
	    label = "Revert";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualRevertCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->revert_mi = w;

	    DO_ADD_MENU_SEP

	    /* This closes the editor, not the selected manual page */
	    icon = (guint8 **)icon_close_20x20_xpm;
	    label = "Close";
/*          accel_key = GDK_F4; */
	    accel_key = 'w';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorCloseMCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->close_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_exit_20x20_xpm;
	    label = "Exit";
	    accel_key = 'q';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorCloseAllMCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->exit_mi = w;
	}
	editor->file_mh = GUIMenuAddToMenuBar(
	    menu_bar, menu,
	    "File",
	    GUI_MENU_BAR_ALIGN_LEFT
	);


	/* Create edit menu */
	menu = GUIMenuCreate();
	if(menu != NULL)
	{
	    icon = (guint8 **)icon_undo_20x20_xpm;
	    label = "Undo";
	    accel_key = 'z';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorUndoCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->undo_mi = w;
	    editor->undo_milabel = fw;

	    icon = (guint8 **)icon_redo_20x20_xpm;
	    label = "Redo";
	    accel_key = 'r';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorRedoCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->redo_mi = w;
	    editor->redo_milabel = fw;

	    DO_ADD_MENU_SEP 

	    icon = (guint8 **)icon_cut_20x20_xpm;
	    label = "Cut";
	    accel_key = 'x';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorCutCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->cut_mi = w;

	    icon = (guint8 **)icon_copy_20x20_xpm;
	    label = "Copy";
	    accel_key = 'c';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorCopyCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->copy_mi = w;

	    icon = (guint8 **)icon_paste_20x20_xpm;
	    label = "Paste";
	    accel_key = 'v';
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorPasteCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->paste_mi = w;

	    DO_ADD_MENU_SEP

	    icon = NULL;
	    label = "Select All";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorSelectAllCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->select_all_mi = w;

	    icon = NULL;
	    label = "Unselect All";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorUnselectAllCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->unselect_all_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_search_20x20_xpm;
	    label = "Find In Pages...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorMapFIPCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->find_in_pages_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_options_20x20_xpm;
	    label = "Preferences...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorPreferencesCB;
	    DO_ADD_MENU_ITEM_LABEL
	}
	editor->edit_mh = GUIMenuAddToMenuBar(
	    menu_bar, menu,
	    "Edit",
	    GUI_MENU_BAR_ALIGN_LEFT
	);

	/* View menu */
	menu = GUIMenuCreate();
	if(menu != NULL)
	{
	    icon = (guint8 **)mp_viewer_20x20_xpm;
	    label = "Preview";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualPreviewCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->preview_mi = w;

	    DO_ADD_MENU_SEP

	    icon = NULL;
	    label = "Syntax Highlighting";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualSyntaxHighlightToggleCB;
	    DO_ADD_MENU_ITEM_CHECK
	    editor->syntax_highlight_cmi = w;
	}
	editor->view_mh = GUIMenuAddToMenuBar(
	    menu_bar, menu,
	    "View",
	    GUI_MENU_BAR_ALIGN_LEFT
	);

	/* Layout menu */   
	menu = GUIMenuCreate();
	if(menu != NULL)
	{
	    icon = (guint8 **)icon_add_20x20_xpm;
	    label = "Add Header";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualAddHeaderCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->add_header_mi = w;

	    icon = (guint8 **)icon_add_20x20_xpm; 
	    label = "Add Section";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualAddSectionCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->add_section_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_remove_20x20_xpm;
	    label = "Remove";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualRemoveSectionCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->remove_mi = w;

	    DO_ADD_MENU_SEP
	    
	    icon = (guint8 **)icon_properties2_20x20_xpm;
	    label = "Properties...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualPropertiesCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->properties_mi = w;
	}
	editor->layout_mh = GUIMenuAddToMenuBar(   
	    menu_bar, menu,
	    "Layout",
	    GUI_MENU_BAR_ALIGN_LEFT
	);

	/* Format menu */
	menu = GUIMenuCreate();
	if(menu != NULL)
	{
	    icon = (guint8 **)icon_paragraphl_20x20_xpm;
	    label = "Paragraph Left";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtParagraphLeftCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_pl_mi = w;

	    icon = (guint8 **)icon_paragraphr_20x20_xpm;
	    label = "Paragraph Right";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtParagraphRightCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_pr_mi = w;

	    icon = (guint8 **)icon_paragraphi_20x20_xpm;
	    label = "Paragraph Indented";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtParagraphIndentedCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_pi_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_listitems_20x20_xpm;
	    label = "List Item";
	    accel_key = 0; 
	    accel_mods = 0;
	    func_cb = EditorFmtListItemCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_li_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_bold_20x20_xpm;
	    label = "Bold";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtBoldCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_b_mi = w;

	    icon = (guint8 **)icon_underline_20x20_xpm;
	    label = "Underline";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtUnderlineCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_u_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_break_20x20_xpm;
	    label = "Line Break";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtLineBreakCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_br_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_amp_20x20_xpm;
	    label = "Ampersand";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtAmpersandCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_amp_mi = w;

	    icon = (guint8 **)icon_lessthan_20x20_xpm;
	    label = "Less Than";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtLessThanCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_lt_mi = w;

	    icon = (guint8 **)icon_greaterthan_20x20_xpm;
	    label = "Greater Than";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtGreaterThanCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_gt_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_strip_tags_20x20_xpm;
	    label = "Strip Tags";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorStripTagsCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->fmt_strip_tags_mi = w;
	}
	editor->fmt_mh = GUIMenuAddToMenuBar(   
	    menu_bar, menu,
	    "Tags",
	    GUI_MENU_BAR_ALIGN_LEFT
	);

	/* Create windows menu */
	menu = GUIMenuCreate();
	if(menu != NULL)
	{
	    old_client_data = client_data;
	    client_data = editor->core;

	    icon = (guint8 **)manedit_20x20_xpm;
	    label = "New Editor";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = MEditEditorNewCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->windows_new_editor = w;

	    icon = (guint8 **)mp_viewer_20x20_xpm;
	    label = "New Viewer";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = MEditViewerNewCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->windows_new_viewer = w;

	    client_data = old_client_data;
	}
	editor->windows_mh = GUIMenuAddToMenuBar(
	    menu_bar, menu,
	    "Windows",
	    GUI_MENU_BAR_ALIGN_LEFT
	);

	/* Help menu */
	menu = MEditCreateHelpMenu(
	    (medit_core_struct *)editor->core,
	    accel_grp
	);
	GUIMenuAddToMenuBar(
	    menu_bar, menu,
	    "Help",
	    GUI_MENU_BAR_ALIGN_RIGHT
	);


#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_ITEM_SUBMENU
#undef DO_ADD_MENU_ITEM_CHECK
#undef DO_ADD_MENU_SEP


	/* Handle for menu bar */
	editor->menu_bar_dock = w = gtk_handle_box_new();
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	gtk_container_add(GTK_CONTAINER(parent2), menu_bar);

	/* Attach accel group to toplevel window */
	if((editor->toplevel != NULL) && (accel_grp != NULL))
	{
	    gtk_window_add_accel_group(
		GTK_WINDOW(editor->toplevel), accel_grp
	    );
	}
}

/*
 *	Creates the tool bar for the editor, this function should be
 *	called by EditorNew().
 *
 *	Given parent is assumed to be a vbox.
 */
static void EditorCreateToolBar(editor_struct *editor, GtkWidget *parent)
{
	gboolean show_tooltips = TRUE;
	gint	bw = 25,
		bh = 25,
		mbw = 80,
		mbh = 25,
		sw = 5,
		sh = -1;
	guint accel_key, accel_mods;
	const gchar *label;
	guint8 **icon;
	gpointer combo_rtn, mclient_data;
	GtkAccelGroup *accel_grp;
	GtkWidget *w, *fw, *menu, *parent2, *parent3;
	void (*func_cb)(GtkWidget *w, gpointer);


#define DO_ADD_MENU_ITEM_LABEL {		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_grp,	\
  icon, label, accel_key, accel_mods, (gpointer *)&fw, \
  mclient_data, func_cb				\
 );						\
}
#define DO_ADD_MENU_ITEM_SUBMENU {		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_SUBMENU, accel_grp,	\
  icon, label, accel_key, accel_mods, (gpointer *)&fw, \
  mclient_data, func_cb				\
 );						\
 GUIMenuItemSetSubMenu(w, submenu);		\
}
#define DO_ADD_MENU_ITEM_CHECK {		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_CHECK, accel_grp,	\
  icon, label, accel_key, accel_mods, (gpointer *)&fw, \
  mclient_data, func_cb				\
 );						\
}
#define DO_ADD_MENU_SEP {			\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL,	\
  NULL, NULL, 0, 0, NULL,			\
  NULL, NULL					\
 );						\
}


	/* Handle for tool bar hbox */
	w = gtk_handle_box_new();
	editor->tool_bar_dock = w;
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Tool bar hbox inside handle */
	w = gtk_hbox_new(FALSE, 0);
	editor->tool_bar = w;
	gtk_container_border_width(GTK_CONTAINER(w), 2);
	gtk_container_add(GTK_CONTAINER(parent2), w);
	gtk_widget_show(w);
	parent3 = w;

	/* New menu button */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_new_20x20_xpm, "New", NULL
	);
	editor->new_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "pressed",
	    GTK_SIGNAL_FUNC(EditorButtonMenuMapCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_NEW_MENU_BTN);
	gtk_widget_show(w);

	/* New menu button menu */
	menu = (GtkWidget *)GUIMenuCreate();
	editor->new_btn_new_menu = menu;
	accel_grp = NULL;
	mclient_data = (void *)editor;
	if(menu != NULL)
	{
	    icon = (guint8 **)icon_new_20x20_xpm;
	    label = "New";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualNewCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->new_btn_new_mi = w;

	    icon = (guint8 **)icon_new_20x20_xpm;
	    label = "New From Template...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualNewFromTemplateCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->new_btn_new_from_template_mi = w;
	}
	/* Need to attach basic "hide" signal to menu so we know when
	 * it is unmapped.
	 */
	gtk_signal_connect(
	    GTK_OBJECT(menu), "hide",
	    GTK_SIGNAL_FUNC(EditorMenuHideCB), editor
	);


	/* Open */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_open_20x20_xpm, "Open", NULL
	);
	editor->open_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualOpenCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_OPEN);
	gtk_widget_show(w);

	/* Save */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_save_20x20_xpm, "Save", NULL
	);
	editor->save_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualSaveCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_SAVE);
	gtk_widget_show(w);

	/* Save as */
/*
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_save_as_20x20_xpm, "Save As", NULL
	);
	editor->save_as_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualSaveAsCB), editor
	);
	if(show_tooltips)   
	    GUISetWidgetTip(w, EDITOR_TT_SAVE_AS);
	gtk_widget_show(w);
 */

	/* Separator */
/*
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);
 */
	/* Close manual page */
/*
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_close_20x20_xpm, "Close", NULL
	);
	editor->close_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualCloseCB), editor
	);
	if(show_tooltips)   
	    GUISetWidgetTip(w, EDITOR_TT_CLOSE_MANUAL);
	gtk_widget_show(w);
 */
	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Undo */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_undo_20x20_xpm, "Undo", NULL
	);
	editor->undo_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorUndoCB), editor
	);
	if(show_tooltips)  
	    GUISetWidgetTip(w, EDITOR_TT_UNDO);
	gtk_widget_show(w);

	/* Redo */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_redo_20x20_xpm, "Redo", NULL
	);
	editor->redo_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorRedoCB), editor
	);
	if(show_tooltips)  
	    GUISetWidgetTip(w, EDITOR_TT_REDO);
	gtk_widget_show(w);

	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Cut */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_cut_20x20_xpm, "Cut", NULL
	);
	editor->cut_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorCutCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_CUT);
	gtk_widget_show(w);

	/* Copy */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_copy_20x20_xpm, "Copy", NULL
	);
	editor->copy_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorCopyCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_COPY); 
	gtk_widget_show(w);

	/* Paste */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_paste_20x20_xpm, "Paste", NULL
	);
	editor->paste_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh); 
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorPasteCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_PASTE);
	gtk_widget_show(w);

	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Add header */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_manpage_heading_20x20_xpm, "Header", NULL
	);
	editor->add_header_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualAddHeaderCB), editor
	);
	if(show_tooltips)  
	    GUISetWidgetTip(w, EDITOR_TT_NEW_HEADER);
	gtk_widget_show(w);

	/* Add section */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_manpage_section_20x20_xpm, "Section", NULL
	);
	editor->add_section_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualAddSectionCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_NEW_SECTION);
	gtk_widget_show(w);

	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Remove */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_remove_20x20_xpm, "Remove", NULL
	);
	editor->remove_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualRemoveSectionCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_REMOVE);
	gtk_widget_show(w);

	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Properties */
/*
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)icon_properties2_20x20_xpm, "Properties", NULL
	);
	editor->properties_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualPropertiesCB), editor
	);
	if(show_tooltips)  
	    GUISetWidgetTip(w, EDITOR_TT_PROPERTIES);
	gtk_widget_show(w);
 */

	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Preview */
	w = (GtkWidget *)GUIButtonPixmapLabelV(
	    (guint8 **)mp_viewer_20x20_xpm, "Preview", NULL
	);
	editor->preview_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorManualPreviewCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_PREVIEW);
	gtk_widget_show(w);


	/* ********************************************************** */
	/* Handle for format bar hbox */
	w = gtk_handle_box_new();
	editor->fmt_bar_dock = w;
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Format bar hbox inside handle */
	w = gtk_hbox_new(FALSE, 0);
	editor->fmt_bar = w;
	gtk_container_add(GTK_CONTAINER(parent2), w);
	gtk_container_border_width(GTK_CONTAINER(w), 2);
	gtk_widget_show(w);
	parent3 = w;

	/* Paragraph left */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_paragraphl_20x20_xpm
	);
	editor->fmt_pl_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtParagraphLeftCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_LP);
	gtk_widget_show(w);

	/* Paragraph right */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_paragraphr_20x20_xpm
	);
	editor->fmt_pr_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtParagraphRightCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_RP);
	gtk_widget_show(w);

	/* Paragraph indented */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_paragraphi_20x20_xpm
	);
	editor->fmt_pi_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtParagraphIndentedCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_IP);
	gtk_widget_show(w);

	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* List item */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_listitems_20x20_xpm
	);
	editor->fmt_li_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtListItemCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_LIST);
	gtk_widget_show(w);

	/* Separator */   
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Bold */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_bold_20x20_xpm
	);
	editor->fmt_b_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtBoldCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_BOLD);
	gtk_widget_show(w);

	/* Underlined */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_underline_20x20_xpm
	);
	editor->fmt_u_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtUnderlineCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_UNDERLINE);
	gtk_widget_show(w);

	/* Separator */   
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Break */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_break_20x20_xpm
	);
	editor->fmt_br_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtLineBreakCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_BREAK);
	gtk_widget_show(w);

	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Ampersand */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_amp_20x20_xpm
	);
	editor->fmt_amp_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtAmpersandCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_AMP);
	gtk_widget_show(w);

	/* Less than */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_lessthan_20x20_xpm
	);
	editor->fmt_lt_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtLessThanCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_LT);
	gtk_widget_show(w);

	/* Greater than */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_greaterthan_20x20_xpm
	);
	editor->fmt_gt_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFmtGreaterThanCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_GT);
	gtk_widget_show(w);

	/* Separator */ 
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Strip tags */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_strip_tags_20x20_xpm
	);
	editor->fmt_strip_tags_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorStripTagsCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FMT_STRIP_TAGS);
	gtk_widget_show(w);


	/* ********************************************************** */

	/* Handle for find bar hbox */
	w = gtk_handle_box_new();
	editor->find_bar_dock = w;
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Find bar hbox inside handle */
	w = gtk_hbox_new(FALSE, 0);
	editor->find_bar = w;
	gtk_container_add(GTK_CONTAINER(parent2), w);
	gtk_container_border_width(GTK_CONTAINER(w), 2);
	gtk_widget_show(w);
	parent3 = w;

	/* Find menu button */
	w = (GtkWidget *)GUIButtonPixmapLabelH(
	    (guint8 **)icon_search_20x20_xpm, "Find:", NULL
	);
	editor->find_btn = w;
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_widget_set_usize(w, mbw, mbh);
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "pressed",
	    GTK_SIGNAL_FUNC(EditorButtonMenuMapCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_FIND_MB); 
	gtk_widget_show(w);

	/* Find menu button menu */
	menu = (GtkWidget *)GUIMenuCreate();
	editor->find_bar_find_menu = menu; 
	accel_grp = NULL;
	mclient_data = (void *)editor;
	if(menu != NULL)
	{
	    icon = (guint8 **)icon_search_20x20_xpm;
	    label = "in Pages...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorMapFIPCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->find_bar_find_in_pages_mi = w;
	}
	/* Need to attach basic "hide" signal to menu so we know when
	 * it is unmapped.
	 */
	gtk_signal_connect(
	    GTK_OBJECT(menu), "hide",
	    GTK_SIGNAL_FUNC(EditorMenuHideCB), editor
	);

	/* Find combo */
	w = (GtkWidget *)GUIComboCreate(
	    NULL,		/* Label */
	    NULL,		/* Initial text value */
	    NULL,		/* Initial glist of items */
	    20,			/* Max items */
	    &combo_rtn,		/* Combo widget return */
	    editor,
	    EditorFindBarFindActivateCB,
	    NULL
	);
	editor->find_combo = (GtkWidget *)combo_rtn;
	gtk_combo_set_case_sensitive(
	    (GtkCombo *)combo_rtn,
	    TRUE
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	if(show_tooltips)
	    GUISetWidgetTip(GTK_COMBO(combo_rtn)->entry, EDITOR_TT_FIND);
	gtk_widget_show(w);

	/* Separator */
	w = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, sw, sh);
	gtk_widget_show(w);

	/* Replace menu button */
	w = (GtkWidget *)GUIButtonPixmapLabelH(
	    (guint8 **)icon_replace_20x20_xpm, "Replace:", NULL
	);
	editor->replace_btn = w;
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_widget_set_usize(w, mbw, mbh);
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "pressed",
	    GTK_SIGNAL_FUNC(EditorButtonMenuMapCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_REPLACE_MB);
	gtk_widget_show(w);

	/* Replace menu button menu */
	menu = (GtkWidget *)GUIMenuCreate();
	editor->find_bar_replace_menu = menu;
	accel_grp = NULL;
	mclient_data = (void *)editor;
	if(menu != NULL)
	{
	    icon = (guint8 **)icon_replace_all_20x20_xpm;
	    label = "through Entire Page";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFindBarReplaceEntirePageCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->find_bar_replace_entire_page_mi = w;
	}
	/* Need to attach basic "hide" signal to menu so we know when
	 * it is unmapped.
	 */
	gtk_signal_connect(
	    GTK_OBJECT(menu), "hide",
	    GTK_SIGNAL_FUNC(EditorMenuHideCB), editor
	);

	/* Replace combo */
	w = (GtkWidget *)GUIComboCreate(
	    NULL,		/* Label */
	    NULL,		/* Initial text value */
	    NULL,		/* Initial glist of items */
	    20,			/* Max items */
	    &combo_rtn,		/* Combo widget return */
	    editor, EditorFindBarReplaceActivateCB,
	    NULL
	);
	editor->replace_combo = (GtkWidget *)combo_rtn;
	gtk_combo_set_case_sensitive(
	    (GtkCombo *)combo_rtn,
	    TRUE
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	if(show_tooltips)
	    GUISetWidgetTip(GTK_COMBO(combo_rtn)->entry, EDITOR_TT_REPLACE);
	gtk_widget_show(w);

	/* Replace all */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)icon_replace_all_20x20_xpm
	);
	editor->replace_all_btn = w;
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, bw, bh);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EditorFindBarReplaceAllCB), editor
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, EDITOR_TT_REPLACE_ALL);
	gtk_widget_show(w);




#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_ITEM_SUBMENU
#undef DO_ADD_MENU_ITEM_CHECK
#undef DO_ADD_MENU_SEP
}

/*
 *	Creates the status bar for the editor, this function should be
 *	called by EditorNew().
 *
 *	Given parent is assumed to be a vbox.
 */
static void EditorCreateStatusBar(
	editor_struct *editor, GtkWidget *parent
)
{
	GtkWidget *w, *parent2, *parent3;
	GtkAdjustment *adj;
	gboolean show_tooltips = TRUE;


	/* Main hbox for status bar and window map buttons */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent = w;

	/* Handle for status bar */
	w = gtk_handle_box_new();
	editor->status_bar_dock = w;
	gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Toplevel hbox inside dock */
	w = gtk_hbox_new(FALSE, 0);
	editor->status_bar_toplevel = w;
	gtk_container_add(GTK_CONTAINER(parent2), w);
	gtk_widget_show(w);
	parent2 = w;

	/* Main frame in toplevel */
	w = gtk_frame_new(NULL);
	gtk_widget_set_usize(w, -1, 25);
	gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_OUT);
	gtk_container_border_width(GTK_CONTAINER(w), 0);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Table in main frame */
	w = gtk_table_new(1, 3, FALSE);
	gtk_container_add(GTK_CONTAINER(parent2), w);
	gtk_widget_show(w);
	parent2 = w;


	/* Progress bar */
	adj = (GtkAdjustment *)gtk_adjustment_new(0, 1, 100, 0, 0, 0);
	w = gtk_progress_bar_new_with_adjustment(adj);
	editor->status_bar_progress = w;
	gtk_widget_set_usize(w, 100, -1);
	gtk_progress_bar_set_orientation(
	    GTK_PROGRESS_BAR(w), GTK_PROGRESS_LEFT_TO_RIGHT
	);
	gtk_progress_bar_set_bar_style(
	    GTK_PROGRESS_BAR(w), GTK_PROGRESS_CONTINUOUS
	);
	gtk_progress_set_activity_mode(
	    GTK_PROGRESS(w), FALSE
	);
	gtk_table_attach(
	    GTK_TABLE(parent2), w,
	    0, 1, 0, 1,
	    0,
	    GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_widget_show(w);


	/* Label */
	w = gtk_frame_new(NULL);
	gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_IN);
	gtk_container_border_width(GTK_CONTAINER(w), 1);
	gtk_table_attach(
	    GTK_TABLE(parent2), w,
	    1, 2, 0, 1,
	    GTK_SHRINK | GTK_EXPAND | GTK_FILL,
	    GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_widget_show(w);
	parent3 = w;

	w = gtk_hbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(parent3), w);
	gtk_widget_show(w);
	parent3 = w;

	w = gtk_label_new("");
	editor->status_bar_label = w;
	gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 2);
	gtk_widget_show(w);


	/* Cursor position label */
	w = gtk_frame_new(NULL);
	gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_IN);
	gtk_container_border_width(GTK_CONTAINER(w), 1);
	gtk_table_attach(
	    GTK_TABLE(parent2), w,
	    2, 3, 0, 1,
	    GTK_SHRINK | GTK_FILL,
	    GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_widget_show(w);
	parent3 = w;

	w = gtk_hbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(parent3), w);
	gtk_widget_show(w);
	parent3 = w;

	w = gtk_label_new("");
	editor->status_bar_cursor_label = w;
	gtk_widget_set_usize(w, 100, -1);
	gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 2);
	gtk_widget_show(w);



	/* Handle bar for window map buttons */
	w = gtk_handle_box_new();
/*	editor->window_map_dock = w; */
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Main frame in toplevel */
	w = gtk_frame_new(NULL);
	gtk_widget_set_usize(w, -1, 25);
	gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_OUT);
	gtk_container_border_width(GTK_CONTAINER(w), 0);
	gtk_container_add(GTK_CONTAINER(parent2), w);
	gtk_widget_show(w);
	parent2 = w;

	/* Hbox for window map buttons */
	w = gtk_hbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(parent2), w); 
	gtk_widget_show(w);
	parent2 = w;

	/* Window map buttons */
	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)manedit_16x16_xpm
	);
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, 25, -1);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(MEditEditorNewCB), editor->core
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, MEDIT_SB_TT_NEW_EDITOR);
	gtk_widget_show(w);

	w = (GtkWidget *)GUIButtonPixmap(
	    (guint8 **)mp_viewer_16x16_xpm
	);
	gtk_button_set_relief(GTK_BUTTON(w), GTK_RELIEF_NONE);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, 25, -1);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(MEditViewerNewCB), editor->core
	);
	if(show_tooltips)
	    GUISetWidgetTip(w, MEDIT_SB_TT_NEW_VIEWER);
	gtk_widget_show(w);
}

/*
 *	Creates a new editor structure with its values reset and widgets
 *	built or NULL on error.
 */
editor_struct *EditorNew(gpointer core_ptr)
{
	gint i, header_label_width;
	guint accel_key, accel_mods;
	gpointer entry_rtn;
	GdkColormap *colormap;
	GtkAccelGroup *accel_grp;
	GtkWidget	*w, *fw, *menu, *submenu,
			*parent, *parent2, *parent3, *parent4,
			*parent5,
			*scroll_parent;
	GtkStyle *style_ptr;
	GtkCList *clist;
	const gchar *label;
	guint8 **icon;
	gpointer mclient_data;
	void (*func_cb)(GtkWidget *w, gpointer);
	gchar *title[1];
	medit_cursors_list_struct *cursors_list = NULL;
	medit_styles_list_struct *styles_list = NULL;
	pref_struct *pref = NULL;
	const GtkTargetEntry dnd_tar_types[] = {
{"text/plain",				0,	MEDIT_DND_TYPE_INFO_TEXT_PLAIN},
{"text/uri-list",			0,	MEDIT_DND_TYPE_INFO_TEXT_URI_LIST},
{"STRING",				0,	MEDIT_DND_TYPE_INFO_STRING},
{MEDIT_DND_TARGET_EDITOR_BRANCH,	GTK_TARGET_SAME_APP,
						MEDIT_DND_TYPE_INFO_EDITOR_BRANCH_CMD},
{MEDIT_DND_TARGET_VIEWER_BRANCH,	GTK_TARGET_SAME_APP,
					MEDIT_DND_TYPE_INFO_VIEWER_BRANCH_CMD}
	};
	const GtkTargetEntry dnd_src_types[] = {
{MEDIT_DND_TARGET_EDITOR_BRANCH,	GTK_TARGET_SAME_APP,
					MEDIT_DND_TYPE_INFO_EDITOR_BRANCH_CMD}
	};
	medit_core_struct *core = MEDIT_CORE(core_ptr);
	editor_struct *editor = EDITOR(g_malloc0(
	    sizeof(editor_struct)
	));
	if(editor == NULL)
	    return(NULL);

	if(core == NULL)
	{
	    g_free(editor);
	    return(NULL);
	}

	cursors_list = &core->cursors_list;
	styles_list = &core->styles_list;
	pref = core->pref;

	editor->freeze_count = 0;
	editor->busy_count = 0;
	editor->syntax_highlighting = PrefParmGetValueB(
	    core->pref,
	    MEDIT_PREF_PARM_EDITOR_ENABLE_SYNHL
	);

	editor->core = core;
	editor->viewer_num = -1;

	editor->synhl_timeout_cb_id = 0;
	editor->synhl_timeout_cb_cursor_pos = -1;
	editor->synhl_timeout_cb_start_pos = -1;
	editor->synhl_timeout_cb_end_pos = -1;

	editor->last_open_path = NULL;
	editor->last_save_as_path = NULL;



#define DO_ADD_MENU_ITEM_LABEL	{		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_LABEL, accel_grp,	\
  icon, label, accel_key, accel_mods, (gpointer *)&fw,	\
  mclient_data, func_cb				\
 );						\
}
#define DO_ADD_MENU_ITEM_SUBMENU {		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_SUBMENU, accel_grp,\
  icon, label, accel_key, accel_mods, (gpointer *)&fw,	\
  mclient_data, func_cb				\
 );						\
 GUIMenuItemSetSubMenu(w, submenu);		\
}
#define DO_ADD_MENU_ITEM_CHECK {		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_CHECK, accel_grp,	\
  icon, label, accel_key, accel_mods, (gpointer *)&fw,	\
  mclient_data, func_cb				\
 );						\
}
#define DO_ADD_MENU_SEP	{			\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL,	\
  NULL, NULL, 0, 0, NULL,			\
  NULL, NULL					\
 );						\
}

	/* Toplevel */
	editor->toplevel = w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_widget_set_events(w,
	    GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK
	);
	gtk_signal_connect(  
	    GTK_OBJECT(w), "key_press_event",
	    GTK_SIGNAL_FUNC(EditorKeyEventCB), editor
	);
	gtk_signal_connect(   
	    GTK_OBJECT(w), "key_release_event",
	    GTK_SIGNAL_FUNC(EditorKeyEventCB), editor
	);
	gtk_widget_realize(w);
	GUISetWMIcon(w->window, (guint8 **)manedit_48x48_xpm);
	if(PrefParmGetValueB(pref, MEDIT_PREF_PARM_RECORD_WIN_POS))
	{
	    /* TRUE implies pref is also valid */
	    gtk_widget_set_usize(
		w,
		MAX(pref->last_editor_width, 256),
		MAX(pref->last_editor_height, 256)
	    );
	}
	else
	{
	    gtk_widget_set_usize(
		w,
		MEDIT_DEF_WIDTH, MEDIT_DEF_HEIGHT
	    );
	}
	gtk_window_set_policy(
	    GTK_WINDOW(w), 
	    TRUE, TRUE, FALSE
	);
	if((pref != NULL) && !GTK_WIDGET_NO_WINDOW(w))
	{
	    GdkGeometry geometry;

	    geometry.min_width = 100;
	    geometry.min_height = 70;

	    geometry.base_width = 0;
	    geometry.base_height = 0;

	    geometry.width_inc = 1;
	    geometry.height_inc = 1;
/*
	    geometry.min_aspect = 1.3;
	    geometry.max_aspect = 1.3;
 */
	    gdk_window_set_geometry_hints(
		w->window,
		&geometry,
		GDK_HINT_MIN_SIZE |
		GDK_HINT_BASE_SIZE |
		/* GDK_HINT_ASPECT | */
		GDK_HINT_RESIZE_INC
	    );
	}
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(EditorCloseCB), editor
	);
	parent = w;

	/* Main GtkVBox */
	editor->main_vbox = w = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(parent), w);
	gtk_widget_show(w);
	parent = w;


	/* Menu bar */
	EditorCreateMenuBar(editor, editor->main_vbox);

	/* Tool bar */
	EditorCreateToolBar(editor, editor->main_vbox);


	/* Paned */
	w = gtk_hpaned_new();
	gtk_paned_set_handle_size(GTK_PANED(w), MEDIT_DEF_PANED_HANDLE_SIZE);
	gtk_paned_set_gutter_size(GTK_PANED(w), MEDIT_DEF_PANED_GUTTER_SIZE);
	gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, 0);
	gtk_paned_set_position(GTK_PANED(w), 200);
	gtk_widget_show(w);
	parent2 = w;


	/* Vbox for layout ctree */
	w = gtk_vbox_new(FALSE, 0);
	gtk_paned_add1(GTK_PANED(parent2), w);
	gtk_widget_show(w);
	parent3 = w;

	/* Layout ctree */
	w = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(
	    GTK_SCROLLED_WINDOW(w),
	    GTK_POLICY_AUTOMATIC,
	    GTK_POLICY_AUTOMATIC
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	scroll_parent = w;

	title[0] = "Layout";
	w = gtk_ctree_new_with_titles(
	    1, 0, title
	);
	clist = (GtkCList *)w;
	editor->layout_ctree = w;
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EditorMenuMapCB), editor
	);
	gtk_clist_column_titles_passive(clist);
	gtk_clist_column_titles_hide(clist);
	gtk_clist_set_row_height(clist, MEDIT_LIST_ROW_SPACING);
	gtk_clist_set_shadow_type(clist, GTK_SHADOW_IN);
	gtk_container_add(GTK_CONTAINER(scroll_parent), w);
	gtk_signal_connect(
	    GTK_OBJECT(w), "tree_select_row",
	    GTK_SIGNAL_FUNC(EditorLayoutCTreeSelectCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "tree_unselect_row",
	    GTK_SIGNAL_FUNC(EditorLayoutCTreeUnselectCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "tree_expand",
	    GTK_SIGNAL_FUNC(EditorLayoutCTreeExpandCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "tree_collapse",
	    GTK_SIGNAL_FUNC(EditorLayoutCTreeExpandCB), editor
	);
	/* Set up DND for the layout ctree */
	GUIDNDSetSrc(
	    w,
	    dnd_src_types,
	    sizeof(dnd_src_types) / sizeof(GtkTargetEntry),
	    GDK_ACTION_COPY | GDK_ACTION_MOVE,  /* Actions */
	    GDK_BUTTON1_MASK,			/* Buttons */
	    NULL,
	    EditorDNDDataRequestCB,
	    EditorDNDDataDeleteCB,
	    NULL,
	    editor
	);
	GUIDNDSetTar(
	    w,
	    dnd_tar_types,
	    sizeof(dnd_tar_types) / sizeof(GtkTargetEntry),
	    GDK_ACTION_COPY | GDK_ACTION_MOVE,  /* Actions */
	    GDK_ACTION_MOVE,                    /* Default action if same */
	    GDK_ACTION_COPY,                    /* Default action */
	    EditorDNDDataRecievedCB,
	    editor
	);
	gtk_widget_show(w);


	/* Layout ctree right click menu */
	menu = (GtkWidget *)GUIMenuCreate();
	editor->layout_menu = menu;
	accel_grp = NULL;
	mclient_data = (void *)editor;

	if(menu != NULL)
	{
	    icon = NULL;
	    label = "Expand/Collapse";
	    accel_key = 0; 
	    accel_mods = 0;
	    func_cb = EditorLayoutCTreeDoExpandCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_expand_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)mp_viewer_20x20_xpm;
	    label = "Preview";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualPreviewCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_preview_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_add_20x20_xpm;
	    label = "New Header";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualAddHeaderCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_add_header_mi = w;

	    icon = (guint8 **)icon_add_20x20_xpm;
	    label = "New Section";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualAddSectionCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_add_section_mi = w;

	    icon = (guint8 **)icon_remove_20x20_xpm;
	    label = "Remove";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualRemoveSectionCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_remove_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_properties2_20x20_xpm;
	    label = "Properties...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualPropertiesCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_properties_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_new_20x20_xpm;
	    label = "New";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualNewCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_new_manual_mi = w;

	    icon = (guint8 **)icon_new_20x20_xpm;
	    label = "New From Template...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualNewFromTemplateCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_new_from_template_mi = w;

	    icon = (guint8 **)icon_open_20x20_xpm;
	    label = "Open...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualOpenCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_open_mi = w;

	    icon = (guint8 **)icon_save_20x20_xpm;
	    label = "Save";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualSaveCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_save_mi = w;

	    icon = (guint8 **)icon_save_as_20x20_xpm;
	    label = "Save As...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualSaveAsCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_save_as_mi = w;

	    DO_ADD_MENU_SEP
	
	    icon = (guint8 **)icon_close_20x20_xpm;
	    label = "Close Manual";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualCloseCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_close_manual_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_revert_20x20_xpm;
	    label = "Revert";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorManualRevertCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->layout_menu_revert_mi = w;
	}


	/* ********************************************************** */
	/* Right panel side vbox */
	w = gtk_vbox_new(FALSE, 0);
	gtk_paned_add2(GTK_PANED(parent2), w);
	gtk_widget_show(w);
	parent2 = w;


	/* File editing panel */
	i = EditorItemTypeFile;

	w = gtk_vbox_new(FALSE, 0);
	editor->edit_panel_vbox[i] = w;
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, 5);
	parent3 = w;




	/* Header editing panel */
	i = EditorItemTypeHeader;

	w = gtk_vbox_new(FALSE, 0);
	editor->edit_panel_vbox[i] = w;
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, 5);
	parent3 = w;


	/* Begin creating header prompts */
	header_label_width = 100;

	/* Header name entry */
	w = gtk_hbox_new(FALSE, 2);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Label alignment and label */
	w = gtk_alignment_new(1.0, 0.5, 0.0, 0.0);
	gtk_widget_set_usize(w, header_label_width, -1);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent5 = w;
	w = gtk_label_new("Name:");
	gtk_container_add(GTK_CONTAINER(parent5), w);
	gtk_widget_show(w);
	/* Entry */
	w = gtk_entry_new_with_max_length(256);
	editor->header_name_entry = w;
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_widget_show(w);

	/* Header section number entry */
	w = gtk_hbox_new(FALSE, 2);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Label alignment and label */
	w = gtk_alignment_new(1.0, 0.5, 0.0, 0.0);
	gtk_widget_set_usize(w, header_label_width, -1);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent5 = w;
	w = gtk_label_new("Section Number:");
	gtk_container_add(GTK_CONTAINER(parent5), w);
	gtk_widget_show(w);
	/* Entry */
	w = gtk_entry_new_with_max_length(256);
	editor->header_section_number_entry = w;
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_widget_show(w);

	/* Header version entry */
	w = gtk_hbox_new(FALSE, 2);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Label alignment and label */
	w = gtk_alignment_new(1.0, 0.5, 0.0, 0.0);
	gtk_widget_set_usize(w, header_label_width, -1);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent5 = w;
	w = gtk_label_new("Version:");
	gtk_container_add(GTK_CONTAINER(parent5), w);
	gtk_widget_show(w);
	/* Entry */
	w = gtk_entry_new_with_max_length(256);
	editor->header_version_entry = w;
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_widget_show(w);

	/* Header author entry */
	w = gtk_hbox_new(FALSE, 2);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Label alignment and label */
	w = gtk_alignment_new(1.0, 0.5, 0.0, 0.0);
	gtk_widget_set_usize(w, header_label_width, -1);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent5 = w;
	w = gtk_label_new("Author:");
	gtk_container_add(GTK_CONTAINER(parent5), w);
	gtk_widget_show(w);
	/* Entry */
	w = gtk_entry_new_with_max_length(256);
	editor->header_author_entry = w;
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_widget_show(w);

	/* Header category entry */
	w = gtk_hbox_new(FALSE, 2);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Label alignment and label */
	w = gtk_alignment_new(1.0, 0.5, 0.0, 0.0);
	gtk_widget_set_usize(w, header_label_width, -1);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent5 = w;
	w = gtk_label_new("Category:");
	gtk_container_add(GTK_CONTAINER(parent5), w);
	gtk_widget_show(w);
	/* Entry */
	w = gtk_entry_new_with_max_length(256);
	editor->header_catagory_entry = w;
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_widget_show(w);

	/* Separator (add 5 pixel extra vertical padding on each side) */
	w = gtk_hseparator_new();
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 5);
	gtk_widget_show(w);

	/* Vbox to hold a separator and widgets for text */
	w = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* Hbox for comments label */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 2);
	gtk_widget_show(w);
	parent5 = w;

	w = gtk_label_new("Comments:");
	gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 2);
	gtk_widget_show(w);


	/* Hbox for table */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent5 = w;

	/* Table for text and scroll bar widgets */
	w = gtk_table_new(2, 2, FALSE);
	gtk_table_set_row_spacing(GTK_TABLE(w), 0, 2);
	gtk_table_set_col_spacing(GTK_TABLE(w), 0, 2);
	gtk_box_pack_start(GTK_BOX(parent5), w, TRUE, TRUE, 2);
	gtk_widget_show(w);
	parent5 = w;

	editor->header_text = w = gtk_text_new(NULL, NULL);
	/* Need to connect button_press_event signal_after just
	 * after text widget is created, this is so that the right
	 * click menu can be mapped properly.
	 */
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "key_press_event",
	    GTK_SIGNAL_FUNC(EditorTextKeyEventCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EditorTextButtonEventCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_release_event",
	    GTK_SIGNAL_FUNC(EditorTextButtonEventCB), editor
	);
	gtk_text_set_editable(GTK_TEXT(w), TRUE);
	gtk_text_set_word_wrap(GTK_TEXT(w), TRUE);
	gtk_table_attach(
	    GTK_TABLE(parent5), w,
	    0, 1, 0, 1,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EditorTextChangeCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "insert_text",
	    GTK_SIGNAL_FUNC(EditorTextInsertCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_text",
	    GTK_SIGNAL_FUNC(EditorTextDeleteCB), editor
	);
	gtk_widget_realize(w);
	if(cursors_list != NULL)
	    gdk_window_set_cursor(w->window, cursors_list->text);
	gtk_widget_show(w);

	scroll_parent = gtk_vscrollbar_new(GTK_TEXT(w)->vadj);
	gtk_table_attach(
	    GTK_TABLE(parent5), scroll_parent,
	    1, 2, 0, 1,
	    GTK_FILL,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_widget_show(scroll_parent);




	/* Section editing panel */
	i = EditorItemTypeSection;

	w = gtk_vbox_new(FALSE, 0);
	editor->edit_panel_vbox[i] = w;
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, 0);
	parent3 = w;


	/* Section name entry */
	w = (GtkWidget *)GUIPromptBar(
	    NULL, "Section:", NULL, &entry_rtn
	);
	editor->section_name_entry = (GtkWidget *)entry_rtn;
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 2);
	gtk_widget_show(w);


	/* Text box */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, 2);
	gtk_widget_show(w);
	parent4 = w;

	w = gtk_table_new(2, 2, FALSE);
	gtk_table_set_row_spacing(GTK_TABLE(w), 0, 2);
	gtk_table_set_col_spacing(GTK_TABLE(w), 0, 2);
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 2);
	gtk_widget_show(w);
	parent4 = w; 

	editor->section_text = w = gtk_text_new(NULL, NULL);
	/* Need to connect button_press_event signal_after just
	 * after text widget is created, this is so that the right
	 * click menu can be mapped properly.   
	 */
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "key_press_event",
	    GTK_SIGNAL_FUNC(EditorTextKeyEventCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EditorTextButtonEventCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_release_event",
	    GTK_SIGNAL_FUNC(EditorTextButtonEventCB), editor
	);
	gtk_text_set_editable(GTK_TEXT(w), TRUE);
	gtk_text_set_word_wrap(GTK_TEXT(w), TRUE);
	gtk_table_attach(
	    GTK_TABLE(parent4), w,
	    0, 1, 0, 1,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EditorTextChangeCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "insert_text",
	    GTK_SIGNAL_FUNC(EditorTextInsertCB), editor
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_text",
	    GTK_SIGNAL_FUNC(EditorTextDeleteCB), editor
	);
	gtk_widget_realize(w);
	if(cursors_list != NULL)
	    gdk_window_set_cursor(w->window, cursors_list->text);

	/* Create a new style for the GtkText, because we may want to
	 * adjust the style later on.
	 */
	if(GTK_WIDGET_NO_WINDOW(w))
	    colormap = NULL;
	else
	    colormap = gdk_window_get_colormap(w->window);
	style_ptr = gtk_widget_get_style(w);
	style_ptr = ((style_ptr == NULL) ?
	    NULL : gtk_style_copy(style_ptr)
	);
	if(style_ptr != NULL)
	{
	    GtkStyle *style_src_ptr;

	    /* Set base color */
	    style_src_ptr = styles_list->edit_text_background;
	    if((style_src_ptr != NULL) && (colormap != NULL))
	    {
		style_ptr->base[GTK_STATE_NORMAL] =
		    style_src_ptr->base[GTK_STATE_NORMAL];
		gdk_color_alloc(
		    colormap,
		    &style_ptr->base[GTK_STATE_NORMAL]
		);
	    }

	    style_src_ptr = styles_list->edit_text_standard;
	    if(style_src_ptr != NULL)
	    {
		if(style_ptr->font != NULL)
		    gdk_font_unref(style_ptr->font);
		style_ptr->font = style_src_ptr->font;
		if(style_ptr->font != NULL)
		    gdk_font_ref(style_ptr->font);
	    }

	    gtk_widget_set_style(w, style_ptr);
	}
	gtk_widget_show(w);

	scroll_parent = gtk_vscrollbar_new(GTK_TEXT(w)->vadj);
	gtk_table_attach(
	    GTK_TABLE(parent4), scroll_parent,
	    1, 2, 0, 1,
	    GTK_FILL,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_widget_show(scroll_parent);


	/* ************************************************************ */

	/* Editing panels right click tags submenu */
	submenu = menu = (GtkWidget *)GUIMenuCreate();
	editor->edit_panel_fmt_sub_menu = submenu;
	accel_grp = NULL;
	mclient_data = editor;

	if(menu != NULL)
	{
	    icon = (guint8 **)icon_paragraphl_20x20_xpm;
	    label = "Paragraph Left";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtParagraphLeftCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_pl_mi = w;

	    icon = (guint8 **)icon_paragraphr_20x20_xpm;
	    label = "Paragraph Right";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtParagraphRightCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_pr_mi = w;
	    
	    icon = (guint8 **)icon_paragraphi_20x20_xpm;
	    label = "Paragraph Indented";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtParagraphIndentedCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_pi_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_listitems_20x20_xpm;
	    label = "List Item";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtListItemCB; 
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_li_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_bold_20x20_xpm;
	    label = "Bold";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtBoldCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_b_mi = w;

	    icon = (guint8 **)icon_underline_20x20_xpm;
	    label = "Underline";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtUnderlineCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_u_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_break_20x20_xpm;
	    label = "Line Break"; 
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtLineBreakCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_br_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_amp_20x20_xpm;
	    label = "Ampersand";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtAmpersandCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_amp_mi = w;

	    icon = (guint8 **)icon_lessthan_20x20_xpm;
	    label = "Less Than";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtLessThanCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_lt_mi = w;

	    icon = (guint8 **)icon_greaterthan_20x20_xpm;
	    label = "Greater Than";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorFmtGreaterThanCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_gt_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_strip_tags_20x20_xpm;
	    label = "Strip Tags";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorStripTagsCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_fmt_strip_tags_mi = w;
	}


	/* Editing panels right click menu */
	menu = (GtkWidget *)GUIMenuCreate();
	editor->edit_panel_menu = menu;
	accel_grp = NULL;
	mclient_data = (void *)editor;

	if(menu != NULL)
	{
	    icon = (guint8 **)icon_undo_20x20_xpm;
	    label = "Undo";
	    accel_key = GDK_BackSpace;
	    accel_mods = GDK_CONTROL_MASK;
	    func_cb = EditorUndoCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_undo_mi = w;
	    editor->edit_panel_undo_milabel = fw;

	    icon = (guint8 **)icon_redo_20x20_xpm;
	    label = "Redo"; 
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorRedoCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_redo_mi = w;
	    editor->edit_panel_redo_milabel = fw;

	    DO_ADD_MENU_SEP 

	    /* Format sub menu */
	    icon = NULL;
	    label = "Tags";
	    accel_key = 0; 
	    accel_mods = 0;
	    func_cb = NULL;
	    /* Variable submenu already set */
	    DO_ADD_MENU_ITEM_SUBMENU

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_cut_20x20_xpm;
	    label = "Cut";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorCutCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_cut_mi = w;

	    icon = (guint8 **)icon_copy_20x20_xpm;
	    label = "Copy";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorCopyCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_copy_mi = w;

	    icon = (guint8 **)icon_paste_20x20_xpm;
	    label = "Paste";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorPasteCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_paste_mi = w;

	    DO_ADD_MENU_SEP

	    icon = NULL;
	    label = "Select All";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorSelectAllCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_select_all_mi = w;

	    icon = NULL;
	    label = "Unselect All";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EditorUnselectAllCB;
	    DO_ADD_MENU_ITEM_LABEL
	    editor->edit_panel_unselect_all_mi = w;
	}





	/* Create status bar */
	EditorCreateStatusBar(editor, editor->main_vbox);

	/* Create editor Find In Page dialog */
	editor->fip_dlg = EditorFIPNew(core, editor);


#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_ITEM_SUBMENU
#undef DO_ADD_MENU_ITEM_CHECK
#undef DO_ADD_MENU_SEP

	/* Reset the values to defaults */
	EditorReset(editor, FALSE);

	/* Update menus */
	EditorUpdateMenus(editor);

	return(editor);
}

/*
 *	Updates all menus on editor.
 */
void EditorUpdateMenus(editor_struct *editor)
{
	GtkWidget *w, *menu;
	medit_core_struct *core;
	gboolean sensitivity, state, sel_manual_has_changes;
	GtkCTreeRow *branch_row;
	editor_item_struct *item;
	gchar *sel_file_name = NULL;
	gint toolbar_btn_layout = 2;

	if(editor == NULL)
	    return;

	editor->freeze_count++;

	core = editor->core;

#define SET_WIDGET_SENSITIVITY	{		\
 if(w != NULL)					\
  gtk_widget_set_sensitive(w, sensitivity);	\
}

#define SET_CHECK_MENU_ITEM_STATE	{	\
 GUIMenuItemSetCheck(w, state, TRUE);		\
}

#define SET_BUTTON_LAYOUT	{		\
 if(w != NULL) {				\
  switch(toolbar_btn_layout) {			\
   case 2:					\
    GUIButtonChangeLayout(w, 1, 1);		\
    gtk_widget_set_usize(w, 60, 50);		\
    break;					\
   case 1:					\
    GUIButtonChangeLayout(w, 1, 0);		\
    gtk_widget_set_usize(w, 30, 30);		\
    break;					\
   default:					\
    GUIButtonChangeLayout(w, 0, 1);		\
    gtk_widget_set_usize(w, -1, 30);		\
    break;					\
  }						\
 }						\
}

	/* Check if the selected branch's manual page (if any) has
	 * changes
	 *
	 * If none is selected then sel_manual_has_changes will be
	 * FALSE
	 */
	sel_manual_has_changes = FALSE;
	if(editor->selected_branch != NULL)
	{
	    GtkCTreeNode *node, *next_node;
	    GtkCTree *ctree = GTK_CTREE(editor->layout_ctree);

	    /* Get toplevel node starting from selected branch node */
	    for(
		node = editor->selected_branch;
		node != NULL;
		
	    )
	    {
		next_node = GTK_CTREE_ROW(node)->parent;
		if(next_node != NULL)
		    node = next_node;
		else
		    break;
	    }
	    if(node != NULL)
	    {
		item = EditorBranchGetData(ctree, node);
		if((item != NULL) ?
		    (item->type == EditorItemTypeFile) : FALSE
		)
		{
		    if(item->has_changes)
			sel_manual_has_changes = TRUE;

		    /* Here's a good time to get the name */
		    sel_file_name = item->name;
		}
	    }
	}

	/* Get tool bar button display type */
	if(PrefParmGetValueB(
	    core->pref, MEDIT_PREF_PARM_TOOLBAR_PT
	))
	    toolbar_btn_layout = 2;
	else if(PrefParmGetValueB(
	    core->pref, MEDIT_PREF_PARM_TOOLBAR_P
	))
	    toolbar_btn_layout = 1;
	else
 	    toolbar_btn_layout = 0;


	/* Update title */
	w = editor->toplevel;
	if(w != NULL)
	{
	    if(sel_file_name == NULL)
	    {
		gtk_window_set_title(GTK_WINDOW(w), PROG_NAME);
	    }
	    else
	    {
		gchar *title = g_strdup_printf(
		    "%s: %s%s",
		    PROG_NAME, sel_file_name,
		    (sel_manual_has_changes) ? " (*)" : ""
		);
		gtk_window_set_title(GTK_WINDOW(w), title);
		g_free(title);
	    }
	}


	/* File menu */
	menu = editor->file_mh;
	if(menu != NULL)
	{
	    w = editor->open_mi;
	    sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY

	    w = editor->save_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity)
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY

	    w = editor->save_as_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity)
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY

	    /* Revert enable only if entire manual has changes */
	    w = editor->revert_mi;
	    sensitivity = sel_manual_has_changes;
	    SET_WIDGET_SENSITIVITY

	    w = editor->close_manual_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity) 
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY
	}

	/* Edit menu */
	menu = editor->edit_mh;
	if(menu != NULL)
	{
	    editor_undo_common_struct *u_common;

	    w = editor->undo_mi;
	    sensitivity = ((editor->total_undos > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->undo_milabel;
	    if(w != NULL)
	    {
		if(editor->total_undos > 0)
		{
		    u_common = (editor_undo_common_struct *)editor->undo[0];
		    if((u_common != NULL) ?
			(u_common->comment != NULL) : FALSE
		    )       
		    {
			gchar *buf = g_strdup_printf(
			    "Undo %s (%i)",
			    u_common->comment, editor->total_undos
			);
			gtk_label_set_text(GTK_LABEL(w), buf);
			g_free(buf);
		    }
		}
		else
		{
		    gtk_label_set_text(GTK_LABEL(w), "Undo");
		}
	    }


	    w = editor->redo_mi;
	    sensitivity = ((editor->total_redos > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->redo_milabel;
	    if(w != NULL)
	    {
		if(editor->total_redos > 0)
		{
		    u_common = (editor_undo_common_struct *)editor->redo[0];
		    if((u_common != NULL) ?
			(u_common->comment != NULL) : FALSE
		    )
		    {
			gchar *buf = g_strdup_printf(
			    "Redo %s (%i)",
			    u_common->comment, editor->total_redos
			);
			gtk_label_set_text(GTK_LABEL(w), buf);
			g_free(buf);
		    }
		}
		else
		{
		    gtk_label_set_text(GTK_LABEL(w), "Redo");
		}
	    }

	    w = editor->cut_mi;
	    sensitivity = ((editor->selected_branch != NULL) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->copy_mi;
	    sensitivity = (editor->selected_branch != NULL) ?
		TRUE : FALSE;
	    SET_WIDGET_SENSITIVITY

	    w = editor->paste_mi;
	    sensitivity = (editor->selected_branch != NULL) ?
		TRUE : FALSE;
	    SET_WIDGET_SENSITIVITY

	    w = editor->select_all_mi;
	    sensitivity = ((editor->selected_branch != NULL) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->unselect_all_mi;
	    sensitivity = ((editor->selected_branch != NULL) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->find_in_pages_mi;
	    sensitivity = ((editor->total_layout_trunks > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY
	}

	/* View menu */
	menu = editor->view_mh;
	if(menu != NULL)
	{
	    w = editor->preview_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->syntax_highlight_cmi;
	    state = editor->syntax_highlighting;
	    SET_CHECK_MENU_ITEM_STATE
	}


	/* Layout menu */
	menu = editor->layout_mh;
	if(menu != NULL)
	{
	    /* Show or hide menu depending on if a branch is selected */
	    if(editor->selected_branch == NULL)
		gtk_widget_hide(menu);
	    else
		gtk_widget_show(menu);
	}

	/* Format menu */
	menu = editor->fmt_mh;
	if(menu != NULL)
	{
	    item = EditorBranchGetData(
		GTK_CTREE(editor->layout_ctree),
		editor->selected_branch
	    );
	    sensitivity = ((item == NULL) ?
		FALSE : (item->type == EditorItemTypeSection)
	    );

	    /* Show or hide menu depending on if a branch is selected */
	    if((item == NULL) ?
		0 : (item->type == EditorItemTypeSection)
	    )
		gtk_widget_show(menu);
	    else
		gtk_widget_hide(menu);
	}


	/* Right click menus */

	/* Layout ctree menu */
	menu = editor->layout_menu;
	if(menu != NULL)
	{
	    if(editor->selected_branch != NULL)
		branch_row = GTK_CTREE_ROW(editor->selected_branch);
	    else
		branch_row = NULL;
	    sensitivity = ((branch_row == NULL) ?
		FALSE : !branch_row->is_leaf
	    );
	    w = editor->layout_menu_expand_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_preview_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_add_header_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_add_section_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_remove_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_properties_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_open_mi;
	    sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_save_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity)
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_save_as_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity)
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY

	    /* Revert enable only if entire manual has changes */
	    w = editor->layout_menu_revert_mi;
	    sensitivity = sel_manual_has_changes;
	    SET_WIDGET_SENSITIVITY

	    w = editor->layout_menu_close_manual_mi;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity)
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY
	}


	/* Editor panel widgets menu */
	menu = editor->edit_panel_menu;
	if(menu != NULL)
	{
	    editor_undo_common_struct *u_common;

	    w = editor->edit_panel_undo_mi;
	    sensitivity = ((editor->total_undos > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_undo_milabel;
	    if(w != NULL)
	    {
		if(editor->total_undos > 0)
		{
		    u_common = (editor_undo_common_struct *)editor->undo[0];
		    if((u_common != NULL) ?
			(u_common->comment != NULL) : FALSE
		    )
		    {
			gchar *buf = g_strdup_printf(
			    "Undo %s (%i)",
			    u_common->comment, editor->total_undos
			);
			gtk_label_set_text(GTK_LABEL(w), buf);
			g_free(buf);
		    }
		}
		else
		{
		    gtk_label_set_text(GTK_LABEL(w), "Undo");
		}
	    }


	    w = editor->edit_panel_redo_mi;
	    sensitivity = ((editor->total_redos > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_redo_milabel;
	    if(w != NULL)
	    {
		if(editor->total_redos > 0)
		{
		    u_common = (editor_undo_common_struct *)editor->redo[0];
		    if((u_common != NULL) ?
			(u_common->comment != NULL) : FALSE
		    )
		    {
			gchar *buf = g_strdup_printf(
			    "Redo %s (%i)",
			    u_common->comment, editor->total_redos
			);
			gtk_label_set_text(GTK_LABEL(w), buf);
			g_free(buf);
		    }
		}
		else
		{
		    gtk_label_set_text(GTK_LABEL(w), "Redo");
		}
	    }

	    w = editor->edit_panel_cut_mi;
	    sensitivity = ((editor->selected_branch != NULL) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_copy_mi;
	    sensitivity = ((editor->selected_branch != NULL) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_paste_mi;
	    sensitivity = ((editor->selected_branch != NULL) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_select_all_mi;
	    sensitivity = ((editor->selected_branch != NULL) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_unselect_all_mi;
	    sensitivity = ((editor->selected_branch != NULL) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY
	}
	/* Edit panel format submenu */
	menu = editor->edit_panel_fmt_sub_menu;
	if(menu != NULL)
	{
	    item = EditorBranchGetData(
		GTK_CTREE(editor->layout_ctree),
		editor->selected_branch
	    );
	    sensitivity = ((item == NULL) ?
		FALSE : (item->type == EditorItemTypeSection)
	    );

	    w = editor->edit_panel_fmt_pl_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_pr_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_pi_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_li_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_b_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_u_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_br_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_amp_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_lt_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_gt_mi;
	    SET_WIDGET_SENSITIVITY

	    w = editor->edit_panel_fmt_strip_tags_mi;
	    SET_WIDGET_SENSITIVITY
	}


	/* Tool bar buttons */
	w = editor->tool_bar;
	if(w != NULL)
	{
	    w = editor->new_btn;
	    SET_BUTTON_LAYOUT

	    w = editor->open_btn;
	    sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT

	    w = editor->save_btn;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity)
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT

	    w = editor->save_as_btn;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity)
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT

	    w = editor->close_btn;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    if(sensitivity)
		sensitivity = !FileBrowserIsQuery();
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT


	    w = editor->undo_btn;
	    sensitivity = ((editor->total_undos > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT

	    w = editor->redo_btn;
	    sensitivity = ((editor->total_redos > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT


	    w = editor->cut_btn;
	    SET_BUTTON_LAYOUT
	    sensitivity = (editor->selected_branch != NULL) ?
		TRUE : FALSE;
	    SET_WIDGET_SENSITIVITY

	    w = editor->copy_btn;
	    SET_BUTTON_LAYOUT
	    sensitivity = (editor->selected_branch != NULL) ?
		TRUE : FALSE;
	    SET_WIDGET_SENSITIVITY

	    w = editor->paste_btn;
	    SET_BUTTON_LAYOUT
	    sensitivity = (editor->selected_branch != NULL) ?
		TRUE : FALSE;
	    SET_WIDGET_SENSITIVITY


	    w = editor->add_header_btn;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT

	    w = editor->add_section_btn;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT

	    w = editor->remove_btn;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT

	    w = editor->properties_btn;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY 
	    SET_BUTTON_LAYOUT

	    w = editor->preview_btn;
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );
	    SET_WIDGET_SENSITIVITY
	    SET_BUTTON_LAYOUT
	}

	/* Format bar buttons */
	w = editor->fmt_bar;
	if(w != NULL)
	{
	    item = EditorBranchGetData(
		GTK_CTREE(editor->layout_ctree),
		editor->selected_branch
	    );
	    sensitivity = ((item == NULL) ?
		FALSE : (item->type == EditorItemTypeSection)
	    );

	    w = editor->fmt_pl_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_pr_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_pi_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_li_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_b_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_u_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_br_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_amp_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_lt_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_gt_btn;
	    SET_WIDGET_SENSITIVITY

	    w = editor->fmt_strip_tags_btn;
	    SET_WIDGET_SENSITIVITY
	}

	/* Find bar */
	w = editor->find_bar;
	if(w != NULL)
	{
	    sensitivity = ((editor->selected_branch == NULL) ?
		FALSE : TRUE
	    );

	    w = editor->find_combo;
	    SET_WIDGET_SENSITIVITY

	    w = editor->replace_combo; 
	    SET_WIDGET_SENSITIVITY

	    w = editor->replace_all_btn;
	    SET_WIDGET_SENSITIVITY
	}
	/* Find bar find button menu */
	w = editor->find_bar_find_menu;
	if(w != NULL)
	{
	    w = editor->find_bar_find_in_pages_mi;
	    sensitivity = ((editor->total_layout_trunks > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY
	}
	/* Find bar replace button menu */
	w = editor->find_bar_replace_menu;
	if(w != NULL)
	{
	    w = editor->find_bar_replace_entire_page_mi;
	    sensitivity = ((editor->total_layout_trunks > 0) ?
		TRUE : FALSE
	    );
	    SET_WIDGET_SENSITIVITY
	}

#undef SET_WIDGET_SENSITIVITY
#undef SET_CHECK_MENU_ITEM_STATE
#undef SET_BUTTON_LAYOUT

	editor->freeze_count--;
}



/*
 *	Updates the cursor position value on the status bar.
 */
void EditorSetStatusPosition(editor_struct *editor, gint row, gint column)
{
	gchar *s;

	if(editor == NULL)
	    return;

	s = g_strdup_printf(
	    "Line: %i / Col: %i",
	    row + 1, column + 1
	);
	gtk_label_set_text(GTK_LABEL(editor->status_bar_cursor_label), s);
	g_free(s);

	while(gtk_events_pending() > 0)
	    gtk_main_iteration();
}

/*
 *	Sets the status message for the editor.
 *
 *	Passing NULL clears the message.
 *
 *      Note that gtk_main_iteration() will be called when this function
 *      is called to update the label properly.
 */
void EditorSetStatusMessage(editor_struct *editor, const gchar *mesg)
{
	GtkWidget *w = (editor != NULL) ?
	    editor->status_bar_label : NULL;
	if(w == NULL)
	    return;

	gtk_label_set_text(
	    GTK_LABEL(w),
	    (mesg != NULL) ? mesg : ""
	);

	while(gtk_events_pending() > 0)
	    gtk_main_iteration();
}

/*
 *	Sets the status of the progress bar on the editor.
 *
 *	Value must be from 0.0 to 1.0 inclusive.
 *
 *	Note that gtk_main_iteration() will be called when this function
 *	is called to update the progress bar properly.
 */
void EditorSetStatusProgress(editor_struct *editor, gfloat percent)
{
	gfloat p;
	GtkWidget *w = (editor != NULL) ?
	    editor->status_bar_progress : NULL;
	if(w == NULL)
	    return;

	/* Do activity? */
	if(percent < 0.0f)
	{
	    GtkAdjustment *adj = GTK_PROGRESS(w)->adjustment;

	    percent = gtk_progress_get_value(GTK_PROGRESS(w)) + 1;

	    if(percent > adj->upper)
		percent = adj->lower;

	    gtk_progress_set_activity_mode(
		GTK_PROGRESS(w), TRUE
	    );
	    gtk_progress_set_value(GTK_PROGRESS(w), percent);

	    while(gtk_events_pending() > 0)
		gtk_main_iteration();
	}

	if(percent > 1.0f)
	    percent = 1.0f;

	gtk_progress_set_activity_mode(
	    GTK_PROGRESS(w), FALSE
	);
	gtk_progress_set_format_string(
	    GTK_PROGRESS(w), "%p%%"
	);
	gtk_progress_set_show_text(
	    GTK_PROGRESS(w), (percent > 0.0f) ? TRUE : FALSE
	);

	p = editor->status_bar_progress_pos_last;
	if(p > percent)
	    p = percent;

	while(TRUE)
	{
	    if(p > percent)
		p = percent;

	    gtk_progress_bar_update(
		GTK_PROGRESS_BAR(w), p
	    );

	    while(gtk_events_pending() > 0)
		gtk_main_iteration();

	    if(p < percent)
		p += 0.05f;
	    else
		break;
	}

	editor->status_bar_progress_pos_last = percent;
}

/*
 *	Records positions and sizes of editor's widgets onto its
 *	core structure's preferences structure.
 */
void EditorRecordPositions(editor_struct *editor)
{
	GtkWidget *w;
	pref_struct *pref;
	medit_core_struct *core;

	if(editor == NULL)
	    return;

	core = editor->core;
	pref = core->pref;

	w = editor->toplevel;
	if(w != NULL)
	{
	    GdkWindow *window = w->window;
	    if(window != NULL)
	    {
		gint x, y, width, height, depth;

		gdk_window_get_geometry(
		    window, &x, &y, &width, &height, &depth
		);

		pref->last_editor_width = MAX(width, 0);
		pref->last_editor_height = MAX(height, 0);
	    }

	    if(editor->last_open_path != NULL)
	    {
		g_free(pref->last_opened_manpage_path);
		pref->last_opened_manpage_path = STRDUP(
		    editor->last_open_path
		);
	    }
	    if(editor->last_save_as_path != NULL)
	    {
		g_free(pref->last_saved_manpage_path);
		pref->last_saved_manpage_path = STRDUP(
		    editor->last_save_as_path
		);
	    }
	}
}


/*
 *	Deletes the undo/redo list on the editor.
 */
void EditorResetUndos(editor_struct *editor)
{
	gint i;

	if(editor == NULL)
	    return;

	/* Delete all undos and redos */
	for(i = 0; i < editor->total_undos; i++)
	    EditorUndoDelete(editor, editor->undo[i]);
	g_free(editor->undo);
	editor->undo = NULL;
	editor->total_undos = 0;
  
	for(i = 0; i < editor->total_redos; i++)
	    EditorUndoDelete(editor, editor->redo[i]);
	g_free(editor->redo);
	editor->redo = NULL;
	editor->total_redos = 0;
}

/*
 *	Deletes the manual pages in memory, undo list, and all
 *	the layout branches.
 */
void EditorReset(editor_struct *editor, const gboolean unmap)
{
	GtkWidget *w;
	pref_struct *pref;
	medit_core_struct *core;

	if(editor == NULL)
	    return;

	core = editor->core;
	pref = core->pref;

	if(unmap)
	    gtk_widget_hide(editor->toplevel);

	editor->freeze_count = 0;
	editor->busy_count = 0;
	editor->syntax_highlighting = PrefParmGetValueB(
	    core->pref,
	    MEDIT_PREF_PARM_EDITOR_ENABLE_SYNHL
	);
	editor->viewer_num = -1;
	editor->max_undos = 5;
	editor->status_bar_progress_pos_last = 0;

	/* Syntax highlight callback id */
	GTK_TIMEOUT_REMOVE(editor->synhl_timeout_cb_id);
	editor->synhl_timeout_cb_id = 0;
	editor->synhl_timeout_cb_cursor_pos = -1;
	editor->synhl_timeout_cb_start_pos = -1;
	editor->synhl_timeout_cb_end_pos = -1;

	/* Resize toplevel */
	w = editor->toplevel;
	if(PrefParmGetValueB(pref, MEDIT_PREF_PARM_RECORD_WIN_POS))
	    gtk_widget_set_usize(
		w, 
		MAX(pref->last_editor_width, 256),
		MAX(pref->last_editor_height, 256)
	    );
	else
	    gtk_widget_set_usize(
		w,  
		MEDIT_DEF_WIDTH, MEDIT_DEF_HEIGHT
	    );

	/* Reset status messages */
	EditorSetStatusPosition(editor, 0, 0);
	EditorSetStatusMessage(editor, NULL);
	EditorSetStatusProgress(editor, 0.0f);

	/* Delete all undos and redos */
	EditorResetUndos(editor);

	/* Delete all layout trunks on layout ctree, this will cause
	 * any of our user set data to be properly deleted as
	 * well.
	 *
	 * Currently selected branch pointer and layout trunks list will
	 * updated properly when the destroy notify is called when the
	 * branch node is destroyed.
	 */
	EditorLayoutTrunkDeleteAll(editor);

	/* Remove layout trunks list, just in case */
	g_free(editor->layout_trunk);
	editor->layout_trunk = NULL;
	editor->total_layout_trunks = 0;

	/* Mark no branch is selected, just in case */
	editor->selected_branch = NULL;


	/* Reset column width on layout ctree */
	w = editor->layout_ctree;
	if(w != NULL)
	    gtk_clist_set_column_width(GTK_CLIST(w), 0, 100);

	/* Get paths */
	if((pref != NULL) ?
	    (pref->last_opened_manpage_path != NULL) : FALSE
	)
	{
	    g_free(editor->last_open_path);
	    editor->last_open_path = STRDUP(pref->last_opened_manpage_path);
	}
	if((pref != NULL) ? 
	    (pref->last_saved_manpage_path != NULL) : FALSE
	)
	{
	    g_free(editor->last_save_as_path);
	    editor->last_save_as_path = STRDUP(pref->last_saved_manpage_path);
	}

	/* Reset title */
	w = editor->toplevel;
	gtk_window_set_title(GTK_WINDOW(w), PROG_NAME);

	/* Reset the Find In Pages dialog */
	EditorFIPReset(editor->fip_dlg, unmap);
}

/*
 *	Maps editor as needed.
 */
void EditorMap(editor_struct *editor)
{
	if(editor == NULL)
	    return;

	gtk_widget_show_raise(editor->toplevel);
}

/*
 *      Unmaps editor as needed.
 */
void EditorUnmap(editor_struct *editor)
{       
	if(editor == NULL)
	    return;

	gtk_widget_hide(editor->toplevel);
}


/*
 *	Destroys the editor and all its widgets and allocated resources.
 *
 *	The editor structure itself will also be deleted.
 */
void EditorDelete(editor_struct *editor)
{
	if(editor == NULL)
	    return;

	editor->freeze_count++;

	/* Remove the syntax highlighting timeout */
	GTK_TIMEOUT_REMOVE(editor->synhl_timeout_cb_id);
	editor->synhl_timeout_cb_id = 0;

	/* Delete all the undos and redos */
	EditorResetUndos(editor);

	/* Delete all the layout trunks */
	EditorLayoutTrunkDeleteAll(editor);
	g_free(editor->layout_trunk);
	editor->layout_trunk = NULL;
	editor->total_layout_trunks = 0;
	editor->selected_branch = NULL;

	/* Delete the Find In Pages dialog */
	EditorFIPDelete(editor->fip_dlg);

	GTK_WIDGET_DESTROY(editor->toplevel);

	editor->freeze_count--;

	g_free(editor->last_open_path);
	g_free(editor->last_save_as_path);

	g_free(editor);
}
