/* Bluefish HTML Editor
 * menu.c - the home of the pulldowns
 *
 * Copyright (C) 1998-2001 Olivier Sessink, Chris Mazuc and Roland Steinbach
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "config.h"
#include "default_include.h"

#include <string.h>
#include <dirent.h>
#include <sys/types.h>

#include <stdio.h>
#include <stdlib.h>

#include "bluefish.h"
#include "bf_lib.h"
#include "callbacks.h"	/* repeat_last_insert_cb , view_in_netscape_cb*/
#include "html.h"
#include "html_form.h"
#include "html_table.h"
#include "coloursel.h"  /* sel_colour_cb() */
#include "html2.h"
#include "javascript.h"
#include "document.h"			/* file_open etc. */
#include "project.h" 		/* project_open etc. */
#include "interface.h"			/* show_about_window_cb() */
#include "stringlist.h" 		/* edit_stringlist() */
#include "init.h" 				/* save_config_files() */
#include "snr2.h" 				/* the new search and replace */
#include "wml.h"
#include "images.h"
#include "wizards.h"
#include "ref_dialog.h"
#include "configure.h"
#include "bf_perl.h"
#include "menu.h" /* my own .h file */

#ifdef UNDO2
#include "undo2.h"
#else
#include "undo.h"
#endif /* UNDO2 */

#include "gtk_easy.h"
#include "highlight.h"
#include "toolbars.h"


/***************************************************************************/
void save_menu_shortcuts();
void load_menu_shortcuts();
static void edit_some_list_lcb(GtkWidget * widget, gpointer data);
#ifdef ENABLE_NLS
gchar *menu_translate(const gchar * path, gpointer data);
#endif /* ENABLE_NLS */
static void insert_char_cb(GtkWidget * widget, gint data);
void get_main_menu(GtkWidget * window, GtkWidget ** menubar);


/***************************************************************************/
#ifdef IMAGEMAP_EDITOR_TEST
void make_imagemap_win(GtkWidget * widget, gpointer data);
#endif

/* I wish there was a better way to show he names of the different chars */
/* as in actually show them in parenthesis */
/* 
gtk_text accelerators are:
<control>a beginning of line
<control>e end
<control>n next line
<control>p previous line
<control>b left
<control>f right
<alt>b backwards one word
<alt>f forward one word
<control>h backspace
<control>d delete
<control>w delete backward word
<alt>d delete forward line
<control>k delete to end of line
<control>u delete line

<control>x cut
<control>c copy
<control>v paste
*/

