From 5a706d9963341b5cb1a4b75ce2603cc5265f29b0 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Thu, 25 May 2000 20:49:07 +0000 Subject: [PATCH] r286: Added some truncation code (not finished yet). Fixed a bug which could cause directories to appear empty when using VFS. --- ROX-Filer/src/Docs/Manual.lyx | 60 +++++++++++++++--- ROX-Filer/src/action.c | 6 +- ROX-Filer/src/action.h | 1 + ROX-Filer/src/collection.c | 5 ++ ROX-Filer/src/dir.c | 7 +- ROX-Filer/src/filer.c | 144 ++++++++++++++++++++++++++++++++++++------ ROX-Filer/src/gui_support.c | 5 ++ ROX-Filer/src/gui_support.h | 2 + ROX-Filer/src/menu.c | 16 ++++- ROX-Filer/src/minibuffer.c | 142 ++++++++++++++++++++++++++++++++++++++--- ROX-Filer/src/minibuffer.h | 8 ++- ROX-Filer/src/my_vfs.h | 1 + ROX-Filer/src/options.c | 2 +- 13 files changed, 349 insertions(+), 50 deletions(-) diff --git a/ROX-Filer/src/Docs/Manual.lyx b/ROX-Filer/src/Docs/Manual.lyx index fd806006..8c5a3bd9 100644 --- a/ROX-Filer/src/Docs/Manual.lyx +++ b/ROX-Filer/src/Docs/Manual.lyx @@ -1,4 +1,4 @@ -#This file was created by Tue May 16 11:38:42 2000 +#This file was created by Tue May 23 19:55:18 2000 #LyX 0.12 (C) 1995-1998 Matthias Ettrich and the LyX Team \lyxformat 2.15 \textclass article @@ -1040,7 +1040,7 @@ The window menu \layout Standard \added_space_top 0.3cm \added_space_bottom 0.3cm \align center \LyXTable multicol5 -10 2 0 0 -1 -1 -1 -1 +11 2 0 0 -1 -1 -1 -1 1 1 0 0 1 1 0 0 0 1 0 0 @@ -1051,6 +1051,7 @@ multicol5 0 1 0 0 0 1 1 0 0 1 0 0 +0 1 0 0 8 1 0 "" "" 2 1 1 "8cm" "" 0 8 0 1 0 0 0 "" "" @@ -1073,6 +1074,8 @@ multicol5 0 8 0 1 0 0 0 "" "" 0 8 0 1 0 0 0 "" "" 0 8 0 1 0 0 0 "" "" +0 8 0 1 0 0 0 "" "" +0 8 0 1 0 0 0 "" "" Entry \newline @@ -1094,7 +1097,7 @@ Close Window \newline Close this window. \newline -Enter Path +Enter Path... \newline Open the path-entry box (see section \begin_inset LatexCommand \ref{sec: mini} @@ -1103,7 +1106,7 @@ Open the path-entry box (see section ). \newline -Shell Command +Shell Command... \newline Open the shell command box (see section \begin_inset LatexCommand \ref{sec: mini} @@ -1112,7 +1115,7 @@ Open the shell command box (see section ). \newline -Set Run Action +Set Run Action... \newline Allows you to set the program to use when double-clicking on a file. \newline @@ -1125,6 +1128,15 @@ See section for details. \newline +Select If... +\newline +Select just those files that match the given pattern --- see section +\begin_inset LatexCommand \ref{sec: SelectIf} + +\end_inset + +. +\newline Show ROX-Filer help \newline Same as selecting ROX-Filer and choosing `Help' from the menu. @@ -1581,6 +1593,38 @@ Commands execute in the background, so you can say: sleep 240; xmessage Time to go! \end_deeper +\layout Subsubsection + + +\begin_inset LatexCommand \label{sec: SelectIf} + +\end_inset + +The conditional selection box +\layout Standard + +Use this if you want to automatically select all files in the directory + which match a condition. + The syntax for the conditions is given in section +\begin_inset LatexCommand \ref{sec: Searching} + +\end_inset + +. + For example, to select all files larger than 5Mb: +\layout Enumerate + +Open the Select If minibuffer. +\layout Enumerate + +Type ` +\family typewriter +Size > 5Mb +\family default +' and press Return. +\layout Standard + +Just those files over 5 Mb in size will be selected. \layout Subsection Action windows @@ -1767,7 +1811,7 @@ IsPipe matches pipes. IsSocket matches sockets. \layout Standard -These look at the permissions set on the file - see section +These look at the permissions set on the file --- see section \begin_inset LatexCommand \ref{sec: Permissions} \end_inset @@ -2300,7 +2344,7 @@ Application directories \layout Standard An application directory is a directory which can be run as an application. - It contains all the resources of an application - source code, binaries, + It contains all the resources of an application --- source code, binaries, documentation and so on. Keeping everything in one place make installation and uninstallation much easier for users. @@ -2569,7 +2613,7 @@ $ patch < patchfile $ ../AppRun --compile \layout Standard -You can remove the patch by simply repeating the above sequence - patch +You can remove the patch by simply repeating the above sequence --- patch will detect that the patch is already applied and offer to remove it. To create a patch you need to take a copy of the old 'src' directory before you modify it (before you compile, even): diff --git a/ROX-Filer/src/action.c b/ROX-Filer/src/action.c index 66620071..7a3002a1 100644 --- a/ROX-Filer/src/action.c +++ b/ROX-Filer/src/action.c @@ -75,8 +75,6 @@ static GtkWidget *w_auto_link = NULL; static GtkWidget *w_auto_delete = NULL; static GtkWidget *w_auto_mount = NULL; -static GdkColor red = {0, 0xffff, 0, 0}; - /* Parent->Child messages are one character each: * * Q/Y/N Quiet/Yes/No button clicked @@ -333,7 +331,7 @@ static void entry_changed(GtkEntry *entry, GUIside *gui_side) fflush(gui_side->to_child); } -static void show_condition_help(gpointer data) +void show_condition_help(void) { static GtkWidget *help = NULL; @@ -1952,7 +1950,7 @@ void action_find(FilerWindow *filer_window) button = gtk_button_new_with_label(_("Show expression reference")); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, TRUE, 4); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", - show_condition_help, NULL); + GTK_SIGNAL_FUNC(show_condition_help), NULL); gtk_window_set_title(GTK_WINDOW(gui_side->window), _("Find")); gtk_window_set_focus(GTK_WINDOW(gui_side->window), gui_side->entry); diff --git a/ROX-Filer/src/action.h b/ROX-Filer/src/action.h index bcc8da45..8a2b249b 100644 --- a/ROX-Filer/src/action.h +++ b/ROX-Filer/src/action.h @@ -20,5 +20,6 @@ void action_find(FilerWindow *filer_window); void action_move(GSList *paths, char *dest); void action_copy(GSList *paths, char *dest, char *leaf); void action_link(GSList *paths, char *dest); +void show_condition_help(void); #endif /* _ACTION_H */ diff --git a/ROX-Filer/src/collection.c b/ROX-Filer/src/collection.c index 607bd99b..8aa7f08a 100644 --- a/ROX-Filer/src/collection.c +++ b/ROX-Filer/src/collection.c @@ -989,6 +989,7 @@ static gint collection_key_press(GtkWidget *widget, GdkEventKey *event) if (!collection->target_cb) { collection_set_cursor_item(collection, -1); + collection_clear_selection(collection); return FALSE; /* Pass it on */ } collection_target(collection, NULL, NULL); @@ -1879,6 +1880,10 @@ void collection_set_item_size(Collection *collection, int width, int height) g_return_if_fail(IS_COLLECTION(collection)); g_return_if_fail(width > 4 && height > 4); + if (collection->item_width == width && + collection->item_height == height) + return; + widget = GTK_WIDGET(collection); collection->item_width = width; diff --git a/ROX-Filer/src/dir.c b/ROX-Filer/src/dir.c index d9b17bfd..24913533 100644 --- a/ROX-Filer/src/dir.c +++ b/ROX-Filer/src/dir.c @@ -168,7 +168,7 @@ static void free_items_array(GPtrArray *array) /* Scanning has finished. Remove all the old items that have gone. * Notify everyone who is watching us of the removed items and tell - * them that the scan is over. + * them that the scan is over, unless 'needs_update'. */ static void sweep_deleted(Directory *dir) { @@ -206,7 +206,8 @@ static void sweep_deleted(Directory *dir) if (old->len) user->callback(dir, DIR_REMOVE, old, user->data); - user->callback(dir, DIR_END_SCAN, NULL, user->data); + if (!dir->needs_update) + user->callback(dir, DIR_END_SCAN, NULL, user->data); list = list->next; } @@ -287,7 +288,7 @@ static void start_scanning(Directory *dir, char *pathname) return; /* Report on attach */ } - dir->dir_start = telldir(dir->dir_handle); + dir->dir_start = mc_telldir(dir->dir_handle); init_for_scan(dir); diff --git a/ROX-Filer/src/filer.c b/ROX-Filer/src/filer.c index 47a02cf3..43d539f6 100644 --- a/ROX-Filer/src/filer.c +++ b/ROX-Filer/src/filer.c @@ -65,6 +65,9 @@ #define PANEL_BORDER 2 #define MIN_ITEM_WIDTH 64 +#define MIN_TRUNCATE 0 +#define MAX_TRUNCATE 250 + extern int collection_menu_button; extern gboolean collection_single_click; @@ -94,6 +97,7 @@ static char *filer_new_window_on_1(char *data); static char *filer_toolbar(char *data); static char *filer_display_style(char *data); static char *filer_sort_by(char *data); +static char *filer_truncate(char *data); static OptionsSection options = { @@ -119,6 +123,10 @@ static gboolean o_sort_nocase = FALSE; static gboolean o_single_click = FALSE; static gboolean o_new_window_on_1 = FALSE; /* Button 1 => New window */ gboolean o_unique_filer_windows = FALSE; +static gint o_small_truncate = 144; +static gint o_large_truncate = 89; +static GtkAdjustment *adj_small_truncate; +static GtkAdjustment *adj_large_truncate; static GtkWidget *toggle_sort_nocase; static GtkWidget *toggle_single_click; static GtkWidget *toggle_new_window_on_1; @@ -158,6 +166,7 @@ static void draw_string(GtkWidget *widget, int x, int y, int width, + int area_width, gboolean selected); static void draw_item_large(GtkWidget *widget, CollectionItem *item, @@ -217,6 +226,7 @@ void filer_init() option_register("filer_toolbar", filer_toolbar); option_register("filer_display_style", filer_display_style); option_register("filer_sort_by", filer_sort_by); + option_register("filer_truncate", filer_truncate); busy_cursor = gdk_cursor_new(GDK_WATCH); @@ -382,6 +392,7 @@ static void filer_window_destroyed(GtkWidget *widget, static int calc_width(FilerWindow *filer_window, DirItem *item) { int pix_width = item->image->width; + int w; switch (filer_window->display_style) { @@ -391,7 +402,8 @@ static int calc_width(FilerWindow *filer_window, DirItem *item) case SMALL_ICONS: return SMALL_ICON_WIDTH + 12 + item->name_width; default: - return MAX(pix_width, item->name_width) + 4; + w = MIN(item->name_width, o_large_truncate); + return MAX(pix_width, w) + 4; } } @@ -630,24 +642,49 @@ static void draw_string(GtkWidget *widget, int x, int y, int width, + int area_width, gboolean selected) { - int text_height = font->ascent + font->descent; + int text_height = font->ascent + font->descent; + GdkRectangle clip; + GdkGC *gc = selected ? widget->style->white_gc + : widget->style->black_gc; if (selected) gtk_paint_flat_box(widget->style, widget->window, GTK_STATE_SELECTED, GTK_SHADOW_NONE, NULL, widget, "text", x, y - font->ascent, - width, + MIN(width, area_width), text_height); + if (width > area_width) + { + clip.x = x; + clip.y = y - font->ascent; + clip.width = area_width; + clip.height = text_height; + gdk_gc_set_clip_origin(gc, 0, 0); + gdk_gc_set_clip_rectangle(gc, &clip); + } + gdk_draw_text(widget->window, font, - selected ? widget->style->white_gc - : widget->style->black_gc, + gc, x, y, string, strlen(string)); + + if (width > area_width) + { + if (!red_gc) + { + red_gc = gdk_gc_new(widget->window); + gdk_gc_set_foreground(red_gc, &red); + } + gdk_draw_rectangle(widget->window, red_gc, TRUE, + x + area_width - 1, clip.y, 1, text_height); + gdk_gc_set_clip_rectangle(gc, NULL); + } } /* Return a string (valid until next call) giving details @@ -691,6 +728,7 @@ static void draw_item_full_info(GtkWidget *widget, int low_text_y = area->y + area->height - fixed_font->descent - 2; gboolean selected = colitem->selected; GdkRectangle pic_area; + int text_area_width = area->width - (text_x - area->x); pic_area.x = area->x; pic_area.y = area->y; @@ -705,12 +743,14 @@ static void draw_item_full_info(GtkWidget *widget, text_x, low_text_y - item_font->descent - fixed_font->ascent, item->name_width, + text_area_width, selected); draw_string(widget, fixed_font, details(item), text_x, low_text_y, item->details_width, + text_area_width, selected); if (item->lstat_errno) @@ -750,6 +790,7 @@ static void draw_item_small(GtkWidget *widget, text_x, low_text_y, item->name_width, + area->width - (text_x - area->x), selected); } @@ -758,16 +799,22 @@ static void draw_item_large(GtkWidget *widget, GdkRectangle *area) { DirItem *item = (DirItem *) colitem->data; - int text_x = area->x + ((area->width - item->name_width) >> 1); + int text_width = item->name_width; + int text_x = area->x + ((area->width - text_width) >> 1); int text_y = area->y + area->height - item_font->descent - 2; gboolean selected = colitem->selected; draw_large_icon(widget, area, item, selected); + if (text_x < area->x) + text_x = area->x; + draw_string(widget, item_font, item->leafname, - text_x, text_y, item->name_width, + text_x, text_y, + item->name_width, + area->width, selected); } @@ -1243,7 +1290,7 @@ static void toolbar_refresh_clicked(GtkWidget *widget, event = gtk_get_current_event(); if (event->type == GDK_BUTTON_RELEASE && - ((GdkEventButton *) event)->button == 3) + ((GdkEventButton *) event)->button != 1) { filer_opendir(filer_window->path, PANEL_NO); } @@ -1260,7 +1307,7 @@ static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window) event = gtk_get_current_event(); if (event->type == GDK_BUTTON_RELEASE && - ((GdkEventButton *) event)->button == 3) + ((GdkEventButton *) event)->button != 1) { filer_opendir(home_dir, PANEL_NO); } @@ -1274,7 +1321,7 @@ static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window) event = gtk_get_current_event(); if (event->type == GDK_BUTTON_RELEASE && - ((GdkEventButton *) event)->button == 3) + ((GdkEventButton *) event)->button != 1) { filer_open_parent(filer_window); } @@ -1768,12 +1815,16 @@ static GtkWidget *create_toolbar(FilerWindow *filer_window) * normally ignores this). Currently, this button does not pop in - * this may be fixed in future versions of GTK+. */ +static gint toolbar_other_button = 0; static gint toolbar_adjust_pressed(GtkButton *button, GdkEventButton *event, FilerWindow *filer_window) { - if (event->button == 3) + gint b = event->button; + + if ((b == 2 || b == 3) && toolbar_other_button == 0) { + toolbar_other_button = event->button; gtk_grab_add(GTK_WIDGET(button)); gtk_button_pressed(button); } @@ -1785,8 +1836,9 @@ static gint toolbar_adjust_released(GtkButton *button, GdkEventButton *event, FilerWindow *filer_window) { - if (event->button == 3) + if (event->button == toolbar_other_button) { + toolbar_other_button = 0; gtk_grab_remove(GTK_WIDGET(button)); gtk_button_released(button); } @@ -1837,7 +1889,7 @@ static void add_button(GtkWidget *box, int pixmap, */ static GtkWidget *create_options() { - GtkWidget *vbox, *menu, *hbox; + GtkWidget *vbox, *menu, *hbox, *slide; vbox = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), 4); @@ -1887,6 +1939,30 @@ static GtkWidget *create_options() gtk_option_menu_set_menu(GTK_OPTION_MENU(menu_toolbar), menu); gtk_box_pack_start(GTK_BOX(hbox), menu_toolbar, TRUE, TRUE, 0); + hbox = gtk_hbox_new(FALSE, 4); + gtk_box_pack_start(GTK_BOX(hbox), + gtk_label_new(_("Max Large Icons width")), + TRUE, TRUE, 0); + adj_large_truncate = GTK_ADJUSTMENT(gtk_adjustment_new(0, + MIN_TRUNCATE, MAX_TRUNCATE, 1, 10, 0)); + slide = gtk_hscale_new(adj_large_truncate); + gtk_widget_set_usize(slide, MAX_TRUNCATE, 24); + gtk_scale_set_draw_value(GTK_SCALE(slide), FALSE); + gtk_box_pack_start(GTK_BOX(hbox), slide, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + + hbox = gtk_hbox_new(FALSE, 4); + gtk_box_pack_start(GTK_BOX(hbox), + gtk_label_new(_("Max Small Icons width")), + TRUE, TRUE, 0); + adj_small_truncate = GTK_ADJUSTMENT(gtk_adjustment_new(0, + MIN_TRUNCATE, MAX_TRUNCATE, 1, 10, 0)); + slide = gtk_hscale_new(adj_small_truncate); + gtk_widget_set_usize(slide, MAX_TRUNCATE, 24); + gtk_scale_set_draw_value(GTK_SCALE(slide), FALSE); + gtk_box_pack_start(GTK_BOX(hbox), slide, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + return vbox; } @@ -1917,6 +1993,9 @@ static void update_options() o_unique_filer_windows); gtk_option_menu_set_history(GTK_OPTION_MENU(menu_toolbar), o_toolbar); + gtk_adjustment_set_value(adj_small_truncate, o_small_truncate); + gtk_adjustment_set_value(adj_large_truncate, o_large_truncate); + update_options_label(); } @@ -1926,6 +2005,7 @@ static void set_options() GtkWidget *item, *menu; GList *list; gboolean old_case = o_sort_nocase; + GList *next = all_filer_windows; o_sort_nocase = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(toggle_sort_nocase)); @@ -1950,19 +2030,21 @@ static void set_options() o_toolbar = (ToolbarType) g_list_index(list, item); g_list_free(list); - if (o_sort_nocase != old_case) + o_small_truncate = adj_small_truncate->value; + o_large_truncate = adj_large_truncate->value; + + while (next) { - GList *next = all_filer_windows; + FilerWindow *filer_window = (FilerWindow *) next->data; - while (next) + if (o_sort_nocase != old_case) { - FilerWindow *filer_window = (FilerWindow *) next->data; - collection_qsort(filer_window->collection, - filer_window->sort_fn); - - next = next->next; + filer_window->sort_fn); } + shrink_width(filer_window); + + next = next->next; } } @@ -1983,6 +2065,8 @@ static guchar *sort_fn_to_name(void) static void save_options() { + guchar *tmp; + option_write("filer_sort_nocase", o_sort_nocase ? "1" : "0"); option_write("filer_new_window_on_1", o_new_window_on_1 ? "1" : "0"); option_write("filer_menu_on_2", @@ -2003,6 +2087,10 @@ static void save_options() o_toolbar == TOOLBAR_NORMAL ? "Normal" : o_toolbar == TOOLBAR_GNOME ? "GNOME" : "Unknown"); + + tmp = g_strdup_printf("%d, %d", o_large_truncate, o_small_truncate); + option_write("filer_truncate", tmp); + g_free(tmp); } static char *filer_sort_nocase(char *data) @@ -2066,6 +2154,20 @@ static char *filer_sort_by(char *data) return NULL; } +static char *filer_truncate(char *data) +{ + guchar *comma; + + comma = strchr(data, ','); + if (!comma) + return "Missing , in filer_truncate"; + + o_large_truncate = CLAMP(atoi(data), MIN_TRUNCATE, MAX_TRUNCATE); + o_small_truncate = CLAMP(atoi(comma + 1), MIN_TRUNCATE, MAX_TRUNCATE); + + return NULL; +} + static char *filer_toolbar(char *data) { if (g_strcasecmp(data, "None") == 0) diff --git a/ROX-Filer/src/gui_support.c b/ROX-Filer/src/gui_support.c index 4c64c42a..2263909b 100644 --- a/ROX-Filer/src/gui_support.c +++ b/ROX-Filer/src/gui_support.c @@ -42,6 +42,9 @@ GdkFont *item_font = NULL; GdkFont *fixed_font = NULL; GtkStyle *fixed_style = NULL; gint fixed_width; +GdkColor red = {0, 0xffff, 0, 0}; +GdkGC *red_gc = NULL; /* Not automatically initialised */ + static GdkAtom xa_cardinal; @@ -56,6 +59,8 @@ void gui_support_init() fixed_width = gdk_string_width(fixed_font, "m"); xa_cardinal = gdk_atom_intern("CARDINAL", FALSE); + + gdk_color_alloc(gtk_widget_get_default_colormap(), &red); } static void choice_clicked(GtkWidget *widget, gpointer number) diff --git a/ROX-Filer/src/gui_support.h b/ROX-Filer/src/gui_support.h index 2152d618..4d688d32 100644 --- a/ROX-Filer/src/gui_support.h +++ b/ROX-Filer/src/gui_support.h @@ -19,6 +19,8 @@ extern GdkFont *fixed_font; extern GdkFont *item_font; extern GtkStyle *fixed_style; extern gint fixed_width; +extern GdkColor red; +extern GdkGC *red_gc; void gui_support_init(); int get_choice(char *title, diff --git a/ROX-Filer/src/menu.c b/ROX-Filer/src/menu.c index fe20952a..6dee23ba 100644 --- a/ROX-Filer/src/menu.c +++ b/ROX-Filer/src/menu.c @@ -117,6 +117,7 @@ static void close_window(gpointer data, guint action, GtkWidget *widget); static void enter_path(gpointer data, guint action, GtkWidget *widget); static void shell_command(gpointer data, guint action, GtkWidget *widget); static void run_action(gpointer data, guint action, GtkWidget *widget); +static void select_if(gpointer data, guint action, GtkWidget *widget); static void rox_help(gpointer data, guint action, GtkWidget *widget); static void open_as_dir(gpointer data, guint action, GtkWidget *widget); @@ -196,9 +197,11 @@ static GtkItemFactoryEntry filer_menu_def[] = { {">" N_("Parent, Same Window"), NULL, open_parent_same, 0, NULL}, {">" N_("New Window"), NULL, new_window, 0, NULL}, {">" N_("Close Window"), NULL, close_window, 0, NULL}, -{">" N_("Enter Path"), NULL, enter_path, 0, NULL}, -{">" N_("Shell Command"), NULL, shell_command, 0, NULL}, -{">" N_("Set Run Action"), NULL, run_action, 0, NULL}, +{">", NULL, NULL, 0, ""}, +{">" N_("Enter Path..."), NULL, enter_path, 0, NULL}, +{">" N_("Shell Command..."), NULL, shell_command, 0, NULL}, +{">" N_("Set Run Action..."), NULL, run_action, 0, NULL}, +{">" N_("Select If..."), NULL, select_if, 0, NULL}, {">", NULL, NULL, 0, ""}, {">" N_("Show ROX-Filer help"), NULL, rox_help, 0, NULL}, }; @@ -1395,6 +1398,13 @@ static void run_action(gpointer data, guint action, GtkWidget *widget) minibuffer_show(window_with_focus, MINI_RUN_ACTION); } +static void select_if(gpointer data, guint action, GtkWidget *widget) +{ + g_return_if_fail(window_with_focus != NULL); + + minibuffer_show(window_with_focus, MINI_SELECT_IF); +} + static void rox_help(gpointer data, guint action, GtkWidget *widget) { g_return_if_fail(window_with_focus != NULL); diff --git a/ROX-Filer/src/minibuffer.c b/ROX-Filer/src/minibuffer.c index eac6006b..56958237 100644 --- a/ROX-Filer/src/minibuffer.c +++ b/ROX-Filer/src/minibuffer.c @@ -33,11 +33,13 @@ #include #include "collection.h" +#include "find.h" #include "gui_support.h" #include "support.h" #include "minibuffer.h" #include "filer.h" #include "main.h" +#include "action.h" static GList *shell_history = NULL; @@ -50,6 +52,7 @@ static void find_next_match(FilerWindow *filer_window, char *pattern, int dir); static gboolean matches(Collection *collection, int item, char *pattern); static void search_in_dir(FilerWindow *filer_window, int dir); static guchar *mini_contents(FilerWindow *filer_window); +static void show_help(FilerWindow *filer_window); /**************************************************************** @@ -62,9 +65,21 @@ static guchar *mini_contents(FilerWindow *filer_window); */ void create_minibuffer(FilerWindow *filer_window) { - GtkWidget *hbox, *label, *mini; + MaskedPixmap *mp; + GtkWidget *hbox, *label, *mini, *help, *icon; hbox = gtk_hbox_new(FALSE, 0); + + mp = g_fscache_lookup(pixmap_cache, + make_path(getenv("APP_DIR"), "pixmaps/help.xpm")->str); + icon = gtk_pixmap_new(mp->pixmap, mp->mask); + g_fscache_data_unref(pixmap_cache, mp); + help = gtk_button_new(); + gtk_container_add(GTK_CONTAINER(help), icon); + gtk_box_pack_start(GTK_BOX(hbox), help, FALSE, TRUE, 0); + gtk_signal_connect_object(GTK_OBJECT(help), "clicked", + GTK_SIGNAL_FUNC(show_help), (GtkObject *) filer_window); + label = gtk_label_new(NULL); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 2); @@ -96,6 +111,7 @@ void minibuffer_show(FilerWindow *filer_window, MiniType mini_type) mini_type == MINI_PATH ? _("Goto:") : mini_type == MINI_SHELL ? _("Shell:") : mini_type == MINI_RUN_ACTION ? _("Run Action:") : + mini_type == MINI_SELECT_IF ? _("Select If:") : "?"); collection = filer_window->collection; @@ -110,6 +126,7 @@ void minibuffer_show(FilerWindow *filer_window, MiniType mini_type) break; case MINI_SHELL: case MINI_RUN_ACTION: + case MINI_SELECT_IF: filer_window->mini_cursor_base = -1; /* History */ gtk_entry_set_text(mini, ""); break; @@ -169,6 +186,42 @@ void minibuffer_add(FilerWindow *filer_window, guchar *leafname) * INTERNAL FUNCTIONS * ****************************************************************/ +static void show_help(FilerWindow *filer_window) +{ + guchar *message; + + gtk_widget_grab_focus(filer_window->minibuffer); + + switch (filer_window->mini_type) + { + case MINI_PATH: + message = _("Enter the name of a file and I'll display " + "it for you. Press Tab to fill in the longest " + "match. Escape to close the minibuffer."); + break; + case MINI_SHELL: + message = _("Enter a shell command to execute. Click " + "on a file to add it to the buffer."); + break; + case MINI_RUN_ACTION: + message = + _("To set the run action for a file, either:\n" + "- Drag a file to an application directory (eg drag an image to the " + "Gimp), or\n" "- Enter a shell command which contains a \"$1\"" + "where the name of the file should go (eg ` gimp \"$1\" ')"); + break; + case MINI_SELECT_IF: + show_condition_help(); + return; + default: + message = "?!?"; + break; + } + + delayed_error(PROJECT, message); +} + + /* PATH ENTRY */ static void path_return_pressed(FilerWindow *filer_window, GdkEventKey *event) @@ -565,11 +618,7 @@ gboolean set_run_action(FilerWindow *filer_window, guchar *command) if (!strchr(command, '$')) { - delayed_error(PROJECT, - _("To set the run action for a file, either:\n" - "- Drag a file to an application directory (eg drag an image to the " - "Gimp), or\n" "- Enter a shell command which contains a \"$1\"" - "where the name of the file should go (eg ` gimp \"$1\" ')")); + show_help(filer_window); return FALSE; } @@ -607,7 +656,7 @@ gboolean set_run_action(FilerWindow *filer_window, guchar *command) } /* Either execute the command or make it the default run action */ -static void shell_return_pressed(FilerWindow *filer_window, GdkEventKey *event) +static void shell_return_pressed(FilerWindow *filer_window) { GPtrArray *argv; int i; @@ -703,6 +752,63 @@ static void shell_recall(FilerWindow *filer_window, int dir) gtk_entry_set_text(GTK_ENTRY(filer_window->minibuffer), command); } +/* SELECT IF */ + +static void select_return_pressed(FilerWindow *filer_window) +{ + FindCondition *cond; + int i, n; + guchar *entry; + Collection *collection = filer_window->collection; + FindInfo info; + + entry = mini_contents(filer_window); + + if (!entry) + goto out; + + add_to_history(entry); + + cond = find_compile(entry); + if (!cond) + { + delayed_error(PROJECT, "Invalid Find condition"); + return; + } + + info.now = time(NULL); + info.prune = FALSE; /* (don't care) */ + n = collection->number_of_items; + + /* If an item at the start is selected then we could lose the + * primary selection after checking that item and then need to + * gain it again at the end. Therefore, if anything is selected + * then select the last item until the end of the search. + */ + if (collection->number_selected) + collection_select_item(collection, n - 1); + + for (i = 0; i < n; i++) + { + DirItem *item = (DirItem *) collection->items[i].data; + + info.leaf = item->leafname; + info.fullpath = make_path(filer_window->path, info.leaf)->str; + + if (lstat(info.fullpath, &info.stats) == 0 && + find_test_condition(cond, &info)) + collection_select_item(collection, i); + else + collection_unselect_item(collection, i); + } + + find_condition_free(cond); + +out: + minibuffer_hide(filer_window); +} + + /* EVENT HANDLERS */ static gint key_press_event(GtkWidget *widget, @@ -761,8 +867,26 @@ static gint key_press_event(GtkWidget *widget, shell_tab(filer_window); break; case GDK_Return: - shell_return_pressed(filer_window, - event); + shell_return_pressed(filer_window); + break; + default: + return FALSE; + } + break; + case MINI_SELECT_IF: + switch (event->keyval) + { + case GDK_Up: + shell_recall(filer_window, 1); + break; + case GDK_Down: + shell_recall(filer_window, -1); + break; + case GDK_Tab: + return TRUE; + case GDK_Return: + select_return_pressed(filer_window); + break; default: return FALSE; } diff --git a/ROX-Filer/src/minibuffer.h b/ROX-Filer/src/minibuffer.h index 64da5036..1f7d5545 100644 --- a/ROX-Filer/src/minibuffer.h +++ b/ROX-Filer/src/minibuffer.h @@ -8,7 +8,13 @@ #ifndef _MINIBUFFER_H #define _MINIBUFFER_H -typedef enum {MINI_NONE, MINI_PATH, MINI_SHELL, MINI_RUN_ACTION} MiniType; +typedef enum { + MINI_NONE, + MINI_PATH, + MINI_SHELL, + MINI_RUN_ACTION, + MINI_SELECT_IF, +} MiniType; #include #include "filer.h" diff --git a/ROX-Filer/src/my_vfs.h b/ROX-Filer/src/my_vfs.h index 4d066297..d8d0a06c 100644 --- a/ROX-Filer/src/my_vfs.h +++ b/ROX-Filer/src/my_vfs.h @@ -55,6 +55,7 @@ int mc_fstat (int fd, struct stat *buf); # define mc_closedir(x) closedir(x) # define mc_readdir(x) readdir(x) # define mc_seekdir(x, o) seekdir(x, o) +# define mc_telldir(x) telldir(x) #endif diff --git a/ROX-Filer/src/options.c b/ROX-Filer/src/options.c index 146464a1..29c16a14 100644 --- a/ROX-Filer/src/options.c +++ b/ROX-Filer/src/options.c @@ -135,7 +135,7 @@ void options_load(void) group = gtk_frame_new(_(section->name)); gtk_box_pack_start(GTK_BOX(sections_vbox), group, - FALSE, TRUE, 0); + FALSE, TRUE, 4); gtk_container_add(GTK_CONTAINER(group), section->create()); next = next->next; -- 2.11.4.GIT