/*
* rootmenu.c: Root menu configuration
*
* Written by: Ullrich Hafner
*
* Copyright (C) 1998 Ullrich Hafner <hafner@bigfoot.de>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "proplist_t.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
/* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
#if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
# include <dirent.h>
# define NLENGTH(dirent) (strlen ((dirent)->d_name))
#else
# define dirent direct
# define NLENGTH(dirent) ((dirent)->d_namlen)
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif /* HAVE_SYS_NDIR_H */
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif /* HAVE_SYS_DIR_H */
# ifdef HAVE_NDIR_H
# include <ndir.h>
# 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);
}
syntax highlighted by Code2HTML, v. 0.9.1