/* * rootmenu.c: Root menu configuration * * Written by: Ullrich Hafner * * Copyright (C) 1998 Ullrich Hafner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. */ /* * $Date: 2000/09/25 18:15:24 $ * $Author: hafner $ * $Revision: 1.49 $ * $State: Exp $ */ #include "config.h" #include #include #include #include #include #include "proplist_t.h" #ifdef HAVE_UNISTD_H # include #endif /* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */ #if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION) # include # define NLENGTH(dirent) (strlen ((dirent)->d_name)) #else # define dirent direct # define NLENGTH(dirent) ((dirent)->d_namlen) # ifdef HAVE_SYS_NDIR_H # include # endif /* HAVE_SYS_NDIR_H */ # ifdef HAVE_SYS_DIR_H # include # endif /* HAVE_SYS_DIR_H */ # ifdef HAVE_NDIR_H # include # endif /* HAVE_NDIR_H */ #endif /* not (HAVE_DIRENT_H or _POSIX_VERSION) */ #include "misc.h" #include "rootmenu.h" #include "icons.h" #include "dialog.h" #include "keys.h" #include "menu.h" #include "load.h" #include "error.h" #include "dndtree.h" /******************************************************************************* local variables *******************************************************************************/ typedef enum {WM_MENU, WM_INCLUDE, WM_PIPE, WM_OPEN_MENU, WM_EXEC, WM_SHEXEC, WM_RESTART, WM_EXIT, WM_SHUTDOWN, WM_SAVE_SESSION, WM_CLEAR_SESSION, WM_WORKSPACE_MENU, WM_REFRESH, WM_ARRANGE_ICONS, WM_HIDE_OTHERS, WM_SHOW_ALL, WM_INFO_PANEL, WM_LEGAL_PANEL, WM_LAST} action_e; typedef struct { char *name; action_e action; char *arg; char *shortcut; } item_t; static const char *cmd_id [WM_LAST + 1]; static const char *cmd_name [WM_LAST + 1]; static GtkWidget *command_box = NULL; static GtkWidget *itemlabel_entry = NULL; static guint itemlabel_entry_sig = 0; static GtkWidget *box_confirm_button = NULL; static GtkWidget *box_commandline_entry = NULL; static GtkWidget *box_wmanager_entry = NULL; static GtkWidget *box_shortcut_widget = NULL; static GtkWidget *box_include_file_widget = NULL; static GtkWidget *box_pipe_cmd_widget = NULL; static GtkWidget *box_dir_widget = NULL; static GtkWidget *box_suffix_button = NULL; static GtkWidget *menu_tree = NULL; static GtkWidget *command_menu = NULL; static GtkWidget *confirm_button = NULL; static GtkWidget *commandline_entry = NULL; static guint commandline_entry_sig = 0; static GtkWidget *wmanager_entry = NULL; static guint wmanager_entry_sig = 0; static GtkWidget *shortcut_widget = NULL; static GtkWidget *include_file_entry = NULL; static guint include_file_entry_sig = 0; static GtkWidget *pipe_command_entry = NULL; static guint pipe_command_entry_sig = 0; static GtkWidget *dir_clist = NULL; static GtkWidget *dir_remove = NULL; static GtkWidget *dir_with_entry = NULL; static guint dir_with_entry_sig = 0; static GtkWidget *suffix_button = NULL; static GtkWidget *notebook_page = NULL; static GtkWidget *info_message = NULL; static GtkTooltips *main_tooltips = NULL; static bool_t menu_changed = NO; static GNode *last_node = NULL; /* node cut buffer */ #ifndef WMCONFIG static bool_t debian_menu = FALSE; #endif /******************************************************************************* prototypes *******************************************************************************/ static GtkCTreeNode * build_tree (GtkCTreeNode *parent, GtkCTreeNode *sibling, proplist_t menu); static GtkWidget * real_rootmenu (GtkTooltips *tooltips, proplist_t menu); static void item_destructor (gpointer data); static item_t * item_constructor (const char *name, action_e action, const char *arg, const char *shortcut); static gboolean itemcopy (GtkCTree *ctree, guint depth, GNode *gnode, GtkCTreeNode *cnode, gpointer data); static void selection_made (GtkCTree *ctree, GtkCTreeNode *node, gint column, GdkEventButton *event, gpointer data); static void set_label (GtkWidget *widget, gpointer ptr); static void set_command (GtkWidget *widget, gpointer ptr); static void show_action_dialog (item_t *item); static void init_action_commands (void) ; static void toggle_confirm (GtkWidget *widget, gpointer ptr); static gint context_menu (GtkCTree *ctree, GdkEventButton *event, gpointer ptr); static void remove_node (GtkWidget *widget, gpointer ptr); static gboolean drag_compare (GtkCTree *ctree, GtkCTreeNode *source_node, GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling); static void cut_node (GtkWidget *widget, gpointer ptr); gboolean node_freeitem (GNode *node, gpointer data); static gboolean nodecopy (GtkCTree *ctree, guint depth, GNode *gnode, GtkCTreeNode *cnode, gpointer data); static void shortcut_changed (const key_widget_t *data); static gint menu_key_pressed (GtkCTree *ctree, GdkEventKey *event, gpointer ptr); static void collapse_recursive (GtkWidget *widget, gpointer ptr); static void expand_recursive (GtkWidget *widget, gpointer ptr); static void set_item_pixmap (GtkCTreeNode *node, item_t *item); static void open_filebrowser (GtkWidget *button, gpointer data); static void open_dirbrowser (GtkWidget *button, gpointer data); static void set_filename (GtkWidget *button, gpointer data); static void set_entry_text (GtkWidget *entry, gpointer data); static void import_menu (GtkWidget *entry, gpointer data); static void set_wmakerconf (GtkWidget *menuitem, gpointer data); #ifdef GNOME_TO_WMAKER static void set_gnomemenu (GtkWidget *menuitem, gpointer data); #endif /* GNOME_TO_WMAKER */ #ifdef PERL # ifdef KDE_TO_WMAKER static void set_kdemenu (GtkWidget *menuitem, gpointer data); # endif /* KDE_TO_WMAKER */ #endif /* PERL */ #ifdef WMCONFIG static void set_wmconfig (GtkWidget *menuitem, gpointer data); #else /* not WMCONFIG */ static void set_debian (GtkWidget *menuitem, gpointer data); #endif /* not WMCONFIG */ static void set_default_menu (GtkWidget *menuitem, gpointer data); static void import_dynamic_menu (GtkWidget *widget, gpointer data); static void remove_dir (GtkWidget *button, gpointer data); static void insert_dir (GtkWidget *button, gpointer data); static void dir_list_to_item (GtkWidget *button, gpointer data); static void tree_moved (GtkCTree *ctree, GtkCTreeNode *node, GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling); static void row_moved (GtkWidget *clist, gint source_row, gint dest_row); static proplist_t convert_to_proplist (const char *filename); static void convert_current_menu (GtkWidget *button, gpointer data); static void empty_menu (GtkWidget *button, gpointer data); static void use_wmaker_menu (GtkWidget *button, gpointer data); static void convert_wmaker_menu (GtkWidget *button, gpointer data); static proplist_t save_node (GNode *gnode); /******************************************************************************* public code *******************************************************************************/ GtkWidget * rootmenu_dialog (GtkWidget *page, GtkTooltips *tooltips) { char *filename = get_gnustep_path ("Defaults/WMRootMenu"); proplist_t menu = read_proplist (filename); if (!menu || WMIsPLString (menu)) { GtkWidget *vbox = gtk_vbox_new (FALSE, 3); gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); gtk_box_pack_start (GTK_BOX (vbox), gtk_pixmap_new (p_array [P_INFO].pixmap, p_array [P_INFO].mask), FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (_("Application menu configuration " "requires that your menu file")), FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (filename), FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (_("is in the new format.")), FALSE, TRUE, 0); { GtkWidget *button; GtkWidget *bbox = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 5); if (menu && WMIsPLString (menu)) { button = gtk_button_new_with_label (_("Convert current menu")); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5); gtk_tooltips_set_tip (tooltips, button, _("Convert current menu file to new format."), NULL); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (convert_current_menu), g_strdup (WMGetFromPLString (menu))); } button = gtk_button_new_with_label (_("Start with empty menu")); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5); gtk_tooltips_set_tip (tooltips, button, _("Replace current menu file with an empty one."), NULL); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (empty_menu), NULL); button = gtk_button_new_with_label (_("Use predefined menu")); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5); gtk_tooltips_set_tip (tooltips, button, _("Use one of Window Maker's predefined menus " "as a starting point."), NULL); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (use_wmaker_menu), NULL); } gtk_box_pack_start (GTK_BOX (page), vbox, TRUE, TRUE, 0); info_message = vbox; notebook_page = page; main_tooltips = tooltips; gtk_widget_show_all (page); if (menu) WMReleasePropList (menu); { GtkWidget *vbox = gtk_vbox_new (FALSE, 5); gtk_box_pack_end (GTK_BOX (page), vbox, FALSE, FALSE, 0); gtk_widget_show (vbox); return vbox; } } else { gtk_box_pack_start (GTK_BOX (page), real_rootmenu (tooltips, menu), TRUE, TRUE, 0); gtk_widget_show (page); return page; } if (filename) Free (filename); } bool_t rootmenu_changed (void) { return menu_changed; } bool_t save_rootmenu (void) { if (menu_changed) { GtkCTreeNode *root = gtk_ctree_node_nth (GTK_CTREE (menu_tree), 0); GNode *node = gtk_ctree_export_to_gnode (GTK_CTREE (menu_tree), NULL, NULL, root, itemcopy, NULL); proplist_t menu = save_node (node); char *filename = get_gnustep_path ("Defaults/WMRootMenu"); g_node_traverse (node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, node_freeitem, NULL); g_node_destroy (node); if (WMWritePropListToFile (menu, filename, YES)) { menu_changed = NO; message (_("Window Maker root menu file '%s' saved."), filename); Free (filename); WMReleasePropList (menu); } else { dialog_popup (DIALOG_ERROR, NULL, NULL, _("Can't write to menu file\n`%s'"), filename); Free (filename); WMReleasePropList (menu); return FALSE; /* ERROR */ } } return TRUE; } /******************************************************************************* private code *******************************************************************************/ static proplist_t save_node (GNode *gnode) { item_t *item = gnode->data; proplist_t pnode = WMCreatePLArray (NULL); unsigned pos = 0; WMInsertInPLArray (pnode, pos++, WMCreatePLString (item->name)); if (item->action == WM_MENU) { GNode *gchild; if (gnode->children || gnode->parent == NULL) for (gchild = gnode->children; gchild; gchild = gchild->next) { proplist_t pchild = save_node (gchild); if (pchild) WMInsertInPLArray (pnode, pos++, pchild); } else { WMReleasePropList (pnode); return NULL; /* don't export empty dir's */ } } else { if (item->action != WM_INCLUDE && item->action != WM_OPEN_MENU && item->action != WM_MENU && item->action != WM_PIPE) { if (item->shortcut && strlen (item->shortcut) && !strcaseeq (item->shortcut, "none")) { WMInsertInPLArray (pnode, pos++, WMCreatePLString ("SHORTCUT")); WMInsertInPLArray (pnode, pos++, WMCreatePLString (item->shortcut)); } } WMInsertInPLArray (pnode, pos++, WMCreatePLString ((char *) cmd_id [item->action])); if (!item->arg) item->arg = g_strdup (""); if (item->action == WM_EXEC || item->action == WM_SHEXEC || item->action == WM_INCLUDE || item->action == WM_OPEN_MENU) WMInsertInPLArray (pnode, pos++, WMCreatePLString (item->arg)); else if (item->action == WM_PIPE) { char *tmp = g_strdup_printf ("| %s", item->arg); WMInsertInPLArray (pnode, pos++, WMCreatePLString (tmp)); Free (tmp); } else if (item->action == WM_EXIT || item->action == WM_SHUTDOWN) { if (streq (item->arg, "QUICK")) WMInsertInPLArray (pnode, pos++, WMCreatePLString (item->arg)); } else if (item->action == WM_RESTART) { if (strlen (item->arg)) WMInsertInPLArray (pnode, pos++, WMCreatePLString (item->arg)); } } return pnode; } static GtkWidget * real_rootmenu (GtkTooltips *tooltips, proplist_t menu) { GtkWidget *scrolled; GtkWidget *ctree; GtkWidget *table; GtkWidget *action_box; GtkCTreeNode *root; init_action_commands (); #ifndef WMCONFIG /* * Check for Debian system menu */ { FILE *file; file = fopen (get_gnustep_path ("Library/WindowMaker/menu.hook"), "r"); if (!file) { file = fopen ("/etc/X11/WindowMaker/menu.hook", "r"); if (file) { debian_menu = YES; fclose (file); } } else { debian_menu = YES; fclose (file); } } #endif /* * Scrolled window for ctree */ scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (scrolled), 5); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); /* * Ctree to show the menu structure */ ctree = menu_tree = (GtkWidget *) gtk_dndtree_new (1, 0); gtk_object_set_user_data (GTK_OBJECT (ctree), ctree); gtk_clist_set_row_height (GTK_CLIST (ctree), 18); gtk_signal_connect (GTK_OBJECT (ctree), "tree_move", GTK_SIGNAL_FUNC (tree_moved), NULL); gtk_ctree_set_drag_compare_func (GTK_CTREE (ctree), drag_compare); gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE); gtk_ctree_set_line_style (GTK_CTREE (ctree), GTK_CTREE_LINES_DOTTED); gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_BROWSE); gtk_container_add (GTK_CONTAINER (scrolled), GTK_WIDGET (ctree)); gtk_widget_set_usize (scrolled, 250, -1); action_box = gtk_vbox_new (FALSE, 0); /* * Menulabel */ { GtkWidget *frame; GtkWidget *box; frame = gtk_frame_new (_("Menu(item) label")); gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5); gtk_container_set_border_width (GTK_CONTAINER (frame), 5); gtk_box_pack_start (GTK_BOX (action_box), frame, FALSE, TRUE, 0); box = gtk_hbox_new (FALSE, 5); gtk_container_add (GTK_CONTAINER (frame), box); gtk_container_set_border_width (GTK_CONTAINER (box), 5); itemlabel_entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (box), itemlabel_entry, TRUE, TRUE, 5); itemlabel_entry_sig = gtk_signal_connect (GTK_OBJECT (itemlabel_entry), "changed", GTK_SIGNAL_FUNC (set_label), NULL); gtk_widget_show_all (frame); } /* * Command */ { GtkWidget *frame; GtkWidget *box; GtkWidget *cmd_vbox; command_box = frame = gtk_frame_new (_("Command")); gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5); gtk_container_set_border_width (GTK_CONTAINER (frame), 5); gtk_box_pack_start (GTK_BOX (action_box), frame, FALSE, TRUE, 0); cmd_vbox = gtk_vbox_new (FALSE, 5); gtk_container_add (GTK_CONTAINER (frame), cmd_vbox); box = gtk_hbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (cmd_vbox), box, FALSE, FALSE, 5); command_menu = generate_option_menu (NULL, NULL, NULL, &cmd_name [WM_MENU + 1], cmd_name [WM_EXEC], NULL, set_command, NULL); gtk_box_pack_start (GTK_BOX (box), command_menu, TRUE, TRUE, 10); /* * Confirmation panel */ box_confirm_button = box = gtk_hbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (cmd_vbox), box, FALSE, FALSE, 5); confirm_button = gtk_check_button_new_with_label (_("Show confirm panel")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (confirm_button), FALSE); gtk_signal_connect (GTK_OBJECT (confirm_button), "toggled", GTK_SIGNAL_FUNC (toggle_confirm), NULL); gtk_box_pack_start (GTK_BOX (box), confirm_button, TRUE, TRUE, 10); /* * Commandline */ box_commandline_entry = box = gtk_hbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (cmd_vbox), box, FALSE, FALSE, 5); { GtkWidget *hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (box), hbox, TRUE, TRUE, 5); gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Command:")), FALSE, TRUE, 5); commandline_entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (hbox), commandline_entry, TRUE, TRUE, 5); } commandline_entry_sig = gtk_signal_connect (GTK_OBJECT(commandline_entry), "changed", GTK_SIGNAL_FUNC (set_entry_text), NULL); gtk_tooltips_set_tip (tooltips, commandline_entry, _("Commandline of application to execute. A %s " "directive is replaced by the current selection" ", %w by the XID of the focused window, " "and %a(title[,prompt]) pops up an input box with " "specified title and optional prompt" " and substitutes with the typed text."), NULL); /* * Commandline of PIPE command */ { GtkWidget *vbox = gtk_vbox_new (FALSE, 5); GtkWidget *hbox; box_pipe_cmd_widget = box = gtk_hbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (cmd_vbox), box, FALSE, FALSE, 5); gtk_box_pack_start (GTK_BOX (box), vbox, TRUE, TRUE, 5); hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Command:")), FALSE, TRUE, 5); pipe_command_entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (hbox), pipe_command_entry, TRUE, TRUE, 5); pipe_command_entry_sig = gtk_signal_connect (GTK_OBJECT (pipe_command_entry), "changed", GTK_SIGNAL_FUNC (set_entry_text), NULL); gtk_tooltips_set_tip (tooltips, pipe_command_entry, _("Commandline to generate dynamic menu."), NULL); { GtkWidget *button; GtkWidget *bbox = gtk_hbutton_box_new (); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 5); button = gtk_button_new_with_label (_("Import")); gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5); gtk_tooltips_set_tip (tooltips, button, _("Import output of command. " "The 'include dynamic menu' item is removed " "afterwards."), NULL); gtk_object_set_user_data (GTK_OBJECT (button), NULL); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (import_dynamic_menu), NULL); } } /* * Windowmanager */ box_wmanager_entry = box = gtk_hbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (cmd_vbox), box, FALSE, FALSE, 5); { GtkWidget *hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (box), hbox, TRUE, TRUE, 5); gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Name:")), FALSE, TRUE, 5); wmanager_entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (hbox), wmanager_entry, TRUE, TRUE, 5); } wmanager_entry_sig = gtk_signal_connect (GTK_OBJECT (wmanager_entry), "changed", GTK_SIGNAL_FUNC (set_entry_text), NULL); gtk_tooltips_set_tip (tooltips, wmanager_entry, _("Name of window manager to start. " "If omitted, restart Window Maker."), NULL); /* * Filename of included menu */ { GtkWidget *vbox = gtk_vbox_new (FALSE, 5); GtkWidget *hbox; box_include_file_widget = box = gtk_hbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (cmd_vbox), box, FALSE, FALSE, 5); gtk_box_pack_start (GTK_BOX (box), vbox, TRUE, TRUE, 5); hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("File:")), FALSE, TRUE, 5); include_file_entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (hbox), include_file_entry, TRUE, TRUE, 5); include_file_entry_sig = gtk_signal_connect (GTK_OBJECT (include_file_entry), "changed", GTK_SIGNAL_FUNC (set_entry_text), NULL); gtk_tooltips_set_tip (tooltips, include_file_entry, _("Filename of menu to include."), NULL); { GtkWidget *button; GtkWidget *bbox = gtk_hbutton_box_new (); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 5); button = gtk_button_new_with_label (_("Import")); gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5); gtk_tooltips_set_tip (tooltips, button, _("Import contents of selected menu file. " "The 'include menu file' item is removed " "afterwards."), NULL); gtk_object_set_user_data (GTK_OBJECT (button), NULL); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (import_menu), NULL); button = gtk_button_new_with_label (_("Browse...")); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5); gtk_tooltips_set_tip (tooltips, button, _("Open file browser to select include file."), NULL); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (open_filebrowser), NULL); } } /* * Directory list */ { GtkWidget *vbox = gtk_vbox_new (FALSE, 5); GtkWidget *hbox; GtkWidget *scrolled; GtkWidget *clist; char *title = _("Directory list"); box_dir_widget = box = gtk_hbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (cmd_vbox), box, FALSE, FALSE, 5); gtk_box_pack_start (GTK_BOX (box), vbox, TRUE, TRUE, 5); hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Command:")), FALSE, TRUE, 5); dir_with_entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (hbox), dir_with_entry, TRUE, TRUE, 5); dir_with_entry_sig = gtk_signal_connect (GTK_OBJECT (dir_with_entry), "changed", GTK_SIGNAL_FUNC (dir_list_to_item), NULL); gtk_tooltips_set_tip (tooltips, dir_with_entry, _("Recursively, a submenu with all files and" " subdirectories of the given directory list is" " generated - each file is then used as argument" " for `command'. If `command' is omitted, a" " submenu with all executable files" " is generated."), NULL); hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (scrolled), 5); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); dir_clist = clist = gtk_clist_new_with_titles (1, &title); gtk_tooltips_set_tip (tooltips, clist, _("Insert new directory."), NULL); gtk_clist_set_reorderable (GTK_CLIST (clist), TRUE); gtk_clist_set_use_drag_icons (GTK_CLIST (clist), TRUE); gtk_signal_connect_after (GTK_OBJECT (clist), "row_move", GTK_SIGNAL_FUNC (row_moved), NULL); gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, YES); gtk_clist_column_titles_passive (GTK_CLIST (clist)); gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_BROWSE); gtk_container_add (GTK_CONTAINER (scrolled), clist); gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 0); gtk_widget_set_usize (clist, -1, 100); { GtkWidget *button; GtkWidget *bbox = gtk_hbutton_box_new (); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 0); gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD); button = gtk_button_new_with_label (_("Insert...")); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5); gtk_tooltips_set_tip (tooltips, button, _("Insert new directory."), NULL); gtk_object_set_user_data (GTK_OBJECT (button), NULL); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (open_dirbrowser), NULL); dir_remove = button = gtk_button_new_with_label (_("Remove")); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5); gtk_tooltips_set_tip (tooltips, button, _("Remove selected directory."), NULL); gtk_signal_connect_after (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (remove_dir), NULL); } } /* * Strip suffix of file names */ box_suffix_button = box = gtk_hbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (cmd_vbox), box, FALSE, FALSE, 0); suffix_button = gtk_check_button_new_with_label (_("Strip suffix of filenames")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (suffix_button), FALSE); gtk_signal_connect (GTK_OBJECT (suffix_button), "toggled", GTK_SIGNAL_FUNC (dir_list_to_item), NULL); gtk_box_pack_start (GTK_BOX (box), suffix_button, TRUE, TRUE, 10); } /* * Shortcut */ { GtkWidget *frame; GtkWidget *box; box_shortcut_widget = frame = gtk_frame_new (_("Shortcut")); gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5); gtk_container_set_border_width (GTK_CONTAINER (frame), 5); gtk_box_pack_start (GTK_BOX (action_box), frame, FALSE, TRUE, 0); box = gtk_hbox_new (FALSE, 5); gtk_container_add (GTK_CONTAINER (frame), box); gtk_container_set_border_width (GTK_CONTAINER (box), 5); shortcut_widget = key_dialog ("None", tooltips, NULL, shortcut_changed, NULL); gtk_box_pack_start (GTK_BOX (box), shortcut_widget, TRUE, TRUE, 5); } if (menu) { root = build_tree (NULL, NULL, menu); WMReleasePropList (menu); } else { char *text = "Applications"; root = gtk_ctree_insert_node (GTK_CTREE (ctree), NULL, NULL, &text, 8, p_array [P_BOOK_CLOSE].pixmap, p_array [P_BOOK_CLOSE].mask, p_array [P_BOOK_OPEN].pixmap, p_array [P_BOOK_OPEN].mask, FALSE, FALSE); gtk_ctree_node_set_row_data_full (GTK_CTREE (ctree), root, item_constructor (text, WM_MENU, NULL, NULL), item_destructor); } /* * Horizontal box for ctree and action area */ table = gtk_hpaned_new (); gtk_paned_add1 (GTK_PANED (table), scrolled); gtk_paned_add2 (GTK_PANED (table), action_box); gtk_widget_show_all (table); gtk_widget_set_usize (scrolled, 300, -1); gtk_widget_show_all (command_box); gtk_widget_hide (command_box); gtk_widget_hide (box_shortcut_widget); gtk_signal_connect (GTK_OBJECT(ctree), "tree_select_row", GTK_SIGNAL_FUNC (selection_made), NULL); gtk_signal_connect (GTK_OBJECT(ctree), "key_press_event", GTK_SIGNAL_FUNC (menu_key_pressed), NULL); gtk_signal_connect (GTK_OBJECT (ctree), "button_press_event", GTK_SIGNAL_FUNC (context_menu), NULL); gtk_ctree_select (GTK_CTREE (ctree), root); return table; } static void init_action_commands (void) /* * Initialize Window Maker's rootmenu commands and short description of * every command. * * No return value. * * Side effects: cmd_id, cmd_name are filled */ { cmd_id [WM_MENU] = "MENU"; cmd_name [WM_MENU] = _("Submenu"); cmd_id [WM_INCLUDE] = "OPEN_MENU"; cmd_name [WM_INCLUDE] = _("Include menu file"); cmd_id [WM_PIPE] = "OPEN_MENU"; cmd_name [WM_PIPE] = _("Include dynamic menu"); cmd_id [WM_OPEN_MENU] = "OPEN_MENU"; cmd_name [WM_OPEN_MENU] = _("Include directory menu"); cmd_id [WM_EXEC] = "EXEC"; cmd_name [WM_EXEC] = _("Execute application"); cmd_id [WM_SHEXEC] = "SHEXEC"; cmd_name [WM_SHEXEC] = _("Execute shell command"); cmd_id [WM_REFRESH] = "REFRESH"; cmd_name [WM_REFRESH] = _("Refresh screen"); cmd_id [WM_RESTART] = "RESTART"; cmd_name [WM_RESTART] = _("(Re)start window manager"); cmd_id [WM_EXIT] = "EXIT"; cmd_name [WM_EXIT] = _("Exit Window Maker"); cmd_id [WM_SHUTDOWN] = "SHUTDOWN"; cmd_name [WM_SHUTDOWN] = _("Exit session"); cmd_id [WM_WORKSPACE_MENU] = "WORKSPACE_MENU"; cmd_name [WM_WORKSPACE_MENU] = _("Workspace menu"); cmd_id [WM_ARRANGE_ICONS] = "ARRANGE_ICONS"; cmd_name [WM_ARRANGE_ICONS] = _("Arrange miniwindows"); cmd_id [WM_HIDE_OTHERS] = "HIDE_OTHERS"; cmd_name [WM_HIDE_OTHERS] = _("Hide other windows"); cmd_id [WM_SHOW_ALL] = "SHOW_ALL"; cmd_name [WM_SHOW_ALL] = _("Show all windows"); cmd_id [WM_SAVE_SESSION] = "SAVE_SESSION"; cmd_name [WM_SAVE_SESSION] = _("Save session"); cmd_id [WM_CLEAR_SESSION] = "CLEAR_SESSION"; cmd_name [WM_CLEAR_SESSION] = _("Discard session data"); cmd_id [WM_INFO_PANEL] = "INFO_PANEL"; cmd_name [WM_INFO_PANEL] = _("Show info panel"); cmd_id [WM_LEGAL_PANEL] = "LEGAL_PANEL"; cmd_name [WM_LEGAL_PANEL] = _("Show legal panel"); cmd_id [WM_LAST] = NULL; cmd_name [WM_LAST] = NULL; } static GtkCTreeNode * build_tree (GtkCTreeNode *parent, GtkCTreeNode *sibling, proplist_t menu) /* * Recursively build a menu tree using the 'ctree' widget. * If 'parent' != NULL insert node as a new child of 'parent'. * If 'sibling' != NULL insert node just before 'sibling'. Otherwise append * the node at the lists tail. * 'menu' is the current part of the menu in proplist format. * * Return value: * new node */ { char *text; proplist_t pl; unsigned n; GtkCTreeNode *node; if (!WMIsPLArray (menu) || (n = WMGetPropListItemCount (menu)) < 1) return NULL; /* ERROR */ pl = WMGetFromPLArray (menu, 0); if (!WMIsPLString (pl)) return NULL; /* ERROR */ text = WMGetFromPLString (pl); pl = WMGetFromPLArray (menu, 1); if (n == 1 || WMIsPLArray (pl)) /* submenu */ { unsigned k; item_t *item = item_constructor (text, WM_MENU, NULL, NULL); node = gtk_ctree_insert_node (GTK_CTREE (menu_tree), parent, sibling, &text, 8, NULL, NULL, NULL, NULL, FALSE, !parent); gtk_ctree_node_set_row_data_full (GTK_CTREE (menu_tree), node, item, item_destructor); set_item_pixmap (node, item); for (k = 1; k < n; k++) { pl = WMGetFromPLArray (menu, k); if (WMIsPLArray (pl)) /* submenu */ build_tree (node, NULL, pl); else return NULL; /* ERROR */ } } else /* leaf */ { item_t *new = item_constructor (text, WM_EXEC, NULL, NULL); char *action; int an; action = WMGetFromPLString (pl); if (streq (action, "SHORTCUT")) { if (n >= 4) /* name SHORTCUT shortcutdef COMMAND */ { pl = WMGetFromPLArray (menu, 2); new->shortcut = g_strdup (WMGetFromPLString (pl)); pl = WMGetFromPLArray (menu, 3); if (n >= 5) /* ... COMMAND OPTIONS */ new->arg = g_strdup (WMGetFromPLString (WMGetFromPLArray (menu, 4))); } else { item_destructor (new); return NULL; /* ERROR */ } } else if (n >= 3) /* ... COMMAND OPTIONS */ new->arg = g_strdup (WMGetFromPLString (WMGetFromPLArray (menu, 2))); action = WMGetFromPLString (pl); new->action = WM_MENU; for (an = 0; an < WM_LAST; an++) if (streq (action, cmd_id [an])) { new->action = an; break; } if (new->action == WM_MENU) { item_destructor (new); return NULL; /* ERROR */ } if (new->action == WM_OPEN_MENU || new->action == WM_INCLUDE || new->action == WM_PIPE) /* check type of command */ { if (!new->arg) /* ERROR */ { item_destructor (new); return NULL; /* ERROR */ } if (new->shortcut) /* not allowed */ { Free (new->shortcut); new->shortcut = NULL; } if (new->arg [0] == '|') /* WM_PIPE */ { char *arg; for (arg = new->arg + 1; *arg == ' '; arg++) ; if (!*arg) /* ERROR */ { item_destructor (new); return NULL; /* ERROR */ } arg = g_strdup (arg); Free (new->arg); new->arg = arg; new->action = WM_PIPE; } else { if (strchr (new->arg, ' ')) /* include list of directories */ { new->action = WM_OPEN_MENU; } else { char *path = expand_tilde (new->arg); DIR *dir; if ((dir = opendir (path))) /* include one directory */ { closedir (dir); new->action = WM_OPEN_MENU; } else /* include single file */ { new->action = WM_INCLUDE; } } } } node = gtk_ctree_insert_node (GTK_CTREE (menu_tree), parent, sibling, &text, 8, NULL, NULL, NULL, NULL, TRUE, TRUE); gtk_ctree_node_set_row_data_full (GTK_CTREE (menu_tree), node, (gpointer) new, item_destructor); set_item_pixmap (node, new); } return node; } static void item_destructor (gpointer data) { item_t *item = (item_t *) data; if (item->name) Free (item->name); if (item->shortcut) Free (item->shortcut); if (item->arg) Free (item->arg); Free (item); } static item_t * item_constructor (const char *name, action_e action, const char *arg, const char *shortcut) { item_t *new = Calloc (1, sizeof (item_t)); assert (name); new->name = g_strdup (name); new->action = action; new->shortcut = g_strdup (shortcut); new->arg = g_strdup (arg); return new; } static void selection_made (GtkCTree *ctree, GtkCTreeNode *node, gint column, GdkEventButton *event, gpointer data) /* * Update widgets after new item has been selected. */ { gchar *text; bool_t changed = menu_changed; item_t *item = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); if (!item) return; gtk_ctree_get_node_info (GTK_CTREE (menu_tree), node, &text, NULL, NULL, NULL, NULL, NULL, NULL, NULL); g_signal_handler_block (itemlabel_entry, itemlabel_entry_sig); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), text); g_signal_handler_unblock (itemlabel_entry, itemlabel_entry_sig); show_action_dialog (gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node)); menu_changed = changed; } static void set_label (GtkWidget *widget, gpointer ptr) /* * Set label of submenu or command. */ { const char *label = gtk_entry_get_text (GTK_ENTRY (itemlabel_entry)); GtkCTreeNode *node = (GTK_CLIST (menu_tree)->selection)->data; item_t *item = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); char *old; guint8 spacing; GdkPixmap *closed, *opened; GdkBitmap *mask_closed, *mask_opened; gboolean is_leaf, expanded; Free (item->name); item->name = g_strdup (label); gtk_ctree_get_node_info (GTK_CTREE (menu_tree), node, &old, &spacing, &closed, &mask_closed, &opened, &mask_opened, &is_leaf, &expanded); gtk_ctree_set_node_info (GTK_CTREE (menu_tree), node, label, spacing, closed, mask_closed, opened, mask_opened, is_leaf, expanded); if (item->action > WM_MENU) gtk_option_menu_set_history (GTK_OPTION_MENU (command_menu), item->action - 1); toggle_save (menu_changed = YES, NULL); } static void set_command (GtkWidget *widget, gpointer ptr) /* * Set type of command for menu item */ { char *text = gtk_object_get_user_data (GTK_OBJECT (widget)); GtkCTreeNode *node = (GTK_CLIST (menu_tree)->selection)->data; item_t *item = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); action_e an; for (an = 0; an < WM_LAST; an++) if (streq (text, cmd_name [an])) { if (an != item->action) /* type of action changed ? */ { item->action = an; if (item->arg) Free (item->arg); item->arg = NULL; set_item_pixmap (node, item); show_action_dialog (item); toggle_save (menu_changed = YES, NULL); } break; } } static void show_action_dialog (item_t *item) /* * Show and hide widgets depending on type of action */ { gtk_widget_hide (command_box); if (item->action == WM_OPEN_MENU || item->action == WM_INCLUDE || item->action == WM_PIPE || item->action == WM_MENU) { gtk_widget_hide (box_shortcut_widget); } else { gtk_widget_show_all (box_shortcut_widget); update_keywidget (gtk_object_get_user_data (GTK_OBJECT (shortcut_widget)), item->shortcut ? item->shortcut : "None"); } /* * First of all, hide all subwidgets of the command_box */ gtk_widget_hide (box_pipe_cmd_widget); gtk_widget_hide (box_include_file_widget); gtk_widget_hide (box_confirm_button); gtk_widget_hide (box_commandline_entry); gtk_widget_hide (box_wmanager_entry); gtk_widget_hide (box_dir_widget); gtk_widget_hide (box_suffix_button); if (item->action > WM_MENU) gtk_option_menu_set_history (GTK_OPTION_MENU (command_menu), item->action - 1); if (item->action == WM_EXEC || item->action == WM_SHEXEC) /* show cmdline */ { guint sighandler = GPOINTER_TO_INT (gtk_object_get_user_data (GTK_OBJECT (commandline_entry))); if (!item->arg) item->arg = g_strdup (""); g_signal_handler_block (commandline_entry, commandline_entry_sig); gtk_entry_set_text (GTK_ENTRY (commandline_entry), item->arg); g_signal_handler_unblock (commandline_entry, commandline_entry_sig); gtk_widget_show (box_commandline_entry); } else if (item->action == WM_INCLUDE) /* show include file entry */ { if (!item->arg) item->arg = g_strdup (""); g_signal_handler_block (include_file_entry, include_file_entry_sig); gtk_entry_set_text (GTK_ENTRY (include_file_entry), item->arg); g_signal_handler_unblock (include_file_entry, include_file_entry_sig); gtk_widget_show (box_include_file_widget); } else if (item->action == WM_PIPE) /* show pipe commandline entry */ { if (!item->arg) item->arg = g_strdup (""); g_signal_handler_block (pipe_command_entry, pipe_command_entry_sig); gtk_entry_set_text (GTK_ENTRY (pipe_command_entry), item->arg); g_signal_handler_unblock (pipe_command_entry, pipe_command_entry_sig); gtk_widget_show (box_pipe_cmd_widget); } else if (item->action == WM_EXIT || item->action == WM_SHUTDOWN) /* show confirm toggle */ { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (confirm_button), !(item->arg && streq (item->arg, "QUICK"))); gtk_widget_show (box_confirm_button); } else if (item->action == WM_RESTART) /* show windowmanger entry */ { g_signal_handler_block (wmanager_entry, wmanager_entry_sig); if (item->arg) gtk_entry_set_text (GTK_ENTRY (wmanager_entry), item->arg); else gtk_entry_set_text (GTK_ENTRY (wmanager_entry), ""); g_signal_handler_unblock (wmanager_entry, wmanager_entry_sig); gtk_widget_show (box_wmanager_entry); } else if (item->action == WM_OPEN_MENU) /* show directory list */ { if (!item->arg) item->arg = g_strdup (""); { char *start, *end; char *dir; bool_t strip_suffix = NO; gtk_clist_clear (GTK_CLIST (dir_clist)); start = item->arg; while (1) { while (*start && isspace (*start)) start++; end = start; while (*end && !isspace (*end)) end++; if (start == end) break; dir = Calloc (end - start + 1, sizeof (char)); strncpy (dir, start, end - start); if (streq (dir, "WITH")) { while (*end && isspace (*end)) end++; g_signal_handler_block (dir_with_entry, dir_with_entry_sig); gtk_entry_set_text (GTK_ENTRY (dir_with_entry), end); g_signal_handler_unblock (dir_with_entry, dir_with_entry_sig); Free (dir); break; } if (streq (dir, "-noext")) strip_suffix = YES; else gtk_clist_insert (GTK_CLIST (dir_clist), -1, &dir); start = end; Free (dir); } gtk_clist_select_row (GTK_CLIST (dir_clist), 0, 0); gtk_widget_set_sensitive (dir_remove, GTK_CLIST (dir_clist)->rows > 1); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (suffix_button), strip_suffix); } gtk_widget_show (box_dir_widget); gtk_widget_show (box_suffix_button); } if (item->action != WM_MENU) gtk_widget_show (command_box); } static void toggle_confirm (GtkWidget *widget, gpointer ptr) /* * Toggle confirm panel when using the EXIT or SHUTDOWN command. */ { GtkCTreeNode *node = (GTK_CLIST (menu_tree)->selection)->data; item_t *item = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); if (GTK_TOGGLE_BUTTON (widget)->active) { if (item->arg) Free (item->arg); item->arg = NULL; } else { if (!item->arg || !streq (item->arg, "QUICK")) { if (item->arg) Free (item->arg); item->arg = g_strdup ("QUICK"); } } toggle_save (menu_changed = YES, NULL); } static void insert_menu (GtkWidget *widget, gpointer ptr) /* * Insert a new submenu just at the current selection. */ { GtkCTreeNode *node; GtkCTreeNode *selection = (GTK_CLIST (menu_tree)->selection)->data; GtkCTreeNode *parent = GTK_CTREE_ROW (selection)->parent; if (!parent || (!GTK_CTREE_ROW (selection)->is_leaf && !GTK_CTREE_ROW (selection)->children)) { parent = selection; selection = GTK_CTREE_ROW (parent)->children; } if (ptr) { char *text = "Command"; node = gtk_ctree_insert_node (GTK_CTREE (menu_tree), parent, selection, &text, 8, p_array [P_EXEC].pixmap, p_array [P_EXEC].mask, NULL, NULL, TRUE, TRUE); gtk_ctree_node_set_row_data_full (GTK_CTREE (menu_tree), node, item_constructor (text, WM_EXEC, "", NULL), item_destructor); } else { char *text = "Submenu"; node = gtk_ctree_insert_node (GTK_CTREE (menu_tree), parent, selection, &text, 8, p_array [P_BOOK_CLOSE].pixmap, p_array [P_BOOK_CLOSE].mask, p_array [P_BOOK_OPEN].pixmap, p_array [P_BOOK_OPEN].mask, FALSE, FALSE); gtk_ctree_node_set_row_data_full (GTK_CTREE (menu_tree), node, item_constructor (text, WM_MENU, NULL, NULL), item_destructor); } if (!gtk_ctree_node_is_visible (GTK_CTREE (menu_tree), node)) gtk_ctree_expand (GTK_CTREE (menu_tree), parent); gtk_ctree_select (GTK_CTREE (menu_tree), node); gtk_entry_select_region (GTK_ENTRY (itemlabel_entry), 0, -1); gtk_widget_grab_focus (itemlabel_entry); toggle_save (menu_changed = YES, NULL); } static void remove_node (GtkWidget *widget, gpointer ptr) /* * Insert a new submenu just behind the current selection. */ { GtkCTreeNode *selection = (GTK_CLIST (menu_tree)->selection)->data; if (GTK_CTREE_ROW (selection)->parent) { if (GTK_CTREE_NODE_NEXT (selection)) gtk_ctree_select (GTK_CTREE (menu_tree), GTK_CTREE_NODE_NEXT (selection)); else if (GTK_CTREE_NODE_PREV (selection)) gtk_ctree_select (GTK_CTREE (menu_tree), GTK_CTREE_NODE_PREV (selection)); gtk_ctree_remove_node (GTK_CTREE (menu_tree), selection); toggle_save (menu_changed = YES, NULL); } } static void cut_node (GtkWidget *widget, gpointer ptr) /* * Insert a new submenu just behind the current selection. */ { GtkCTreeNode *selection = (GTK_CLIST (menu_tree)->selection)->data; if (GTK_CTREE_ROW (selection)->parent) { if (last_node) /* free memory */ { g_node_traverse (last_node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, node_freeitem, NULL); g_node_destroy (last_node); } last_node = gtk_ctree_export_to_gnode (GTK_CTREE (menu_tree), NULL, NULL, selection, itemcopy, NULL); remove_node (widget, ptr); toggle_save (menu_changed = YES, NULL); } } static void expand_recursive (GtkWidget *widget, gpointer ptr) { gtk_ctree_expand_recursive (GTK_CTREE (menu_tree), gtk_ctree_node_nth (GTK_CTREE (menu_tree), 0)); } static void collapse_recursive (GtkWidget *widget, gpointer ptr) { gtk_ctree_collapse_recursive (GTK_CTREE (menu_tree), gtk_ctree_node_nth (GTK_CTREE (menu_tree), 0)); gtk_ctree_expand (GTK_CTREE (menu_tree), gtk_ctree_node_nth (GTK_CTREE (menu_tree), 0)); } static void paste_node (GtkWidget *widget, gpointer ptr) /* * Insert a new submenu just behind the current selection. */ { GtkCTreeNode *selection = (GTK_CLIST (menu_tree)->selection)->data; if (last_node) { GtkCTreeNode *parent = GTK_CTREE_ROW (selection)->parent; GtkCTreeNode *node; if (!parent || (!GTK_CTREE_ROW (selection)->is_leaf && !GTK_CTREE_ROW (selection)->children)) { parent = selection; selection = GTK_CTREE_ROW (parent)->children; } node = gtk_ctree_insert_gnode (GTK_CTREE (menu_tree), parent, selection, last_node, nodecopy, NULL); if (!gtk_ctree_node_is_visible (GTK_CTREE (menu_tree), node)) gtk_ctree_expand (GTK_CTREE (menu_tree), parent); toggle_save (menu_changed = YES, NULL); } } gboolean node_freeitem (GNode *node, gpointer data) { item_destructor (node->data); node->data = NULL; return FALSE; } static gint context_menu (GtkCTree *ctree, GdkEventButton *event, gpointer ptr) /* * Popup context menu (right click) */ { gint row; gint column; GtkCTreeNode *node; if (!gtk_clist_get_selection_info (GTK_CLIST (menu_tree), event->x, event->y, &row, &column) || event->button != 3) return FALSE; node = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (menu_tree)->row_list, row)); gtk_ctree_select (GTK_CTREE (menu_tree), node); { static GtkWidget *menu = NULL; GtkWidget *menu_item; if (!menu) { menu = gtk_menu_new (); menu_item = gtk_menu_item_new_with_label (_("Insert new command")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (insert_menu), ""); menu_item = gtk_menu_item_new_with_label (_("Insert new submenu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (insert_menu), NULL); menu_item = gtk_menu_item_new (); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label (_("Insert WMAKERCONF menu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (set_wmakerconf), NULL); #ifdef GNOME_TO_WMAKER menu_item = gtk_menu_item_new_with_label (_("Insert GNOME menu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (set_gnomemenu), NULL); #endif /* GNOME_TO_WMAKER */ #ifdef PERL # ifdef KDE_TO_WMAKER menu_item = gtk_menu_item_new_with_label (_("Insert KDE menu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (set_kdemenu), NULL); # endif /* KDE_TO_WMAKER */ #endif /* PERL */ #ifdef WMCONFIG menu_item = gtk_menu_item_new_with_label (_("Insert RedHat menu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (set_wmconfig), NULL); #else /* not WMCONFIG */ if (debian_menu) { menu_item = gtk_menu_item_new_with_label (_("Insert Debian menu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (set_debian), NULL); } #endif /* not WMCONFIG */ menu_item = gtk_menu_item_new_with_label (_("Insert default menu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (set_default_menu), NULL); menu_item = gtk_menu_item_new (); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label (_("Cut item/submenu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (cut_node), NULL); menu_item = gtk_menu_item_new_with_label (_("Paste item/submenu")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (paste_node), NULL); menu_item = gtk_menu_item_new (); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label (_("Expand submenus")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (expand_recursive), NULL); menu_item = gtk_menu_item_new_with_label (_("Collapse submenus")); gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); gtk_signal_connect (GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC (collapse_recursive), NULL); } gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, event->time); } return TRUE; } static gboolean drag_compare (GtkCTree *ctree, GtkCTreeNode *source_node, GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling) { if (new_parent) return TRUE; else return FALSE; } static gboolean itemcopy (GtkCTree *ctree, guint depth, GNode *gnode, GtkCTreeNode *cnode, gpointer data) { if (!cnode || !gnode) return FALSE; else { item_t *old = gtk_ctree_node_get_row_data (ctree, cnode); item_t *new = item_constructor (old->name, old->action, old->arg, old->shortcut); gnode->data = new; return TRUE; } } static gboolean nodecopy (GtkCTree *ctree, guint depth, GNode *gnode, GtkCTreeNode *cnode, gpointer data) { item_t *item; if (!cnode || !gnode || (!(item = gnode->data))) return FALSE; else { set_item_pixmap (cnode, item); gtk_ctree_node_set_row_data_full (GTK_CTREE (menu_tree), cnode, item_constructor (item->name, item->action, item->arg, item->shortcut), item_destructor); return TRUE; } } static void shortcut_changed (const key_widget_t *data) { GtkCTreeNode *node = (GTK_CLIST (menu_tree)->selection)->data; item_t *item = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); if (item->shortcut) Free (item->shortcut); item->shortcut = g_strdup (data->keytext); toggle_save (menu_changed = YES, NULL); } static gint menu_key_pressed (GtkCTree *ctree, GdkEventKey *event, gpointer ptr) { GtkCTreeNode *selection = (GTK_CLIST (menu_tree)->selection)->data; switch (event->keyval) { case GDK_Return: case GDK_space: if (GTK_CTREE_ROW (selection)->expanded) gtk_ctree_collapse (GTK_CTREE (menu_tree), selection); else gtk_ctree_expand (GTK_CTREE (menu_tree), selection); return TRUE; case GDK_Insert: paste_node (menu_tree, NULL); return TRUE; case GDK_y: if (event->state & GDK_CONTROL_MASK) paste_node (menu_tree, NULL); return TRUE; case GDK_BackSpace: case GDK_Delete: cut_node (menu_tree, NULL); return TRUE; case GDK_k: if (event->state & GDK_CONTROL_MASK) cut_node (menu_tree, NULL); return TRUE; case GDK_m: if (event->state & GDK_CONTROL_MASK) insert_menu (menu_tree, NULL); return TRUE; case GDK_c: if (event->state & GDK_CONTROL_MASK) insert_menu (menu_tree, ""); return TRUE; default: break; } return FALSE; } static void set_item_pixmap (GtkCTreeNode *node, item_t *item) /* * Set pixmap of tree item. */ { if (item->action == WM_MENU) { char *old; guint8 spacing; GdkPixmap *closed, *opened; GdkBitmap *mask_closed, *mask_opened; gboolean is_leaf, expanded; gtk_ctree_get_node_info (GTK_CTREE (menu_tree), node, &old, &spacing, &closed, &mask_closed, &opened, &mask_opened, &is_leaf, &expanded); gtk_ctree_set_node_info (GTK_CTREE (menu_tree), node, item->name, 8, p_array [P_BOOK_CLOSE].pixmap, p_array [P_BOOK_CLOSE].mask, p_array [P_BOOK_OPEN].pixmap, p_array [P_BOOK_OPEN].mask, FALSE, expanded); } else if (item->action == WM_INCLUDE) gtk_ctree_set_node_info (GTK_CTREE (menu_tree), node, item->name, 8, p_array [P_MINIPAGE].pixmap, p_array [P_MINIPAGE].mask, NULL, NULL, TRUE, TRUE); else if (item->action == WM_PIPE) gtk_ctree_set_node_info (GTK_CTREE (menu_tree), node, item->name, 8, p_array [P_PIPE].pixmap, p_array [P_PIPE].mask, NULL, NULL, TRUE, TRUE); else if (item->action == WM_OPEN_MENU) gtk_ctree_set_node_info (GTK_CTREE (menu_tree), node, item->name, 8, p_array [P_DIR].pixmap, p_array [P_DIR].mask, NULL, NULL, TRUE, TRUE); else if (item->action == WM_EXEC || item->action == WM_SHEXEC) gtk_ctree_set_node_info (GTK_CTREE (menu_tree), node, item->name, 8, p_array [P_EXEC].pixmap, p_array [P_EXEC].mask, NULL, NULL, TRUE, TRUE); else gtk_ctree_set_node_info (GTK_CTREE (menu_tree), node, item->name, 8, p_array [P_GNUSTEP].pixmap, p_array [P_GNUSTEP].mask, NULL, NULL, TRUE, TRUE); } static void open_filebrowser (GtkWidget *button, gpointer data) { static GtkWidget *filesel = NULL; if (!filesel) { GtkFileSelection *fs; /* * Fileselection dialog window */ filesel = gtk_file_selection_new (_("Menu file selection")); fs = GTK_FILE_SELECTION (filesel); gtk_file_selection_hide_fileop_buttons (fs); gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE); gtk_signal_connect (GTK_OBJECT (filesel), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &filesel); gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked", GTK_SIGNAL_FUNC (set_filename), (gpointer) filesel); gtk_signal_connect_object (GTK_OBJECT (fs->cancel_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (filesel)); gtk_signal_connect_object (GTK_OBJECT (fs->ok_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (filesel)); { const char *filename = gtk_entry_get_text (GTK_ENTRY (include_file_entry)); if (streq (filename, "")) gtk_file_selection_set_filename (fs, WMAKERDIR "/"); else gtk_file_selection_set_filename (fs, filename); } } if (!GTK_WIDGET_VISIBLE (filesel)) gtk_widget_show (filesel); else gtk_widget_destroy (filesel); } static void set_filename (GtkWidget *button, gpointer data) { GtkFileSelection *fs = GTK_FILE_SELECTION (data); g_signal_handler_block (include_file_entry, include_file_entry_sig); gtk_entry_set_text (GTK_ENTRY (include_file_entry), gtk_file_selection_get_filename (fs)); g_signal_handler_unblock (include_file_entry, include_file_entry_sig); gtk_entry_set_position (GTK_ENTRY (include_file_entry), -1); toggle_save (menu_changed = YES, NULL); } static void set_entry_text (GtkWidget *entry, gpointer data) { GtkCTreeNode *node = (GTK_CLIST (menu_tree)->selection)->data; item_t *item = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); if (item->arg) Free (item->arg); item->arg = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); toggle_save (menu_changed = YES, NULL); } static void import_menu (GtkWidget *widget, gpointer data) { proplist_t menu; GtkCTreeNode *node = (GTK_CLIST (menu_tree)->selection)->data; GtkCTreeNode *new; item_t *item_old = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); char *filename; item_t *item_new; filename = expand_tilde (data ? data : item_old->arg); if (!strlen (filename)) return; if (filename [0] != '/') /* relative path */ { FILE *file; char *tmp = g_strdup_printf ("Library/WindowMaker/%s", filename); Free (filename); filename = get_gnustep_path (tmp); Free (tmp); file = fopen (filename, "r"); if (!file) /* check WMAKERDIR */ { Free (filename); tmp = expand_tilde (data ? data : item_old->arg); filename = g_strdup_printf ("%s/%s", WMAKERDIR, tmp); Free (tmp); /* error checking is done a few lines below */ } else { fclose (file); } } menu = convert_to_proplist (filename); Free (filename); if (!menu) return; /* ERROR */ gtk_clist_freeze (GTK_CLIST (menu_tree)); new = build_tree (GTK_CTREE_ROW (node)->parent, node, menu); WMReleasePropList (menu); item_new = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), new); Free (item_new->name); if (data) item_new->name = g_strdup_printf (_("Output of command '%s'"), item_old->arg); else item_new->name = g_strdup_printf (_("Imported file '%s'"), item_old->arg); { char *old; guint8 spacing; GdkPixmap *closed, *opened; GdkBitmap *mask_closed, *mask_opened; gboolean is_leaf, expanded; gtk_ctree_get_node_info (GTK_CTREE (menu_tree), new, &old, &spacing, &closed, &mask_closed, &opened, &mask_opened, &is_leaf, &expanded); gtk_ctree_set_node_info (GTK_CTREE (menu_tree), new, item_new->name, spacing, closed, mask_closed, opened, mask_opened, is_leaf, expanded); } remove_node (widget, NULL); gtk_clist_thaw (GTK_CLIST (menu_tree)); gtk_ctree_select (GTK_CTREE (menu_tree), new); gtk_entry_select_region (GTK_ENTRY (itemlabel_entry), 0, -1); gtk_widget_grab_focus (itemlabel_entry); toggle_save (menu_changed = YES, NULL); } #ifdef GNOME_TO_WMAKER static void set_gnomemenu (GtkWidget *menuitem, gpointer data) { insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_PIPE]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (pipe_command_entry), GNOME_TO_WMAKER); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "GNOME menu"); toggle_save (menu_changed = YES, NULL); } #endif /* GNOME_TO_WMAKER */ #ifdef PERL # ifdef KDE_TO_WMAKER static void set_kdemenu (GtkWidget *menuitem, gpointer data) { insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_PIPE]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (pipe_command_entry), KDE_TO_WMAKER); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "KDE menu"); toggle_save (menu_changed = YES, NULL); } # endif /* KDE_TO_WMAKER */ #endif /* PERL */ static void set_wmakerconf (GtkWidget *menuitem, gpointer data) { insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_MENU]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "WM Configuration"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show themes"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Themes"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show appearance"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Appearance"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show menu"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Menu"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_MENU]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Settings"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show misc"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Misc"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show paths"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Paths"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show workspace"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Workspace"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show windows"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Windows"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show effects"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Effects"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show mouse"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Mouse"); insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_EXEC]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (commandline_entry), "wmakerconf --show shortcuts"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Shortcuts"); toggle_save (menu_changed = YES, NULL); } #ifdef WMCONFIG static void set_wmconfig (GtkWidget *menuitem, gpointer data) { insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_PIPE]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (pipe_command_entry), WMCONFIG " --output wmaker"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "RedHat menu"); toggle_save (menu_changed = YES, NULL); } #else static void set_debian (GtkWidget *menuitem, gpointer data) { insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_INCLUDE]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (include_file_entry), "menu.hook"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Debian menu"); toggle_save (menu_changed = YES, NULL); } #endif /* WMCONFIG */ static void set_default_menu (GtkWidget *menuitem, gpointer data) { insert_menu (menuitem, ""); gtk_object_set_user_data (GTK_OBJECT (menuitem), (gpointer) cmd_name [WM_INCLUDE]); set_command (menuitem, NULL); gtk_entry_set_text (GTK_ENTRY (include_file_entry), WMAKERDIR "/menu"); gtk_entry_set_text (GTK_ENTRY (itemlabel_entry), "Default menu"); toggle_save (menu_changed = YES, NULL); } static void import_dynamic_menu (GtkWidget *widget, gpointer data) { GtkCTreeNode *node = (GTK_CLIST (menu_tree)->selection)->data; item_t *item = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); char *tmp_name = get_temporary_file_name (); char *command = g_strdup_printf ("%s > %s", item->arg, tmp_name); if (system (command)) { dialog_popup (DIALOG_ERROR, NULL, NULL, _("Can't execute dynamic menu command." "\nPlease check `stderr' for more details.")); Free (command); return; } Free (command); import_menu (widget, tmp_name); delete_file_or_dir (tmp_name); toggle_save (menu_changed = YES, NULL); } static void open_dirbrowser (GtkWidget *button, gpointer data) { static GtkWidget *filesel = NULL; if (!filesel) { GtkFileSelection *fs; /* * Fileselection dialog window */ filesel = gtk_file_selection_new (_("Choose directory")); fs = GTK_FILE_SELECTION (filesel); gtk_widget_set_sensitive (fs->file_list, FALSE); gtk_file_selection_hide_fileop_buttons (fs); gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE); gtk_signal_connect (GTK_OBJECT (filesel), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &filesel); gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked", GTK_SIGNAL_FUNC (insert_dir), (gpointer) filesel); gtk_signal_connect_object (GTK_OBJECT (fs->cancel_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (filesel)); gtk_signal_connect_object (GTK_OBJECT (fs->ok_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (filesel)); { char *filename; if (GTK_CLIST (dir_clist)->rows > 0) gtk_clist_get_text (GTK_CLIST (dir_clist), GPOINTER_TO_INT (GTK_CLIST (dir_clist)->selection->data), 0, &filename); else filename = ""; if (streq (filename, "")) gtk_file_selection_set_filename (fs, WMAKERDATADIR "/"); else gtk_file_selection_set_filename (fs, filename); } } if (!GTK_WIDGET_VISIBLE (filesel)) gtk_widget_show (filesel); else gtk_widget_destroy (filesel); } static void remove_dir (GtkWidget *button, gpointer data) { if (GTK_CLIST (dir_clist)->rows > 1) { gint row = GPOINTER_TO_INT (GTK_CLIST (dir_clist)->selection->data); if (row == GTK_CLIST (dir_clist)->rows - 1) /* last row */ gtk_clist_select_row (GTK_CLIST (dir_clist), row - 1, 0); else gtk_clist_select_row (GTK_CLIST (dir_clist), row + 1, 0); gtk_clist_remove (GTK_CLIST (dir_clist), row); if (GTK_CLIST (dir_clist)->rows <= 1) gtk_widget_set_sensitive (button, FALSE); dir_list_to_item (button, data); } } static void insert_dir (GtkWidget *button, gpointer data) { GtkFileSelection *fs = GTK_FILE_SELECTION (data); char *text = g_strdup (gtk_file_selection_get_filename (fs)); if (strlen (text) > 1 && text [strlen (text) - 1] == '/') text [strlen (text) - 1] = 0; if (GTK_CLIST (dir_clist)->rows > 0) gtk_clist_insert (GTK_CLIST (dir_clist), GPOINTER_TO_INT (GTK_CLIST (dir_clist)->selection->data), &text); else gtk_clist_insert (GTK_CLIST (dir_clist), 0, &text); Free (text); if (GTK_CLIST (dir_clist)->rows > 1) gtk_widget_set_sensitive (dir_remove, TRUE); dir_list_to_item (button, data); } static void dir_list_to_item (GtkWidget *button, gpointer data) { int n; unsigned len = 0; char *text; const char *ctext; GtkCTreeNode *node = (GTK_CLIST (menu_tree)->selection)->data; item_t *item = gtk_ctree_node_get_row_data (GTK_CTREE (menu_tree), node); if (GTK_TOGGLE_BUTTON (suffix_button)->active) len += strlen ("-noext "); for (n = 0; n < GTK_CLIST (dir_clist)->rows; n++) { gtk_clist_get_text (GTK_CLIST (dir_clist), n, 0, &text); len += strlen (text) + 1; } if (strlen (ctext = gtk_entry_get_text (GTK_ENTRY (dir_with_entry))) > 0) { len += strlen ("WITH "); len += strlen (ctext) + 1; } if (!len) return; /* should not happen ;-) */ if (item->arg) Free (item->arg); item->arg = Calloc (len, sizeof (char)); if (GTK_TOGGLE_BUTTON (suffix_button)->active) strcpy (item->arg, "-noext "); for (n = 0; n < GTK_CLIST (dir_clist)->rows; n++) { gtk_clist_get_text (GTK_CLIST (dir_clist), n, 0, &text); strcat (item->arg, text); if (n != GTK_CLIST (dir_clist)->rows - 1) strcat (item->arg, " "); } if (strlen (ctext = gtk_entry_get_text (GTK_ENTRY (dir_with_entry))) > 0) { strcat (item->arg, " WITH "); strcat (item->arg, ctext); } toggle_save (menu_changed = YES, NULL); } static void tree_moved (GtkCTree *ctree, GtkCTreeNode *node, GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling) { toggle_save (menu_changed = YES, NULL); } static void row_moved (GtkWidget *clist, gint source_row, gint dest_row) { dir_list_to_item (clist, NULL); } static proplist_t convert_to_proplist (const char *cfilename) { proplist_t menu; int c = 0; char *filename = g_strdup (cfilename); char *tmp_name = NULL; FILE *file = NULL; /* * Check if file is already in proplist format */ if (filename[0] == '/') file = fopen (filename, "r"); else /* not an absolute path; look for file in the usual places */ { int i; char * prefixes[2]; prefixes[0] = get_gnustep_path ("Library/WindowMaker/"); prefixes[1] = g_strdup ("/etc/X11/WindowMaker/"); for (i = 0; i < 2 && !file; i++) { Free (filename); filename = g_strconcat (prefixes[i], cfilename, NULL); file = fopen (filename, "r"); } Free (prefixes[0]); Free (prefixes[1]); } if (file) { while ((c = fgetc (file)) != EOF && isspace (c)) ; fclose (file); } if (c == '(') menu = read_proplist (filename); else { char *command; char *txt = g_strdup_printf (_("Can't convert old style menu\n%s\n" "to menu in proplist format."), filename); tmp_name = get_temporary_file_name (); command = g_strdup_printf ("%s/wm-oldmenu2new.sh %s %s", PKGDATADIR, filename, tmp_name); Free (filename); if (shell_command (command, txt)) { Free (command); Free (txt); return NULL; } Free (txt); Free (command); menu = read_proplist (tmp_name); } if (!menu || !WMIsPLArray (menu)) { dialog_popup (DIALOG_ERROR, NULL, NULL, _("Can't parse generated menu file\n`%s'.\n" "Please check syntax of this file."), tmp_name); if (menu) WMReleasePropList (menu); return NULL; /* ERROR */ } if (tmp_name) delete_file_or_dir (tmp_name); return menu; } static void convert_current_menu (GtkWidget *button, gpointer data) { char *menu = (char *) data; gtk_widget_destroy (info_message); gtk_box_pack_start (GTK_BOX (notebook_page), real_rootmenu (main_tooltips, convert_to_proplist (menu)), TRUE, TRUE, 0); toggle_save (menu_changed = YES, NULL); } static void empty_menu (GtkWidget *button, gpointer data) { gtk_widget_destroy (info_message); gtk_box_pack_start (GTK_BOX (notebook_page), real_rootmenu (main_tooltips, NULL), TRUE, TRUE, 0); toggle_save (menu_changed = YES, NULL); } static void convert_wmaker_menu (GtkWidget *button, gpointer data) { GtkFileSelection *fs = GTK_FILE_SELECTION (data); const char *menu = gtk_file_selection_get_filename (fs); gtk_widget_destroy (info_message); gtk_box_pack_start (GTK_BOX (notebook_page), real_rootmenu (main_tooltips, convert_to_proplist (menu)), TRUE, TRUE, 0); toggle_save (menu_changed = YES, NULL); } static void use_wmaker_menu (GtkWidget *button, gpointer data) { static GtkWidget *filesel = NULL; if (!filesel) { GtkFileSelection *fs; /* * Fileselection dialog window */ filesel = gtk_file_selection_new ("Menu file selection"); fs = GTK_FILE_SELECTION (filesel); gtk_file_selection_hide_fileop_buttons (fs); gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE); gtk_signal_connect (GTK_OBJECT (filesel), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &filesel); gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked", GTK_SIGNAL_FUNC (convert_wmaker_menu), (gpointer) filesel); gtk_signal_connect_object (GTK_OBJECT (fs->cancel_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (filesel)); gtk_signal_connect_object (GTK_OBJECT (fs->ok_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (filesel)); gtk_file_selection_set_filename (fs, WMAKERDIR "/"); gtk_file_selection_complete (fs, "*menu*"); } if (!GTK_WIDGET_VISIBLE (filesel)) gtk_widget_show (filesel); else gtk_widget_destroy (filesel); }