static GtkItemFactoryEntry menu_items[] = {
	{N_("/_File"), NULL, NULL, 0, "<Branch>"},
	{N_("/File/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/File/_New"), "F8", file_new_cb, 0, NULL},
	{N_("/File/_Open..."), "<control>O", file_open_cb, 0, NULL},
	{N_("/File/Open advanced..."), NULL, file_open_cb, 1, NULL},
	{N_("/File/Open from the web..."), NULL, open_from_web_cb, 0, NULL},
	{N_("/File/Open recent"), NULL, NULL, 0, "<Branch>"},
	{N_("/File/Open recent/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/File/Revert to saved"), NULL, revert_to_saved_cb, 0, NULL},
	{N_("/File/Insert..."), NULL, file_insert_cb, 0, NULL},
	{N_("/File/sep2"), NULL, NULL, 0, "<Separator>"},
	{N_("/File/_Save"), "<control>S", file_save_cb, 0, NULL},
	{N_("/File/Save _as..."), NULL, file_save_as_cb, 0, NULL},
	{N_("/File/Move to..."), NULL, file_move_to_cb, 0, NULL},
	{N_("/File/Save all"), NULL, file_save_all_cb, 0, NULL},
	{N_("/File/sep3"), NULL, NULL, 0, "<Separator>"},
	{N_("/File/Close"), NULL, file_close_cb, 0, NULL},
	{N_("/File/Close all"), NULL, file_close_all_cb, 0, NULL},
	{N_("/File/sep4"), NULL, NULL, 0, "<Separator>"},
	{N_("/File/Print..."), NULL, file_print_cb, 0, NULL},
	{N_("/File/sep5"), NULL, NULL, 0, "<Separator>"},
	{N_("/File/Quit"), "<control>Q", cya_later, 0, NULL},
	{N_("/_Edit"), NULL, NULL, 0, "<Branch>"},
	{N_("/_Edit/Tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Edit/Cut"), "<control>x", cut_cb, 0, NULL},
	{N_("/Edit/Copy"), "<control>c", copy_cb, 0, NULL},
	{N_("/Edit/Paste"), "<control>v", paste_cb, 0, NULL},
	{N_("/Edit/sep2"), NULL, NULL, 0, "<Separator>"},
	{N_("/Edit/Select all"), "<control>F8", sel_all_cb, 0, NULL},
	{N_("/Edit/Go to line..."), "<control>g", go_to_line_win_cb, 0, NULL},
	{N_("/Edit/sep3"), NULL, NULL, 0, "<Separator>"},
	{N_("/Edit/Find..."), "F6", search_cb, 0, NULL},
	{N_("/Edit/New find..."), NULL, new_search_cb, 0, NULL},
	{N_("/Edit/Find again"), "<shift>F6", search_again_cb, 0, NULL},
	{N_("/Edit/Replace..."), "F7", replace_cb, 0, NULL},
	{N_("/Edit/New replace..."), NULL, new_replace_cb, 0, NULL},
	{N_("/Edit/Replace again"), "<shift>F7", replace_again_cb, 0, NULL},
	{N_("/_Edit/Replace special"), NULL, NULL, 0, "<Branch>"},
	{N_("/_Edit/Replace special/Tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Edit/Replace special/Replace iso 8859-1 chars"), NULL, iso8859_1_replace_cb, 0, NULL},
	{N_("/Edit/Replace special/Replace ascii chars"), NULL, ascii_replace_cb, 0, NULL},
	{N_("/Edit/Replace special/Escape double quotes"), "<shift>F10", escape_quotes_replace_cb, 0, NULL},
	{N_("/Edit/sep4"), NULL, NULL, 0, "<Separator>"},
	{N_("/Edit/Undo"), "<control>z", undo_cb, 0, NULL},
	{N_("/Edit/Redo"), "<control>r", redo_cb, 0, NULL},
	{N_("/Edit/Undo all"), NULL, undo_all_cb, 0, NULL},
	{N_("/Edit/Redo all"), NULL, redo_all_cb, 0, NULL},
	{N_("/Edit/sep5"), NULL, NULL, 0, "<Separator>"},
	{N_("/Edit/Selection to uppercase"), NULL, selection_to_uppercase_cb, 0, NULL},
	{N_("/Edit/Selection to lowercase"), NULL, selection_to_lowercase_cb, 0, NULL},
	{N_("/Edit/sep6"), NULL, NULL, 0, "<Separator>"},
	{N_("/Edit/Indent region"), NULL, indent_region_cb, 0, NULL},
	{N_("/Edit/Unindent region"), NULL, unindent_region_cb, 0, NULL},
	{N_("/Edit/sep7"), NULL, NULL, 0, "<Separator>"},
	{N_("/Edit/Word Count"), NULL, word_count_cb, 0, NULL},
	{N_("/_View"), NULL, NULL, 0, "<Branch>"},
	{N_("/_View/Tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/View/View in _Netscape"), NULL, view_in_netscape_cb, 0, NULL},
	{N_("/View/_Drag 'n Drop Window"), NULL, dndwin_cb, 0, NULL},
#ifdef HAVE_IMAGE_LIBS
	{N_("/View/_Preview image under cursor"), NULL, preview_image_by_position_cb, 0, NULL},
#endif
#ifdef WITH_INTERNAL_PREVIEW
   {N_("/View/_Preview "), "F4" , preview_cb, 0, NULL},
#endif

	{N_("/View/sep1"), NULL, NULL, 0, "<Separator>"},
	{N_("/View/Next document"), "F1", notebook_next_document_cb, 0, NULL},
	{N_("/View/Previous document"), "F2", notebook_prev_document_cb, 0, NULL},
	{N_("/View/sep3"), NULL, NULL, 0, "<Separator>"},
	{N_("/View/Highlight syntax"), NULL, toggle_highlight_syntax_cb, 0, "<ToggleItem>"},
	{N_("/View/Refresh highlighting"), "F5", refresh_hi_cb, 0, NULL},
	{N_("/View/sep2"), NULL, NULL, 0, "<Separator>"},
	{N_("/View/Document status"), "F3", show_document_status_cb, 0, NULL},
	{N_("/_Project"), NULL, NULL, 0, "<Branch>"},
	{N_("/Project/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Project/Open..."), NULL, project_open_cb, 0, NULL},
	{N_("/Project/Close"), NULL, project_close_cb, 0, NULL},
	{N_("/Project/Save"), NULL, project_save_cb, 0, NULL},
	{N_("/Project/Save as..."), NULL, project_save_as_cb, 0, NULL},
	{N_("/Project/sep1"), NULL, NULL, 0, "<Separator>"},
	{N_("/Project/Edit..."), NULL, project_edit_cb, 0, NULL},
	{N_("/Project/sep2"), NULL, NULL, 0, "<Separator>"},
	{N_("/Project/Add current document"), NULL, project_add_document_cb, 0, NULL},
	{N_("/Project/Add all open documents"), NULL, project_add_document_cb, 1, NULL},
	{N_("/_Project/Files"), NULL, NULL, 0, "<Branch>"},
	{N_("/Project/Files/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/_Tags"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Repeat last"), "F4", repeat_last_insert_cb, 0, NULL},
	{N_("/Tags/Headings"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Headings/Tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Headings/H1"), "<alt>F1", general_html_cb, 18, NULL},
	{N_("/Tags/Headings/H2"), "<alt>F2", general_html_cb, 19, NULL},
	{N_("/Tags/Headings/H3"), "<alt>F3", general_html_cb, 20, NULL},
	{N_("/Tags/Headings/H4"), "<alt>F4", general_html_cb, 21, NULL},
	{N_("/Tags/Headings/H5"), "<alt>F5", general_html_cb, 22, NULL},
	{N_("/Tags/Headings/H6"), "<alt>F6", general_html_cb, 23, NULL},
	{N_("/Tags/Special"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Special/Accent"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Accent/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Special/Accent/Uppercase"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Accent/Uppercase/A-I"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Accent/Uppercase/A-I/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Special/Accent/Uppercase/A-I/A grave"), NULL, insert_char_cb, 0, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/A acute"), NULL, insert_char_cb, 1, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/A circumflex"), NULL, insert_char_cb, 2, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/A tilde"), NULL, insert_char_cb, 3, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/AE ligature"), NULL, insert_char_cb, 4, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/A diaeresis"), NULL, insert_char_cb, 5, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/A ring"), NULL, insert_char_cb, 6, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/C cedilla"), NULL, insert_char_cb, 7, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/E grave"), NULL, insert_char_cb, 8, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/E acute"), NULL, insert_char_cb, 9, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/E circumflex"), NULL, insert_char_cb, 10, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/E diaeresis"), NULL, insert_char_cb, 11, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/I grave"), NULL, insert_char_cb, 12, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/I acute"), NULL, insert_char_cb, 13, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/I circumflex"), NULL, insert_char_cb, 14, NULL},
	{N_("/Tags/Special/Accent/Uppercase/A-I/I diaeresis"), NULL, insert_char_cb, 15, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/N tilde"), NULL, insert_char_cb, 16, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/O grave"), NULL, insert_char_cb, 17, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/O acute"), NULL, insert_char_cb, 18, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/O circumflex"), NULL, insert_char_cb, 19, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/O tilde"), NULL, insert_char_cb, 20, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/O diaeresis"), NULL, insert_char_cb, 21, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/O slash"), NULL, insert_char_cb, 22, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/U grave"), NULL, insert_char_cb, 23, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/U acute"), NULL, insert_char_cb, 24, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/U circumflex"), NULL, insert_char_cb, 25, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/U diaeresis"), NULL,
	 insert_char_cb, 26, NULL},
	{N_("/Tags/Special/Accent/Uppercase/J-Z/Y acute"), NULL, insert_char_cb,
	 27, NULL},
	{N_("/Tags/Special/Accent/Lowercase"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Accent/Lowercase/A-I"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Accent/Lowercase/A-I/tearoff1"), NULL, NULL, 0,
	 "<Tearoff>"},
	{N_("/Tags/Special/Accent/Lowercase/A-I/a grave"), NULL, insert_char_cb,
	 28, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/a acute"), NULL, insert_char_cb,
	 29, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/a circumflex"), NULL,
	 insert_char_cb, 30, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/a tilde"), NULL, insert_char_cb,
	 31, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/a ring"), NULL, insert_char_cb,
	 32, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/ae ligature"), NULL,
	 insert_char_cb, 33, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/a diaeresis"), NULL,
	 insert_char_cb, 34, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/c cedilla"), NULL, insert_char_cb,
	 35, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/e grave"), NULL, insert_char_cb,
	 36, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/e acute"), NULL, insert_char_cb,
	 37, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/e circumflex"), NULL,
	 insert_char_cb, 38, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/e diaeresis"), NULL,
	 insert_char_cb, 39, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/i grave"), NULL, insert_char_cb,
	 40, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/i acute"), NULL, insert_char_cb,
	 41, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/i circumflex"), NULL,
	 insert_char_cb, 42, NULL},
	{N_("/Tags/Special/Accent/Lowercase/A-I/i diaeresis"), NULL,
	 insert_char_cb, 43, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/tearoff1"), NULL, NULL, 0,
	 "<Tearoff>"},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/n tilde"), NULL, insert_char_cb,
	 44, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/o grave"), NULL, insert_char_cb,
	 45, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/o acute"), NULL, insert_char_cb,
	 46, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/o circumflex"), NULL,
	 insert_char_cb, 47, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/o tilde"), NULL, insert_char_cb,
	 48, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/o diaeresis"), NULL,
	 insert_char_cb, 49, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/o slash"), NULL, insert_char_cb,
	 50, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/u grave"), NULL, insert_char_cb,
	 51, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/u acute"), NULL, insert_char_cb,
	 52, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/u circumflex"), NULL,
	 insert_char_cb, 53, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/u diaeresis"), NULL,
	 insert_char_cb, 54, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/y acute"), NULL, insert_char_cb,
	 55, NULL},
	{N_("/Tags/Special/Accent/Lowercase/J-Z/y diaeresis"), NULL,
	 insert_char_cb, 56, NULL},
	{N_("/Tags/Special/Accent/separator"), NULL, NULL, 0, "<Separator>"},
	{N_("/Tags/Special/Accent/Umlaut"), NULL, insert_char_cb, 57, NULL},
	{N_("/Tags/Special/Accent/Acute"), NULL, insert_char_cb, 58, NULL},
	{N_("/Tags/Special/Accent/Cedilla"), NULL, insert_char_cb, 59, NULL},
	{N_("/Tags/Special/Currency"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Currency/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Special/Currency/Cent sign"), NULL, insert_char_cb,
	 60, NULL},
	{N_("/Tags/Special/Currency/Pound sterling"), NULL, insert_char_cb,
	 61, NULL},
	{N_("/Tags/Special/Currency/Currency sign"), NULL, insert_char_cb,
	 62, NULL},
	{N_("/Tags/Special/Currency/Yen sign"), NULL, insert_char_cb, 63, NULL},
	{N_("/Tags/Special/Math-Science"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Math-Science/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Special/Math-Science/Logical not sign"), "<alt>1", insert_char_cb,
	 64, NULL},
	{N_("/Tags/Special/Math-Science/Multiplication sign"), "<alt>8",
	 insert_char_cb, 65, NULL},
	{N_("/Tags/Special/Math-Science/Division sign"), "<alt>slash", insert_char_cb,
	 66, NULL},
	{N_("/Tags/Special/Math-Science/Plus-minus sign"), NULL, insert_char_cb,
	 67, NULL},
	{N_("/Tags/Special/Math-Science/Less-than sign"), "<alt>comma", insert_char_cb,
	 68, NULL},
	{N_("/Tags/Special/Math-Science/Greater-than sign"), "<alt>period", insert_char_cb,
	 69, NULL},
	{N_("/Tags/Special/Math-Science/Superscript 1"), NULL, insert_char_cb,
	 70, NULL},
	{N_("/Tags/Special/Math-Science/Superscript 2"), NULL, insert_char_cb,
	 71, NULL},
	{N_("/Tags/Special/Math-Science/Superscript 3"), NULL, insert_char_cb,
	 72, NULL},
	{N_("/Tags/Special/Math-Science/One quarter"), NULL, insert_char_cb,
	 73, NULL},
	{N_("/Tags/Special/Math-Science/One half"), NULL, insert_char_cb,
	 74, NULL},
	{N_("/Tags/Special/Math-Science/Three quarters"), NULL, insert_char_cb,
	 75, NULL},
	{N_("/Tags/Special/Math-Science/Degree sign"), NULL, insert_char_cb,
	 76, NULL},
	{N_("/Tags/Special/Non Latin"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Non Latin/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Special/Non Latin/ETH (Icelandic)"), NULL, insert_char_cb,
	 77, NULL},
	{N_("/Tags/Special/Non Latin/THORN (Icelandic)"), NULL, insert_char_cb,
	 78, NULL},
	{N_("/Tags/Special/Non Latin/eth (Icelandic)"), NULL, insert_char_cb,
	 79, NULL},
	{N_("/Tags/Special/Non Latin/thorn"), NULL, insert_char_cb, 80, NULL},
	{N_("/Tags/Special/Non Latin/Sharp s"), NULL, insert_char_cb, 81, NULL},
	{N_("/Tags/Special/Non Latin/Micro sign"), NULL, insert_char_cb,
	 82, NULL},
	{N_("/Tags/Special/Other"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Special/Other/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Special/Other/Non-breaking space"), NULL, insert_char_cb,
	 83, NULL},
	{N_("/Tags/Special/Other/Section sign"), NULL, insert_char_cb,
	 84, NULL},
	{N_("/Tags/Special/Other/Copyright sign"), NULL, insert_char_cb,
	 85, NULL},
	{N_("/Tags/Special/Other/Left angle quotes"), NULL, insert_char_cb,
	 86, NULL},
	{N_("/Tags/Special/Other/Right angle quotes"), NULL, insert_char_cb,
	 87, NULL},
	{N_("/Tags/Special/Other/Registered trademark"), NULL, insert_char_cb,
	 88, NULL},
	{N_("/Tags/Special/Other/Inverted exclamation"), NULL, insert_char_cb,
	 89, NULL},
	{N_("/Tags/Special/Other/Inverted question mark"), NULL, insert_char_cb,
	 90, NULL},
	{N_("/Tags/Special/Other/Feminine ordinal"), NULL, insert_char_cb,
	 91, NULL},
	{N_("/Tags/Special/Other/Masculine ordinal"), NULL, insert_char_cb,
	 92, NULL},
	{N_("/Tags/Special/Other/Pilcrow (paragraph sign)"), NULL, insert_char_cb,
	 93, NULL},
	{N_("/Tags/Special/Other/Broken bar"), NULL, insert_char_cb, 94, NULL},
	{N_("/Tags/Special/Other/Soft hypen"), "<alt>minus", insert_char_cb, 95, NULL},
	{N_("/Tags/Special/Other/Spacing macron"), NULL, insert_char_cb,
	 96, NULL},
	{N_("/Tags/Special/Other/Middle dot"), NULL, insert_char_cb,
	 97, NULL},
	{N_("/Tags/Format by layout"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Format by layout/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Format by layout/Bold"), "<alt>v", general_html_cb, 1, NULL},
	{N_("/Tags/Format by layout/Italic"), "<alt>i", general_html_cb, 2, NULL},
	{N_("/Tags/Format by layout/Underline"), "<alt>u", general_html_cb, 3, NULL},
	{N_("/Tags/Format by layout/Strikeout"), "<alt>s", general_html_cb, 4, NULL},	
	{N_("/Tags/Format by context"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Format by context/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Format by context/Strong"), NULL, general_html_cb, 16, NULL},
	{N_("/Tags/Format by context/Emphasis"), NULL, general_html_cb, 17, NULL},
	{N_("/Tags/Format by context/Define"), NULL, general_html_cb, 48, NULL},
	{N_("/Tags/Format by context/Code"), NULL, general_html_cb, 49, NULL},
	{N_("/Tags/Format by context/Sample"), NULL, general_html_cb, 50, NULL},
	{N_("/Tags/Format by context/Keyboard"), NULL, general_html_cb, 51, NULL},
	{N_("/Tags/Format by context/Variable"), NULL, general_html_cb, 52, NULL},
	{N_("/Tags/Format by context/Citation"), NULL, general_html_cb, 53, NULL},
	{N_("/Tags/Format by context/Abbreviation"), NULL, general_html_cb, 54, NULL},
	{N_("/Tags/Format by context/Acronym"), NULL, general_html_cb, 55, NULL},
	{N_("/Tags/Format general"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Format general/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Format general/Paragraph"), "<alt>P", general_html_cb, 5, NULL},
	{N_("/Tags/Format general/Break"),  "<Control><Alt>r", general_html_cb, 6, NULL},
	{N_("/Tags/Format general/Break clear all"), NULL, general_html_cb, 41, NULL},
	{N_("/Tags/Format general/Non-Breaking Space"), "<alt>n", general_html_cb, 7, NULL},
	{N_("/Tags/Format general/<separator>"), NULL, NULL, 0, "<Separator>"},
	{N_("/Tags/Format general/Font Size +1"), "<control>equal", general_html_cb, 11, NULL},
	{N_("/Tags/Format general/Font Size -1"), "<control>minus", general_html_cb, 12, NULL},
	{N_("/Tags/Format general/<separator>"), NULL, NULL, 0, "<Separator>"},
	{N_("/Tags/Format general/Preformatted Text"), "<Control><Alt>p", general_html_cb, 13, NULL},
	{N_("/Tags/Format general/Subscript"), "<alt><shift>s", general_html_cb, 14, NULL},
	{N_("/Tags/Format general/Superscript"), "<alt><control>s", general_html_cb, 15, NULL},
	{N_("/Tags/Format general/<separator>"), NULL, NULL, 0, "<Separator>"},
	{N_("/Tags/Format general/Center"), "<alt>c", general_html_cb, 8, NULL},
	{N_("/Tags/Format general/Align right"), "<Alt>r", general_html_cb, 9, NULL},
	{N_("/Tags/Table"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/Table/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/Table/Table"), NULL, general_html_cb, 24, NULL},
	{N_("/Tags/Table/Tablerow"), NULL, general_html_cb, 25, NULL},
	{N_("/Tags/Table/Tableheader"), NULL, general_html_cb, 26, NULL},
	{N_("/Tags/Table/Tabledata"), NULL, general_html_cb, 27, NULL},
	{N_("/Tags/Table/Tablecaption"), NULL, general_html_cb, 28, NULL},
	{N_("/Tags/List"), NULL, NULL, 0, "<Branch>"},
	{N_("/Tags/List/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Tags/List/Unordered list"), NULL, general_html_cb, 33, NULL},
	{N_("/Tags/List/Ordered list"), NULL, general_html_cb, 34, NULL},
	{N_("/Tags/List/List item"), "<alt>l", general_html_cb, 35, NULL},
	{N_("/Tags/List/Definition list"), NULL, general_html_cb, 36, NULL},
	{N_("/Tags/List/Definition term"), NULL, general_html_cb, 37, NULL},
	{N_("/Tags/List/Definition"), NULL, general_html_cb, 38, NULL},
	{N_("/Tags/List/menu"), NULL, general_html_cb, 39, NULL},
	{N_("/Tags/Insert Generator META-Tag"), NULL, general_html_cb, 47, NULL},
	{N_("/Tags/Comment"), NULL, general_html_cb, 10, NULL},
	{N_("/_Dialogs"), NULL, NULL, 0, "<Branch>"},
	{N_("/Dialogs/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Dialogs/General"), NULL, NULL, 0, "<Branch>"},
	{N_("/Dialogs/General/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Dialogs/General/Quickstart..."), "<alt>q", quickstart_cb, 0, NULL},
/*	{N_("/Dialogs/General/DTD"), NULL, dtd_cb, 0, NULL},
	{N_("/Dialogs/General/Head"), NULL, head_cb, 0, NULL}, */
	{N_("/Dialogs/General/Body..."), NULL, body_cb, 0, NULL},
	{N_("/Dialogs/General/Anchor..."), "<alt>a", quickanchor_cb, 0, NULL},
	{N_("/Dialogs/General/Email..."), NULL, email_cb, 0, NULL},
	{N_("/Dialogs/General/Rule..."), "<alt>h", quickrule_cb, 0, NULL},
	{N_("/Dialogs/General/Font..."), NULL, fontdialog_cb, 0, NULL},
	{N_("/Dialogs/General/Basefont..."), NULL, basefont_cb, 0, NULL},
	{N_("/Dialogs/General/Quicklist..."), NULL, quicklist_cb, 0, NULL},
	{N_("/Dialogs/General/Meta..."), "<alt>m", meta_cb, 0, NULL},
	{N_("/Dialogs/General/Embed..."), NULL, embed_cb, 0, NULL},
	{N_("/Dialogs/General/Select colour..."), NULL, sel_colour_cb, 0, NULL},
	{N_("/Dialogs/General/Insert time..."), NULL, insert_time_cb, 0, NULL},
	{N_("/Dialogs/General/Insert image..."), "<control>i", image_insert_dialog_cb, 0, NULL},
#if HAVE_LIBGDK_IMLIB
	{N_("/Dialogs/General/Insert thumbnail..."), "<control>t", image_thumbnail_dialog_cb, 0, NULL},
#endif
	{N_("/Dialogs/Table"), NULL, NULL, 0, "<Branch>"},
	{N_("/Dialogs/Table/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Dialogs/Table/Table..."), NULL, tabledialog_cb, 0, NULL},
	{N_("/Dialogs/Table/Tablerow..."), NULL, tablerowdialog_cb, 0, NULL},
	{N_("/Dialogs/Table/Tablehead..."), NULL, tableheaddialog_cb, 0, NULL},
	{N_("/Dialogs/Table/Tabledata..."), NULL, tabledatadialog_cb, 0, NULL},
	{N_("/Dialogs/CSS"), NULL, NULL, 0, "<Branch>"},
	{N_("/Dialogs/CSS/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Dialogs/CSS/Create style..."), NULL, new_css_dialog, 0, NULL},
	{N_("/Dialogs/CSS/Span..."), NULL, span_dialog, 0, NULL},
	{N_("/Dialogs/CSS/Div..."), NULL, div_dialog, 0, NULL},
#ifdef OLD_CSS_DIALOG
	{N_("/Dialogs/CSS/Add class..."), NULL, insert_class, 0, NULL},
#endif
	{N_("/Dialogs/CSS/Style..."), NULL, general_html_cb, 42, NULL},
	{N_("/Dialogs/CSS/Link to stylesheet..."), NULL, link_cb, 0, NULL},
	{N_("/Dialogs/Frame"), NULL, NULL, 0, "<Branch>"},
	{N_("/Dialogs/Frame/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Dialogs/Frame/Frameset..."), NULL, framesetdialog_cb, 0, NULL},
	{N_("/Dialogs/Frame/Frame..."), NULL, framedialog_cb, 0, NULL},
	{N_("/Dialogs/Form"), NULL, NULL, 0, "<Branch>"},
	{N_("/Dialogs/Form/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Dialogs/Form/Form..."), NULL, formdialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Input button..."), NULL, buttondialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Text..."), NULL, textdialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Hidden..."), NULL, hiddendialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Textarea..."), NULL, textareadialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Radio buttons..."), NULL, radiodialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Check buttons..."), NULL, checkdialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Select..."), NULL, selectdialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Option..."), NULL, optiondialog_cb, 0, NULL},
	{N_("/Dialogs/Form/Option group..."), NULL, optgroupdialog_cb, 0, NULL},
	{N_("/Dialogs/Javascript"), NULL, NULL, 0, "<Branch>"},
	{N_("/Dialogs/Javascript/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Dialogs/Javascript/Mouseover Script"), NULL, mouseover_script_cb, 0, NULL},
	{N_("/Dialogs/Javascript/Netscape 4 Resize Bugfix Script"), NULL, ns47_bugfix_script_cb, 0, NULL},
	{N_("/Dialogs/Javascript/Image Preload Script"), NULL, imagepreload_script_cb, 0, NULL},
	{N_("/Dialogs/_WML"), NULL, NULL, 0, "<Branch>"},
	{N_("/Dialogs/WML/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Dialogs/WML/Standard Document"), NULL, general_wml_cb, 6, NULL},
	{N_("/Dialogs/WML/Card..."), NULL, carddialog_cb, 0, NULL},
	{N_("/Dialogs/WML/Postfield..."), NULL, postfielddialog_cb, 0, NULL},
	{N_("/Dialogs/WML/Go..."), NULL, godialog_cb, 0, NULL},
	{N_("/Dialogs/WML/Do..."), NULL, dodialog_cb, 0, NULL},
	{N_("/Dialogs/WML/Anchor..."), NULL, anchordialog_cb, 0, NULL},
	{N_("/Dialogs/WML/Access..."), NULL, accessdialog_cb, 0, NULL},
	{N_("/Dialogs/WML/sep11"), NULL, NULL, 0, "<Separator>"},
	{N_("/Dialogs/WML/Paragraph"), NULL, general_wml_cb, 1, NULL},
	{N_("/Dialogs/WML/Line Break"), NULL, general_wml_cb, 2, NULL},
	{N_("/Dialogs/WML/Italic"), NULL, general_wml_cb, 3, NULL},
	{N_("/Dialogs/WML/Non-Breaking Space"), NULL, general_wml_cb, 4, NULL},
	{N_("/Dialogs/WML/Bold"), NULL, general_wml_cb, 5, NULL},
	{N_("/Dialogs/WML/sep12"), NULL, NULL, 0, "<Separator>"},
	{N_("/Dialogs/WML/Prev"), NULL, general_wml_cb, 7, NULL},
	{N_("/Dialogs/WML/Refresh"), NULL, general_wml_cb, 8, NULL},
	{N_("/Dialogs/WML/Noop"), NULL, general_wml_cb, 9, NULL},
	{N_("/Dialogs/WML/sep13"), NULL, NULL, 0, "<Separator>"},
	{N_("/Dialogs/WML/Set Variable..."), NULL, vardialog_cb, 0, NULL},
#ifdef IMAGEMAP_EDITOR_TEST
	{N_("/Dialogs/imagemap development..."), NULL, make_imagemap_win, 0, NULL},
#endif
	{N_("/E_xternal"), NULL, NULL, 0, "<Branch>"},
	{N_("/External/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/External/Weblint..."), NULL, run_weblint_cb, 0, NULL},
	{N_("/External/sep1"), NULL, NULL, 0, "<Separator>"},
	{N_("/External/Filters"), NULL, NULL, 0, "<Branch>"},
	{N_("/External/Filters/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/External/Commands"), NULL, NULL, 0, "<Branch>"},
	{N_("/External/Commands/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
#ifdef PERL
	{N_("/_Perl"), NULL, NULL, 0, "<Branch>"},
	{N_("/Perl/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Perl/Status..."), NULL, perl_status_cb, 0, NULL},
	{N_("/Perl/Strip CR Codes"), NULL, perl_strip_cr_cb, 0, NULL},
#endif
	{N_("/_Options"), NULL, NULL, 0, "<Branch>"},
	{N_("/Options/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Options/Preferences..."), NULL, configure_cb, 0, NULL},
	{N_("/Options/View Main toolbar"), NULL, toggle_main_toolbar_cb, 0, "<ToggleItem>"},
	{N_("/Options/View HTML toolbar"), NULL, toggle_html_toolbar_cb, 0, "<ToggleItem>"},
	{N_("/Options/View Custom toolbar"), NULL, toggle_cust_menubar_cb, 0, "<ToggleItem>"},
	{N_("/Options/View Filebrowser"), NULL, toggle_filebrowser_cb, 0, "<ToggleItem>"},
	{N_("/Options/sep2"), NULL, NULL, 0, "<Separator>"},
	{N_("/Options/_Lists"), NULL, NULL, 0, "<Branch>"},
	{N_("/Options/Lists/tearoff1"), NULL, NULL, 0, "<Tearoff>"},
	{N_("/Options/Lists/External filters..."), NULL, edit_some_list_lcb, 1, NULL},
	{N_("/Options/Lists/External programs..."), NULL, edit_some_list_lcb, 2, NULL},
	{N_("/Options/Lists/Syntax highlighting..."), NULL, edit_some_list_lcb, 3, NULL},
	{N_("/Options/Lists/Reset syntax highlighting"), NULL, reset_syntax_highlighting_lcb, 0, NULL},
	{N_("/Options/sep1"), NULL, NULL, 0, "<Separator>"},
	{N_("/Options/Save config"), NULL, save_config_files, 0, NULL},
	{N_("/Options/Save shortcut key settings"), NULL, save_menu_shortcuts, 0, NULL},
	{N_("/_Help"), NULL, NULL, 0, "<Branch>"},
	{N_("/Help/_About..."), NULL, show_about_window_cb, 0, NULL}
};

static gchar *sp_chars[] = {
	"&Agrave;", "&Aacute;", "&Acirc;", "&Atilde;", "&AElig;",
	"&Auml;", "&Aring;", "&Ccedil;", "&Egrave;", "&Eacute;",
	"&Ecirc;", "&Euml;", "&Igrave;", "&Iacute;", "&Icirc;",
	"&Iuml;", "&Ntilde;", "&Ograve;", "&Oacute;", "&Ocirc;",
	"&Otilde;", "&Ouml;", "&Oslash;", "&Ugrave;", "&Uacute;",
	"&Ucirc;", "&Uuml;", "&Yacute;", "&agrave;", "&aacute;",
	"&acirc;", "&atilde;", "&aring;", "&aelig;", "&auml;",
	"&ccedil;", "&egrave;", "&eacute;", "&ecirc;", "&euml;",
	"&igrave;", "&iacute;", "&icirc;", "&iuml;", "&ntilde;",
	"&ograve;", "&oacute;", "&ocirc;", "&otilde;", "&ouml;",
	"&oslash;", "&ugrave;", "&uacute;", "&ucirc;", "&uuml;",
	"&yacute;", "&yuml;", "&uml;", "&acute;", "&cedil;", "&cent;",
	"&pound;", "&curren;", "&yen;", "&not;", "&mult;", "&divide;",
	"&plusmn;", "&lt;", "&gt;", "&sup1;", "&sup2;", "&sup3;",
	"&frac14;", "&frac12;", "&frac34;", "&deg;", "&ETH;", "&THORN;",
	"&eth;", "&thorn;", "&szlig;", "&micro;", "&nbsp;", "&sect;",
	"&copy;", "&laquo;", "&raquo;", "&reg;", "&iexcl;", "&iquest;",
	"&ordf;", "&ordm;", "&para;", "&brvbar;", "&shy;", "&macr;",
	"&middot;"
};
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif

void save_menu_shortcuts() {
	gchar *filename;
	
	filename = g_malloc(PATH_MAX+1);
	filename = strncat(strncpy(filename, g_get_home_dir(), PATH_MAX), "/.bluefish/menudump", PATH_MAX);
	gtk_item_factory_dump_rc(filename, NULL, TRUE);
	g_free(filename);
}

void load_menu_shortcuts() {
	gchar *filename;
	
	filename = g_malloc(PATH_MAX+1);
	filename = strncat(strncpy(filename, g_get_home_dir(), PATH_MAX), "/.bluefish/menudump", PATH_MAX);
	gtk_item_factory_parse_rc(filename);
	g_free(filename);
}

static void make_external_commands() {
	make_external_menu_entries(2);
}
static void make_external_filters() {
	make_external_menu_entries(1);
}

static void edit_some_list_lcb(GtkWidget * widget, gpointer data)
{
	switch (GPOINTER_TO_INT(data)) {
	case 1:
		{
		gchar *titles[] = { _("name"), _("command"), NULL};
		estrl_dialog(&main_v->props.external_filters, _("Bluefish configuration - external filters"), 7, 2, &titles[0], make_external_filters);
		}
		break;
	case 2:
		{
		gchar *titles[] = { _("name"), _("command"), NULL};
		estrl_dialog(&main_v->props.external_commands, _("Bluefish configuration - external commands"), 7, 2, &titles[0], make_external_commands);
		}
		break;
	case 3:
		{
		gchar *titles[] = {_("color"), _("regex pattern"), NULL};
		estrl_dialog(&main_v->props.syntax_configstrings, _("Bluefish configuration - syntax highlighting"), 8, 2, &titles[0], make_syntax_struct_list);
		}
		break;
	default:

		break;
	}
}


/***************************************************************************/
/* takes care of inserting the special characters */
static void insert_char_cb(GtkWidget * widget, gint data)
{
	insert_dbl_text(sp_chars[data], NULL);
}

/* 
 * menu factory crap, thanks to the gtk tutorial for this
 * both the 1.0 and the 1.2 code is directly from the tutorial
 */
void get_main_menu(GtkWidget * window, GtkWidget ** menubar)
{
	GtkItemFactory *item_factory;
	GtkAccelGroup *accel_group;
	gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
	accel_group = gtk_accel_group_new();
	item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
#ifdef ENABLE_NLS
	gtk_item_factory_set_translate_func(item_factory, menu_translate, "<main>", NULL);
#endif
	gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
	gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
	if (menubar)
		*menubar = gtk_item_factory_get_widget(item_factory, "<main>");
	setup_toggle_item(item_factory, "/Options/View Main toolbar", main_v->props.v_main_tb);
	setup_toggle_item(item_factory, "/Options/View HTML toolbar", main_v->props.v_html_tb);
	setup_toggle_item(item_factory, "/Options/View Custom toolbar", main_v->props.v_custom_tb);
	setup_toggle_item(item_factory, "/Options/View Filebrowser", main_v->props.v_filebrowser);
	setup_toggle_item(item_factory, "/View/Highlight syntax", main_v->props.cont_highlight_update);
}


/*********************************************************************/
#define MAX_TEXT_ENTRY 10

typedef struct {
	GtkWidget *dialog;
	GtkWidget *textentry[MAX_TEXT_ENTRY];
	gint type;
	gchar **array;
} Tcust_con_struc;

/*
Tcust_con_struc->array[0] = title / menupath
Tcust_con_struc->array[1] = type:
										0 = custom dialog
										1 = custom search and replace

** for dialog **
Tcust_con_struc->array[2] = formatstring before, containing %0, %1... that should be replaced by the 
				values from the dialog
Tcust_con_struc->array[3] = formatstring after
Tcust_con_struc->array[4] = number of variables from the dialog
Tcust_con_struc->array[5..] = the description of those variables

** for search and replace **
Tcust_con_struc->array[2] = search pattern, containing %0 etc.
Tcust_con_struc->array[3] = replace pattern, containing %0 etc.
Tcust_con_struc->array[4] = replace where:
										0 = from beginning
										1 = from cursor
										2 = selection (selection required)
										3 = all open documents
										4 = ask
Tcust_con_struc->array[5] = replace type:
										0 = normal
										1 = regular expression
Tcust_con_struc->array[6] = case sensitivity:
										0 = no
										1 = yes
Tcust_con_struc->array[7] = number of variables from the dialog
Tcust_con_struc->array[8..] = the description of those variables
*/


static gchar *replace_with(gchar numc, gchar **array) {
	gint numi, i;

	numi = ((int) numc) -48;
	for (i=0; array[i] != NULL; i++) {
		DEBUG_MSG("replace_with, i=%d, searching for numi=%d\n", i, numi);
		if (i == numi) {
			DEBUG_MSG("replace_with, returning %d= %s\n", i, array[i]);
			return array[i];
		}
	}
	return NULL;
}


static gchar *replace_string(gchar *in_string, gchar **array) {
	gchar *tmp3;
	gchar *found, *search_in, *freestr;
	gchar *newstring, *tmpnewstring, *begin, *replace_w;

	newstring = g_strdup("");
	freestr = search_in = begin = g_strdup(in_string);
	while ( (search_in) && (found = strchr(search_in, '%')) ) {
		DEBUG_MSG("replace_string, found=%s, search_in=%s\n", found, search_in);
		tmp3 = found;
		DEBUG_MSG("replace_string, char=%c\n", *tmp3);
		tmp3++;
		DEBUG_MSG("replace_string, char=%c\n", *tmp3);
		if ((replace_w = replace_with(*tmp3, array))) {
			*found = '\0';
			tmpnewstring = newstring;
			newstring = g_strconcat(tmpnewstring, begin, replace_w, NULL);
			DEBUG_MSG("replace_string, newstring=%s\n", newstring);
			g_free(tmpnewstring);
			begin = ++tmp3;
			search_in = tmp3;
		} else if (*tmp3 == '\0') {
			DEBUG_MSG("replace_string, *tmp3 = \\0, found end of string\n");
			search_in = NULL;
		} else {
			search_in = ++found;
			DEBUG_MSG("replace_string, search_in=%s\n", search_in);
		}
	}
	tmpnewstring = newstring;
	newstring = g_strconcat(tmpnewstring, begin,NULL);
	DEBUG_MSG("replace_string, newstring=%s\n", newstring);
	g_free(tmpnewstring);
	
	g_free(freestr);
	return newstring;
}

static void cust_con_struc_dialog_destroy_lcb(GtkWidget *widget, GdkEvent *event,  Tcust_con_struc *ccs) {
	window_destroy(ccs->dialog);
	g_free(ccs);
}

static void cust_con_struc_dialog_cancel_lcb(GtkWidget *widget, gpointer data) {
	cust_con_struc_dialog_destroy_lcb(NULL, NULL, data);
}

static void cust_con_struc_dialog_ok_lcb(GtkWidget *widget, Tcust_con_struc *ccs) {
	gchar **dialogarray;
	gint num_vars, i;

	DEBUG_MSG("cust_con_struc_dialog_ok_lcb, ccs at %p\n", ccs);
	DEBUG_MSG("cust_con_struc_dialog_ok_lcb, array at %p, &array[0]=%p\n", ccs->array, &ccs->array[0]);
	DEBUG_MSG("cust_con_struc_dialog_ok_lcb, array[0] at %p, *array=%p\n", ccs->array[0], *ccs->array);
	if (ccs->type == 0) {
		gchar *before=NULL, *after=NULL;
		num_vars = atoi(ccs->array[4]);
		DEBUG_MSG("cust_con_struc_dialog_ok_lcb, num_vars=%d, ccs->array[3]=%s\n", num_vars, ccs->array[3]);
		dialogarray = g_malloc((num_vars+1) * sizeof(char *));
		for (i=0; i<num_vars; i++) {
			dialogarray[i] = gtk_editable_get_chars(GTK_EDITABLE(ccs->textentry[i]), 0, -1);
			DEBUG_MSG("cust_con_struc_dialog_ok_lcb, i=%d, dialogarray[i]=%s\n", i, dialogarray[i]);
		}
		dialogarray[i] = NULL;
		DEBUG_MSG("cust_con_struc_dialog_ok_lcb, i=%d, dialogarray[i]=%p\n", i, dialogarray[i]);

		if (strlen(ccs->array[2])) {
			DEBUG_MSG("cust_con_struc_dialog_ok_lcb, ccs->array[2]=%s\n",ccs->array[2] );
			before = replace_string(ccs->array[2], dialogarray);
		}
		if (strlen(ccs->array[3])) {
			after = replace_string(ccs->array[3], dialogarray);
		}
		insert_dbl_text(before, after);
		g_strfreev(dialogarray);

		if (before) {
			g_free(before);
		}
		if (after) {
			g_free(after);
		}
	} else {
		gchar *search=NULL, *replace=NULL;
		num_vars = atoi(ccs->array[7]);
		dialogarray = g_malloc((num_vars+1) * sizeof(char *));
		for (i=0; i<num_vars; i++) {
			dialogarray[i] = gtk_editable_get_chars(GTK_EDITABLE(ccs->textentry[i]), 0, -1);
			DEBUG_MSG("cust_con_struc_dialog_ok_lcb, i=%d, dialogarray[i]=%s\n", i, dialogarray[i]);
		}
		dialogarray[i] = NULL;
		if (strlen(ccs->array[2])) {
			DEBUG_MSG("cust_con_struc_dialog_ok_lcb, ccs->array[2]=%s\n",ccs->array[2] );
			search = replace_string(ccs->array[2], dialogarray);
		}
		if (strlen(ccs->array[3])) {
			replace = replace_string(ccs->array[3], dialogarray);
		} else {
			replace = g_strdup("");
		}
		snr2_run_extern_replace(search, atoi(ccs->array[4]),
				atoi(ccs->array[5]), atoi(ccs->array[6]), replace);
		g_strfreev(dialogarray);
		if (search) {
			g_free(search);
		}
		if (replace) {
			g_free(replace);
		} 
	}
	cust_con_struc_dialog_cancel_lcb(NULL, ccs);
}

static void cust_con_struc_dialog(gchar **array, gint type) {
	Tcust_con_struc *ccs;
	GtkWidget *vbox, *hbox, *okb, *cancb;
	gint i, num_vars;

	ccs = g_malloc(sizeof(Tcust_con_struc));
	ccs->type = type;
	DEBUG_MSG("cust_con_struc_dialog_cb, ccs at %p\n", ccs);
	ccs->array = array;
	DEBUG_MSG("cust_con_struc_dialog_cb, array at %p, &array[0]=%p\n", ccs->array, &ccs->array[0]);
	DEBUG_MSG("cust_con_struc_dialog_cb, array[0] at %p, *array=%p\n", ccs->array[0], *ccs->array);
	ccs->dialog = window_full(ccs->array[0], GTK_WIN_POS_MOUSE, GTK_WINDOW_DIALOG, 
			5, cust_con_struc_dialog_cancel_lcb, ccs);
	vbox = gtk_vbox_new(TRUE, 0);
	gtk_container_add(GTK_CONTAINER(ccs->dialog), vbox);
	DEBUG_MSG("cust_con_struc_dialog_cb, ccs->array[0]=%s\n", ccs->array[0]);
	
	if (type == 0) {
		num_vars = atoi(ccs->array[4]);
	} else {
		num_vars = atoi(ccs->array[7]);
	}
	DEBUG_MSG("cust_con_struc_dialog_cb, num_vars=%d\n", num_vars);

	for (i=0; i<num_vars; i++) {
		hbox = gtk_hbox_new(FALSE, 0);
		if (type ==0) {
			gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(ccs->array[i+5]), TRUE, TRUE, 2);
		} else {
			gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(ccs->array[i+8]), TRUE, TRUE, 2);
		}
		ccs->textentry[i] = gtk_entry_new();
		DEBUG_MSG("cust_con_struc_dialog_cb, textentry[%d]=%p\n", i, ccs->textentry[i]);
		gtk_box_pack_start(GTK_BOX(hbox), ccs->textentry[i], TRUE, TRUE, 0);		
		gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
	}

	hbox = gtk_hbox_new(TRUE, 0);
	okb = bf_stock_ok_button(cust_con_struc_dialog_ok_lcb, ccs);
	cancb = bf_stock_cancel_button(cust_con_struc_dialog_cancel_lcb, ccs);
	gtk_box_pack_start(GTK_BOX(hbox), okb, TRUE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), cancb, TRUE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);

	gtk_widget_grab_focus(ccs->textentry[0]);
	gtk_widget_show_all(ccs->dialog);
}
/*****************************************************************************/


typedef struct {
	GtkItemFactoryEntry entry;
	gchar **array;
} Tcmenu_entry;

static void cust_menu_lcb(GtkWidget * widget, gpointer data) {
	Tcmenu_entry *cmentry;

	cmentry = (Tcmenu_entry *) g_list_nth_data(main_v->cmenu_arrays, GPOINTER_TO_INT(data));
	if (strcmp(cmentry->array[1], "0") ==0) {
		DEBUG_MSG("cust_menu_lcb, a custom dialog, array[4]=%s\n", cmentry->array[4]);
		if (atoi(cmentry->array[4]) > 0) {
		     cust_con_struc_dialog(cmentry->array, 0);
		} else {
		     insert_dbl_text (cmentry->array[2],cmentry->array[3]);
		}
	} else {
		DEBUG_MSG("cust_menu_lcb, count_array(cmentry->array)=%d\n", count_array(cmentry->array));
		DEBUG_MSG("cust_menu_lcb, a custom search and replace!, cmentry->array[7]=%s\n", cmentry->array[7]);
		if (strcmp(cmentry->array[4], "2")==0 && !GTK_EDITABLE(main_v->current_document->textbox)->has_selection) {
			error_dialog(_("Bluefish error"), _("This custom search and replace requires a selection"));
			return;
		}
		if (atoi(cmentry->array[7]) > 0) {
			cust_con_struc_dialog(cmentry->array, 1);
		} else {
		     snr2_run_extern_replace(cmentry->array[2], atoi(cmentry->array[4]),
							atoi(cmentry->array[5]), atoi(cmentry->array[6]), cmentry->array[3]);
		}
	}
}

static void create_parent_and_tearoff(gchar *menupath, GtkItemFactory *ifactory) {
	char *basepath;
	GtkWidget *widg=NULL;
	GtkItemFactoryEntry entry;

	basepath = g_strndup(menupath, (strlen(menupath) - strlen(strrchr(menupath, '/'))));
	DEBUG_MSG("create_parent_and_tearoff, basepath=%s\n", basepath);
	widg = gtk_item_factory_get_widget(ifactory, basepath);
	if (!widg) {
		create_parent_and_tearoff(basepath, ifactory);
		entry.path = g_strconcat(basepath, "/sep", NULL);
		entry.accelerator = NULL;
		entry.callback = NULL;
		entry.callback_action = 0;
		entry.item_type = "<Tearoff>";
		gtk_item_factory_create_item(ifactory, &entry, NULL, 2);
		g_free(entry.path);
	}
}

static gchar **convert_old_cmenu_entry(gchar **old_entry) {
	gchar ** new_entry;
	gint i, j, count = count_array(old_entry) + 1;

	DEBUG_MSG("convert_old_cmenu_entry, converting %s\n", old_entry[0]);
	new_entry = g_malloc((count+1) * sizeof(gchar *) );
	for (i=0; i<count;i++) {
		j = i > 0 ? i+1 : i;
		new_entry[j] = g_strdup(old_entry[i]);
	}
	new_entry[1] = g_strdup("0");
	new_entry[count] = NULL;
	return new_entry;
}

static void fill_cust_menubar() {
	GtkItemFactory *ifactory;
	gint count;
	gchar **splittedstring;
	GList *tmplist;
	Tcmenu_entry *cmentry;

	ifactory = gtk_item_factory_from_widget(main_v->cmenu);

	tmplist = g_list_first(main_v->cmenu_arrays);
	while (tmplist) {
		cmentry = (Tcmenu_entry *) tmplist->data;
		gtk_item_factory_delete_entry(ifactory, &cmentry->entry);
		DEBUG_MSG("fill_cust_menubar, removed entry.path=%s\n", cmentry->entry.path);
		g_free(cmentry->entry.path);
		g_free(cmentry);
		tmplist = g_list_next(tmplist);
	}
	g_list_free(main_v->cmenu_arrays);
	main_v->cmenu_arrays = NULL;

	count = 0;
	tmplist = g_list_first(main_v->props.cust_menu);
	while (tmplist) {
		gint count2;
		splittedstring = (gchar **) tmplist->data;
		count2 = count_array(splittedstring);
		
		/* this is for backwards compatibility with bluefish < 0.7 */
		if (count2 < 4) {
			tmplist = g_list_next(tmplist);
			continue;
		}
		DEBUG_MSG("fill_cust_menubar, splittedstring[1]='%s'\n", splittedstring[1]);
		if ((strcmp(splittedstring[1], "0") != 0) && (strcmp(splittedstring[1], "1") != 0)) {
			gchar **new_splittedstring = convert_old_cmenu_entry(splittedstring);
			tmplist->data = new_splittedstring;
			g_strfreev (splittedstring);
			splittedstring = new_splittedstring;
		}

		if (count2 < 5) {
			DEBUG_MSG("fill_cust_menubar, array count < 4, this is invalid\n");
			tmplist = g_list_next(tmplist);
			continue;
		}
		if ((strcmp(splittedstring[1] , "1")==0) && (count2 < 8)) {
			DEBUG_MSG("fill_cust_menubar, type 1, array count < 8, this is invalid\n");
			tmplist = g_list_next(tmplist);
			continue;
		}
		
		cmentry = g_malloc0(sizeof(Tcmenu_entry));
		cmentry->entry.path = g_strdup(splittedstring[0]);
		DEBUG_MSG("fill_cust_menubar, entry.path=%s, count=%d\n", cmentry->entry.path, count);
		cmentry->entry.callback = cust_menu_lcb;
		cmentry->entry.callback_action = count;
		cmentry->array = splittedstring;
		create_parent_and_tearoff(cmentry->entry.path, ifactory);
		gtk_item_factory_create_item(ifactory, &cmentry->entry, GINT_TO_POINTER(count), 2);
		main_v->cmenu_arrays = g_list_append(main_v->cmenu_arrays, cmentry);
		count++;
		tmplist = g_list_next(tmplist);
	}
}

static GList *add_ar(GList *list, gchar **ar) {
	gchar **tmp = ar, **array;
	gint count = count_array(ar);

	array = g_malloc((count+1) * sizeof(gchar *) );
	count=0;
	while (*tmp) {
		array[count] = g_strdup(*tmp);
		count++;
		tmp++;
	}
	array[count] = NULL;
	return g_list_append(list, array);
}
/* the format of the array is explained above */

void reset_cust_menu_list_cb(GtkWidget * widget, gpointer data)
{
	gchar *ar1[]= {N_("/php/ibase/ibase fetch row"), "0", "while ($%1 = ibase_fetch_row($%0)) {\n	echo $%1[0];\n", "\n}\nibase_free_result($%0);\n", "2", _("ibase result variable name"), _("row variable name"), NULL};
	gchar *ar2[]= {N_("/php/mysql/mysql fetch row"), "0", "while ($%1 = mysql_fetch_row($%0)) {\n	echo $%1[0];\n", "\n}\nmysql_free_result($%0);\n", "2", _("mysql result variable name"), _("row variable name"), NULL};
	gchar *ar3[]= {N_("/php/mysql/mysql connect"), "0", "$mysql_id = mysql_connect('%0', '%1', '%2');\nmysql_select_db('%3', $mysql_id);\n", "", "4", _("mysql host"), _("mysql username"), _("mysql password"), _("database name"), NULL};
	gchar *ar4[]= {N_("/php/ibase/ibase connect"), "0", "$ibase_id = ibase_connect('%0:%1', '%2', '%3');\n", "", "4", _("ibase host"), _("ibase database path"), _("ibase username"), _("ibase password"), NULL};
	gchar *ar5[]= {N_("/php/general/while each in array list"), "0", "while (list($key, $val) = each($%0)) {\n	", "\n}\n", "1", _("array name"), NULL};
	gchar *ar6[]= {N_("/sql/select all from table"), "0", "SELECT * FROM %0", "", "1", _("table name"), NULL};
	gchar *ar7[] = {N_("/php/general/mail"), "0", "mail(\"%0\", \"%1\", $%2);\n", "", "3", _("email adress"), _("subject"), _("mail body variable name"),  NULL};
	gchar *ar8[] = {N_("/php/general/for loop"), "0", "for ($%0 = %1; $%0 <= %2; $%0++) {\n ", "\n}\n", "3", _("loop variable name"), _("from value"), _("to value"),  NULL};
	gchar *ar9[] = {N_("/php/ibase/query"), "0", "$%0 = ibase_query(%1, %2);\nif (ibase_errmsg() != 0){\n	echo 'Error: '.%2.' returned '.ibase_errmsg().\"<br>\\n\";\n}\n", "", "3", _("result variable name"), _("ibase connection id name"), _("query string (quoted) or variable (including $)"),  NULL};
	gchar *ar10[] = {N_("/php/general/include file"), "0", "include('%0');\n", "", "1", _("filename to include"), NULL};
	gchar *ar11[] = {N_("/php/general/require file"), "0", "require('%0');\n", "", "1", _("filename to require"), NULL};
	gchar *ar12[] = {N_("/php/general/if isset"), "0", "if (isset($%0)) {\n	", "\n}", "1", _("variable name to test for"), NULL};
	gchar *ar13[] = {N_("/php/general/if not isset"), "0", "if (!isset($%0)) {\n	", "\n}", "1", _("variable name to test for"), NULL};
	gchar *ar14[] = {N_("/php/mysql/query"), "0", "$%0 = mysql_query(%2, %1);\n", "", "3", _("result variable name"), _("mysql connection id name"), _("query string (quoted) or variable (including $)"),  NULL};
	gchar *ar15[] = {N_("/html/font symbol"), "0", "<font face=\"Symbol\">", "</font>", NULL};
	gchar *ar16[] = {N_("/html/div with class"), "0", "<div class=\"%0\">", "</div>", "1", _("CSS class name"), NULL};
	gchar *ar17[] = {N_("/html/span with class"), "0", "<span class=\"%0\">", "</span>", "1", _("CSS class name"), NULL};
	gchar *ar18[]= {N_("/php/php block"), "0", "\n<?php\n", "\n?>\n", NULL};
	gchar *ar19[]= {N_("/html/made with bluefish"), "0", "<a href=\"http://bluefish.openoffice.nl/\">Made with the Bluefish HTML editor</a>", "", NULL};
	gchar *ar20[]= {N_("/html/meta keywords"), "0", "<meta name=\"keywords\" value=\"%0\">", "", "1", _("keywords, space separated"), NULL};
	gchar *ar21[]= {N_("/html/meta refresh (client pull)"), "0", "<meta http-equiv=\"refresh\" content=\"%0; URL=%1\">", "", "2", _("refresh time, in seconds"), _("URL to redirect to"), NULL};
	gchar *ar22[]= {N_("/active html/form"), "0", "<form method=\"POST\" action=\"<?php echo $SCRIPT_NAME ?>\">\n\n", "</form>", NULL};
	gchar *ar23[]= {N_("/active html/form and action"), "0", "<?php if (isset($submitted)) {\n//form submit code here\n} else { ?>\n<form method=\"POST\" action=\"<?php echo $SCRIPT_NAME ?>\">\n\n<input type=\"submit\" name=\"submitted\" value=\"%0\"></form>\n<?php } // end of form ?>", "", "1", _("Submit button text"), NULL};
	gchar *ar24[]= {N_("/active html/input text"), "0", "<input type=\"text\" name=\"%0\" value=\"<?php if (isset($%0)) { echo $%0; } ?>\">", "", "1", _("variable name"), NULL};
	gchar *ar25[]= {N_("/active html/input checkbox"), "0", "<input type=\"checkbox\" name=\"%0\" value=\"%1\" <?php if (isset($%0)) { echo 'checked'; } ?>>", "", "2", _("variable name"), _("value when checked"), NULL};
	gchar *ar26[]= {N_("/active html/textarea"), "0", "<textarea name=\"%0\" rows=\"20\" cols=\"40\"><?php if (isset($%0)) { echo $%0; } ?></textarea>", "", "1", _("variable name"), NULL};
	gchar *ar27[]= {N_("/active html/select options/from array"), "0", "<select name=\"%0\">\n<?php\nwhile(list($key, $val)=each($%1)) {\n\tif (isset($%0) && ($%0 == $val)) {\n\t\techo '<option value=\"'.$key.'\" selected>'.$val.'</option>';\n\t} else {\n\t\techo '<option value=\"'.$key.'\">'.$val.'</option>';\n\t}\n}\n?></select>", "", "2", _("variable name"), _("array name containing options"), NULL};
	gchar *ar28[]= {N_("/active html/select options/from mysql result"), "0", "<select name=\"%0\">\n<?php\nwhile($row = mysql_fetch_row($%1)) {\n\tif (isset($%0) && ($%0 == $row[%2])) {\n\t\techo '<option value=\"'.$row[%2].'\" selected>'.$row[%3].'</option>';\n\t} else {\n\t\techo '<option value=\"'.$row[%2].'\">'.$row[%3].'</option>';\n\t}\n}\n?></select>", "", "4", _("variable name"), _("mysql query result"), _("index of the value"), _("index of the label"), NULL};
	gchar *ar29[]= {N_("/active html/select options/from ibase result"), "0", "<select name=\"%0\">\n<?php\nwhile($row = ibase_fetch_row($%1)) {\n\tif (isset($%0) && ($%0 == $row[%2])) {\n\t\techo '<option value=\"'.$row[%2].'\" selected>'.$row[%3].'</option>';\n\t} else {\n\t\techo '<option value=\"'.$row[%2].'\">'.$row[%3].'</option>';\n\t}\n}\n?></select>", "", "4", _("variable name"), _("ibase query result"), _("index of the value"), _("index of the label"), NULL};
	gchar *ar30[]= {N_("/DHTML/mouseover image"), "0", "<a href=\"\" onMouseOver=\"bfmovepic('%0', '%2')\" onMouseOut=\"bfmovepic('%0', '%1')\"><img src=\"%1\" name=\"%0\"></a>", "", "3", _("unique name"), _("onMouseOut src"), _("onMouseOver src"), NULL};
	gchar *ar31[]= {N_("/php/odbc/odbc connect"), "0", "$odbc_id = odbc_connect('%0', '%1', '%2');\n", "", "3", _("odbc data source name"), _("username"), _("password"), NULL};
	gchar *ar32[]= {N_("/php/odbc/odbc exec query"), "0", "$%0 = odbc_exec(%1, %2);\n", "", "3", _("result variable name"), _("odbc connection id name"), _("query string (quoted) or variable (including $)"), NULL};
	gchar *ar33[]= {N_("/php/odbc/odbc fetch row"), "0", "while($success = odbc_fetch_row($%0)) {\n\t\n}", "", "1", _("result variable name"), NULL};
	gchar *ar34[]= {N_("/php/general/echo date"), "0", "echo date(\"l dS of F Y h:i:s A\");", "", NULL};
	gchar *ar35[]= {N_("/php/filesystem/open and echo file"), "0", "$fd = fopen(%0, 'r');\nwhile (!feof($fd)) {\n\t$buffer = fgets($fd, 4096);\n\techo $buffer;\n}\nfclose($fd);", "", "1", _("file (quoted) or variable (including $)"), NULL};
	gchar *ar36[]= {N_("/php/general/location header"), "0", "header('Location: '.%0);", "", "1", _("location (URL) to redirect to (quoted) or variable (including $)"), NULL};
	gchar *ar37[]= {N_("/apache/basic password required"), "0", "AuthName \"%1\"\nAuthType Basic\nrequire valid-user\nAuthUserFile %0\n", "", "2", _("full path to password file"), _("security description"), NULL};
	gchar *ar38[]= {N_("/apache/deny access to .inc"), "0", "<FilesMatch \"\\.inc$\">\n	Order allow,deny\n	Deny from all\n</FilesMatch>", "", "0", NULL};	
	gchar *ar39[]= {N_("/replace/strip <font>"), "1", "(<font[^>]*>|</font>)", "", "0", "1", "0", "0", NULL};
	gchar *ar40[]= {N_("/replace/strip <any tag> in selection"), "1", "(<%0[^>]*>|</%0>)", "", "2", "1", "0", "1", "tag name, like td, font or a", NULL};
	gchar *ar41[]= {N_("/replace/convert <td> in <th> in selection"), "1", "(<|</)(td)([^>]*)(>)", "\\0th\\2>", "2", "1", "0", "0", NULL};
	gchar *ar42[]= {N_("/replace/convert <any tag> in <any other tag> in selection"), "1", "(<|</)(%0)([^>]*)(>)", "\\0%1\\2>", "2", "1", "0", "2", "any tag name", "any other tag name", NULL};
	free_arraylist(main_v->props.cust_menu);

	main_v->props.cust_menu = NULL;

/* generated in BASH 2 using:
for ((i=1;i<37;i++)) ; do echo "main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar$i);"; done
*/

	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar1);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar2);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar3);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar4);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar5);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar6);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar7);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar8);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar9);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar10);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar11);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar12);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar13);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar14);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar15);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar16);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar17);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar18);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar19);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar20);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar21);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar22);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar23);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar24);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar25);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar26);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar27);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar28);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar29);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar30);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar31);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar32);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar33);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar34);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar35);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar36);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar37);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar38);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar39);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar40);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar41);
	main_v->props.cust_menu = add_ar(main_v->props.cust_menu, ar42);
	fill_cust_menubar();
}

