From 312ba610a1e98fc656fb58178227d7d45a64494e Mon Sep 17 00:00:00 2001 From: Perberos Date: Mon, 14 Nov 2011 18:24:48 -0300 Subject: initial --- mini-commander/src/Makefile.am | 115 ++ mini-commander/src/about.c | 56 + mini-commander/src/about.h | 4 + mini-commander/src/browser-mini.xpm | 11 + mini-commander/src/cmd_completion.c | 246 +++++ mini-commander/src/cmd_completion.h | 34 + mini-commander/src/command_line.c | 598 +++++++++++ mini-commander/src/command_line.h | 41 + mini-commander/src/exec.c | 93 ++ mini-commander/src/exec.h | 35 + mini-commander/src/help.c | 42 + mini-commander/src/help.h | 4 + mini-commander/src/history-mini.xpm | 11 + mini-commander/src/history.c | 144 +++ mini-commander/src/history.h | 6 + mini-commander/src/macro.c | 155 +++ mini-commander/src/macro.h | 42 + mini-commander/src/mate-mini-commander.png | Bin 0 -> 703 bytes mini-commander/src/mc-default-macros.h | 65 ++ mini-commander/src/mc-install-default-macros.c | 179 ++++ mini-commander/src/mini-commander-applet-menu.xml | 4 + .../src/mini-commander-global.schemas.in | 31 + mini-commander/src/mini-commander.schemas.in | 193 ++++ mini-commander/src/mini-commander.ui | 713 +++++++++++++ mini-commander/src/mini-commander_applet.c | 430 ++++++++ mini-commander/src/mini-commander_applet.h | 72 ++ ...ets.MiniCommanderApplet.mate-panel-applet.in.in | 16 + ...el.applet.MiniCommanderAppletFactory.service.in | 3 + mini-commander/src/preferences.c | 1128 ++++++++++++++++++++ mini-commander/src/preferences.h | 109 ++ 30 files changed, 4580 insertions(+) create mode 100644 mini-commander/src/Makefile.am create mode 100644 mini-commander/src/about.c create mode 100644 mini-commander/src/about.h create mode 100644 mini-commander/src/browser-mini.xpm create mode 100644 mini-commander/src/cmd_completion.c create mode 100644 mini-commander/src/cmd_completion.h create mode 100644 mini-commander/src/command_line.c create mode 100644 mini-commander/src/command_line.h create mode 100644 mini-commander/src/exec.c create mode 100644 mini-commander/src/exec.h create mode 100644 mini-commander/src/help.c create mode 100644 mini-commander/src/help.h create mode 100644 mini-commander/src/history-mini.xpm create mode 100644 mini-commander/src/history.c create mode 100644 mini-commander/src/history.h create mode 100644 mini-commander/src/macro.c create mode 100644 mini-commander/src/macro.h create mode 100644 mini-commander/src/mate-mini-commander.png create mode 100644 mini-commander/src/mc-default-macros.h create mode 100644 mini-commander/src/mc-install-default-macros.c create mode 100644 mini-commander/src/mini-commander-applet-menu.xml create mode 100644 mini-commander/src/mini-commander-global.schemas.in create mode 100644 mini-commander/src/mini-commander.schemas.in create mode 100644 mini-commander/src/mini-commander.ui create mode 100644 mini-commander/src/mini-commander_applet.c create mode 100644 mini-commander/src/mini-commander_applet.h create mode 100644 mini-commander/src/org.mate.applets.MiniCommanderApplet.mate-panel-applet.in.in create mode 100644 mini-commander/src/org.mate.panel.applet.MiniCommanderAppletFactory.service.in create mode 100644 mini-commander/src/preferences.c create mode 100644 mini-commander/src/preferences.h (limited to 'mini-commander/src') diff --git a/mini-commander/src/Makefile.am b/mini-commander/src/Makefile.am new file mode 100644 index 00000000..1eace378 --- /dev/null +++ b/mini-commander/src/Makefile.am @@ -0,0 +1,115 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES = \ + -I. \ + -I$(srcdir) \ + -DMC_MENU_UI_DIR=\""$(uidir)"\" \ + $(MATE_APPLETS3_CFLAGS) \ + $(WARN_CFLAGS) \ + $(MATE_INCLUDEDIR) + +libexec_PROGRAMS = mini_commander_applet + +tooldir = $(libexecdir)/mate-applets +tool_PROGRAMS = mc-install-default-macros + +mini_commander_applet_SOURCES = \ + about.c \ + about.h \ + cmd_completion.c \ + cmd_completion.h \ + command_line.c \ + command_line.h \ + exec.c \ + exec.h \ + mini-commander_applet.c \ + mini-commander_applet.h \ + help.c \ + help.h \ + history.c \ + history.h \ + macro.c \ + macro.h \ + preferences.c \ + preferences.h \ + mc-default-macros.h + +mini_commander_applet_LDADD = \ + $(MATE_APPLETS3_LIBS) + +mc_install_default_macros_SOURCES = \ + mc-install-default-macros.c \ + mc-default-macros.h + +mc_install_default_macros_LDADD = \ + $(MATE_APPLETS_LIBS) + +builder_DATA = mini-commander.ui + +BITMAPS = \ + browser-mini.xpm \ + history-mini.xpm + +desktop_iconsdir = $(iconsdir)/hicolor/48x48/apps +desktop_icons_DATA = mate-mini-commander.png + +gtk_update_icon_cache = gtk-update-icon-cache -f -t $(iconsdir)/hicolor +install-data-hook: update-icon-cache +uninstall-hook: update-icon-cache +update-icon-cache: + @-if test -z "$(DESTDIR)"; then \ + echo "Updating Gtk icon cache."; \ + $(gtk_update_icon_cache); \ + else \ + echo "*** Icon cache not updated. After (un)install, run this:"; \ + echo "*** $(gtk_update_icon_cache)"; \ + fi + +appletdir = $(datadir)/mate-panel/applets +applet_in_files = org.mate.applets.MiniCommanderApplet.mate-panel-applet.in +applet_DATA = $(applet_in_files:.mate-panel-applet.in=.mate-panel-applet) + +$(applet_in_files): $(applet_in_files).in Makefile + $(AM_V_GEN)sed \ + -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ + -e "s|\@VERSION\@|$(PACKAGE_VERSION)|" \ + $< > $@ + +%.mate-panel-applet: %.mate-panel-applet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache + +servicedir = $(datadir)/dbus-1/services +service_in_files = org.mate.panel.applet.MiniCommanderAppletFactory.service.in +service_DATA = $(service_in_files:.service.in=.service) + +org.mate.panel.applet.MiniCommanderAppletFactory.service: $(service_in_files) + $(AM_V_GEN)sed \ + -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ + $< > $@ + +CLEANFILES = $(applet_DATA) $(applet_DATA).in $(service_DATA) $(schemas_DATA) + +schemasdir = @MATECONF_SCHEMA_FILE_DIR@ +schemas_in_files = mini-commander.schemas.in mini-commander-global.schemas.in +schemas_DATA = $(schemas_in_files:.schemas.in=.schemas) + +@INTLTOOL_SCHEMAS_RULE@ + +uidir = $(datadir)/mate-2.0/ui +ui_DATA = mini-commander-applet-menu.xml + +if MATECONF_SCHEMAS_INSTALL +install-data-local: + MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-install-rule $(schemas_DATA) ; + MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(top_builddir)/mini-commander/src/mc-install-default-macros +endif + +EXTRA_DIST = \ + org.mate.applets.MiniCommanderApplet.mate-panel-applet.in.in \ + $(service_in_files) \ + $(desktop_icons_DATA) \ + $(BITMAPS) \ + $(ui_DATA) \ + $(builder_DATA) \ + $(schemas_in_files) + +-include $(top_srcdir)/git.mk diff --git a/mini-commander/src/about.c b/mini-commander/src/about.c new file mode 100644 index 00000000..d862d4ed --- /dev/null +++ b/mini-commander/src/about.c @@ -0,0 +1,56 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998, 1999 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include +#include + +#include "about.h" + +void about_box (GtkAction *action, + MCData *mcdata) +{ + static const gchar *authors[] = { + "Oliver Maruhn ", + "Mark McLoughlin ", + NULL + }; + + const gchar *documenters[] = { + "Dan Mueth ", + "Oliver Maruhn ", + "Sun MATE Documentation Team ", + NULL + }; + + gtk_show_about_dialog (NULL, + "version", VERSION, + "copyright", "\xc2\xa9 1998-2005 Oliver Maruhn and others", + "comments", _("This MATE applet adds a command line to " + "the panel. It features command completion, " + "command history, and changeable macros."), + "authors", authors, + "documenters", documenters, + "translator-credits", _("translator-credits"), + "logo-icon-name", "mate-mini-commander", + NULL); +} diff --git a/mini-commander/src/about.h b/mini-commander/src/about.h new file mode 100644 index 00000000..875ea62d --- /dev/null +++ b/mini-commander/src/about.h @@ -0,0 +1,4 @@ +#include "mini-commander_applet.h" + +void about_box (GtkAction *action, + MCData *mcdata); diff --git a/mini-commander/src/browser-mini.xpm b/mini-commander/src/browser-mini.xpm new file mode 100644 index 00000000..6fb6b7fb --- /dev/null +++ b/mini-commander/src/browser-mini.xpm @@ -0,0 +1,11 @@ +/* XPM */ +static const char * browser_mini_xpm[] = { +"7 6 2 1", +" c NONE", +". c #000000000000", +" ... ", +" ..... ", +" ..... ", +" ..... ", +" ... ", +" "}; diff --git a/mini-commander/src/cmd_completion.c b/mini-commander/src/cmd_completion.c new file mode 100644 index 00000000..7b91ff5b --- /dev/null +++ b/mini-commander/src/cmd_completion.c @@ -0,0 +1,246 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998, 1999 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + If you expect tons of C code for command completion then you will + probably be astonished... + + These routines have probably to be rewritten in future. But they + should work on every system with a bash-alike shell. +*/ + +#include +#include +#include + +#include + +#include +#include + +#include "cmd_completion.h" +#include "preferences.h" +#include "macro.h" + + +static GList* cmdc( char* ); +static void process_dir( const gchar* ); +static void cleanup( void ); +static gint g_list_str_cmp( gconstpointer, gconstpointer ); + +/* global declaration so g_atexit() can reference it to free it. + * (not strictly necessary). + */ +static GList *path_elements = NULL; + +void +mc_cmd_completion (MCData *mc, + char *cmd) +{ + char buffer[MC_MAX_COMMAND_LENGTH] = ""; + char largest_possible_completion[MC_MAX_COMMAND_LENGTH] = ""; + int num_whitespaces, i, pos; + + GList *possible_completions_list = NULL; + GList *completion_element; + + + if(strlen(cmd) == 0) + { + return; + } + + num_whitespaces = mc_macro_prefix_len_wspace (mc, cmd) - mc_macro_prefix_len (mc, cmd); + possible_completions_list = cmdc(cmd + mc_macro_prefix_len_wspace (mc, cmd)); + + /* get first possible completion */ + completion_element = g_list_first(possible_completions_list); + if(completion_element) + strcpy(largest_possible_completion, (char *) completion_element->data); + else + strcpy(largest_possible_completion, ""); + + /* get the rest */ + while((completion_element = g_list_next(completion_element))) + { + strcpy(buffer, (char *) completion_element->data); + pos = 0; + while(largest_possible_completion[pos] != '\000' + && buffer[pos] != '\000' + && strncmp(largest_possible_completion, buffer, pos + 1) == 0) + pos++; + strncpy(largest_possible_completion, buffer, pos); + /* strncpy does not add \000 to the end */ + largest_possible_completion[pos] = '\000'; + } + + if(strlen(largest_possible_completion) > 0) + { + if(mc_macro_get_prefix(mc, cmd) != NULL) + strcpy(cmd, mc_macro_get_prefix(mc, cmd)); + else + strcpy(cmd, ""); + + /* fill up the whitespaces */ + for(i = 0; i < num_whitespaces; i++) + strcat(cmd, " "); + + strcat(cmd, largest_possible_completion); + } +} + +/* + * cmdc() -- command completion function. + * + * cmdc takes a char* and returns a GList* of possible completions. + * + * Initial version by Travis Hume . + * + */ +static GList * +cmdc( char *s ) +{ + GCompletion *completion = NULL; + GList *ret_list = NULL; + static GHashTable *path_hash = NULL; + static char *path = NULL; + gchar *path_elem; + struct stat buf; + static gboolean inited = FALSE; + gpointer hash_key = NULL; + + + /* + * Only want to build the GCompletion once. At some point I'd like to add + * code to refresh the GCompletion, either at a regular interval, or when + * there is a completion failure, ... + * + */ + if(!inited) + { + /* Make a local copy of the path variable. Otherwise the path + environment variable would be modified. */ + path = (char *) malloc(sizeof(char) * (strlen(getenv("PATH")) + 1)); + strcpy(path, getenv("PATH")); + + path_hash = g_hash_table_new( g_str_hash, g_str_equal ); + + for( path_elem = strtok( path, ":" ); path_elem; + path_elem = strtok( NULL, ":" )) + { + if( stat( path_elem, &buf )) + continue; + + if( buf.st_mode & S_IFDIR ) + { + /* keep a hash of processed paths, to avoid reprocessing + * dupped path entries. + */ + hash_key = g_hash_table_lookup( path_hash, path_elem ); + if( hash_key ) + continue; /* duplicate $PATH entry */ + else + { + g_hash_table_insert( + path_hash, (gpointer)path_elem, (gpointer)path_elem ); + + process_dir( path_elem ); + } + } + } + + /* atexit() we want to free the completion. */ + g_atexit( cleanup ); + + inited = TRUE; + } + + completion = g_completion_new( NULL ); + g_completion_add_items( completion, path_elements ); + ret_list = g_list_copy( g_completion_complete( completion, s, NULL )); + g_completion_free( completion ); + + return g_list_sort( ret_list, (GCompareFunc)g_list_str_cmp ); +} + + +/* + * Compare function to return a sorted completion. + */ +static gint +g_list_str_cmp( gconstpointer a, gconstpointer b ) +{ + return( strcmp( (char *)a, (char *)b )); +} + + + +/* + * Reads directory entries and adds non-dir, executable files + * to the GCompletion. + * Initial version by Travis Hume . + */ +static void +process_dir( const char *d ) +{ + DIR *dir; + struct dirent *de; + struct stat buf; + gpointer data; + gchar *path_str; + + + if( (dir = opendir( d )) == NULL ) + return; + + while( (de = readdir( dir )) != NULL ) + { + if( strcmp( de->d_name, "." ) == 0 || strcmp( de->d_name, "..") == 0) + continue; + + path_str = (gchar *)g_malloc( strlen( d ) + 1 + strlen( de->d_name ) + 1); + strcpy( path_str, d ); + strcat( path_str, "/" ); + strcat( path_str, de->d_name ); + if( stat( path_str, &buf ) != 0) + continue; + g_free( (gpointer)path_str ); + + if( S_ISDIR( buf.st_mode ) ) + continue; + + data = g_malloc( strlen( (gchar *)de->d_name ) + 1 ); + strcpy( (gchar *)data, (gchar *)(de->d_name) ); + if( buf.st_mode & S_IXUSR ) + path_elements = g_list_append( path_elements, data ); + } + closedir( dir ); +} + + +/* + * cleanup() -- free the memory used by the GCompletion. + */ +static void +cleanup( void ) +{ + g_list_free( path_elements ); +} diff --git a/mini-commander/src/cmd_completion.h b/mini-commander/src/cmd_completion.h new file mode 100644 index 00000000..042092fe --- /dev/null +++ b/mini-commander/src/cmd_completion.h @@ -0,0 +1,34 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __CMD_COMPLETION_H__ +#define __CMD_COMPLETION_H__ + +#include + +G_BEGIN_DECLS + +#include "mini-commander_applet.h" + +void mc_cmd_completion (MCData *mc, char *cmd); + +G_END_DECLS + +#endif /* __CMD_COMPLETION_H__ */ diff --git a/mini-commander/src/command_line.c b/mini-commander/src/command_line.c new file mode 100644 index 00000000..ef0c8d17 --- /dev/null +++ b/mini-commander/src/command_line.c @@ -0,0 +1,598 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998, 1999 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include + +#include + +#include "mini-commander_applet.h" +#include "command_line.h" +#include "preferences.h" +#include "exec.h" +#include "cmd_completion.h" +#include "history.h" + +static gint file_browser_response_signal(GtkWidget *widget, gint response, gpointer mc_data); +static gint history_popup_clicked_cb(GtkWidget *widget, gpointer data); +static gint history_popup_clicked_inside_cb(GtkWidget *widget, gpointer data); +static gchar* history_auto_complete(GtkWidget *widget, GdkEventKey *event); + + +static int history_position = MC_HISTORY_LIST_LENGTH; +static gchar *browsed_folder = NULL; + +static gboolean +button_press_cb (GtkEntry *entry, + GdkEventButton *event, + MCData *mc) +{ + const gchar *str; + + mate_panel_applet_request_focus (mc->applet, event->time); + + if (mc->error) { + mc->error = FALSE; + str = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); + gtk_entry_set_text (entry, (gchar *) str + 3); + } + return FALSE; +} + +static gboolean +command_key_event (GtkEntry *entry, + GdkEventKey *event, + MCData *mc) +{ + guint key = event->keyval; + char *command; + static char current_command[MC_MAX_COMMAND_LENGTH]; + char buffer[MC_MAX_COMMAND_LENGTH]; + gboolean propagate_event = TRUE; + const gchar *str; + + if (mc->error) { + mc->error = FALSE; + str = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); + gtk_entry_set_text (entry, (gchar *) str + 3); + gtk_editable_set_position (GTK_EDITABLE (entry), strlen (str)); + } + if(key == GDK_Tab + || key == GDK_KP_Tab + || key == GDK_ISO_Left_Tab) + { + if(event->state == GDK_CONTROL_MASK) + { + /* + * Move focus to the next widget (browser) button. + */ + gtk_widget_child_focus (GTK_WIDGET (mc->applet), GTK_DIR_TAB_FORWARD); + propagate_event = FALSE; + } + else if(event->state != GDK_SHIFT_MASK) + { + /* tab key pressed */ + strcpy(buffer, (char *) gtk_entry_get_text(GTK_ENTRY(entry))); + mc_cmd_completion (mc, buffer); + gtk_entry_set_text(GTK_ENTRY(entry), (gchar *) buffer); + + propagate_event = FALSE; + } + } + else if(key == GDK_Up + || key == GDK_KP_Up + || key == GDK_ISO_Move_Line_Up + || key == GDK_Pointer_Up) + { + /* up key pressed */ + if(history_position == MC_HISTORY_LIST_LENGTH) + { + /* store current command line */ + strcpy(current_command, (char *) gtk_entry_get_text(entry)); + } + if(history_position > 0 && exists_history_entry(history_position - 1)) + { + gtk_entry_set_text(entry, (gchar *) get_history_entry(--history_position)); + } + + propagate_event = FALSE; + } + else if(key == GDK_Down + || key == GDK_KP_Down + || key == GDK_ISO_Move_Line_Down + || key == GDK_Pointer_Down) + { + /* down key pressed */ + if(history_position < MC_HISTORY_LIST_LENGTH - 1) + { + gtk_entry_set_text(entry, (gchar *) get_history_entry(++history_position)); + } + else if(history_position == MC_HISTORY_LIST_LENGTH - 1) + { + gtk_entry_set_text(entry, (gchar *) current_command); + ++history_position; + } + + propagate_event = FALSE; + } + else if(key == GDK_Return + || key == GDK_KP_Enter + || key == GDK_ISO_Enter + || key == GDK_3270_Enter) + { + /* enter pressed -> exec command */ + command = (char *) malloc(sizeof(char) * MC_MAX_COMMAND_LENGTH); + strcpy(command, (char *) gtk_entry_get_text(entry)); + mc_exec_command(mc, command); + + history_position = MC_HISTORY_LIST_LENGTH; + free(command); + + strcpy(current_command, ""); + propagate_event = FALSE; + } + else if (mc->preferences.auto_complete_history && key >= GDK_space && key <= GDK_asciitilde ) + { + char *completed_command; + gint current_position = gtk_editable_get_position(GTK_EDITABLE(entry)); + + if(current_position != 0) + { + gtk_editable_delete_text( GTK_EDITABLE(entry), current_position, -1 ); + completed_command = history_auto_complete(GTK_WIDGET (entry), event); + + if(completed_command != NULL) + { + gtk_entry_set_text(entry, completed_command); + gtk_editable_set_position(GTK_EDITABLE(entry), current_position + 1); + propagate_event = FALSE; + } + } + } + + return !propagate_event; +} + +static gint +history_popup_clicked_cb(GtkWidget *widget, gpointer data) +{ + gdk_pointer_ungrab(GDK_CURRENT_TIME); + gdk_keyboard_ungrab(GDK_CURRENT_TIME); + gtk_grab_remove(GTK_WIDGET(widget)); + gtk_widget_destroy(GTK_WIDGET(widget)); + widget = NULL; + + /* go on */ + return (FALSE); +} + +static gint +history_popup_clicked_inside_cb(GtkWidget *widget, gpointer data) +{ + /* eat signal (prevent that popup will be destroyed) */ + return(TRUE); +} + +static gboolean +history_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + if (event->keyval == GDK_Escape) { + gdk_pointer_ungrab(GDK_CURRENT_TIME); + gdk_keyboard_ungrab(GDK_CURRENT_TIME); + gtk_grab_remove(GTK_WIDGET(widget)); + gtk_widget_destroy(GTK_WIDGET(widget)); + widget = NULL; + } + + return FALSE; + +} + +static gboolean +history_list_key_press_cb (GtkWidget *widget, + GdkEventKey *event, + MCData *mc) +{ + GtkTreeView *tree = g_object_get_data (G_OBJECT (mc->applet), "tree"); + GtkTreeIter iter; + GtkTreeModel *model; + gchar *command; + + switch (event->keyval) { + case GDK_KP_Enter: + case GDK_ISO_Enter: + case GDK_3270_Enter: + case GDK_Return: + case GDK_space: + case GDK_KP_Space: + if ((event->state & GDK_CONTROL_MASK) && + (event->keyval == GDK_space || event->keyval == GDK_KP_Space)) + break; + + if (!gtk_tree_selection_get_selected (gtk_tree_view_get_selection (tree), + &model, + &iter)) + return FALSE; + gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, + 0, &command, -1); + mc_exec_command (mc, command); + g_free (command); + gtk_widget_destroy(GTK_WIDGET(widget->parent->parent->parent)); + + return TRUE; + + default: + break; + } + + return FALSE; +} + +static gboolean +history_list_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + MCData *mc) +{ + GtkTreeView *tree = g_object_get_data (G_OBJECT (mc->applet), "tree"); + GtkTreeIter iter; + GtkTreeModel *model; + gchar *command; + + if (event->type == GDK_2BUTTON_PRESS) { + if (!gtk_tree_selection_get_selected (gtk_tree_view_get_selection (tree), + &model, + &iter)) + return FALSE; + gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, + 0, &command, -1); + mc_exec_command(mc, command); + g_free (command); + gtk_widget_destroy(GTK_WIDGET(widget->parent->parent->parent)); + + return TRUE; + } + + return FALSE; +} + +int +mc_show_history (GtkWidget *widget, + MCData *mc) +{ + GtkWidget *window; + GtkWidget *frame; + GtkWidget *scrolled_window; + GtkListStore *store; + GtkTreeIter iter; + GtkTreeModel *model; + GtkWidget *treeview; + GtkCellRenderer *cell_renderer; + GtkTreeViewColumn *column; + GtkRequisition req; + gchar *command_list[1]; + int i, j; + gint x, y, width, height, screen_width, screen_height; + + /* count commands stored in history list */ + for(i = 0, j = 0; i < MC_HISTORY_LIST_LENGTH; i++) + if(exists_history_entry(i)) + j++; + + window = gtk_window_new(GTK_WINDOW_POPUP); + gtk_window_set_screen (GTK_WINDOW (window), + gtk_widget_get_screen (GTK_WIDGET (mc->applet))); + gtk_window_set_resizable(GTK_WINDOW(window), FALSE); + gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_COMBO); + /* cb */ + g_signal_connect_after(GTK_OBJECT(window), + "button_press_event", + G_CALLBACK(history_popup_clicked_cb), + NULL); + g_signal_connect_after (G_OBJECT (window), "key_press_event", + G_CALLBACK (history_key_press_cb), NULL); + + /* size */ + gtk_widget_set_size_request(GTK_WIDGET(window), 200, 350); + + + /* frame */ + frame = gtk_frame_new(NULL); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); + gtk_widget_show(frame); + gtk_container_add(GTK_CONTAINER(window), frame); + + /* scrollbars */ + /* create scrolled window to put the Gtk_list widget inside */ + scrolled_window=gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + g_signal_connect(GTK_OBJECT(scrolled_window), + "button_press_event", + G_CALLBACK(history_popup_clicked_inside_cb), + NULL); + gtk_container_add(GTK_CONTAINER(frame), scrolled_window); + gtk_container_set_border_width (GTK_CONTAINER(scrolled_window), 2); + gtk_widget_show(scrolled_window); + + store = gtk_list_store_new (1, G_TYPE_STRING); + + /* add history entries to list */ + if (j == 0) { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter,0, _("No items in history"), -1); + } + else { + for(i = 0; i < MC_HISTORY_LIST_LENGTH; i++) + { + if(exists_history_entry(i)) + { + command_list[0] = get_history_entry(i); + gtk_list_store_prepend (store, &iter); + gtk_list_store_set (store, &iter,0,command_list[0],-1); + } + } + } + model = GTK_TREE_MODEL(store); + treeview = gtk_tree_view_new_with_model (model); + g_object_set_data (G_OBJECT (mc->applet), "tree", treeview); + cell_renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (NULL, cell_renderer, + "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); + if (j == 0) { + gtk_tree_selection_set_mode( (GtkTreeSelection *)gtk_tree_view_get_selection + (GTK_TREE_VIEW (treeview)), + GTK_SELECTION_NONE); + } + else { + gtk_tree_selection_set_mode( (GtkTreeSelection *)gtk_tree_view_get_selection + (GTK_TREE_VIEW (treeview)), + GTK_SELECTION_SINGLE); + g_signal_connect (G_OBJECT (treeview), "button_press_event", + G_CALLBACK (history_list_button_press_cb), mc); + g_signal_connect (G_OBJECT (treeview), "key_press_event", + G_CALLBACK (history_list_key_press_cb), mc); + } + + g_object_unref (G_OBJECT (model)); + gtk_container_add(GTK_CONTAINER(scrolled_window),treeview); + gtk_widget_show (treeview); + + gtk_widget_size_request (window, &req); + gdk_window_get_origin (GTK_WIDGET (mc->applet)->window, &x, &y); + gdk_window_get_geometry (GTK_WIDGET (mc->applet)->window, NULL, NULL, + &width, &height, NULL); + + switch (mate_panel_applet_get_orient (mc->applet)) { + case MATE_PANEL_APPLET_ORIENT_DOWN: + y += height; + break; + case MATE_PANEL_APPLET_ORIENT_UP: + y -= req.height; + break; + case MATE_PANEL_APPLET_ORIENT_LEFT: + x -= req.width; + break; + case MATE_PANEL_APPLET_ORIENT_RIGHT: + x += width; + break; + } + + screen_width = gdk_screen_width (); + screen_height = gdk_screen_height (); + x = CLAMP (x - 2, 0, MAX (0, screen_width - req.width)); + y = CLAMP (y - 2, 0, MAX (0, screen_height - req.height)); + gtk_window_move (GTK_WINDOW (window), x, y); + gtk_widget_show(window); + + /* grab focus */ + gdk_pointer_grab (window->window, + TRUE, + GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_POINTER_MOTION_MASK, + NULL, + NULL, + GDK_CURRENT_TIME); + gdk_keyboard_grab (window->window, TRUE, GDK_CURRENT_TIME); + gtk_grab_add(window); + gtk_widget_grab_focus (treeview); + + return FALSE; +} + +static gint +file_browser_response_signal(GtkWidget *widget, gint response, gpointer mc_data) +{ + MCData *mc = mc_data; + gchar *filename; + + if (response == GTK_RESPONSE_OK) { + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(mc->file_select)); + + if (filename != NULL) { + if (browsed_folder) + g_free (browsed_folder); + + browsed_folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER(mc->file_select)); + + mc_exec_command(mc, filename); + g_free(filename); + } + } + + /* destroy file select dialog */ + gtk_widget_destroy (mc->file_select); + mc->file_select = NULL; + + /* go on */ + return FALSE; +} + +int +mc_show_file_browser (GtkWidget *widget, + MCData *mc) +{ + if(mc->file_select && GTK_WIDGET_VISIBLE(mc->file_select)) { + gtk_window_present (GTK_WINDOW (mc->file_select)); + return TRUE; + } + + /* build file select dialog */ + mc->file_select = gtk_file_chooser_dialog_new((gchar *) _("Start program"), + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_EXECUTE, GTK_RESPONSE_OK, + NULL); + + g_signal_connect(G_OBJECT(mc->file_select), + "response", + G_CALLBACK(file_browser_response_signal), + mc); + + /* set path to last selected path */ + if (browsed_folder) + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(mc->file_select), + (gchar *) browsed_folder); + + /* Set as modal */ + gtk_window_set_modal(GTK_WINDOW(mc->file_select),TRUE); + + gtk_window_set_screen (GTK_WINDOW (mc->file_select), + gtk_widget_get_screen (GTK_WIDGET (mc->applet))); + gtk_window_set_position (GTK_WINDOW (mc->file_select), GTK_WIN_POS_CENTER); + + gtk_widget_show(mc->file_select); + + return FALSE; +} + +void +mc_create_command_entry (MCData *mc) +{ + mc->entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (mc->entry), MC_MAX_COMMAND_LENGTH); + + g_signal_connect (mc->entry, "key_press_event", + G_CALLBACK (command_key_event), mc); + + g_signal_connect (mc->entry, "button_press_event", + G_CALLBACK (button_press_cb), mc); + + if (!mc->preferences.show_default_theme) + { + gtk_widget_set_name (mc->entry, "minicommander-applet-entry"); + mc_command_update_entry_color (mc); + } + else + gtk_widget_set_name (mc->entry, + "minicommander-applet-entry-default"); + + mc_command_update_entry_size (mc); + + set_atk_name_description (mc->entry, + _("Command line"), + _("Type a command here and Mate will execute it for you")); +} + +void +mc_command_update_entry_color (MCData *mc) +{ + GdkColor fg; + GdkColor bg; + char *rc_string; + + fg.red = mc->preferences.cmd_line_color_fg_r; + fg.green = mc->preferences.cmd_line_color_fg_g; + fg.blue = mc->preferences.cmd_line_color_fg_b; + + /* FIXME: wish we had an API for this, see bug #79585 */ + rc_string = g_strdup_printf ( + "\n" + " style \"minicommander-applet-entry-style\"\n" + " {\n" + " GtkWidget::cursor-color=\"#%04x%04x%04x\"\n" + " }\n" + " widget \"*.minicommander-applet-entry\" " + "style \"minicommander-applet-entry-style\"\n" + "\n", + fg.red, fg.green, fg.blue); + gtk_rc_parse_string (rc_string); + g_free (rc_string); + + gtk_widget_modify_text (mc->entry, GTK_STATE_NORMAL, &fg); + gtk_widget_modify_text (mc->entry, GTK_STATE_PRELIGHT, &fg); + + bg.red = mc->preferences.cmd_line_color_bg_r; + bg.green = mc->preferences.cmd_line_color_bg_g; + bg.blue = mc->preferences.cmd_line_color_bg_b; + + gtk_widget_modify_base (mc->entry, GTK_STATE_NORMAL, &bg); + gtk_widget_modify_base (mc->entry, GTK_STATE_PRELIGHT, &bg); +} + +void +mc_command_update_entry_size (MCData *mc) +{ + int size_x = -1; + + size_x = mc->preferences.normal_size_x - 17; + if ((mc->orient == MATE_PANEL_APPLET_ORIENT_LEFT) || (mc->orient == MATE_PANEL_APPLET_ORIENT_RIGHT)) { + size_x = MIN(size_x, mc->preferences.panel_size_x - 17); + gtk_widget_set_size_request (GTK_WIDGET (mc->entry), size_x, -1); + } else { + gtk_widget_set_size_request (GTK_WIDGET (mc->entry), size_x, mc->preferences.normal_size_y+2); + } +} + + +/* Thanks to Halfline for his initial version + of history_auto_complete */ +gchar * +history_auto_complete(GtkWidget *widget, GdkEventKey *event) +{ + gchar current_command[MC_MAX_COMMAND_LENGTH]; + gchar* completed_command; + int i; + + g_snprintf(current_command, sizeof(current_command), "%s%s", + gtk_entry_get_text(GTK_ENTRY(widget)), event->string); + for(i = MC_HISTORY_LIST_LENGTH - 1; i >= 0; i--) + { + if(!exists_history_entry(i)) + break; + completed_command = get_history_entry(i); + if(!strncmp(completed_command, current_command, strlen(current_command))) + return completed_command; + } + + return NULL; +} diff --git a/mini-commander/src/command_line.h b/mini-commander/src/command_line.h new file mode 100644 index 00000000..195b2425 --- /dev/null +++ b/mini-commander/src/command_line.h @@ -0,0 +1,41 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998, 1999 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COMMAND_LINE_H__ +#define __COMMAND_LINE_H__ + +#include + +G_BEGIN_DECLS + +#include "mini-commander_applet.h" + +void mc_create_command_entry (MCData *mc); +int mc_show_history (GtkWidget *widget, + MCData *mc); +int mc_show_file_browser (GtkWidget *widget, + MCData *mc); +void mc_command_update_entry_color (MCData *mc); +void mc_command_update_entry_size (MCData *mc); + +G_END_DECLS + +#endif /* __COMMAND_LINE_H__ */ diff --git a/mini-commander/src/exec.c b/mini-commander/src/exec.c new file mode 100644 index 00000000..40688bfa --- /dev/null +++ b/mini-commander/src/exec.c @@ -0,0 +1,93 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include +#include +#include +#include + +#include "exec.h" +#include "macro.h" +#include "preferences.h" +#include "history.h" + +#define KEY_AUDIBLE_BELL "/apps/marco/general/audible_bell" + +static void beep (void); + +void +mc_exec_command (MCData *mc, + const char *cmd) +{ + GError *error = NULL; + char command [1000]; + char **argv = NULL; + gchar *str; + + strncpy (command, cmd, sizeof (command)); + command [sizeof (command) - 1] = '\0'; + + mc_macro_expand_command (mc, command); + + if (!g_shell_parse_argv (command, NULL, &argv, &error)) { + if (error != NULL) { + g_error_free (error); + error = NULL; + } + + return; + } + + if(!gdk_spawn_on_screen (gtk_widget_get_screen (GTK_WIDGET (mc->applet)), + g_get_home_dir (), argv, NULL, + G_SPAWN_SEARCH_PATH, + NULL, NULL, NULL, + &error)) { + str = g_strconcat ("(?)", command, NULL); + gtk_entry_set_text (GTK_ENTRY (mc->entry), str); + //gtk_editable_set_position (GTK_EDITABLE (mc->entry), 0); + mc->error = TRUE; + beep (); + g_free (str); + } else { + gtk_entry_set_text (GTK_ENTRY (mc->entry), (gchar *) ""); + append_history_entry (mc, cmd, FALSE); + } + g_strfreev (argv); + + if (error != NULL) + g_error_free (error); +} + +static void beep (void) +{ + MateConfClient *default_client; + gboolean audible_bell_set; + + default_client = mateconf_client_get_default (); + audible_bell_set = mateconf_client_get_bool (default_client, KEY_AUDIBLE_BELL, NULL); + if (audible_bell_set) { + gdk_beep (); + } +} diff --git a/mini-commander/src/exec.h b/mini-commander/src/exec.h new file mode 100644 index 00000000..01d46c10 --- /dev/null +++ b/mini-commander/src/exec.h @@ -0,0 +1,35 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __EXEC_H__ +#define __EXEC_H__ + +#include + +G_BEGIN_DECLS + +#include "mini-commander_applet.h" + +void mc_exec_command (MCData *mc, + const char *cmd); + +G_END_DECLS + +#endif /* __EXEC_H__ */ diff --git a/mini-commander/src/help.c b/mini-commander/src/help.c new file mode 100644 index 00000000..b5c4b66b --- /dev/null +++ b/mini-commander/src/help.c @@ -0,0 +1,42 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "help.h" + +void +show_help (GtkAction *action, + MCData *mcdata) +{ + GError *error = NULL; + + gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (mcdata->applet)), + "command-line", + gtk_get_current_event_time (), + &error); + + if (error) { /* FIXME: this error needs to be seen by the user */ + g_warning ("help error: %s\n", error->message); + g_error_free (error); + error = NULL; + } +} diff --git a/mini-commander/src/help.h b/mini-commander/src/help.h new file mode 100644 index 00000000..495984ab --- /dev/null +++ b/mini-commander/src/help.h @@ -0,0 +1,4 @@ +#include "mini-commander_applet.h" + +void show_help (GtkAction *action, + MCData *mcdata); diff --git a/mini-commander/src/history-mini.xpm b/mini-commander/src/history-mini.xpm new file mode 100644 index 00000000..b7ad65eb --- /dev/null +++ b/mini-commander/src/history-mini.xpm @@ -0,0 +1,11 @@ +/* XPM */ +static const char * history_mini_xpm[] = { +"7 6 2 1", +" c NONE", +". c #000000000000", +" ", +".......", +" ..... ", +" ... ", +" . ", +" "}; diff --git a/mini-commander/src/history.c b/mini-commander/src/history.c new file mode 100644 index 00000000..750796da --- /dev/null +++ b/mini-commander/src/history.c @@ -0,0 +1,144 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Actually the command history is a simple list. So, I guess this + here could also be done with the list routines of glib. */ + +#include +#include +#include + +#include +#include +#include + +#include "history.h" +#include "preferences.h" + +static char *history_command[MC_HISTORY_LIST_LENGTH]; +static void delete_history_entry(int element_number); + + +int +exists_history_entry(int pos) +{ + return(history_command[pos] != NULL); +} + +char * +get_history_entry(int pos) +{ + return(history_command[pos]); +} + +void +set_history_entry(int pos, char * entry) +{ + if(history_command[pos] != NULL) + free(history_command[pos]); + history_command[pos] = (char *)malloc(sizeof(char) * (strlen(entry) + 1)); + strcpy(history_command[pos], entry); +} + +/* load_history indicates whether the history list is being loaded at startup. +** If true then don't save the new entries with mateconf (since they are being read +** using mateconf +*/ +void +append_history_entry(MCData *mcdata, const char * entry, gboolean load_history) +{ + MatePanelApplet *applet = mcdata->applet; + MateConfValue *history; + GSList *list = NULL; + int pos, i; + + /* remove older dupes */ + for(pos = 0; pos <= MC_HISTORY_LIST_LENGTH - 1; pos++) + { + if(exists_history_entry(pos) && strcmp(entry, history_command[pos]) == 0) + /* dupe found */ + delete_history_entry(pos); + } + + /* delete oldest entry */ + if(history_command[0] != NULL) + free(history_command[0]); + + /* move entries */ + for(pos = 0; pos < MC_HISTORY_LIST_LENGTH - 1; pos++) + { + history_command[pos] = history_command[pos+1]; + /* printf("%s\n", history_command[pos]); */ + } + + /* append entry */ + history_command[MC_HISTORY_LIST_LENGTH - 1] = (char *)malloc(sizeof(char) * (strlen(entry) + 1)); + strcpy(history_command[MC_HISTORY_LIST_LENGTH - 1], entry); + + if (load_history) + return; + + /* If not writable, just keeps the history around for this session */ + if ( ! mc_key_writable (mcdata, "history")) + return; + + /* Save history - this seems like a waste to do it every time it's updated + ** but it doesn't seem to work when called on the destroy signal of the applet + */ + for(i = 0; i < MC_HISTORY_LIST_LENGTH; i++) + { + MateConfValue *value_entry; + + value_entry = mateconf_value_new (MATECONF_VALUE_STRING); + if(exists_history_entry(i)) { + mateconf_value_set_string (value_entry, (gchar *) get_history_entry(i)); + list = g_slist_append (list, value_entry); + } + + } + + history = mateconf_value_new (MATECONF_VALUE_LIST); + if (list) { + mateconf_value_set_list_type (history, MATECONF_VALUE_STRING); + mateconf_value_set_list (history, list); + mate_panel_applet_mateconf_set_value (applet, "history", history, NULL); + } + + while (list) { + MateConfValue *value = list->data; + mateconf_value_free (value); + list = g_slist_next (list); + } + + mateconf_value_free (history); + +} + +void +delete_history_entry(int element_number) +{ + int pos; + + for(pos = element_number; pos > 0; --pos) + history_command[pos] = history_command[pos - 1]; + + history_command[0] = NULL; +} diff --git a/mini-commander/src/history.h b/mini-commander/src/history.h new file mode 100644 index 00000000..1dd5dea2 --- /dev/null +++ b/mini-commander/src/history.h @@ -0,0 +1,6 @@ +#include "mini-commander_applet.h" + +int exists_history_entry(int pos); +extern char *get_history_entry(int pos); +extern void set_history_entry(int pos, char * entry); +extern void append_history_entry(MCData *mcdata, const char * entry, gboolean load_history); diff --git a/mini-commander/src/macro.c b/mini-commander/src/macro.c new file mode 100644 index 00000000..060d4c50 --- /dev/null +++ b/mini-commander/src/macro.c @@ -0,0 +1,155 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "macro.h" +#include "preferences.h" + +/* search for the longest matching prefix */ +static MCMacro * +mc_macro_with_prefix (MCData *mc, + char *command) +{ + MCMacro *retval = NULL; + GSList *l; + int prefix_len_found = 0; + + for (l = mc->preferences.macros; l; l = l->next) { + MCMacro *macro = l->data; + int pattern_len; + + pattern_len = strlen (macro->pattern); + + if (pattern_len > prefix_len_found && + !strncmp (command, macro->pattern, pattern_len) && + (strstr (macro->command, "$1") || pattern_len == strlen (command))) { + /* found a matching prefix; + * if macro does not contain "$1" then the prefix has + * to to have the same length as the command + */ + prefix_len_found = pattern_len; + retval = macro; + } + } + + return retval; +} + +int +mc_macro_prefix_len (MCData *mc, + char *command) +{ + MCMacro *macro; + + macro = mc_macro_with_prefix (mc, command); + if (!macro) + return 0; + + return strlen (macro->pattern); +} + +int +mc_macro_prefix_len_wspace (MCData *mc, + char *command) +{ + char *c_ptr; + + c_ptr = command + mc_macro_prefix_len (mc, command); + + while (*c_ptr != '\0' && *c_ptr == ' ') + c_ptr++; + + return c_ptr - command; +} + +char * +mc_macro_get_prefix (MCData *mc, + char *command) +{ + MCMacro *macro; + + macro = mc_macro_with_prefix (mc, command); + if (!macro) + return NULL; + + return macro->pattern; +} + +void +mc_macro_expand_command (MCData *mc, + char *command) +{ + GSList *l; + char command_exec [1000]; + + command_exec [0] = '\0'; + + for (l = mc->preferences.macros; l; l = l->next) { + regmatch_t regex_matches [MC_MAX_NUM_MACRO_PARAMETERS]; + MCMacro *macro = l->data; + + if (regexec (¯o->regex, command, MC_MAX_NUM_MACRO_PARAMETERS, regex_matches, 0) != REG_NOMATCH) { + char placeholder [100]; + char *char_p; + int inside_placeholder; + int parameter_number; + + inside_placeholder = 0; + + for (char_p = macro->command; *char_p != '\0'; ++char_p) { + if (inside_placeholder == 0 && + *char_p == '\\' && + *(char_p + 1) >= '0' && + *(char_p + 1) <= '9') { + strcpy (placeholder, ""); + inside_placeholder = 1; + } else if (inside_placeholder && + (*(char_p + 1) < '0' || *(char_p + 1) > '9')) + inside_placeholder = 2; + + if (inside_placeholder == 0) + strncat (command_exec, char_p, 1); + else + strncat (placeholder, char_p, 1); + + if (inside_placeholder == 2) { + parameter_number = atoi (placeholder + 1); + + if (parameter_number <= MC_MAX_NUM_MACRO_PARAMETERS && + regex_matches [parameter_number].rm_eo > 0) + strncat (command_exec, + command + regex_matches [parameter_number].rm_so, + regex_matches [parameter_number].rm_eo - regex_matches [parameter_number].rm_so); + + inside_placeholder = 0; + } + } + } + } + + if (command_exec [0] != '\0') + strcpy (command, command_exec); +} diff --git a/mini-commander/src/macro.h b/mini-commander/src/macro.h new file mode 100644 index 00000000..7beb2fb6 --- /dev/null +++ b/mini-commander/src/macro.h @@ -0,0 +1,42 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn + * + * Author: Oliver Maruhn + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MACRO_H__ +#define __MACRO_H__ + +#include + +G_BEGIN_DECLS + +#include "mini-commander_applet.h" + +void mc_macro_expand_command (MCData *mc, + char *command); +int mc_macro_prefix_len (MCData *mc, + char *command); +int mc_macro_prefix_len_wspace (MCData *mc, + char *command); +char *mc_macro_get_prefix (MCData *mc, + char *command); + +G_END_DECLS + +#endif /* __MACRO_H__ */ diff --git a/mini-commander/src/mate-mini-commander.png b/mini-commander/src/mate-mini-commander.png new file mode 100644 index 00000000..b2152e3c Binary files /dev/null and b/mini-commander/src/mate-mini-commander.png differ diff --git a/mini-commander/src/mc-default-macros.h b/mini-commander/src/mc-default-macros.h new file mode 100644 index 00000000..9ede9c73 --- /dev/null +++ b/mini-commander/src/mc-default-macros.h @@ -0,0 +1,65 @@ +/* + * Mini-Commander Applet + * Copyright (C) 2002 Sun Microsystems Inc. + * + * Authors: Mark McLoughlin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MC_DEFAULT_MACROS_H__ +#define __MC_DEFAULT_MACROS_H__ + +#include + +G_BEGIN_DECLS + +typedef struct { + char *pattern; + char *command; +} MCDefaultMacro; + +/* These are both the defaults stored in the MateConfSchema + * and the fallback defaults that are used if we are + * having MateConf problems. + * + * See mc-install-default-macros.c for how they get + * installed into the schemas. + */ +static const MCDefaultMacro mc_default_macros [] = { + { "^(https?://.*)$", "mate-open \\1" }, + { "^(ftp://.*)", "mate-open \\1" }, + { "^(www\\..*)$", "mate-open http://\\1" }, + { "^(ftp\\..*)$", "mate-open ftp://\\1" }, + + /* altavista search */ + { "^av: *(.*)$", "mate-open http://www.altavista.net/cgi-bin/query?pg=q\\&kl=XX\\&q=$(echo '\\1'|sed -e ': p;s/+/%2B/;t p;: s;s/\\ /+/;t s;: q;s/\\\"/%22/;t q')" }, + + /* yahoo search */ + { "^yahoo: *(.*)$", "mate-open http://ink.yahoo.com/bin/query?p=$(echo '\\1'|sed -e ': p;s/+/%2B/;t p;: s;s/\\ /+/;t s;: q;s/\\\"/%22/;t q')" }, + + /* freshmeat search */ + { "^fm: *(.*)$", "mate-open http://core.freshmeat.net/search.php3?query=$(echo '\\1'|tr \" \" +)" }, + + /* dictionary search */ + { "^dictionary: *(.*)$", "mate-dictionary \"\\1\"" }, + + /* google search */ + { "^google: *(.*)$", "mate-open http://www.google.com/search?q=\\1" }, +}; + +G_END_DECLS + +#endif /* __MC_DEFAULT_MACROS_H__ */ diff --git a/mini-commander/src/mc-install-default-macros.c b/mini-commander/src/mc-install-default-macros.c new file mode 100644 index 00000000..51750173 --- /dev/null +++ b/mini-commander/src/mc-install-default-macros.c @@ -0,0 +1,179 @@ +/* + * mc-install-default-macros.c: + * Copyright (C) 2002 Sun Microsystems Inc. + * + * Authors: Mark McLoughlin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This reads the macro patterns and commands lists + * schemas and sets the default values to be our + * default list of macros. + * + * This is easier than trying to have this stuff + * in the .schemas file - you would believe the + * kind of escaping and hackery needed to get + * it into the .schemas, and even then its impossible + * to tell which pattern is for which macro ... + */ + +/* This is to have access to mateconf_engine_get_local() */ +#define MATECONF_ENABLE_INTERNALS 1 + +#include +#include + +#include +#include +#include +#include + +/* Okay, I'm VERY bold. I deserve to be spanked. + * + * But this isn't installed, its only used at build time, + * so I don't feel too bad. If these disappear from the + * ABI or their signature changes, the build will break + * and someone will have to figure out how to fix it. + * Too bad, whoever you are :/ + */ +void mateconf_shutdown_daemon (GError **err); + +#include "mc-default-macros.h" + +#define MC_PATTERNS_SHEMA_KEY "/schemas/apps/mini-commander-global/macro_patterns" +#define MC_COMMANDS_SHEMA_KEY "/schemas/apps/mini-commander-global/macro_commands" + +/* + * Keep these old schemas around in order to keep + * old configurations from breaking. See bug #91194 + */ +#define MC_DEPRECATED_PATTERNS_SHEMA_KEY "/schemas/apps/mini-commander/prefs/macro_patterns" +#define MC_DEPRECATED_COMMANDS_SHEMA_KEY "/schemas/apps/mini-commander/prefs/macro_commands" + +static void +install_default_macros_list (MateConfClient *client, + const char *key, + int offset) +{ + MateConfSchema *schema; + MateConfValue *value; + GSList *list = NULL; + GError *error; + int i; + + error = NULL; + schema = mateconf_client_get_schema (client, key, &error); + if (error) { + g_warning (_("Cannot get schema for %s: %s"), key, error->message); + g_error_free (error); + return; + } + + /* mateconf has started to return NULL with no error set. */ + g_return_if_fail (schema != NULL); + + /* Some sanity checks */ + g_assert (mateconf_schema_get_type (schema) == MATECONF_VALUE_LIST); + g_assert (mateconf_schema_get_list_type (schema) == MATECONF_VALUE_STRING); + + value = mateconf_value_new (MATECONF_VALUE_LIST); + mateconf_value_set_list_type (value, MATECONF_VALUE_STRING); + + for (i = 0; i < G_N_ELEMENTS (mc_default_macros); i++) + list = g_slist_prepend (list, + mateconf_value_new_from_string (MATECONF_VALUE_STRING, + G_STRUCT_MEMBER (char *, &mc_default_macros [i], offset), + NULL)); + list = g_slist_reverse (list); + + mateconf_value_set_list_nocopy (value, list); + list = NULL; + + mateconf_schema_set_default_value_nocopy (schema, value); + value = NULL; + + error = NULL; + mateconf_client_set_schema (client, key, schema, &error); + if (error) { + g_warning (_("Cannot set schema for %s: %s"), key, error->message); + g_error_free (error); + } + + mateconf_schema_free (schema); + + printf (_("Set default list value for %s\n"), key); +} + +int +main (int argc, char **argv) +{ + MateConfClient *client; + MateConfEngine *conf; + GError *error = NULL; + const char *config_source; + + if (g_getenv ("MATECONF_DISABLE_MAKEFILE_SCHEMA_INSTALL")) { + fprintf (stderr, _("MATECONF_DISABLE_MAKEFILE_SCHEMA_INSTALL is set, not installing schemas\n")); + return 0; + } + + g_type_init (); + + config_source = g_getenv ("MATECONF_CONFIG_SOURCE"); + if (!config_source) { + fprintf (stderr, _("Must set the MATECONF_CONFIG_SOURCE environment variable\n")); + return -1; + } + + if (*config_source == '\0') + config_source = NULL; + + /* shut down daemon, this is a race condition, but will usually work. */ + mateconf_shutdown_daemon (NULL); + + if (!config_source) + conf = mateconf_engine_get_default (); + else + conf = mateconf_engine_get_local (config_source, &error); + + if (!conf) { + g_assert (error != NULL); + fprintf (stderr, _("Failed to access configuration source(s): %s\n"), error->message); + g_error_free (error); + return -1; + } + + client = mateconf_client_get_for_engine (conf); + + install_default_macros_list (client, MC_PATTERNS_SHEMA_KEY, G_STRUCT_OFFSET (MCDefaultMacro, pattern)); + install_default_macros_list (client, MC_COMMANDS_SHEMA_KEY, G_STRUCT_OFFSET (MCDefaultMacro, command)); + + install_default_macros_list (client, MC_DEPRECATED_PATTERNS_SHEMA_KEY, G_STRUCT_OFFSET (MCDefaultMacro, pattern)); + install_default_macros_list (client, MC_DEPRECATED_COMMANDS_SHEMA_KEY, G_STRUCT_OFFSET (MCDefaultMacro, command)); + + mateconf_client_suggest_sync (client, &error); + if (error) { + fprintf (stderr, _("Error syncing config data: %s"), + error->message); + g_error_free (error); + return 1; + } + + mateconf_engine_unref (conf); + g_object_unref (client); + + return 0; +} diff --git a/mini-commander/src/mini-commander-applet-menu.xml b/mini-commander/src/mini-commander-applet-menu.xml new file mode 100644 index 00000000..5cef44fa --- /dev/null +++ b/mini-commander/src/mini-commander-applet-menu.xml @@ -0,0 +1,4 @@ + + + + diff --git a/mini-commander/src/mini-commander-global.schemas.in b/mini-commander/src/mini-commander-global.schemas.in new file mode 100644 index 00000000..b9714085 --- /dev/null +++ b/mini-commander/src/mini-commander-global.schemas.in @@ -0,0 +1,31 @@ + + + + + /schemas/apps/mini-commander-global/macro_patterns + /apps/mini-commander/macro_patterns + mini-commander-applet + list + string + [blah] + + Macro pattern list + List of MateConfValue entries containing strings for the macro patterns. + + + + + /schemas/apps/mini-commander-global/macro_commands + /apps/mini-commander/macro_commands + mini-commander-applet + list + string + [blah] + + Macro command list + List of MateConfValue entries containing strings for the macro commands. + + + + + diff --git a/mini-commander/src/mini-commander.schemas.in b/mini-commander/src/mini-commander.schemas.in new file mode 100644 index 00000000..2d5413de --- /dev/null +++ b/mini-commander/src/mini-commander.schemas.in @@ -0,0 +1,193 @@ + + + + + /schemas/apps/mini-commander/prefs/show_handle + mini-commander-applet + bool + false + + Show handle + Show a handle so the applet can be detached from the panel. + + + + + /schemas/apps/mini-commander/prefs/show_frame + mini-commander-applet + bool + false + + Show frame + Show a frame surrounding the applet. + + + + + /schemas/apps/mini-commander/prefs/autocomplete_history + mini-commander-applet + bool + true + + Perform history autocompletion + Attempt to autocomplete a command from the history of commands entered. + + + + + /schemas/apps/mini-commander/prefs/normal_size_x + mini-commander-applet + int + 150 + + Width + Width of the applet + + + + + /schemas/apps/mini-commander/prefs/normal_size_y + mini-commander-applet + int + 48 + + Not used anymore + + + + + /schemas/apps/mini-commander/prefs/cmd_line_y + mini-commander-applet + int + 24 + + Not used anymore + + + + + /schemas/apps/mini-commander/prefs/show_default_theme + mini-commander-applet + bool + true + + Use the default theme colors + Use theme colors instead of custom ones. + + + + + /schemas/apps/mini-commander/prefs/cmd_line_color_fg_r + mini-commander-applet + int + 64613 + + Foreground color, red component + The red component of the foreground color. + + + + + /schemas/apps/mini-commander/prefs/cmd_line_color_fg_g + mini-commander-applet + int + 64613 + + Foreground color, green component + The green component of the foreground color. + + + + + /schemas/apps/mini-commander/prefs/cmd_line_color_fg_b + mini-commander-applet + int + 64613 + + Foreground color, blue component + The blue component of the foreground color. + + + + + /schemas/apps/mini-commander/prefs/cmd_line_color_bg_r + mini-commander-applet + int + 0 + + Background color, red component + The red component of the background color. + + + + + /schemas/apps/mini-commander/prefs/cmd_line_color_bg_g + mini-commander-applet + int + 0 + + Background color, green component + The green component of the background color. + + + + + /schemas/apps/mini-commander/prefs/cmd_line_color_bg_b + mini-commander-applet + int + 0 + + Background color, blue component + The blue component of the background color. + + + + + /schemas/apps/mini-commander/prefs/history + mini-commander-applet + list + string + [] + + History list + List of MateConfValue entries containing strings for history entries. + + + + + + + /schemas/apps/mini-commander/prefs/macro_patterns + mini-commander-applet + list + string + [blah] + + Macro pattern list + + This per-applet key is deprecated in favour of the global key, + /schemas/apps/mini-commander-global/macro_patterns. + + + + + + /schemas/apps/mini-commander/prefs/macro_commands + mini-commander-applet + list + string + [blah] + + Macro command list + + This per-applet key is deprecated in favour of the global key, + /schemas/apps/mini-commander-global/macro_patterns. + + + + + + diff --git a/mini-commander/src/mini-commander.ui b/mini-commander/src/mini-commander.ui new file mode 100644 index 00000000..00ea5a90 --- /dev/null +++ b/mini-commander/src/mini-commander.ui @@ -0,0 +1,713 @@ + + + + + + 1 + 50 + 400 + 5 + 10 + + + 5 + Command Line Preferences + dialog + False + + + True + 2 + + + True + True + 5 + + + True + 12 + 18 + + + True + 6 + + + True + 0 + Auto Completion + + + + + + False + False + 0 + + + + + True + + + True + + + + False + False + 0 + + + + + E_nable history-based auto completion + True + True + False + True + True + + + False + False + 1 + + + + + 1 + + + + + 0 + + + + + True + 6 + + + True + 0 + Size + + + + + + False + False + 0 + + + + + True + + + True + + + + False + False + 0 + + + + + True + 12 + + + True + _Width: + True + size_spinner + + + False + False + 0 + + + + + True + 6 + + + True + True + adjustment1 + 10 + True + + + + + + + False + False + 0 + + + + + True + pixels + + + + + + False + False + 1 + + + + + False + 1 + + + + + 1 + + + + + 1 + + + + + 1 + + + + + True + 6 + + + True + 0 + Colors + + + + + + False + False + 0 + + + + + True + + + True + + + + False + False + 0 + + + + + True + 3 + 2 + 12 + 6 + + + _Use default theme colors + True + True + False + True + True + + + GTK_FILL + + + + + + True + 0 + Command line _foreground: + True + right + fg_color_picker + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + Command line _background: + True + right + bg_color_picker + + + 2 + 3 + GTK_FILL + + + + + + True + False + True + False + Pick a color + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + + True + False + True + False + Pick a color + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + + + + + 1 + + + + + 1 + + + + + 2 + + + + + + + True + General + + + False + + + + + True + 12 + 6 + + + True + 0 + _Macros: + True + macros_tree + + + False + False + 0 + + + + + True + 12 + + + True + True + automatic + automatic + in + + + True + True + + + + + 0 + + + + + True + 4 + 6 + + + True + True + False + + + True + 0 + 0 + 0 + + + True + 2 + + + True + gtk-add + + + False + False + 0 + + + + + True + _Add Macro... + True + + + False + False + 1 + + + + + + + + + False + False + 0 + + + + + True + True + False + + + True + 0 + 0 + 0 + + + True + 2 + + + True + gtk-delete + + + False + False + 0 + + + + + True + _Delete Macro + True + + + False + False + 1 + + + + + + + + + False + False + 1 + + + + + False + 1 + + + + + 1 + + + + + 1 + + + + + True + Macros + True + + + 1 + False + + + + + 1 + + + + + True + end + + + gtk-help + True + True + True + False + True + + + False + False + 0 + + + + + gtk-close + True + True + True + True + False + True + + + False + False + 1 + + + + + False + end + 0 + + + + + + help_button + done_button + + + + True + 5 + Add New Macro + False + dialog + False + + + True + 2 + + + True + 5 + 2 + 2 + 12 + 6 + + + True + 0 + _Pattern: + True + pattern_entry + + + GTK_FILL + + + + + + True + 0 + Co_mmand: + True + command_entry + + + 1 + 2 + GTK_FILL + + + + + + True + True + True + + + 1 + 2 + + + + + + True + True + True + + + 1 + 2 + 1 + 2 + + + + + + 1 + + + + + True + end + + + gtk-help + True + True + True + False + True + + + False + False + 0 + + + + + gtk-cancel + True + True + True + False + True + + + False + False + 1 + + + + + gtk-add + True + True + True + True + False + True + + + False + False + 2 + + + + + False + end + 0 + + + + + + helpbutton1 + button1 + button2 + + + diff --git a/mini-commander/src/mini-commander_applet.c b/mini-commander/src/mini-commander_applet.c new file mode 100644 index 00000000..20dd4969 --- /dev/null +++ b/mini-commander/src/mini-commander_applet.c @@ -0,0 +1,430 @@ + /* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn , + * 2002 Sun Microsystems + * + * Authors: Oliver Maruhn , + * Mark McLoughlin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include + + +#include + +#include +#include +#include "mini-commander_applet.h" +#include "preferences.h" +#include "command_line.h" +#include "about.h" +#include "help.h" + +#include "browser-mini.xpm" +#include "history-mini.xpm" + +#define COMMANDLINE_BROWSER_STOCK "commandline-browser" +#define COMMANDLINE_HISTORY_STOCK "commandline-history" + +#define COMMANDLINE_DEFAULT_ICON_SIZE 6 + +static gboolean icons_initialized = FALSE; +static GtkIconSize button_icon_size = 0; + +static const GtkActionEntry mini_commander_menu_actions [] = { + { "Props", GTK_STOCK_PROPERTIES, N_("_Preferences"), + NULL, NULL, + G_CALLBACK (mc_show_preferences) }, + { "Help", GTK_STOCK_HELP, N_("_Help"), + NULL, NULL, + G_CALLBACK (show_help) }, + { "About", GTK_STOCK_ABOUT, N_("_About"), + NULL, NULL, + G_CALLBACK (about_box) } +}; + +typedef struct { + char *stock_id; + const char **icon_data; +} CommandLineStockIcon; + +static CommandLineStockIcon items[] = { + { COMMANDLINE_BROWSER_STOCK, browser_mini_xpm }, + { COMMANDLINE_HISTORY_STOCK, history_mini_xpm } +}; + +static void +register_command_line_stock_icons (GtkIconFactory *factory) +{ + gint i; + + for (i = 0; i < G_N_ELEMENTS (items); ++i) { + GtkIconSet *icon_set; + GdkPixbuf *pixbuf; + + pixbuf = gdk_pixbuf_new_from_xpm_data ((items[i].icon_data)); + + icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); + gtk_icon_factory_add (factory, items[i].stock_id, icon_set); + + gtk_icon_set_unref (icon_set); + g_object_unref (G_OBJECT (pixbuf)); + } + +} + +static void +command_line_init_stock_icons (void) +{ + + GtkIconFactory *factory; + + if (icons_initialized) + return; + + factory = gtk_icon_factory_new (); + gtk_icon_factory_add_default (factory); + + register_command_line_stock_icons (factory); + + button_icon_size = gtk_icon_size_register ("mini-commander-icon", + COMMANDLINE_DEFAULT_ICON_SIZE, + COMMANDLINE_DEFAULT_ICON_SIZE); + + icons_initialized = TRUE; + g_object_unref (factory); + +} + +void +set_atk_name_description (GtkWidget *widget, + const char *name, + const char *description) +{ + AtkObject *aobj; + + aobj = gtk_widget_get_accessible (widget); + if (GTK_IS_ACCESSIBLE (aobj) == FALSE) + return; + + atk_object_set_name (aobj, name); + atk_object_set_description (aobj, description); +} + +/* This is a hack around the fact that gtk+ doesn't + * propogate button presses on button2/3. + */ +static gboolean +button_press_hack (GtkWidget *widget, + GdkEventButton *event, + MCData *mc) +{ + if (event->button == 3 || event->button == 2) { + gtk_propagate_event (GTK_WIDGET (mc->applet), (GdkEvent *) event); + return TRUE; + } + + return FALSE; +} + +/* Send button presses on the applet to the entry. This makes Fitts' law work (ie click on the bottom +** most pixel and the key press will be sent to the entry */ +static gboolean +send_button_to_entry_event (GtkWidget *widget, GdkEventButton *event, MCData *mc) +{ + + if (event->button == 1) { + gtk_widget_grab_focus (mc->entry); + return TRUE; + } + return FALSE; + +} + +static gboolean +key_press_cb (GtkWidget *widget, GdkEventKey *event, MCData *mc) +{ + switch (event->keyval) { + case GDK_b: + if (event->state == GDK_CONTROL_MASK) { + mc_show_file_browser (NULL, mc); + return TRUE; + } + break; + case GDK_h: + if (event->state == GDK_CONTROL_MASK) { + mc_show_history (NULL, mc); + return TRUE; + } + break; + default: + break; + } + + return FALSE; + +} + +void +mc_applet_draw (MCData *mc) +{ + GtkWidget *icon; + GtkWidget *button; + GtkWidget *hbox_buttons; + MCPreferences prefs = mc->preferences; + int size_frames = 0; + gchar *command_text = NULL; + + if (mc->entry != NULL) + command_text = g_strdup (gtk_editable_get_chars (GTK_EDITABLE (mc->entry), 0, -1)); + + mc->cmd_line_size_y = mc->preferences.normal_size_y - size_frames; + + if (mc->applet_box) { + gtk_widget_destroy (mc->applet_box); + } + + if ( ((mc->orient == MATE_PANEL_APPLET_ORIENT_LEFT) || (mc->orient == MATE_PANEL_APPLET_ORIENT_RIGHT)) && (prefs.panel_size_x < 36) ) + mc->applet_box = gtk_vbox_new (FALSE, 0); + else + mc->applet_box = gtk_hbox_new (FALSE, 0); + + gtk_container_set_border_width (GTK_CONTAINER (mc->applet_box), 0); + + mc_create_command_entry (mc); + + if (command_text != NULL) { + gtk_entry_set_text (GTK_ENTRY (mc->entry), command_text); + g_free (command_text); + } + + /* hbox for message label and buttons */ + if ((mc->orient == MATE_PANEL_APPLET_ORIENT_LEFT) || (mc->orient == MATE_PANEL_APPLET_ORIENT_RIGHT)) + if (prefs.panel_size_x < 36) + hbox_buttons = gtk_vbox_new (TRUE, 0); + else + hbox_buttons = gtk_hbox_new (TRUE, 0); + else + if (prefs.normal_size_y > 36) + hbox_buttons = gtk_vbox_new (TRUE, 0); + else + hbox_buttons = gtk_hbox_new (TRUE, 0); + + /* add file-browser button */ + button = gtk_button_new (); + + g_signal_connect (button, "clicked", + G_CALLBACK (mc_show_file_browser), mc); + g_signal_connect (button, "button_press_event", + G_CALLBACK (button_press_hack), mc); + + icon = gtk_image_new_from_stock (COMMANDLINE_BROWSER_STOCK, button_icon_size); + gtk_container_add (GTK_CONTAINER (button), icon); + + gtk_widget_set_tooltip_text (button, _("Browser")); + gtk_box_pack_start (GTK_BOX (hbox_buttons), button, TRUE, TRUE, 0); + + set_atk_name_description (button, + _("Browser"), + _("Click this button to start the browser")); + + /* add history button */ + button = gtk_button_new (); + + g_signal_connect (button, "clicked", + G_CALLBACK (mc_show_history), mc); + g_signal_connect (button, "button_press_event", + G_CALLBACK (button_press_hack), mc); + + icon = gtk_image_new_from_stock (COMMANDLINE_HISTORY_STOCK, button_icon_size); + gtk_container_add (GTK_CONTAINER (button), icon); + + gtk_widget_set_tooltip_text (button, _("History")); + gtk_box_pack_end (GTK_BOX (hbox_buttons), button, TRUE, TRUE, 0); + + set_atk_name_description (button, + _("History"), + _("Click this button for the list of previous commands")); + + gtk_box_pack_start (GTK_BOX (mc->applet_box), mc->entry, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (mc->applet_box), hbox_buttons, TRUE, TRUE, 0); + + gtk_container_add (GTK_CONTAINER (mc->applet), mc->applet_box); + + gtk_widget_show_all (mc->applet_box); +} + +static void +mc_destroyed (GtkWidget *widget, + MCData *mc) +{ + MateConfClient *client; + int i; + + client = mateconf_client_get_default (); + for (i = 0; i < MC_NUM_LISTENERS; i++) { + mateconf_client_notify_remove (client, mc->listeners [i]); + mc->listeners [i] = 0; + } + g_object_unref (client); + + mc_macros_free (mc->preferences.macros); + + if (mc->prefs_dialog.dialog) + gtk_widget_destroy (mc->prefs_dialog.dialog); + + if (mc->prefs_dialog.dialog) + g_object_unref (mc->prefs_dialog.macros_store); + + if (mc->file_select) + gtk_widget_destroy (mc->file_select); + + g_free (mc); +} + +static void +mc_orient_changed (MatePanelApplet *applet, + MatePanelAppletOrient orient, + MCData *mc) +{ + mc->orient = orient; + mc_applet_draw (mc); +} + +static void +mc_pixel_size_changed (MatePanelApplet *applet, + GtkAllocation *allocation, + MCData *mc) +{ + if ((mc->orient == MATE_PANEL_APPLET_ORIENT_LEFT) || (mc->orient == MATE_PANEL_APPLET_ORIENT_RIGHT)) { + if (mc->preferences.panel_size_x == allocation->width) + return; + mc->preferences.panel_size_x = allocation->width; + } else { + if (mc->preferences.normal_size_y == allocation->height) + return; + mc->preferences.normal_size_y = allocation->height; + } + + mc_applet_draw (mc); +} + +static gboolean +mini_commander_applet_fill (MatePanelApplet *applet) +{ + MCData *mc; + MateConfClient *client; + GtkActionGroup *action_group; + gchar *ui_path; + + client = mateconf_client_get_default (); + if (mateconf_client_get_bool (client, "/desktop/mate/lockdown/inhibit_command_line", NULL)) { + GtkWidget *error_dialog; + + error_dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Command line has been disabled by your system administrator")); + + gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE); + gtk_dialog_set_has_separator (GTK_DIALOG (error_dialog), FALSE); + gtk_window_set_screen (GTK_WINDOW (error_dialog), + gtk_widget_get_screen (GTK_WIDGET (applet))); + gtk_dialog_run (GTK_DIALOG (error_dialog)); + gtk_widget_destroy (error_dialog); + + /* Note that this is only kosher if this is an out of process thing, + which we really are. We really don't need/want this applet when + command line is disabled */ + exit (1); + } + + g_set_application_name (_("Command Line")); + + gtk_window_set_default_icon_name ("mate-mini-commander"); + + mc = g_new0 (MCData, 1); + mc->applet = applet; + + mate_panel_applet_add_preferences (applet, "/schemas/apps/mini-commander/prefs", NULL); + mate_panel_applet_set_flags (applet, MATE_PANEL_APPLET_EXPAND_MINOR); + mc_load_preferences (mc); + command_line_init_stock_icons (); + + g_signal_connect (mc->applet, "change_orient", + G_CALLBACK (mc_orient_changed), mc); + g_signal_connect (mc->applet, "size_allocate", + G_CALLBACK (mc_pixel_size_changed), mc); + + mc->preferences.normal_size_y = mate_panel_applet_get_size (applet); + mc->orient = mate_panel_applet_get_orient (applet); + mc_applet_draw(mc); + gtk_widget_show (GTK_WIDGET (mc->applet)); + + g_signal_connect (mc->applet, "destroy", G_CALLBACK (mc_destroyed), mc); + g_signal_connect (mc->applet, "button_press_event", + G_CALLBACK (send_button_to_entry_event), mc); + g_signal_connect (mc->applet, "key_press_event", + G_CALLBACK (key_press_cb), mc); + + action_group = gtk_action_group_new ("MiniCommander Applet Actions"); + gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions (action_group, + mini_commander_menu_actions, + G_N_ELEMENTS (mini_commander_menu_actions), + mc); + ui_path = g_build_filename (MC_MENU_UI_DIR, "mini-commander-applet-menu.xml", NULL); + mate_panel_applet_setup_menu_from_file (mc->applet, ui_path, action_group); + + if (mate_panel_applet_get_locked_down (mc->applet)) { + GtkAction *action; + + action = gtk_action_group_get_action (action_group, "Props"); + gtk_action_set_visible (action, FALSE); + } + g_object_unref (action_group); + + set_atk_name_description (GTK_WIDGET (applet), + _("Mini-Commander applet"), + _("This applet adds a command line to the panel")); + + return TRUE; +} + +static gboolean +mini_commander_applet_factory (MatePanelApplet *applet, + const gchar *iid, + gpointer data) +{ + gboolean retval = FALSE; + + if (!strcmp (iid, "MiniCommanderApplet")) + retval = mini_commander_applet_fill(applet); + + return retval; +} + +MATE_PANEL_APPLET_OUT_PROCESS_FACTORY ("MiniCommanderAppletFactory", + PANEL_TYPE_APPLET, + "command-line", + mini_commander_applet_factory, + NULL) diff --git a/mini-commander/src/mini-commander_applet.h b/mini-commander/src/mini-commander_applet.h new file mode 100644 index 00000000..4b4f6ddf --- /dev/null +++ b/mini-commander/src/mini-commander_applet.h @@ -0,0 +1,72 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998 Oliver Maruhn , + * 2002 Sun Microsystems + * + * Authors: Oliver Maruhn , + * Mark McLoughlin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MC_APPLET_H__ +#define __MC_APPLET_H__ + +#include +#include + +G_BEGIN_DECLS + +#include +#include + +typedef struct _MCData MCData; + +#include "preferences.h" + +/* Constants */ +#define MC_NUM_LISTENERS 12 +#define MC_HISTORY_LIST_LENGTH 50 +#define MC_MAX_COMMAND_LENGTH 505 +#define MC_MAX_NUM_MACRO_PARAMETERS 100 + +struct _MCData { + MatePanelApplet *applet; + + GtkWidget *applet_box; + + GtkWidget *entry; + GtkWidget *file_select; + + int label_timeout; + int cmd_line_size_y; + + MCPreferences preferences; + MCPrefsDialog prefs_dialog; + + guint listeners [MC_NUM_LISTENERS]; + gboolean error; + MatePanelAppletOrient orient; +}; + +void mc_applet_draw (MCData *mc); + +void set_atk_name_description (GtkWidget *widget, + const char *name, + const char *description); + +G_END_DECLS + +#endif /* __MC_APPLET_H__ */ diff --git a/mini-commander/src/org.mate.applets.MiniCommanderApplet.mate-panel-applet.in.in b/mini-commander/src/org.mate.applets.MiniCommanderApplet.mate-panel-applet.in.in new file mode 100644 index 00000000..a1a80bef --- /dev/null +++ b/mini-commander/src/org.mate.applets.MiniCommanderApplet.mate-panel-applet.in.in @@ -0,0 +1,16 @@ +[Applet Factory] +Id=MiniCommanderAppletFactory +Location=@LIBEXECDIR@/mini_commander_applet +_Name=MiniCommander Applet Factory +_Description=MiniCommander Applet Factory + +[MiniCommanderApplet] +_Name=Command Line +_Description=Mini-Commander +Icon=mate-mini-commander.png +MateComponentId=OAFIID:MATE_MiniCommanderApplet +X-MATE-Bugzilla-Bugzilla=MATE +X-MATE-Bugzilla-Product=mate-applets +X-MATE-Bugzilla-Component=mini-commander +X-MATE-Bugzilla-Version=@VERSION@ +X-MATE-Bugzilla-OtherBinaries=mini_commander_applet diff --git a/mini-commander/src/org.mate.panel.applet.MiniCommanderAppletFactory.service.in b/mini-commander/src/org.mate.panel.applet.MiniCommanderAppletFactory.service.in new file mode 100644 index 00000000..e7cf453f --- /dev/null +++ b/mini-commander/src/org.mate.panel.applet.MiniCommanderAppletFactory.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.mate.panel.applet.MiniCommanderAppletFactory +Exec=/home/carlos/mate-cvs/libexec/mini_commander_applet diff --git a/mini-commander/src/preferences.c b/mini-commander/src/preferences.c new file mode 100644 index 00000000..4cc2705a --- /dev/null +++ b/mini-commander/src/preferences.c @@ -0,0 +1,1128 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998, 1999 Oliver Maruhn + * 2002 Sun Microsystems Inc. + * + * Authors: Oliver Maruhn + * Mark McLoughlin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "preferences.h" + +#include + +#include + +#include +#include +#include + +#include "mini-commander_applet.h" +#include "command_line.h" +#include "history.h" +#include "mc-default-macros.h" + +enum { + COLUMN_PATTERN, + COLUMN_COMMAND +}; + +#define NEVER_SENSITIVE "never_sensitive" + +static GSList *mc_load_macros (MCData *mc); + +/* set sensitive and setup NEVER_SENSITIVE appropriately */ +static void +hard_set_sensitive (GtkWidget *w, gboolean sensitivity) +{ + gtk_widget_set_sensitive (w, sensitivity); + g_object_set_data (G_OBJECT (w), NEVER_SENSITIVE, + GINT_TO_POINTER ( ! sensitivity)); +} + + +/* set sensitive, but always insensitive if NEVER_SENSITIVE is set */ +static void +soft_set_sensitive (GtkWidget *w, gboolean sensitivity) +{ + if (g_object_get_data (G_OBJECT (w), NEVER_SENSITIVE)) + gtk_widget_set_sensitive (w, FALSE); + else + gtk_widget_set_sensitive (w, sensitivity); +} + +gboolean +mc_key_writable (MCData *mc, const char *key) +{ + gboolean writable; + char *fullkey; + static MateConfClient *client = NULL; + if (client == NULL) + client = mateconf_client_get_default (); + + fullkey = mate_panel_applet_mateconf_get_full_key (mc->applet, key); + + writable = mateconf_client_key_is_writable (client, fullkey, NULL); + + g_free (fullkey); + + return writable; +} + + +/* MateConf notification handlers + */ +static void +show_default_theme_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_BOOL) + return; + + mc->preferences.show_default_theme = mateconf_value_get_bool (entry->value); + + mc_applet_draw (mc); /* FIXME: we shouldn't have to redraw the whole applet */ +} + +static void +auto_complete_history_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_BOOL) + return; + + mc->preferences.auto_complete_history = mateconf_value_get_bool (entry->value); +} + +static void +normal_size_x_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_INT) + return; + + mc->preferences.normal_size_x = mateconf_value_get_int (entry->value); + + mc_command_update_entry_size (mc); +} + +static void +normal_size_y_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_INT) + return; + + mc->preferences.normal_size_y = mateconf_value_get_int (entry->value); + + mc_applet_draw (mc); /* FIXME: we shouldn't have to redraw the whole applet */ +} + +static void +cmd_line_color_fg_r_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_INT) + return; + + mc->preferences.cmd_line_color_fg_r = mateconf_value_get_int (entry->value); + + mc_command_update_entry_color (mc); +} + +static void +cmd_line_color_fg_g_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_INT) + return; + + mc->preferences.cmd_line_color_fg_g = mateconf_value_get_int (entry->value); + + mc_command_update_entry_color (mc); +} + +static void +cmd_line_color_fg_b_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_INT) + return; + + mc->preferences.cmd_line_color_fg_b = mateconf_value_get_int (entry->value); + + mc_command_update_entry_color (mc); +} + +static void +cmd_line_color_bg_r_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_INT) + return; + + mc->preferences.cmd_line_color_bg_r = mateconf_value_get_int (entry->value); + + mc_command_update_entry_color (mc); +} + +static void +cmd_line_color_bg_g_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_INT) + return; + + mc->preferences.cmd_line_color_bg_g = mateconf_value_get_int (entry->value); + + mc_command_update_entry_color (mc); +} + +static void +cmd_line_color_bg_b_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_INT) + return; + + mc->preferences.cmd_line_color_bg_b = mateconf_value_get_int (entry->value); + + mc_command_update_entry_color (mc); +} + +static gboolean +load_macros_in_idle (MCData *mc) +{ + mc->preferences.idle_macros_loader_id = 0; + + if (mc->preferences.macros) + mc_macros_free (mc->preferences.macros); + + mc->preferences.macros = mc_load_macros (mc); + + return FALSE; +} + +static void +macros_changed (MateConfClient *client, + guint cnxn_id, + MateConfEntry *entry, + MCData *mc) +{ + if (!entry->value || entry->value->type != MATECONF_VALUE_LIST) + return; + + if (mc->preferences.idle_macros_loader_id == 0) + mc->preferences.idle_macros_loader_id = + g_idle_add ((GSourceFunc) load_macros_in_idle, mc); +} + +/* Properties dialog + */ +static void +save_macros_to_mateconf (MCData *mc) +{ + MCPrefsDialog *dialog; + GtkTreeIter iter; + MateConfValue *patterns; + MateConfValue *commands; + GSList *pattern_list = NULL; + GSList *command_list = NULL; + MateConfClient *client; + + dialog = &mc->prefs_dialog; + + if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dialog->macros_store), &iter)) + return; + + patterns = mateconf_value_new (MATECONF_VALUE_LIST); + mateconf_value_set_list_type (patterns, MATECONF_VALUE_STRING); + + commands = mateconf_value_new (MATECONF_VALUE_LIST); + mateconf_value_set_list_type (commands, MATECONF_VALUE_STRING); + + do { + char *pattern = NULL; + char *command = NULL; + + gtk_tree_model_get ( + GTK_TREE_MODEL (dialog->macros_store), &iter, + 0, &pattern, + 1, &command, + -1); + + pattern_list = g_slist_prepend (pattern_list, + mateconf_value_new_from_string (MATECONF_VALUE_STRING, pattern, NULL)); + command_list = g_slist_prepend (command_list, + mateconf_value_new_from_string (MATECONF_VALUE_STRING, command, NULL)); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (dialog->macros_store), &iter)); + + pattern_list = g_slist_reverse (pattern_list); + command_list = g_slist_reverse (command_list); + + mateconf_value_set_list_nocopy (patterns, pattern_list); pattern_list = NULL; + mateconf_value_set_list_nocopy (commands, command_list); command_list = NULL; + + client = mateconf_client_get_default (); + mateconf_client_set (client, "/apps/mini-commander/macro_patterns", + patterns, NULL); + mateconf_client_set (client, "/apps/mini-commander/macro_commands", + commands, NULL); + + mateconf_value_free (patterns); + mateconf_value_free (commands); +} + +static gboolean +duplicate_pattern (MCData *mc, + const char *new_pattern) +{ + MCPrefsDialog *dialog; + GtkTreeIter iter; + + dialog = &mc->prefs_dialog; + + if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dialog->macros_store), &iter)) + return FALSE; + + do { + char *pattern = NULL; + + gtk_tree_model_get ( + GTK_TREE_MODEL (dialog->macros_store), &iter, + 0, &pattern, -1); + + if (!strcmp (pattern, new_pattern)) + return TRUE; + + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (dialog->macros_store), &iter)); + + + return FALSE; +} + +static void +show_help_section (GtkWindow *dialog, gchar *section) +{ + GError *error = NULL; + char *uri; + + if (section) + uri = g_strdup_printf ("ghelp:command-line?%s", section); + else + uri = g_strdup ("ghelp:command-line"); + + gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)), + uri, + gtk_get_current_event_time (), + &error); + + g_free (uri); + + if (error) { + GtkWidget *error_dialog; + + error_dialog = gtk_message_dialog_new ( + NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("There was an error displaying help: %s"), + error->message); + + g_signal_connect (error_dialog, "response", + G_CALLBACK (gtk_widget_destroy), + NULL); + + gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE); + gtk_window_set_screen (GTK_WINDOW (error_dialog), + gtk_widget_get_screen (GTK_WIDGET (dialog))); + gtk_widget_show (error_dialog); + g_error_free (error); + } +} + +static void +add_response (GtkWidget *window, + int id, + MCData *mc) +{ + MCPrefsDialog *dialog; + + dialog = &mc->prefs_dialog; + + switch (id) { + case GTK_RESPONSE_OK: { + const char *pattern; + const char *command; + GtkTreeIter iter; + const char *error_message = NULL; + + pattern = gtk_entry_get_text (GTK_ENTRY (dialog->pattern_entry)); + command = gtk_entry_get_text (GTK_ENTRY (dialog->command_entry)); + + if (!pattern || !pattern [0]) + error_message = _("You must specify a pattern"); + + if (!command || !command [0]) + error_message = error_message != NULL ? + _("You must specify a pattern and a command") : + _("You must specify a command"); + + if (!error_message && duplicate_pattern (mc, pattern)) + error_message = _("You may not specify duplicate patterns"); + + if (error_message) { + GtkWidget *error_dialog; + + error_dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + error_message); + + g_signal_connect (error_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); + gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE); + gtk_widget_show_all (error_dialog); + return; + } + + gtk_widget_hide (window); + + gtk_list_store_append (dialog->macros_store, &iter); + gtk_list_store_set (dialog->macros_store, &iter, + COLUMN_PATTERN, pattern, + COLUMN_COMMAND, command, + -1); + + gtk_tree_view_columns_autosize (GTK_TREE_VIEW (dialog->macros_tree)); + + gtk_editable_delete_text (GTK_EDITABLE (dialog->pattern_entry), 0, -1); + gtk_editable_delete_text (GTK_EDITABLE (dialog->command_entry), 0, -1); + + save_macros_to_mateconf (mc); + } + break; + case GTK_RESPONSE_HELP: + show_help_section (GTK_WINDOW (window), "command-line-prefs-2"); + break; + case GTK_RESPONSE_CLOSE: + default: + gtk_editable_delete_text (GTK_EDITABLE (dialog->pattern_entry), 0, -1); + gtk_editable_delete_text (GTK_EDITABLE (dialog->command_entry), 0, -1); + gtk_widget_hide (window); + break; + } +} + +static void +setup_add_dialog (GtkBuilder *builder, + MCData *mc) +{ + MCPrefsDialog *dialog; + + dialog = &mc->prefs_dialog; + + g_signal_connect (dialog->macro_add_dialog, "response", + G_CALLBACK (add_response), mc); + + dialog->pattern_entry = GTK_WIDGET (gtk_builder_get_object (builder, "pattern_entry")); + dialog->command_entry = GTK_WIDGET (gtk_builder_get_object (builder, "command_entry")); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog->macro_add_dialog), GTK_RESPONSE_OK); +} + +static void +macro_add (GtkWidget *button, + MCData *mc) +{ + if (!mc->prefs_dialog.macro_add_dialog) { + GtkBuilder *builder; + + builder = gtk_builder_new (); + gtk_builder_add_from_file (builder, GTK_BUILDERDIR "/mini-commander.ui", NULL); + + mc->prefs_dialog.macro_add_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "mc_macro_add_dialog")); + + g_object_add_weak_pointer (G_OBJECT (mc->prefs_dialog.macro_add_dialog), + (gpointer *) &mc->prefs_dialog.macro_add_dialog); + + setup_add_dialog (builder, mc); + + g_object_unref (builder); + } + + gtk_window_set_screen (GTK_WINDOW (mc->prefs_dialog.macro_add_dialog), + gtk_widget_get_screen (GTK_WIDGET (mc->applet))); + gtk_widget_grab_focus (mc->prefs_dialog.pattern_entry); + gtk_window_present (GTK_WINDOW (mc->prefs_dialog.macro_add_dialog)); +} + +static void +macro_delete (GtkWidget *button, + MCData *mc) +{ + MCPrefsDialog *dialog; + GtkTreeModel *model = NULL; + GtkTreeSelection *selection; + GtkTreeIter iter; + + dialog = &mc->prefs_dialog; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->macros_tree)); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + gtk_list_store_remove (dialog->macros_store, &iter); + + save_macros_to_mateconf (mc); +} + +static void +show_macros_list (MCData *mc) +{ + MCPrefsDialog *dialog; + GtkTreeIter iter; + GSList *l; + + dialog = &mc->prefs_dialog; + + gtk_list_store_clear (dialog->macros_store); + + for (l = mc->preferences.macros; l; l = l->next) { + MCMacro *macro = l->data; + + gtk_list_store_append (dialog->macros_store, &iter); + gtk_list_store_set (dialog->macros_store, &iter, + COLUMN_PATTERN, macro->pattern, + COLUMN_COMMAND, macro->command, + -1); + } + + gtk_tree_view_columns_autosize (GTK_TREE_VIEW (dialog->macros_tree)); +} + +static void +macro_edited (GtkCellRendererText *renderer, + const char *path, + const char *new_text, + MCData *mc) +{ + MCPrefsDialog *dialog; + GtkTreeIter iter; + int col; + + dialog = &mc->prefs_dialog; + + col = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (renderer), "column")); + + if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dialog->macros_store), &iter, path)) + gtk_list_store_set (dialog->macros_store, &iter, col, new_text, -1); + + save_macros_to_mateconf (mc); +} + +static void +foreground_color_set (GtkColorButton *color_button, + MCData *mc) +{ + GdkColor color; + + gtk_color_button_get_color (color_button, &color); + + mate_panel_applet_mateconf_set_int (mc->applet, "cmd_line_color_fg_r", (int) color.red, NULL); + mate_panel_applet_mateconf_set_int (mc->applet, "cmd_line_color_fg_g", (int) color.green, NULL); + mate_panel_applet_mateconf_set_int (mc->applet, "cmd_line_color_fg_b", (int) color.blue, NULL); +} + +static void +background_color_set (GtkColorButton *color_button, + MCData *mc) +{ + GdkColor color; + + gtk_color_button_get_color (color_button, &color); + + mate_panel_applet_mateconf_set_int (mc->applet, "cmd_line_color_bg_r", (int) color.red, NULL); + mate_panel_applet_mateconf_set_int (mc->applet, "cmd_line_color_bg_g", (int) color.green, NULL); + mate_panel_applet_mateconf_set_int (mc->applet, "cmd_line_color_bg_b", (int) color.blue, NULL); +} + +static void +auto_complete_history_toggled (GtkToggleButton *toggle, + MCData *mc) +{ + gboolean auto_complete_history; + + auto_complete_history = gtk_toggle_button_get_active (toggle); + if (auto_complete_history == mc->preferences.auto_complete_history) + return; + + mate_panel_applet_mateconf_set_bool (mc->applet, "autocomplete_history", + auto_complete_history, NULL); +} + +static void +size_value_changed (GtkSpinButton *spinner, + MCData *mc) +{ + int size; + + size = gtk_spin_button_get_value (spinner); + if (size == mc->preferences.normal_size_x) + return; + + mate_panel_applet_mateconf_set_int (mc->applet, "normal_size_x", size, NULL); +} + +static void +use_default_theme_toggled (GtkToggleButton *toggle, + MCData *mc) +{ + gboolean use_default_theme; + + use_default_theme = gtk_toggle_button_get_active (toggle); + if (use_default_theme == mc->preferences.show_default_theme) + return; + + soft_set_sensitive (mc->prefs_dialog.fg_color_picker, !use_default_theme); + soft_set_sensitive (mc->prefs_dialog.bg_color_picker, !use_default_theme); + + mate_panel_applet_mateconf_set_bool (mc->applet, "show_default_theme", use_default_theme, NULL); +} + +static void +preferences_response (MCPrefsDialog *dialog, + int id, + MCData *mc) +{ + switch (id) { + case GTK_RESPONSE_HELP: + show_help_section (GTK_WINDOW (dialog), "command-line-prefs-0"); + break; + case GTK_RESPONSE_CLOSE: + default: { + GtkTreeViewColumn *col; + + dialog = &mc->prefs_dialog; + + /* A hack to make sure 'edited' on the renderer if we + * close the dialog while editing. + */ + col = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->macros_tree), 0); + if (col->editable_widget && GTK_IS_CELL_EDITABLE (col->editable_widget)) + gtk_cell_editable_editing_done (col->editable_widget); + + col = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->macros_tree), 1); + if (col->editable_widget && GTK_IS_CELL_EDITABLE (col->editable_widget)) + gtk_cell_editable_editing_done (col->editable_widget); + + gtk_widget_hide (dialog->dialog); + } + break; + } +} + +static void +mc_preferences_setup_dialog (GtkBuilder *builder, + MCData *mc) +{ + MCPrefsDialog *dialog; + GtkCellRenderer *renderer; + MateConfClient *client; + GdkColor color; + + dialog = &mc->prefs_dialog; + + g_signal_connect (dialog->dialog, "response", + G_CALLBACK (preferences_response), mc); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog->dialog), GTK_RESPONSE_CLOSE); + gtk_window_set_default_size (GTK_WINDOW (dialog->dialog), 400, -1); + + dialog->auto_complete_history_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "auto_complete_history_toggle")); + dialog->size_spinner = GTK_WIDGET (gtk_builder_get_object (builder, "size_spinner")); + dialog->use_default_theme_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "default_theme_toggle")); + dialog->fg_color_picker = GTK_WIDGET (gtk_builder_get_object (builder, "fg_color_picker")); + dialog->bg_color_picker = GTK_WIDGET (gtk_builder_get_object (builder, "bg_color_picker")); + dialog->macros_tree = GTK_WIDGET (gtk_builder_get_object (builder, "macros_tree")); + dialog->delete_button = GTK_WIDGET (gtk_builder_get_object (builder, "delete_button")); + dialog->add_button = GTK_WIDGET (gtk_builder_get_object (builder, "add_button")); + + /* History based autocompletion */ + g_signal_connect (dialog->auto_complete_history_toggle, "toggled", + G_CALLBACK (auto_complete_history_toggled), mc); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->auto_complete_history_toggle), + mc->preferences.auto_complete_history); + if ( ! mc_key_writable (mc, "autocomplete_history")) + hard_set_sensitive (dialog->auto_complete_history_toggle, FALSE); + + /* Width */ + gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->size_spinner), mc->preferences.normal_size_x); + g_signal_connect (dialog->size_spinner, "value_changed", + G_CALLBACK (size_value_changed), mc); + if ( ! mc_key_writable (mc, "normal_size_x")) { + hard_set_sensitive (dialog->size_spinner, FALSE); + hard_set_sensitive (GTK_WIDGET (gtk_builder_get_object (builder, "size_label")), FALSE); + hard_set_sensitive (GTK_WIDGET (gtk_builder_get_object (builder, "size_post_label")), FALSE); + } + + /* Use default theme */ + g_signal_connect (dialog->use_default_theme_toggle, "toggled", + G_CALLBACK (use_default_theme_toggled), mc); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->use_default_theme_toggle), + mc->preferences.show_default_theme); + if ( ! mc_key_writable (mc, "show_default_theme")) + hard_set_sensitive (dialog->use_default_theme_toggle, FALSE); + + /* Foreground color */ + g_signal_connect (dialog->fg_color_picker, "color_set", + G_CALLBACK (foreground_color_set), mc); + color.red = mc->preferences.cmd_line_color_fg_r; + color.green = mc->preferences.cmd_line_color_fg_g; + color.blue = mc->preferences.cmd_line_color_fg_b; + gtk_color_button_set_color (GTK_COLOR_BUTTON (dialog->fg_color_picker), &color); + soft_set_sensitive (dialog->fg_color_picker, !mc->preferences.show_default_theme); + + if ( ! mc_key_writable (mc, "cmd_line_color_fg_r") || + ! mc_key_writable (mc, "cmd_line_color_fg_g") || + ! mc_key_writable (mc, "cmd_line_color_fg_b")) { + hard_set_sensitive (dialog->fg_color_picker, FALSE); + hard_set_sensitive (GTK_WIDGET (gtk_builder_get_object (builder, "fg_color_label")), FALSE); + } + + /* Background color */ + g_signal_connect (dialog->bg_color_picker, "color_set", + G_CALLBACK (background_color_set), mc); + color.red = mc->preferences.cmd_line_color_bg_r; + color.green = mc->preferences.cmd_line_color_bg_g; + color.blue = mc->preferences.cmd_line_color_bg_b; + gtk_color_button_set_color (GTK_COLOR_BUTTON (dialog->bg_color_picker), &color); + soft_set_sensitive (dialog->bg_color_picker, !mc->preferences.show_default_theme); + + if ( ! mc_key_writable (mc, "cmd_line_color_bg_r") || + ! mc_key_writable (mc, "cmd_line_color_bg_g") || + ! mc_key_writable (mc, "cmd_line_color_bg_b")) { + hard_set_sensitive (dialog->bg_color_picker, FALSE); + hard_set_sensitive (GTK_WIDGET (gtk_builder_get_object (builder, "bg_color_label")), FALSE); + } + + + /* Macros Delete and Add buttons */ + g_signal_connect (dialog->delete_button, "clicked", G_CALLBACK (macro_delete), mc); + g_signal_connect (dialog->add_button, "clicked", G_CALLBACK (macro_add), mc); + + client = mateconf_client_get_default (); + if ( ! mateconf_client_key_is_writable (client, + "/apps/mini-commander/macro_patterns", NULL) || + ! mateconf_client_key_is_writable (client, + "/apps/mini-commander/macro_commands", NULL)) { + hard_set_sensitive (dialog->add_button, FALSE); + hard_set_sensitive (dialog->delete_button, FALSE); + hard_set_sensitive (dialog->macros_tree, FALSE); + } + + /* Macros tree view */ + dialog->macros_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING, NULL); + gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->macros_tree), + GTK_TREE_MODEL (dialog->macros_store)); + + renderer = g_object_new (GTK_TYPE_CELL_RENDERER_TEXT, "editable", TRUE, NULL); + g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_PATTERN)); + g_signal_connect (renderer, "edited", G_CALLBACK (macro_edited), mc); + + gtk_tree_view_insert_column_with_attributes ( + GTK_TREE_VIEW (dialog->macros_tree), -1, + _("Pattern"), renderer, + "text", COLUMN_PATTERN, + NULL); + + renderer = g_object_new (GTK_TYPE_CELL_RENDERER_TEXT, "editable", TRUE, NULL); + g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_COMMAND)); + g_signal_connect (renderer, "edited", G_CALLBACK (macro_edited), mc); + + gtk_tree_view_insert_column_with_attributes ( + GTK_TREE_VIEW (dialog->macros_tree), -1, + _("Command"), renderer, + "text", COLUMN_COMMAND, + NULL); + + show_macros_list (mc); +} + +void +mc_show_preferences (GtkAction *action, + MCData *mc) +{ + if (!mc->prefs_dialog.dialog) { + GtkBuilder *builder; + + builder = gtk_builder_new (); + gtk_builder_add_from_file (builder, GTK_BUILDERDIR "/mini-commander.ui", NULL); + + mc->prefs_dialog.dialog = GTK_WIDGET (gtk_builder_get_object (builder, + "mc_preferences_dialog")); + + g_object_add_weak_pointer (G_OBJECT (mc->prefs_dialog.dialog), + (gpointer *) &mc->prefs_dialog.dialog); + + mc_preferences_setup_dialog (builder, mc); + + g_object_unref (builder); + } + + gtk_window_set_screen (GTK_WINDOW (mc->prefs_dialog.dialog), + gtk_widget_get_screen (GTK_WIDGET (mc->applet))); + gtk_window_present (GTK_WINDOW (mc->prefs_dialog.dialog)); +} + +static MCMacro * +mc_macro_new (const char *pattern, + const char *command) +{ + MCMacro *macro; + + g_return_val_if_fail (pattern != NULL, NULL); + g_return_val_if_fail (command != NULL, NULL); + + macro = g_new0 (MCMacro, 1); + + macro->pattern = g_strdup (pattern); + macro->command = g_strdup (command); + + if (macro->pattern [0] != '\0') + regcomp (¯o->regex, macro->pattern, REG_EXTENDED); + + return macro; +} + +void +mc_macros_free (GSList *macros) +{ + GSList *l; + + for (l = macros; l; l = l->next) { + MCMacro *macro = l->data; + + regfree(¯o->regex); + g_free (macro->pattern); + g_free (macro->command); + g_free (macro); + } + + g_slist_free (macros); +} + +static GSList * +mc_load_macros (MCData *mc) +{ + MateConfValue *macro_patterns; + MateConfValue *macro_commands; + GSList *macros_list = NULL; + MateConfClient *client; + + client = mateconf_client_get_default (); + macro_patterns = mateconf_client_get (client, + "/apps/mini-commander/macro_patterns", NULL); + macro_commands = mateconf_client_get (client, + "/apps/mini-commander/macro_commands", NULL); + + if (macro_patterns && macro_commands) { + GSList *patterns; + GSList *commands; + + patterns = mateconf_value_get_list (macro_patterns); + commands = mateconf_value_get_list (macro_commands); + + for (; patterns && commands; patterns = patterns->next, commands = commands->next) { + MateConfValue *v1 = patterns->data; + MateConfValue *v2 = commands->data; + MCMacro *macro; + const char *pattern, *command; + + pattern = mateconf_value_get_string (v1); + command = mateconf_value_get_string (v2); + + if (!(macro = mc_macro_new (pattern, command))) + continue; + + macros_list = g_slist_prepend (macros_list, macro); + } + } else { + int i; + + for (i = 0; i < G_N_ELEMENTS (mc_default_macros); i++) + macros_list = g_slist_prepend (macros_list, + mc_macro_new (mc_default_macros [i].pattern, + mc_default_macros [i].command)); + } + + macros_list = g_slist_reverse (macros_list); + + if (macro_commands) + mateconf_value_free (macro_commands); + + if (macro_patterns) + mateconf_value_free (macro_patterns); + + return macros_list; +} + +static void +mc_setup_listeners (MCData *mc) +{ + MateConfClient *client; + char *key; + int i = 0; + + client = mateconf_client_get_default (); + mateconf_client_add_dir (client, "/apps/mini-commander", + MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL); + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "show_default_theme"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) show_default_theme_changed, + mc, + NULL, NULL); + g_free (key); + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "autocomplete_history"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) auto_complete_history_changed, + mc, + NULL, NULL); + g_free (key); + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "normal_size_x"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) normal_size_x_changed, + mc, + NULL, NULL); + g_free (key); + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "normal_size_y"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) normal_size_y_changed, + mc, + NULL, NULL); + g_free (key); + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "cmd_line_color_fg_r"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) cmd_line_color_fg_r_changed, + mc, + NULL, NULL); + g_free (key); + + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "cmd_line_color_fg_g"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) cmd_line_color_fg_g_changed, + mc, + NULL, NULL); + g_free (key); + + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "cmd_line_color_fg_b"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) cmd_line_color_fg_b_changed, + mc, + NULL, NULL); + g_free (key); + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "cmd_line_color_bg_r"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) cmd_line_color_bg_r_changed, + mc, + NULL, NULL); + g_free (key); + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "cmd_line_color_bg_g"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) cmd_line_color_bg_g_changed, + mc, + NULL, NULL); + g_free (key); + + key = mate_panel_applet_mateconf_get_full_key (MATE_PANEL_APPLET (mc->applet), "cmd_line_color_bg_b"); + mc->listeners [i++] = mateconf_client_notify_add ( + client, key, + (MateConfClientNotifyFunc) cmd_line_color_bg_b_changed, + mc, + NULL, NULL); + g_free (key); + + mc->listeners [i++] = mateconf_client_notify_add ( + client, "/apps/mini-commander/macro_patterns", + (MateConfClientNotifyFunc) macros_changed, + mc, + NULL, NULL); + + mc->listeners [i++] = mateconf_client_notify_add ( + client, "/apps/mini-commander/macro_commands", + (MateConfClientNotifyFunc) macros_changed, + mc, + NULL, NULL); + + g_assert (i == MC_NUM_LISTENERS); + + g_object_unref (client); +} + +void +mc_load_preferences (MCData *mc) +{ + MateConfValue *history; + GError *error = NULL; + + g_return_if_fail (mc != NULL); + g_return_if_fail (PANEL_IS_APPLET (mc->applet)); + + mc->preferences.show_default_theme = + mate_panel_applet_mateconf_get_bool (mc->applet, "show_default_theme", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.show_default_theme = MC_DEFAULT_SHOW_DEFAULT_THEME; + } + + mc->preferences.auto_complete_history = + mate_panel_applet_mateconf_get_bool (mc->applet, "autocomplete_history", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.auto_complete_history = MC_DEFAULT_AUTO_COMPLETE_HISTORY; + } + + mc->preferences.normal_size_x = + mate_panel_applet_mateconf_get_int (mc->applet, "normal_size_x", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.normal_size_x = MC_DEFAULT_NORMAL_SIZE_X; + } + mc->preferences.normal_size_x = MAX (mc->preferences.normal_size_x, 50); + + mc->preferences.normal_size_y = + mate_panel_applet_mateconf_get_int (mc->applet, "normal_size_y", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.normal_size_y = MC_DEFAULT_NORMAL_SIZE_Y; + } + mc->preferences.normal_size_y = CLAMP (mc->preferences.normal_size_y, 5, 200); + + mc->preferences.cmd_line_color_fg_r = + mate_panel_applet_mateconf_get_int (mc->applet, "cmd_line_color_fg_r", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.cmd_line_color_fg_r = MC_DEFAULT_CMD_LINE_COLOR_FG_R; + } + + mc->preferences.cmd_line_color_fg_g = + mate_panel_applet_mateconf_get_int (mc->applet, "cmd_line_color_fg_g", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.cmd_line_color_fg_g = MC_DEFAULT_CMD_LINE_COLOR_FG_G; + } + + mc->preferences.cmd_line_color_fg_b = + mate_panel_applet_mateconf_get_int (mc->applet, "cmd_line_color_fg_b", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.cmd_line_color_fg_b = MC_DEFAULT_CMD_LINE_COLOR_FG_B; + } + + mc->preferences.cmd_line_color_bg_r = + mate_panel_applet_mateconf_get_int (mc->applet, "cmd_line_color_bg_r", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.cmd_line_color_bg_r = MC_DEFAULT_CMD_LINE_COLOR_BG_R; + } + + mc->preferences.cmd_line_color_bg_g = + mate_panel_applet_mateconf_get_int (mc->applet, "cmd_line_color_bg_g", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.cmd_line_color_bg_g = MC_DEFAULT_CMD_LINE_COLOR_BG_G; + } + + mc->preferences.cmd_line_color_bg_b = + mate_panel_applet_mateconf_get_int (mc->applet, "cmd_line_color_bg_b", &error); + if (error) { + g_error_free (error); + error = NULL; + mc->preferences.cmd_line_color_bg_b = MC_DEFAULT_CMD_LINE_COLOR_BG_B; + } + + mc->preferences.macros = mc_load_macros (mc); + + history = mate_panel_applet_mateconf_get_value (mc->applet, "history", NULL); + if (history) { + GSList *l; + + for (l = mateconf_value_get_list (history); l; l = l->next) { + const char *entry = NULL; + + if ((entry = mateconf_value_get_string (l->data))) + append_history_entry (mc, entry, TRUE); + } + + mateconf_value_free (history); + } + + mc_setup_listeners (mc); + + mc->preferences.idle_macros_loader_id = 0; +} diff --git a/mini-commander/src/preferences.h b/mini-commander/src/preferences.h new file mode 100644 index 00000000..875a7fa2 --- /dev/null +++ b/mini-commander/src/preferences.h @@ -0,0 +1,109 @@ +/* + * Mini-Commander Applet + * Copyright (C) 1998, 1999 Oliver Maruhn + * 2002 Sun Microsystems Inc. + * + * Authors: Oliver Maruhn + * Mark McLoughlin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PREFERENCES_H__ +#define __PREFERENCES_H__ + +#include + +G_BEGIN_DECLS + +#include +#include + +#include + +typedef struct { + char *pattern; + char *command; + regex_t regex; +} MCMacro; + +typedef struct { + int show_default_theme; + int auto_complete_history; + + int normal_size_x; + int normal_size_y; + int panel_size_x; + + int cmd_line_color_fg_r; + int cmd_line_color_fg_g; + int cmd_line_color_fg_b; + int cmd_line_color_bg_r; + int cmd_line_color_bg_g; + int cmd_line_color_bg_b; + + GSList *macros; + + guint idle_macros_loader_id; + +} MCPreferences; + +typedef struct { + GtkWidget *dialog; + GtkWidget *auto_complete_history_toggle; + GtkWidget *size_spinner; + GtkWidget *use_default_theme_toggle; + GtkWidget *fg_color_picker; + GtkWidget *bg_color_picker; + GtkWidget *macros_tree; + GtkWidget *delete_button; + GtkWidget *add_button; + + GtkListStore *macros_store; + + GtkWidget *macro_add_dialog; + GtkWidget *pattern_entry; + GtkWidget *command_entry; +} MCPrefsDialog; + +/* Defaults */ +#define MC_DEFAULT_SHOW_DEFAULT_THEME TRUE +#define MC_DEFAULT_SHOW_HANDLE FALSE +#define MC_DEFAULT_SHOW_FRAME FALSE +#define MC_DEFAULT_AUTO_COMPLETE_HISTORY TRUE + +#define MC_DEFAULT_NORMAL_SIZE_X 150 +#define MC_DEFAULT_NORMAL_SIZE_Y 48 + +#define MC_DEFAULT_CMD_LINE_COLOR_FG_R 0xfc65 +#define MC_DEFAULT_CMD_LINE_COLOR_FG_G 0xfc65 +#define MC_DEFAULT_CMD_LINE_COLOR_FG_B 0xfc65 +#define MC_DEFAULT_CMD_LINE_COLOR_BG_R 0x0 +#define MC_DEFAULT_CMD_LINE_COLOR_BG_G 0x0 +#define MC_DEFAULT_CMD_LINE_COLOR_BG_B 0x0 + +#include "mini-commander_applet.h" + +void mc_load_preferences (MCData *mc); +void mc_show_preferences (GtkAction *action, + MCData *mc); +void mc_macros_free (GSList *macros); + +gboolean mc_key_writable (MCData *mc, + const char *key); + +G_END_DECLS + +#endif -- cgit v1.2.1