/*******************************************************************/
/*               Custom menu editor                                */
/*******************************************************************/

typedef struct {
	GtkWidget *win;
	GtkWidget *type[2];
	GtkWidget *clist;
	GtkWidget *label1;
	GtkWidget *label2;
	GtkWidget *menupath;
	GtkWidget *before;
	GtkWidget *after;
	GtkWidget *num;
	gchar **lastarray;
	GtkWidget *dynvbox;
	GtkWidget *hboxes[MAX_TEXT_ENTRY];
	GtkWidget *descriptions[MAX_TEXT_ENTRY];
	GtkWidget *csnr_box;
	GtkWidget *region;
	GtkWidget *is_regex;
	GtkWidget *is_case_sens;
	GList *worklist;
} Tcmenu_editor;

static void cme_destroy_lcb(GtkWidget *widget, GdkEvent *event, Tcmenu_editor* cme) {
	window_destroy(cme->win);
	free_arraylist(cme->worklist);
	g_free(cme);
}

static void cme_close_lcb(GtkWidget *widget, gpointer data) {
	cme_destroy_lcb(NULL, NULL, data);
}

static void cme_ok_lcb(GtkWidget *widget, Tcmenu_editor *cme) {
	GList *tmplist;

	tmplist = main_v->props.cust_menu;
	main_v->props.cust_menu = cme->worklist;
	cme->worklist = tmplist;
	cme_destroy_lcb(NULL, NULL, cme);
	fill_cust_menubar();
}

static void cme_clist_unselect_lcb(GtkWidget * widget, gint row, gint column, GdkEventButton * event, Tcmenu_editor *cme) {
	gint i;

	DEBUG_MSG("cme_clist_unselect_lcb, column=%d, row=%d\n", column, row);
	gtk_entry_set_text(GTK_ENTRY(cme->menupath), "");
	gtk_editable_delete_text(GTK_EDITABLE(cme->before), 0, -1);
	gtk_editable_delete_text(GTK_EDITABLE(cme->after), 0, -1);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(cme->num), 0);
	for (i = 0 ; i < MAX_TEXT_ENTRY; i++) {
		gtk_entry_set_text(GTK_ENTRY(cme->descriptions[i]), "");
	}
	cme->lastarray = NULL;
	DEBUG_MSG("cme_clist_unselect_lcb, lastarray=%p\n", cme->lastarray);
}

static void cme_create_entries(Tcmenu_editor *cme, gint num) {
	gint i;

	for (i = 0; i < MAX_TEXT_ENTRY ; i++) {
		if (i < num) {
			gtk_widget_show(cme->hboxes[i]);
		} else {
			gtk_widget_hide(cme->hboxes[i]); 
		}
	}
}

static void cme_spin_changed_lcb(GtkWidget *widget, Tcmenu_editor *cme) {
	cme_create_entries(cme, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cme->num)));
}

static void cme_type_changed_lcb(GtkWidget *widget, Tcmenu_editor *cme) {
	if (GTK_TOGGLE_BUTTON(cme->type[1])->active) {
		DEBUG_MSG("cme_clist_select_lcb, type[1] is active\n");
		gtk_widget_show(cme->csnr_box);
		gtk_label_set_text(GTK_LABEL(cme->label1), _("Search pattern"));
		gtk_label_set_text(GTK_LABEL(cme->label2), _("Replace string"));
	} else {
		gtk_widget_hide(cme->csnr_box);
		gtk_label_set_text(GTK_LABEL(cme->label1), _("Formatstring before"));
		gtk_label_set_text(GTK_LABEL(cme->label2), _("Formatstring after"));
	}
}

static void cme_clist_select_lcb(GtkWidget * widget, gint row, gint column, GdkEventButton * event, Tcmenu_editor *cme) {
	gint num=0, pos=0, i;
	gint type=0;

	DEBUG_MSG("cme_clist_select_lcb, row=%d\n", row);
	cme->lastarray = g_list_nth_data(cme->worklist, row);
	DEBUG_MSG("cme_clist_select_lcb, lastarray=%p\n", cme->lastarray);

	i = count_array(cme->lastarray);
	if (i<5) {
		DEBUG_MSG("cme_clist_select_lcb, invalid array count! (1)\n");
		cme->lastarray = NULL;
		return;
	}
	if (strcmp(cme->lastarray[1], "0")==0) {
		type = 0;
		DEBUG_MSG("cme_clist_select_lcb, type=%d\n", type);
	}
	if (strcmp(cme->lastarray[1], "1")==0) {
		type = 1;
		if (i < 8) {
			DEBUG_MSG("cme_clist_select_lcb, invalid array count (2)!\n");
			cme->lastarray = NULL;
			return;
		}
		DEBUG_MSG("cme_clist_select_lcb, type=%d\n", type);
	}
	if (type > 1) {
		DEBUG_MSG("cme_clist_select_lcb, invalid type! (type=%d)\n", type);
		cme->lastarray = NULL;
		return;
	}

	DEBUG_MSG("cme_clist_select_lcb, cme->lastarray[0]=%s, [i]='%s'\n", cme->lastarray[0], cme->lastarray[1]);
	gtk_entry_set_text(GTK_ENTRY(cme->menupath), cme->lastarray[0]);
	
	gtk_editable_delete_text(GTK_EDITABLE(cme->before), 0, -1);
	DEBUG_MSG("cme_clist_select_lcb, cme->lastarray[2]='%s'\n", cme->lastarray[2]);
	gtk_editable_insert_text(GTK_EDITABLE(cme->before), cme->lastarray[2], strlen(cme->lastarray[2]), &pos);
	gtk_editable_delete_text(GTK_EDITABLE(cme->after), 0, -1);
	DEBUG_MSG("cme_clist_select_lcb, cme->lastarray[3]='%s'\n", cme->lastarray[3]);
	pos = 0;
	gtk_editable_insert_text(GTK_EDITABLE(cme->after), cme->lastarray[3], strlen(cme->lastarray[3]), &pos);
	DEBUG_MSG("cme_clist_select_lcb, type=%d\n", type);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cme->type[type]), TRUE);
	if (type == 0) {
		DEBUG_MSG("cme_clist_select_lcb, type=0, custom dialog\n");
		gtk_widget_hide(cme->csnr_box);
		
		num = atoi(cme->lastarray[4]);
		DEBUG_MSG("cme_clist_select_lcb, num=%d\n", num);
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(cme->num), num);
	
		cme_create_entries(cme, num);
		DEBUG_MSG("cme_clist_select_lcb, %d entries created\n", num);
		for (i = 0 ; i < num; i++) {
			gtk_entry_set_text(GTK_ENTRY(cme->descriptions[i]), cme->lastarray[i+5]);
		}
		for (i = num ; i < MAX_TEXT_ENTRY; i++) {
			gtk_entry_set_text(GTK_ENTRY(cme->descriptions[i]), "");
		}
	}
	if (type == 1) {
		static Tconvert_table table1[] = {{0, "0"}, {1, "1"}, NULL};
		static Tconvert_table table2[] = {{0, "current document"}, {1, "from cursor"}, {2, "in selection"}, {3, "in all open documents"}, NULL};
		gint regioni;
		gchar *regionc;
		DEBUG_MSG("cme_clist_select_lcb, type=1, custom search and replace\n");
		gtk_widget_show(cme->csnr_box);
		DEBUG_MSG("cme_clist_select_lcb, cme->lastarray[5]=%s\n", cme->lastarray[5]);
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cme->is_regex), table_convert_char2int(table1, cme->lastarray[5]));
		DEBUG_MSG("cme_clist_select_lcb, cme->lastarray[6]=%s\n", cme->lastarray[6]);
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cme->is_case_sens), table_convert_char2int(table1, cme->lastarray[6]));
		
		gtk_editable_delete_text(GTK_EDITABLE(GTK_COMBO(cme->region)->entry), 0, -1);
		regioni = atoi(cme->lastarray[4]);
		regionc = table_convert_int2char(table2, regioni);
		if (regionc) {
			gtk_editable_insert_text(GTK_EDITABLE(GTK_COMBO(cme->region)->entry), regionc, strlen(regionc), &pos);
		}

		num = atoi(cme->lastarray[7]);
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(cme->num), num);
	
		cme_create_entries(cme, num);
		for (i = 0 ; i < num; i++) {
			gtk_entry_set_text(GTK_ENTRY(cme->descriptions[i]), cme->lastarray[i+8]);
		}
		for (i = num ; i < MAX_TEXT_ENTRY; i++) {
			gtk_entry_set_text(GTK_ENTRY(cme->descriptions[i]), "");
		}
	}
	DEBUG_MSG("cme_clist_select_lcb, finished\n");
}

static gchar **cme_create_array(Tcmenu_editor *cme) {
	gchar **newarray;
	gint num, i, type;
	
	gtk_spin_button_update(GTK_SPIN_BUTTON(cme->num));
	num  = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cme->num));
	DEBUG_MSG("cme_create_array, num=%d\n", num);
	if (GTK_TOGGLE_BUTTON(cme->type[1])->active) {
		type = 1;
	} else {
		type = 0;
	}
	if (type == 0) {
		newarray = g_malloc0((num+6) * sizeof(char *));
	} else {
		newarray = g_malloc0((num+9) * sizeof(char *));
	}
	newarray[0] = gtk_editable_get_chars(GTK_EDITABLE(cme->menupath), 0, -1);
	if (newarray[0][0] != '/') {
		DEBUG_MSG("cme_create_array, menupath does not start with slash, returning NULL\n");
		g_free(newarray[0]);
		g_free(newarray);
		return (NULL);
	}
	
	if (type == 0) {
		newarray[1] = g_strdup("0");

		newarray[4] = gtk_editable_get_chars(GTK_EDITABLE(cme->num), 0, -1);
		DEBUG_MSG("cme_create_array, newarray[4]=%s\n", newarray[4]);
		for (i = 0 ; i < num; i++) {
			DEBUG_MSG("cme_create_array, adding descriptions[%d] to newarray[%d]\n", i, i+5);
			newarray[5+i] = gtk_editable_get_chars(GTK_EDITABLE(cme->descriptions[i]), 0, -1);
		}
		DEBUG_MSG("cme_create_array, setting newarray[%d] to NULL\n",i+5);
		newarray[5+i] = NULL;
	} else {
		static Tconvert_table table2[] = {{0, "current document"}, {1, "from cursor"}, {2, "in selection"}, {3, "in all open documents"}, NULL};
		gint regioni;
		gchar *regionc;
		newarray[1] = g_strdup("1");
		regionc = gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(cme->region)->entry), 0, -1);
		regioni = table_convert_char2int(table2, regionc);
		g_free(regionc);
		newarray[4] = g_strdup_printf("%d", regioni);
		newarray[5] = g_strdup_printf("%d", GTK_TOGGLE_BUTTON(cme->is_regex)->active);
		newarray[6] = g_strdup_printf("%d", GTK_TOGGLE_BUTTON(cme->is_case_sens)->active);
	
		newarray[7] = gtk_editable_get_chars(GTK_EDITABLE(cme->num), 0, -1);
		DEBUG_MSG("cme_create_array, newarray[7]=%s\n", newarray[7]);
		for (i = 0 ; i < num; i++) {
			DEBUG_MSG("cme_create_array, adding descriptions[%d] to newarray[%d]\n", i, i+8);
			newarray[8+i] = gtk_editable_get_chars(GTK_EDITABLE(cme->descriptions[i]), 0, -1);
		}
		DEBUG_MSG("cme_create_array, setting newarray[%d] to NULL\n",i+8);
		newarray[8+i] = NULL;
	}
	newarray[2] = gtk_editable_get_chars(GTK_EDITABLE(cme->before), 0, -1);
	newarray[3] = gtk_editable_get_chars(GTK_EDITABLE(cme->after), 0, -1);
	
	return newarray;
}

static void cme_add_lcb(GtkWidget *widget, Tcmenu_editor *cme) {
	gchar **newarray;
	gchar *tmplistentry[1]; 
	gint row;

	newarray = cme_create_array(cme);
	if (newarray != NULL){
	     cme->worklist = g_list_append(cme->worklist, newarray);
	     tmplistentry[0] = newarray[0];
	     row = gtk_clist_append(GTK_CLIST(cme->clist), tmplistentry);
		  cme->lastarray = newarray;
		  DEBUG_MSG("cme_add_lcb, about to select row %d\n", row);
		  gtk_clist_select_row(GTK_CLIST(cme->clist), row, 0);
	}
}

static void cme_update_lcb(GtkWidget *widget, Tcmenu_editor *cme) {
	GList *tmplist;
	gchar **newarray;
	gint row;

	if (cme->lastarray == NULL) {
		cme_add_lcb(NULL, cme);
		return;
	}

	newarray = cme_create_array(cme);
	if (newarray) {

		row = g_list_index(cme->worklist, cme->lastarray);
		tmplist = g_list_nth(cme->worklist, row);
		g_strfreev(cme->lastarray);
		DEBUG_MSG ("cme_update_lcb, row=%d\n", row);

		tmplist->data = newarray;
		gtk_clist_set_text(GTK_CLIST(cme->clist), row, 0, newarray[0]);

		cme->lastarray = g_list_nth_data(cme->worklist, row);
	} else {
		DEBUG_MSG ("cme_update_lcb, no new array, cancelled\n");
	}
	DEBUG_MSG ("cme_update_lcb finished\n");
}

static void cme_delete_lcb(GtkWidget *widget, Tcmenu_editor *cme) {
	gint row;
	gchar **array;
	
	if (cme->lastarray) {
		array = cme->lastarray;
		DEBUG_MSG("cme_delete_lcb, delete lastarray %p\n", array);
		row = g_list_index(cme->worklist, array);
		DEBUG_MSG("cme_delete_lcb, g_list_length=%d\n", g_list_length(cme->worklist));
		cme->worklist = g_list_remove(cme->worklist, array);
		DEBUG_MSG("cme_delete_lcb, row=%d, g_list_length=%d\n", row, g_list_length(cme->worklist));
		gtk_clist_remove(GTK_CLIST(cme->clist), row);
		g_strfreev(array);
		cme->lastarray = NULL;
	} else {
		DEBUG_MSG("cme_delete_lcb, lastarray=NULL, nothing to delete\n");
	}
}

gint menu_entry_sort(gchar ** a,gchar ** b) {
	return strcmp(a[0],b[0]);
}

void cmenu_editor(GtkWidget *widget, gpointer data) {
	Tcmenu_editor *cme;
	GtkWidget *hbox, *vbox,*frame, *vbox2, *but, *scrolwin, *hbox2;
	GList *tmplist, *popuplist;
	gchar *tmplistentry[1];
	gchar **splittedstring;
	gint i;
	gchar *tmpstr;
	
	cme = g_malloc0(sizeof(Tcmenu_editor));
	cme->win = window_full(_("Bluefish config - custom menu"), GTK_WIN_POS_NONE
			, GTK_WINDOW_DIALOG, 5, cme_destroy_lcb, cme);

	vbox = gtk_vbox_new(FALSE, 2);
	gtk_container_add(GTK_CONTAINER(cme->win), vbox);
	/* upper area */
	hbox = gtk_hbox_new(FALSE, 2);
	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);

	gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(_("Menu path")), FALSE, FALSE, 0);
	cme->menupath = gtk_entry_new();
	gtk_box_pack_start(GTK_BOX(hbox),cme->menupath , TRUE, TRUE, 0);

	hbox = gtk_hbox_new(FALSE, 2);
	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

	/* clist & type area */
	vbox2 = gtk_vbox_new(FALSE, 0);	
	gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
	scrolwin = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	cme->clist = gtk_clist_new(1);
	gtk_signal_connect(GTK_OBJECT(cme->clist), "select_row", GTK_SIGNAL_FUNC(cme_clist_select_lcb), cme);
	gtk_signal_connect(GTK_OBJECT(cme->clist), "unselect_row", GTK_SIGNAL_FUNC(cme_clist_unselect_lcb), cme);

	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolwin), cme->clist);
	gtk_widget_set_usize(scrolwin, 180, 250);
	gtk_box_pack_start(GTK_BOX(vbox2), scrolwin, TRUE, TRUE, 0);

	cme->type[0] = gtk_radio_button_new_with_label(NULL, _("custom dialog"));
	gtk_box_pack_start(GTK_BOX(vbox2), cme->type[0], TRUE, TRUE, 0);
	cme->type[1] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(cme->type[0]), _("custom search and replace"));
	gtk_box_pack_start(GTK_BOX(vbox2), cme->type[1], TRUE, TRUE, 0);

	gtk_signal_connect(GTK_OBJECT(cme->type[0]), "toggled", cme_type_changed_lcb, cme);

	/* dynamic entries area */
	vbox2 = gtk_vbox_new(FALSE, 0);	
	gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);

	gtk_box_pack_start(GTK_BOX(vbox2), gtk_label_new(_("Number of variables")), FALSE, FALSE, 0);		
	cme->num = spinbut_with_value(NULL, 0, MAX_TEXT_ENTRY, 1,1);
	gtk_signal_connect(GTK_OBJECT(cme->num), "changed", cme_spin_changed_lcb, cme);
	gtk_box_pack_start(GTK_BOX(vbox2),cme->num , FALSE, FALSE, 0);
	
	frame = gtk_frame_new(_("Variables"));
	gtk_box_pack_end(GTK_BOX(vbox2), frame, TRUE, TRUE, 0);
	cme->dynvbox = gtk_vbox_new(FALSE, 0);	
	gtk_container_add(GTK_CONTAINER(frame), cme->dynvbox);
	for (i = 0; i <  MAX_TEXT_ENTRY; i++) {
		cme->hboxes[i] = gtk_hbox_new(FALSE, 0);
		gtk_box_pack_start(GTK_BOX(cme->dynvbox), cme->hboxes[i], FALSE, FALSE, 0);
		tmpstr = g_strdup_printf("%%%d", i);
		gtk_box_pack_start(GTK_BOX(cme->hboxes[i]), gtk_label_new(tmpstr), FALSE, FALSE, 0);
		g_free(tmpstr);
		cme->descriptions[i] = gtk_entry_new();
		gtk_box_pack_start(GTK_BOX(cme->hboxes[i]), cme->descriptions[i], TRUE, TRUE, 0);
	}

	/* lower area */
	hbox = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);

	/* before and after text area */
	vbox2 = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
	
	/* csnr area */
	cme->csnr_box = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(vbox2), cme->csnr_box, TRUE, TRUE, 0);

	hbox2 = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(cme->csnr_box), hbox2, TRUE, TRUE, 0);
	
	gtk_box_pack_start(GTK_BOX(hbox2),gtk_label_new(_("Replace where")), FALSE, FALSE, 0);
	popuplist = g_list_append(NULL, "current document");
	popuplist = g_list_append(popuplist, "from cursor");
	popuplist = g_list_append(popuplist, "in selection");
	popuplist = g_list_append(popuplist, "in all open documents");
	cme->region = combo_with_popdown(NULL, popuplist, 0);
	g_list_free(popuplist);
	gtk_box_pack_start(GTK_BOX(hbox2),cme->region , TRUE, TRUE, 0);

	hbox2 = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(cme->csnr_box), hbox2, TRUE, TRUE, 0);
	cme->is_case_sens = boxed_checkbut_with_value(_("case sensitive"), 0, hbox2);
	cme->is_regex = boxed_checkbut_with_value(_("regular expression"), 0, hbox2);
	
	cme->label1 = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(vbox2), cme->label1, FALSE, FALSE, 0);
	cme->before = gtk_text_new(NULL, NULL);
	gtk_text_set_editable(GTK_TEXT(cme->before), TRUE);
	gtk_widget_set_usize(cme->before, 280, 50);
	gtk_box_pack_start(GTK_BOX(vbox2), cme->before, TRUE, TRUE, 0);
	cme->label2 = gtk_label_new("");
	gtk_box_pack_start(GTK_BOX(vbox2), cme->label2, FALSE, FALSE, 0);
	cme->after = gtk_text_new(NULL, NULL);
	gtk_text_set_editable(GTK_TEXT(cme->after), TRUE);
	gtk_widget_set_usize(cme->after, 280, 50);
	gtk_box_pack_start(GTK_BOX(vbox2), cme->after, TRUE, TRUE, 0);
	
	/* button area */
	vbox2 = gtk_vbox_new(FALSE, 0);	
	gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
	but = bf_stock_button(_("Add"), cme_add_lcb, cme);
	gtk_box_pack_start(GTK_BOX(vbox2), but, FALSE, FALSE, 5);
	but = bf_stock_button(_("Update"), cme_update_lcb, cme);
	gtk_box_pack_start(GTK_BOX(vbox2), but, FALSE, FALSE, 5);
	but = bf_stock_button(_("Delete"), cme_delete_lcb, cme);
	gtk_box_pack_start(GTK_BOX(vbox2), but, FALSE, FALSE, 5);

	/* frame for cancel/ok buttons */
	frame = gtk_frame_new(NULL);
	gtk_box_pack_end(GTK_BOX(vbox2), frame, FALSE, FALSE, 0);
	hbox = gtk_hbox_new(TRUE, 1);
	gtk_container_add(GTK_CONTAINER(frame), hbox);
	but = bf_stock_ok_button(cme_ok_lcb, cme);
	gtk_window_set_default(GTK_WINDOW(cme->win), but);
	gtk_box_pack_start(GTK_BOX(hbox), but, TRUE, TRUE, 0);
	
	but = bf_stock_cancel_button(cme_close_lcb, cme);
	gtk_box_pack_start(GTK_BOX(hbox), but, TRUE, TRUE, 0);
	/* ready !! */
	cme->worklist = duplicate_arraylist(main_v->props.cust_menu);
	
	tmplist = g_list_first(g_list_sort(cme->worklist, (GCompareFunc)menu_entry_sort));
	while (tmplist) {
		splittedstring = (gchar **) tmplist->data;
		tmplistentry[0] = splittedstring[0];
		gtk_clist_append(GTK_CLIST(cme->clist), tmplistentry);
		tmplist = g_list_next(tmplist);
	}
	gtk_widget_show_all(cme->win);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cme->type[0]), TRUE);
	cme_type_changed_lcb(NULL, cme);
}

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

void make_cust_menubar(GtkWidget *cust_handle_box)
{
	static GtkItemFactoryEntry cust_menu[] = {
		{N_("/_Custom menu"), NULL, NULL, 0, "<Branch>"},
		{N_("/Custom menu/sep"), NULL, NULL, 0, "<Tearoff>"},
		{N_("/Custom menu/Edit custom menu..."), NULL, cmenu_editor, 0, NULL},
		{N_("/Custom menu/Reset custom menu"), NULL, reset_cust_menu_list_cb, 0, NULL}
	};
	GtkItemFactory *item_factory;
	GtkAccelGroup *accel_group;
	gint nmenu_items = sizeof(cust_menu) / sizeof(cust_menu[0]);

	DEBUG_MSG("make_cust_menubar, started\n");

	/* this should only happen once !!!!!!!!!! */
	accel_group = gtk_accel_group_new();
	item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
#ifdef ENABLE_NLS
	gtk_item_factory_set_translate_func(item_factory, menu_translate, "<main>", NULL);
#endif
	gtk_item_factory_create_items(item_factory, nmenu_items, cust_menu, NULL);
	gtk_window_add_accel_group(GTK_WINDOW(main_v->main_window), accel_group);

	main_v->cmenu = gtk_item_factory_get_widget(item_factory, "<main>");
	gtk_container_add(GTK_CONTAINER(cust_handle_box), main_v->cmenu);
	gtk_widget_show(main_v->cmenu);

	fill_cust_menubar();

	DEBUG_MSG("make_cust_menubar, finished\n");
}

/*******************************************************************/
/*               Open Recent menu handling                         */
/*******************************************************************/

/* the only required header */
static GtkWidget *create_recent_entry(char *filename);
/*******************************************************************/

/* save_recent_list
 * Saves the items of main_v->recent_files to the .bluefish/recentlist file
 * so that they can be restored in the next Bluefish session */
/* this function is removed, append_to_file() is used instead */
/*
static void save_recent_list() {
	gchar *recentfile;
	GList *putlist=NULL, *list;

	DEBUG_MSG("save_recent_list, started\n");
#ifndef WIN32
	recentfile = g_strconcat(getenv("HOME"), "/.bluefish/recentlist", NULL);
#else
	recentfile = g_strconcat("C:\\", "recentlist", NULL);
#endif
	list = g_list_first(main_v->recent_files);	
	while (list) {
		putlist = add_to_stringlist(putlist, g_strdup(GTK_LABEL(GTK_BIN(list->data)->child)->label));
		list = g_list_next(list);
	}
	
	put_stringlist(recentfile, putlist);
	free_stringlist(putlist);
	g_free(recentfile);
}
*/

/* This function was nessecary I'm afraid, if you find a way
 * that it is not needed for open_recent_file_cb, please
 * send the patch. This also removes the last entry if
 * filename == 'last' */
static GtkWidget *remove_recent_entry(gchar *filename) {
	GList *list;
	gpointer tmp;

	if(strcmp(filename, "last") ==0) {
		list = g_list_first(main_v->recent_files);
		tmp = list->data;
		DEBUG_MSG("remove_recent_entry, remove last entry\n");
		main_v->recent_files = g_list_remove(main_v->recent_files, list->data);
		return tmp;
	}	else {
		list = g_list_first(main_v->recent_files);
		while (list) {
			DEBUG_MSG("remove_recent_entry, list=%p, data=%p\n", list, list->data);
			DEBUG_MSG("remove_recent_entry, list->data=%s\n",GTK_LABEL(GTK_BIN(list->data)->child)->label);
			if(!strcmp(GTK_LABEL(GTK_BIN(list->data)->child)->label, filename)) {
				tmp = list->data;
				main_v->recent_files = g_list_remove(main_v->recent_files, list->data);
				DEBUG_MSG("remove_recent_entry, returning %p\n", tmp);
				return tmp;
			}
			list = g_list_next(list);
		}
	}
	return NULL;
}

/* open_recent_file
 * This function should be called when a menu from the Open Recent list
 * has been selected. */

static void open_recent_file_cb(gchar *data) {
	gchar *filename=data;

	DEBUG_MSG("open_recent_file_cb, started, filename is %s\n", filename);

	/* Now, let's check if that file still exists and is readable, before loading it */
	if (!file_exists_and_readable(filename)) {
		return;
	}

	/* Open the file that was asked */
	doc_new_with_file(filename);
	DEBUG_MSG("open_recent_file_cb, document %s opened\n", filename);

/*
	tmp = remove_recent_entry(filename);
	gtk_widget_hide(tmp);

	main_v->recent_files = g_list_prepend(main_v->recent_files,
								create_recent_entry(GTK_LABEL(GTK_BIN(tmp)->child)->label, 0));
	gtk_widget_destroy(tmp);*/

	/* save the new list */
/*	save_recent_list();*/
	add_to_recent_list(filename, 0);
	return;
}

/* create_recent_entry
 * This function builds the gtkitemfactoryentry and inserts it at the
 * main_v->menubar. Furthermore, it returns a pointer to it, so that
 * this pointer can be added in the main_v->recent_files list */
static GtkWidget *create_recent_entry(char *filename) {
	GtkWidget *tmp, *menu;
	GtkItemFactory *factory;

	tmp = remove_recent_entry(filename);
	if (tmp) {
		gtk_widget_hide(tmp);
		gtk_widget_destroy(tmp);
	}

	/* add it to main_v->menubar */
	factory = gtk_item_factory_from_widget(main_v->menubar);
	menu = gtk_item_factory_get_widget(factory, N_("<main>/File/Open recent"));

	tmp = gtk_menu_item_new_with_label(filename);
	gtk_signal_connect_object(GTK_OBJECT(tmp), "activate",
					GTK_SIGNAL_FUNC(open_recent_file_cb), (gpointer) GTK_LABEL(GTK_BIN(tmp)->child)->label);
/*	gtk_signal_connect_object(GTK_OBJECT(tmp), "activate",
					GTK_SIGNAL_FUNC(open_recent_file_cb), (gpointer) g_strdup("Hello World")); */

	gtk_widget_show(tmp);
	gtk_menu_insert(GTK_MENU(menu), tmp, 1);

	flush_queue();

	/* return it */
	return tmp;
}


/* open_recent_list()
 * Gets the list of documents from .bluefish/recentlist and inserts
 * it at the File-->Open Recent menu. If the file doesn't exist (probably
 * because this is the first time Bluefish is running) then a menu
 * item telling that no recent files exist will appear */

void open_recent_list() {
	gchar *recentfile;
	GList *filenames=NULL, *tmp, *tmp2, *newlist=NULL;
	gint recent_file_count=0;

	DEBUG_MSG("open_recent_list, started\n");
	recentfile = g_strconcat(getenv("HOME"), "/.bluefish/recentlist", NULL);
	filenames = get_stringlist(recentfile, filenames);
	if (!filenames) {
		filenames = add_to_stringlist(main_v->recent_files, _("(none)"));
	}

	tmp = g_list_last(filenames);
	while (tmp && recent_file_count <= main_v->props.max_recent_files) {
		gint already_found=0;
		tmp2 = g_list_first(newlist);
		while (tmp2) {
			if (strcmp(tmp->data, tmp2->data)==0) {
				already_found=1;
			}
			tmp2 = g_list_next(tmp2);
		}
		if (!already_found) {
			recent_file_count++;
			DEBUG_MSG("open_recent_list, added %s to top of list\n", (gchar *)tmp->data);
			newlist = g_list_prepend(newlist, tmp->data);
		}
		already_found = 0;
		tmp = g_list_previous(tmp);
	}

	tmp2 = g_list_first(newlist);
	while (tmp2) {
		main_v->recent_files  = g_list_append(main_v->recent_files, create_recent_entry(tmp2->data));
		tmp2 = g_list_next(tmp2);
	}

	put_stringlist(recentfile, newlist);
	g_list_free(newlist);
	free_stringlist(filenames);

	g_free(recentfile);
}

/* Add_to_recent_list
 * This should be called when a new file is opened, i.e. from
 * file_open_cb, it adds a new entry which also appears in the
 * menu bar, and (if nessecary) deletes the last entry */
void add_to_recent_list(gchar *filename, gint closed_file) {
	DEBUG_MSG("add_to_recent_list, started for %s\n", filename);
	if (closed_file) {
		GtkWidget *tmp;

		/* First of all, create the entry and insert it at the list*/
		main_v->recent_files = g_list_append(main_v->recent_files,
								create_recent_entry(filename));

		DEBUG_MSG("add_to_recent_list, inserted item in menu\n");
		if(g_list_length(main_v->recent_files) > main_v->props.max_recent_files) {
			tmp = remove_recent_entry("last");
			DEBUG_MSG("add_to_recent_list, list too long, entry %s to be deleted\n", GTK_LABEL(GTK_BIN(tmp)->child)->label);
			gtk_widget_hide(tmp);
			gtk_widget_destroy(tmp);
		}
		flush_queue();

	} else {
		gchar *tmpfilename, *recentfile;
		recentfile = g_strconcat(getenv("HOME"), "/.bluefish/recentlist", NULL);
		/* save the new list */
		tmpfilename = g_strconcat(filename, "\n", NULL);
		DEBUG_MSG("add_to_recent_list, trying to append to %s\n", recentfile);
		append_to_file(recentfile, tmpfilename);
		g_free(recentfile);
		g_free(tmpfilename);
	}
}

/*******************************************************************/
/*           End of Open Recent menu handling                      */
/*******************************************************************/


#ifdef ENABLE_NLS

gchar *menu_translate(const gchar * path, gpointer data)
{
	static gchar *menupath = NULL;

	gchar *retval;
	gchar *factory;

	factory = (gchar *) data;

	if (menupath)
		g_free(menupath);

	menupath = g_strdup(path);

	if ((strstr(path, "/tearoff1") != NULL) || (strstr(path, "/---") != NULL) || (strstr(path, "/MRU") != NULL))
		return menupath;

	retval = gettext(menupath);

	return retval;
}

#endif							/*  ENABLE_NLS  */
