1 /*
2  * Copyright (C) 2003-2012 Edscott Wilson Garcia
3  * EMail: edscott@users.sf.net
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24 
25 #include "rodent.h"
26 #include "rfm_modules.h"
27 
28 #include "find-module_gui.h"
29 
30 // default values:
31 gint result_limit=256;
32 gint size_greater=16;
33 gint size_smaller=1024;
34 gint last_minutes=60;
35 gint last_hours=2;
36 gint last_days=7;
37 gint last_months=2;
38 gboolean default_recursive=TRUE;
39 gboolean default_recursiveH=FALSE;
40 gboolean default_xdev=TRUE;
41 gboolean default_case_sensitive=FALSE;
42 gboolean default_ext_regexp=FALSE;
43 gboolean default_look_in_binaries=FALSE;
44 gboolean default_line_count=FALSE;
45 gint default_type_index=0;
46 gboolean default_anywhere=TRUE;
47 gboolean default_match_words=FALSE;
48 gboolean default_match_lines=FALSE;
49 gboolean default_match_no_match=FALSE;
50 GSList *find_list = NULL;
51 gchar  *last_workdir = NULL;
52 
53 gboolean have_grep = FALSE;
54 gboolean have_gnu_grep = FALSE;
55 
56 static const gchar *
57 filter_text_help=
58 	        N_("Basic rules:\n" "\n"
59                           "*  Will match any character zero or more times.\n"
60                           "?  Will match any character exactly one time\n"
61                           "[] Match any character within the [] \n"
62                           "^  Match at beginning of string\n"
63 			  "$  Match at end of string \n");
64 static const gchar *
65 grep_text_help=
66 		N_("Reserved characters for extended regexp are\n"
67                           ". ^ $ [ ] ? * + { } | \\ ( ) : \n"
68                           "In  basic regular expressions the metacharacters\n"
69                           "?, +, {, |, (, and ) lose their special meaning.\n"
70                           "\n"
71                           "The  period  .   matches  any  single  character.\n"
72                           "The caret ^ matches at the start of line.\n"
73                           "The dollar $ matches at the end of line.\n" "\n"
74                           "Characters within [ ] matches any single \n"
75                           "       character in the list.\n"
76                           "Characters within [^ ] matches any single\n"
77                           "       character *not* in the list.\n"
78                           "Characters inside [ - ] matches a range of\n"
79                           "       characters (ie [0-9] or [a-z]).\n" "\n"
80                           "A regular expression may be followed by one\n"
81                           "       of several repetition operators:\n"
82                           "?      The preceding item is optional and matched\n"
83                           "       at most once.\n"
84                           "*      The preceding item will be matched zero\n"
85                           "       or more times.\n"
86                           "+      The preceding item will be matched one or\n"
87                           "       more times.\n"
88                           "{n}    The preceding item is matched exactly n times.\n"
89                           "{n,}   The preceding item is matched n or more times.\n"
90                           "{n,m}  The preceding item is matched at least n times,\n"
91                           "       but not more than m times.\n" "\n"
92                           "To match any reserved character, precede it with \\. \n"
93                           "\n"
94                           "Two regular expressions may be joined by the logical or\n"
95                           "       operator |.\n"
96                           "Two regular expressions may be concatenated.\n" "\n"
97                           "More information is available by typing \"man grep\"\n"
98 			  );
99 
100 static void
on_help_filter(GtkToggleButton * button,gpointer data)101 on_help_filter (GtkToggleButton * button, gpointer data) {
102     GtkWidget *dialog=data;
103     widgets_t *widgets_p=g_object_get_data(G_OBJECT(dialog), "widgets_p");
104     if (gtk_toggle_button_get_active (button)) {
105 	rfm_clear_text(widgets_p);
106 	rfm_show_text (widgets_p);
107 	rfm_diagnostics(widgets_p,"xffm_tag/blue", _(filter_text_help), NULL);
108 	rfm_scroll_to_top(widgets_p);
109     } else {
110 	rfm_clear_text(widgets_p);
111     }
112 }
113 
114 static void
on_help_grep(GtkToggleButton * button,gpointer data)115 on_help_grep (GtkToggleButton * button, gpointer data) {
116     GtkWidget *dialog=data;
117     widgets_t *widgets_p=g_object_get_data(G_OBJECT(dialog), "widgets_p");
118     if (gtk_toggle_button_get_active (button)) {
119 	rfm_clear_text(widgets_p);
120 	rfm_show_text (widgets_p);
121 	rfm_diagnostics(widgets_p,"xffm_tag/blue", _(grep_text_help), NULL);
122 	rfm_scroll_to_top(widgets_p);
123     } else {
124 	rfm_clear_text(widgets_p);
125     }
126 }
127 
128 GtkWidget *
fill_string_option_menu(GtkComboBox * om,GSList * strings)129 fill_string_option_menu (GtkComboBox *om, GSList * strings) {
130     if (!om || ! strings){
131 	DBG("create_string_option_menu: GtkComboBox==NULL || GList==NULL\n");
132 	return NULL;
133     }
134     GSList *p;
135     for (p=strings; p && p->data; p=p->next) {
136 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
137     // this is deprecated...
138 	gtk_combo_box_append_text (om, (const gchar *)p->data);
139 #else
140         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(om), (const gchar *)p->data);
141 #endif
142       /* Note: The model will keep a copy of the string internally,
143        * so the list may be freed */
144     }
145     gtk_combo_box_set_active(om, default_type_index);
146     return (GtkWidget *)om;
147 }
148 
149 static void
edit_command(GtkWidget * button,gpointer data)150 edit_command (GtkWidget * button, gpointer data) {
151     GtkWidget *dialog=g_object_get_data(G_OBJECT(button), "dialog");
152     widgets_t *widgets_p=g_object_get_data(G_OBJECT(dialog), "widgets_p");
153 
154     GSList *list = find_list;
155     rfm_show_text (widgets_p);
156     if (!list || g_slist_length(list) < 1) {
157 	rfm_diagnostics(widgets_p, "xffm/stock_dialog-warning",NULL);
158 	rfm_diagnostics(widgets_p, "xffm_tag/stderr", _("Search returned no results"), "\n", NULL);
159 	return;
160     }
161 
162     const gchar *editor = getenv("EDITOR");
163     if (!editor || strlen(editor)==0){
164 	rfm_diagnostics(widgets_p, "xffm/stock_dialog-warning",NULL);
165 	rfm_diagnostics(widgets_p, "xffm_tag/stderr", _("No editor component found."), "\n", NULL);
166 	return;
167     }
168 
169     gchar *command = g_strdup(editor);
170 
171 
172     for (; list && list->data; list=list->next){
173 	gchar *g = g_strconcat(command, " \"", (gchar *)list->data, "\"", NULL);
174 	g_free(command);
175 	command = g;
176     }
177 
178     rfm_diagnostics(widgets_p, "xffm/stock_execute",NULL);
179     rfm_diagnostics(widgets_p, "xffm_tag/blue", " ", command, "\n", NULL);
180 
181     g_free(widgets_p->workdir);
182     widgets_p->workdir = g_strdup(last_workdir);
183 
184     // Hack: for nano or vi, run in terminal
185     gboolean in_terminal = FALSE;
186     if (strstr(command, "nano") ||
187 	    (strstr(command, "vi") && !strstr(command, "gvim")))
188     {
189 	in_terminal = TRUE;
190     }
191 
192     RFM_THREAD_RUN2ARGV(widgets_p, command, in_terminal);
193 
194     g_free(widgets_p->workdir);
195     widgets_p->workdir = g_strdup(g_get_home_dir());
196 }
197 
198 
199 static void
command_help(GtkWidget * button,gpointer data)200 command_help (GtkWidget * button, gpointer data) {
201     GtkWidget *dialog=g_object_get_data(G_OBJECT(button), "dialog");
202     widgets_t *widgets_p=g_object_get_data(G_OBJECT(dialog), "widgets_p");
203     gchar *argv[]={data, "--help", NULL};
204     rfm_clear_text (widgets_p);
205     rfm_show_text (widgets_p);
206     rfm_thread_run_argv_full (widgets_p, argv, FALSE, NULL, rfm_markup_stdout_f, rfm_dump_output, rfm_null_function);
207 }
208 
209 static void
clear_text(GtkWidget * button,gpointer data)210 clear_text (GtkWidget * button, gpointer data) {
211     GtkWidget *dialog=g_object_get_data(G_OBJECT(button), "dialog");
212     widgets_t *widgets_p=g_object_get_data(G_OBJECT(dialog), "widgets_p");
213     rfm_clear_text (widgets_p);
214 }
215 
216 static GSList *
get_user_slist(void)217 get_user_slist(void){
218     GSList *g_user = NULL;
219     struct passwd *pw;
220     while((pw = getpwent ()) != NULL) {
221         g_user = g_slist_append (g_user, g_strdup (pw->pw_name));
222     }
223     g_user = g_slist_sort (g_user, (GCompareFunc) strcmp);
224     endpwent ();
225     pw = getpwuid (geteuid ());
226     gchar *buf = g_strdup_printf ("%s", pw ? pw->pw_name : _("unknown"));
227     g_user = g_slist_prepend (g_user, buf);
228     return g_user;
229 }
230 
231 static GSList *
get_group_slist(void)232 get_group_slist(void){
233     GSList *g_group=NULL;
234     struct group *gr;
235     while((gr = getgrent ()) != NULL) {
236        g_group = g_slist_append (g_group, g_strdup (gr->gr_name));
237     }
238     endgrent ();
239     g_group = g_slist_sort (g_group, (GCompareFunc) strcmp);
240     gr = getgrgid (geteuid ());
241     gchar *buf = g_strdup_printf ("%s", gr ? gr->gr_name : _("unknown"));
242     g_group = g_slist_prepend (g_group, buf);
243     return g_group;
244 }
245 
246 static void
sensitivize(GtkToggleButton * togglebutton,gpointer data)247 sensitivize (GtkToggleButton *togglebutton, gpointer data){
248     GtkWidget *hbox = data;
249     gtk_widget_set_sensitive(hbox, gtk_toggle_button_get_active(togglebutton));
250 }
251 
252 typedef struct radio_t {
253     GtkWidget *box;
254     GtkToggleButton *toggle[5];
255 } radio_t;
256 
257 static void
sensitivize_radio(GtkToggleButton * togglebutton,gpointer data)258 sensitivize_radio (GtkToggleButton *togglebutton, gpointer data){
259     if (!data) return;
260     radio_t *radio_p = data;
261     gtk_widget_set_sensitive(radio_p->box, FALSE);
262     GtkToggleButton **tb_p = radio_p->toggle;
263     for (; tb_p && *tb_p; tb_p++){
264 	if (gtk_toggle_button_get_active(*tb_p)){
265 	    gtk_widget_set_sensitive(radio_p->box, TRUE);
266 	}
267     }
268 }
269 
270 static radio_t *
create_radios(GtkWidget * dialog,GtkWidget * options_vbox)271 create_radios(GtkWidget *dialog, GtkWidget *options_vbox){
272     radio_t *radio_p = (radio_t *)malloc(sizeof(radio_t));
273     if (!radio_p) g_error("malloc: %s", strerror(errno));
274     g_object_set_data(G_OBJECT(dialog), "radio_p", radio_p );
275     memset(radio_p, 0, sizeof(radio_t));
276 
277     GtkWidget *radio1 = gtk_radio_button_new_with_label (NULL, "mtime");
278     rfm_add_custom_tooltip(radio1, NULL, _("Modified"));
279     GtkWidget *radio2 = gtk_radio_button_new_with_label_from_widget (
280 	    GTK_RADIO_BUTTON (radio1), "ctime");
281     rfm_add_custom_tooltip(radio2, NULL, _("Created"));
282     GtkWidget *radio3 = gtk_radio_button_new_with_label_from_widget (
283 	    GTK_RADIO_BUTTON (radio1), "atime");
284     rfm_add_custom_tooltip(radio3, NULL, _("Accessed"));
285 
286     g_object_set_data(G_OBJECT(dialog), "radio1", radio1 );
287     g_object_set_data(G_OBJECT(dialog), "radio2", radio2 );
288     g_object_set_data(G_OBJECT(dialog), "radio3", radio3 );
289     gtk_widget_show (radio1);
290     gtk_widget_show (radio2);
291     gtk_widget_show (radio3);
292 
293     GtkWidget *radio_box=rfm_vbox_new (FALSE, 0);
294     g_object_set_data(G_OBJECT(dialog), "radio_box", radio_box );
295     gtk_widget_show (radio_box);
296     gtk_box_pack_start (GTK_BOX (options_vbox), radio_box, TRUE, FALSE, 0);
297     gtk_widget_set_sensitive(radio_box, FALSE);
298     radio_p->box = radio_box;
299 
300 
301     /*GtkWidget *label = gtk_label_new(_("modified"));
302     gtk_box_pack_start (GTK_BOX (radio_box), label, TRUE, FALSE, 0);
303     gtk_widget_show (label);*/
304     GtkWidget *box=rfm_vbox_new (FALSE, 0);
305     gtk_widget_show (box);
306     gtk_box_pack_start (GTK_BOX (radio_box), box, TRUE, FALSE, 0);
307 
308     gtk_box_pack_start (GTK_BOX (box), radio1, TRUE, FALSE, 0);
309     gtk_box_pack_start (GTK_BOX (box), radio2, TRUE, FALSE, 0);
310     gtk_box_pack_start (GTK_BOX (box), radio3, TRUE, FALSE, 0);
311 
312     /*label = gtk_label_new(_("within the last"));
313     gtk_box_pack_start (GTK_BOX (radio_box), label, TRUE, FALSE, 0);
314     gtk_widget_show (label);*/
315     return radio_p;
316 }
317 
318 
319 static  GtkToggleButton *
add_option_entry(GtkWidget * dialog,GtkWidget * options_vbox,const gchar * check_name,const gchar * entry_name,const gchar * text,const gchar * default_value)320 add_option_entry(GtkWidget *dialog,
321 	GtkWidget *options_vbox,
322 	const gchar *check_name,
323 	const gchar *entry_name,
324 	const gchar *text,
325 	const gchar *default_value)
326 {
327     if ((!entry_name && !check_name)|| !options_vbox || !dialog) {
328 	DBG("add_option_entry(): incorrect function call\n");
329 	return NULL;
330     }
331     GtkWidget *hbox = rfm_hbox_new (FALSE, 0);
332     gtk_widget_show (hbox);
333     gtk_box_pack_start (GTK_BOX (options_vbox), hbox, TRUE, FALSE, 0);
334 
335     GtkWidget *size_hbox = rfm_hbox_new (FALSE, 0);
336     GtkWidget *check = NULL;
337     if (check_name) {
338 	check = gtk_check_button_new();
339 	gtk_widget_show (check);
340 	g_object_set_data(G_OBJECT(dialog), check_name, check);
341 	gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
342 	g_signal_connect (G_OBJECT (check), "toggled", G_CALLBACK (sensitivize),
343 		size_hbox);
344 	gtk_widget_set_sensitive(size_hbox, FALSE);
345     }
346     gtk_widget_show (size_hbox);
347     gtk_box_pack_start (GTK_BOX (hbox), size_hbox, FALSE, FALSE, 0);
348 
349     if (text) {
350 	GtkWidget *label = gtk_label_new (text);
351 	gtk_widget_show (label);
352 	gtk_box_pack_start (GTK_BOX (size_hbox), label, TRUE, FALSE, 0);
353     }
354 
355     if (entry_name) {
356 	GtkWidget *label = gtk_label_new (": ");
357 	gtk_widget_show (label);
358 	gtk_box_pack_start (GTK_BOX (size_hbox), label, FALSE, FALSE, 0);
359 
360 	GtkWidget *entry = gtk_entry_new();
361 	gtk_widget_show (entry);
362 	gtk_box_pack_start (GTK_BOX (size_hbox), entry, TRUE, TRUE, 0);
363 	g_object_set_data(G_OBJECT(dialog), entry_name, entry);
364 	gtk_entry_set_text (GTK_ENTRY(entry), default_value);
365     }
366 
367     if (check) return GTK_TOGGLE_BUTTON(check);
368     return NULL;
369 }
370 
371 
372 static  GtkToggleButton *
add_option_radio2(GtkWidget * dialog,GtkWidget * options_vbox,const gchar * check_name,const gchar * radio1_name,const gchar * radio2_name,const gchar * text1,const gchar * text2)373 add_option_radio2(GtkWidget *dialog,
374 	GtkWidget *options_vbox,
375 	const gchar *check_name,
376 	const gchar *radio1_name,
377 	const gchar *radio2_name,
378 	const gchar *text1,
379 	const gchar *text2)
380 {
381     if ((!radio1_name  && !check_name)|| !options_vbox || !dialog) {
382 	DBG("add_option_radio2(): incorrect function call\n");
383 	return NULL;
384     }
385     GtkWidget *hbox = rfm_hbox_new (FALSE, 0);
386     gtk_widget_show (hbox);
387     gtk_box_pack_start (GTK_BOX (options_vbox), hbox, TRUE, FALSE, 0);
388 
389     GtkWidget *size_hbox = rfm_hbox_new (FALSE, 0);
390     GtkWidget *check = NULL;
391     if (check_name) {
392 	check = gtk_check_button_new();
393 	gtk_widget_show (check);
394 	g_object_set_data(G_OBJECT(dialog), check_name, check);
395 	gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
396 	g_signal_connect (G_OBJECT (check), "toggled", G_CALLBACK (sensitivize),
397 		size_hbox);
398 	gtk_widget_set_sensitive(size_hbox, FALSE);
399     }
400     gtk_widget_show (size_hbox);
401     gtk_box_pack_start (GTK_BOX (hbox), size_hbox, FALSE, FALSE, 0);
402 
403     if (text1 && radio1_name) {
404 	GtkWidget *radio1 = gtk_radio_button_new_with_label (NULL, text1);
405 	gtk_widget_show (radio1);
406 	gtk_box_pack_start (GTK_BOX (size_hbox), radio1, TRUE, TRUE, 0);
407 	g_object_set_data(G_OBJECT(dialog), radio1_name, radio1);
408         if (text2 && radio2_name) {
409 	    GtkWidget *radio2 = gtk_radio_button_new_with_label_from_widget (
410 	    GTK_RADIO_BUTTON (radio1), text2);
411 	    gtk_widget_show (radio2);
412 	    gtk_box_pack_start (GTK_BOX (size_hbox), radio2, TRUE, TRUE, 0);
413 	    g_object_set_data(G_OBJECT(dialog), radio2_name, radio2);
414 	}
415     }
416 
417     if (check) return GTK_TOGGLE_BUTTON(check);
418     return NULL;
419 }
420 
421 static  GtkToggleButton *
add_option_spin(GtkWidget * dialog,GtkWidget * options_vbox,const gchar * check_name,const gchar * spin_name,const gchar * text,gint default_value)422 add_option_spin(GtkWidget *dialog,
423 	GtkWidget *options_vbox,
424 	const gchar *check_name,
425 	const gchar *spin_name,
426 	const gchar *text,
427 	gint default_value)
428 {
429     /*GtkIconInfo *icon_info =
430         gtk_icon_theme_lookup_icon (gtk_icon_theme_get_default(),
431                             "list-add-symbolic",
432                             GTK_ICON_SIZE_MENU,
433                             0);*/
434     // gtk bug workaround. if no icotheme in use, plus/minus icons cannot be loaded.
435     //if (icon_info) {
436 /*    if (!getenv("RFM_USE_GTK_ICON_THEME") || !strlen(getenv("RFM_USE_GTK_ICON_THEME"))) {
437         gchar *def_val = g_strdup_printf("%d", default_value);
438         GtkToggleButton *t = add_option_entry(dialog, options_vbox, check_name, spin_name, text, def_val);
439         g_free(def_val);
440         return t;
441     }*/
442     //if (icon_info) g_object_unref(icon_info);
443 
444     if ((!spin_name && !check_name)|| !options_vbox || !dialog) {
445 	DBG("add_option_spin(): incorrect function call\n");
446 	return NULL;
447     }
448     GtkWidget *hbox = rfm_hbox_new (FALSE, 0);
449     gtk_widget_show (hbox);
450     gtk_box_pack_start (GTK_BOX (options_vbox), hbox, TRUE, FALSE, 0);
451 
452     GtkWidget *size_hbox = rfm_hbox_new (FALSE, 0);
453     GtkWidget *check = NULL;
454     if (check_name) {
455 	check = gtk_check_button_new();
456 	gtk_widget_show (check);
457 	g_object_set_data(G_OBJECT(dialog), check_name, check);
458 	gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
459 	g_signal_connect (G_OBJECT (check), "toggled", G_CALLBACK (sensitivize),
460 		size_hbox);
461 	gtk_widget_set_sensitive(size_hbox, FALSE);
462     }
463     gtk_widget_show (size_hbox);
464     gtk_box_pack_start (GTK_BOX (hbox), size_hbox, FALSE, FALSE, 0);
465 
466     if (text) {
467 	GtkWidget *label = gtk_label_new (text);
468 	gtk_widget_show (label);
469 	gtk_box_pack_start (GTK_BOX (size_hbox), label, TRUE, FALSE, 0);
470     }
471 
472     if (spin_name) {
473 	GtkWidget *label = gtk_label_new (": ");
474 	gtk_widget_show (label);
475 	gtk_box_pack_start (GTK_BOX (size_hbox), label, FALSE, FALSE, 0);
476 	GtkAdjustment *spinbutton_adj = GTK_ADJUSTMENT(gtk_adjustment_new (default_value, 0, 4096*4096, 1, 64, 0));
477 	GtkWidget *spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 0, 0);
478 	gtk_widget_show (spinbutton);
479 	gtk_box_pack_start (GTK_BOX (size_hbox), spinbutton, TRUE, TRUE, 0);
480 	gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinbutton), GTK_UPDATE_IF_VALID);
481 	g_object_set_data(G_OBJECT(dialog), spin_name, spinbutton);
482 	gtk_widget_set_size_request (spinbutton, 75, -1);
483     }
484 
485     if (check) return GTK_TOGGLE_BUTTON(check);
486     return NULL;
487 }
488 
489 
490 
491 static  GtkToggleButton *
add_option_combo(GtkWidget * dialog,GtkWidget * options_vbox,const gchar * check_name,const gchar * combo_name,const gchar * text,GSList * list)492 add_option_combo(GtkWidget *dialog,
493 	GtkWidget *options_vbox,
494 	const gchar *check_name,
495 	const gchar *combo_name,
496 	const gchar *text,
497 	GSList *list)
498 {
499     if ((!combo_name && !check_name)|| !options_vbox || !dialog) {
500 	DBG("add_option_spin(): incorrect function call\n");
501 	return NULL;
502     }
503     GtkWidget *hbox = rfm_hbox_new (FALSE, 0);
504     gtk_widget_show (hbox);
505     gtk_box_pack_start (GTK_BOX (options_vbox), hbox, TRUE, FALSE, 0);
506 
507     GtkWidget *size_hbox = rfm_hbox_new (FALSE, 0);
508     GtkWidget *check = NULL;
509     if (check_name) {
510 	check = gtk_check_button_new();
511 	gtk_widget_show (check);
512 	g_object_set_data(G_OBJECT(dialog), check_name, check);
513 	gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
514 	g_signal_connect (G_OBJECT (check), "toggled", G_CALLBACK (sensitivize),
515 		size_hbox);
516 	gtk_widget_set_sensitive(size_hbox, FALSE);
517     }
518     gtk_widget_show (size_hbox);
519     gtk_box_pack_start (GTK_BOX (hbox), size_hbox, FALSE, FALSE, 0);
520 
521     if (text) {
522 	GtkWidget *label = gtk_label_new (text);
523 	gtk_widget_show (label);
524 	gtk_box_pack_start (GTK_BOX (size_hbox), label, TRUE, FALSE, 0);
525  	label = gtk_label_new (": ");
526 	gtk_widget_show (label);
527 	gtk_box_pack_start (GTK_BOX (size_hbox), label, FALSE, FALSE, 0);
528    }
529 
530     if (combo_name) {
531 	GtkListStore *usermodel=gtk_list_store_new (1, G_TYPE_STRING);
532 	rfm_set_store_data_from_list (usermodel, &list);
533 
534 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
535 	GtkWidget *combo =
536 	    gtk_combo_box_entry_new_with_model((GtkTreeModel *)usermodel, 0);
537 #else
538 	 GtkWidget *combo = gtk_combo_box_new_with_entry();
539 	gtk_combo_box_set_model (GTK_COMBO_BOX(combo),(GtkTreeModel *)usermodel);
540 	gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX(combo),0);
541 
542 #endif
543 
544 	GtkWidget *entry  = gtk_bin_get_child(GTK_BIN(combo));
545 	gtk_entry_set_text (GTK_ENTRY (entry), (gchar *)list->data);
546 	gtk_widget_show(combo);
547 	gtk_box_pack_start (GTK_BOX (size_hbox), combo, TRUE, TRUE, 0);
548 	g_object_set_data(G_OBJECT(dialog), combo_name, combo);
549 	gtk_widget_set_size_request (combo, 120, -1);
550     }
551     if (check) return GTK_TOGGLE_BUTTON(check);
552     return NULL;
553 }
554 
555 static GSList *
free_string_slist(GSList * slist)556 free_string_slist(GSList *slist){
557     GSList *tmp;
558     for (tmp=slist; tmp && tmp->data; tmp=tmp->next){
559         g_free(tmp->data);
560     }
561     g_slist_free(slist);
562     return NULL;
563 }
564 
565 /////////////////////////////////////////////////////////////////////////////////////////
566 /////////////////////////////////////////////////////////////////////////////////////////
567 /////////////////////////////////////////////////////////////////////////////////////////
568 /////////////////////////////////////////////////////////////////////////////////////////
569 #define MAX_WIDTH 600
570 
571 GtkWidget *
create_find_dialog()572 create_find_dialog () {
573 
574 
575 
576     gchar *grep = g_find_program_in_path ("grep");
577     if(grep) {
578         FILE *pipe;
579         const gchar *cmd = "grep --version";
580         have_grep = TRUE;
581         pipe = popen (cmd, "r");
582         if(pipe) {
583             gchar line[256];
584             memset (line, 0, 256);
585             if(fgets (line, 255, pipe) == NULL)
586                 DBG ("fgets: %s\n", strerror (errno));
587             pclose (pipe);
588             if(strstr (line, "GNU"))
589                 have_gnu_grep = TRUE;
590         }
591     }
592     g_free (grep);
593 
594     GtkAccelGroup *accel_group = gtk_accel_group_new ();
595 
596     GtkWidget *dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
597     gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
598     GdkGeometry geometry;
599     rfm_get_drawable_geometry (gdk_x11_get_default_root_xwindow (),
600 	    NULL, NULL, &(geometry.max_width), &(geometry.max_height), NULL);
601     geometry.max_width -= 25;
602     geometry.max_height -= 25;
603     gtk_window_set_geometry_hints (GTK_WINDOW(dialog), dialog,
604 	    &geometry, GDK_HINT_MAX_SIZE);
605 
606     widgets_t *widgets_p =(widgets_t *)malloc(sizeof(widgets_t));
607     memset(widgets_p, 0, sizeof(widgets_t));
608     g_object_set_data(G_OBJECT(dialog), "widgets_p", widgets_p);
609 
610     g_object_set_data(G_OBJECT(dialog), "window", dialog);
611 
612 
613     gtk_window_set_title (GTK_WINDOW (dialog), _("Find"));
614     gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
615 
616     GdkPixbuf *pixbuf = rfm_get_pixbuf("xffm/stock_find", SIZE_ICON);
617     gtk_window_set_icon ((GtkWindow *) dialog, pixbuf);
618     g_object_unref(pixbuf);
619 
620     GtkWidget *main_vbox = rfm_vbox_new (FALSE, 0);
621     gtk_widget_show (main_vbox);
622     gtk_container_add (GTK_CONTAINER (dialog), main_vbox);
623 
624     GtkWidget *vpane = rfm_vpaned_new ();
625     g_object_set_data(G_OBJECT(dialog), "vpane", vpane);
626     // hack:
627     widgets_p->paper = dialog;
628 
629     gtk_widget_show (vpane);
630     gtk_box_pack_start (GTK_BOX (main_vbox), vpane, TRUE, TRUE, 0);
631     GtkWidget *top_pane_vbox = rfm_vbox_new (FALSE, 6);
632     GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL);
633     gtk_paned_pack1 (GTK_PANED (vpane),
634 	    GTK_WIDGET (sw), FALSE, TRUE);
635 #if GTK_MAJOR_VERSION==3 && GTK_MINOR_VERSION>=8
636     gtk_container_add(GTK_CONTAINER(sw), top_pane_vbox);
637 
638 #else
639     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), top_pane_vbox);
640 #endif
641     gtk_widget_show (sw);
642     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw),
643 	    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
644 
645     widgets_p->diagnostics = gtk_text_view_new ();
646     GtkWidget *scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
647     gtk_widget_show (scrolledwindow);
648     gtk_widget_show ((widgets_p->diagnostics));
649     gtk_paned_pack2 (GTK_PANED (vpane), scrolledwindow, TRUE, TRUE);
650     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
651 	    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
652 
653     gtk_container_add (GTK_CONTAINER (scrolledwindow), (widgets_p->diagnostics));
654     gtk_container_set_border_width (GTK_CONTAINER ((widgets_p->diagnostics)), 2);
655     gtk_widget_set_can_focus((widgets_p->diagnostics), FALSE);
656     gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW ((widgets_p->diagnostics)), GTK_WRAP_WORD);
657     gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW ((widgets_p->diagnostics)), FALSE);
658 
659 
660 
661     gtk_container_set_border_width (GTK_CONTAINER (top_pane_vbox), 5);
662 
663 
664     GtkWidget *hbox= rfm_hbox_new (FALSE, 0);
665     gtk_box_pack_start (GTK_BOX (top_pane_vbox), hbox, FALSE, FALSE, 0);
666 
667     gchar *t=g_strdup_printf("<b>%s <i>(fgr)</i></b>  ", _("Find"));
668     GtkWidget *label42 = gtk_label_new (t);
669     g_free(t);
670     gtk_widget_show (label42);
671     gtk_box_pack_start (GTK_BOX (hbox), label42, FALSE, FALSE, 0);
672     gtk_label_set_use_markup (GTK_LABEL (label42), TRUE);
673 
674     GtkWidget *button;
675 
676     button = rfm_dialog_button ("xffm/stock_dialog-question", NULL);
677     rfm_add_custom_tooltip(button, NULL, "fgr --help");
678     g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (command_help), "fgr");
679     g_object_set_data(G_OBJECT(button), "dialog", dialog);
680     gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
681     gtk_widget_show(button);
682 
683 
684 
685     GtkWidget *vbox7a = rfm_vbox_new (FALSE, 5);
686     gtk_widget_show (vbox7a);
687     gtk_box_pack_start (GTK_BOX (top_pane_vbox), vbox7a, TRUE, TRUE, 0);
688 
689     GtkWidget *path_box = rfm_hbox_new (FALSE, 0);
690     gtk_box_pack_start (GTK_BOX (vbox7a), path_box, FALSE, FALSE, 0);
691 
692     t=g_strdup_printf("%s:", _("Path"));
693     GtkWidget *path_label = gtk_label_new (t);
694     g_free(t);
695     gtk_widget_show (path_label);
696 
697 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
698     // this is deprecated...
699     GtkWidget *path_combo = gtk_combo_box_entry_new ();
700 #else
701     GtkWidget *path_combo = gtk_combo_box_new_with_entry ();
702 #endif
703 
704     g_object_set_data (G_OBJECT (path_combo), "GladeParentKey", path_combo);
705     g_object_set_data(G_OBJECT(dialog), "path_combo", path_combo);
706 
707 
708     button = rfm_dialog_button ("xffm/stock_directory", NULL);
709     GtkWidget *vbox = rfm_vbox_new (FALSE, 6);
710     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
711     gtk_box_pack_start (GTK_BOX (path_box), path_label, FALSE, FALSE, 0);
712     gtk_box_pack_start (GTK_BOX (path_box), path_combo, FALSE, TRUE, 0);
713     gtk_box_pack_start (GTK_BOX (path_box), vbox, FALSE, FALSE, 0);
714     gtk_widget_show (vbox);
715     gtk_widget_show (path_combo);
716     gtk_widget_show (button);
717     g_object_set_data(G_OBJECT(dialog), "fileselector", button);
718 
719     GtkWidget *filter_box = rfm_hbox_new (FALSE, 0);
720     gtk_box_pack_start (GTK_BOX (vbox7a), filter_box, TRUE, FALSE, 5);
721 
722     gchar *text=g_strdup_printf("%s ", _("Filter:"));
723     GtkWidget *filter_label = gtk_label_new (text);
724     g_free(text);
725     gtk_widget_show (filter_label);
726     gtk_box_pack_start (GTK_BOX (filter_box), filter_label, FALSE, FALSE, 0);
727 
728 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
729     // this is deprecated...
730     GtkWidget *filter_combo = gtk_combo_box_entry_new ();
731 #else
732     GtkWidget *filter_combo = gtk_combo_box_new_with_entry ();
733 #endif
734     g_object_set_data (G_OBJECT (filter_combo), "GladeParentKey", filter_combo);
735     gtk_widget_show (filter_combo);
736     gtk_box_pack_start (GTK_BOX (filter_box), filter_combo, FALSE, TRUE, 0);
737     g_object_set_data(G_OBJECT(dialog), "filter_combo", filter_combo);
738 
739 
740     GtkWidget *togglebutton2 = rfm_toggle_button("xffm/stock_dialog-question", "");
741     gtk_box_pack_start (GTK_BOX (filter_box), togglebutton2, FALSE, FALSE, 0);
742     g_object_set_data(G_OBJECT(dialog), "togglebutton2", togglebutton2);
743     rfm_add_custom_tooltip(togglebutton2, NULL,  _(filter_text_help));
744     g_signal_connect (togglebutton2,
745                       "toggled", G_CALLBACK (on_help_filter),
746 		      (gpointer) dialog);
747 
748     GtkWidget *hbox17 = rfm_hbox_new (FALSE, 0);
749     gtk_widget_show (hbox17);
750     gtk_box_pack_start (GTK_BOX (vbox7a), hbox17, TRUE, FALSE, 0);
751 
752     GtkWidget *left_options_vbox = rfm_vbox_new (FALSE, 0);
753     gtk_box_pack_start (GTK_BOX (hbox17), left_options_vbox, FALSE, FALSE, 0);
754     GtkWidget *center_options_vbox = rfm_vbox_new (FALSE, 0);
755     gtk_box_pack_start (GTK_BOX (hbox17), center_options_vbox, FALSE, FALSE, 0);
756     GtkWidget *right_options_vbox = rfm_vbox_new (FALSE, 0);
757     gtk_box_pack_start (GTK_BOX (hbox17), right_options_vbox, FALSE, FALSE, 0);
758 
759     /// option -r "recursive"
760     gtk_toggle_button_set_active(add_option_spin(dialog, left_options_vbox, "recursive", NULL, _("Recursive"), 0), default_recursive);
761 
762     /// option -D "recursiveH"
763     gtk_toggle_button_set_active(add_option_spin(dialog, left_options_vbox, "recursiveH", NULL, _("Find hidden files and directories"), 0), default_recursiveH);
764 
765     /// option -a "xdev"
766     gtk_toggle_button_set_active(add_option_spin(dialog, left_options_vbox, "xdev", NULL, _("Stay on single filesystem"), 0), default_xdev);
767 
768     /// option "upper_limit_spin" (only in gtk dialog)
769     text = g_strdup_printf("%s (%s)", _("Results"), _("Upper limit"));
770     add_option_spin(dialog, left_options_vbox, NULL, "upper_limit_spin", text, result_limit);
771     g_free(text);
772 
773     // option -s +KByte "size_greater", "size_greater_spin"
774     text = g_strdup_printf("%s (%s)", _("At Least"), _("kBytes"));
775     add_option_spin(dialog, center_options_vbox, "size_greater", "size_greater_spin", text, size_greater);
776     g_free(text);
777 
778     // option -s -KByte "size_smaller", "size_smaller_spin"
779     text = g_strdup_printf("%s (%s)", _("At Most"), _("kBytes"));
780     add_option_spin(dialog, center_options_vbox, "size_smaller", "size_smaller_spin", text, size_smaller);
781     g_free(text);
782 
783     GSList *slist;
784     // option -u uid "uid" "uid_combo"
785     slist = get_user_slist();
786     add_option_combo(dialog, center_options_vbox, "uid", "uid_combo", _("User"), slist);
787     slist = free_string_slist(slist);
788 
789     // option -g gid "gid" "gid_combo"
790     slist = get_group_slist();
791     add_option_combo(dialog, center_options_vbox, "gid", "gid_combo", _("Group"), slist);
792     slist = free_string_slist(slist);
793 
794     // option -o octal "octal_p" "permissions_entry"
795     add_option_entry(dialog, center_options_vbox, "octal_p", "permissions_entry", _("Octal Permissions"), "0666");
796     GtkWidget *entry = g_object_get_data(G_OBJECT(dialog), "permissions_entry");
797     gtk_widget_set_size_request (entry, 75, -1);
798 
799     // option -p suid | exe
800     add_option_radio2(dialog, center_options_vbox, "suidexe", "suid_radio", "exe_radio", _("SUID"), _("Executable"));
801 
802 
803     // option -M -A -C
804     radio_t *radio_p = create_radios(dialog, right_options_vbox);
805     // radio_p freed on destroy event for dialog.
806 
807     // option -k minutes "last_minutes", "last_minutes_spin"
808     radio_p->toggle[0] = add_option_spin(dialog, right_options_vbox, "last_minutes", "last_minutes_spin", _("Minutes"), last_minutes);
809     g_signal_connect (G_OBJECT (radio_p->toggle[0]), "toggled", G_CALLBACK (sensitivize_radio), radio_p);
810 
811    // option -h hours "last_hours", "last_hours_spin"
812     radio_p->toggle[1] = add_option_spin(dialog, right_options_vbox, "last_hours", "last_hours_spin", _("Hours"), last_hours);
813     g_signal_connect (G_OBJECT (radio_p->toggle[1]), "toggled", G_CALLBACK (sensitivize_radio), radio_p);
814 
815     // option -d days "last_days", "last_days_spin"
816     radio_p->toggle[2] = add_option_spin(dialog, right_options_vbox, "last_days", "last_days_spin", _("Days"), last_days);
817     g_signal_connect (G_OBJECT (radio_p->toggle[2]), "toggled", G_CALLBACK (sensitivize_radio), radio_p);
818 
819     // option -m months "last_months", "last_months_spin"
820     radio_p->toggle[3] = add_option_spin(dialog, right_options_vbox, "last_months", "last_months_spin", _("Months"), last_months);
821     g_signal_connect (G_OBJECT (radio_p->toggle[3]), "toggled", G_CALLBACK (sensitivize_radio), radio_p);
822 
823      ///////////
824 
825 
826     GtkWidget *hbox21 = rfm_hbox_new (FALSE, 0);
827     gtk_widget_show (hbox21);
828     gtk_box_pack_start (GTK_BOX (left_options_vbox), hbox21, TRUE, FALSE, 0);
829 
830     GtkWidget *label37 = gtk_label_new (_("File type : "));
831     gtk_widget_show (label37);
832     gtk_box_pack_start (GTK_BOX (hbox21), label37, FALSE, FALSE, 0);
833 
834 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
835     // this is deprecated...
836     GtkWidget *file_type_om =  gtk_combo_box_new_text();
837 #else
838     GtkWidget *file_type_om =  gtk_combo_box_text_new();
839 #endif
840     gtk_widget_show (file_type_om);
841     gtk_box_pack_start (GTK_BOX (hbox21), file_type_om, TRUE, TRUE, 0);
842     g_object_set_data(G_OBJECT(dialog), "file_type_om", file_type_om);
843 
844     ////////////////  grep options.... /////////////////////////
845 
846     t=g_strdup_printf("<b>%s</b>", _("Contains"));
847     GtkWidget *contains_label = gtk_label_new (t);
848     g_free(t);
849     gtk_widget_show (contains_label);
850     gtk_box_pack_start (GTK_BOX (top_pane_vbox), contains_label, FALSE, FALSE, 1);
851     gtk_label_set_use_markup (GTK_LABEL (contains_label), TRUE);
852 
853     GtkWidget *hbox26 = rfm_hbox_new (FALSE, 0);
854     gtk_widget_show (hbox26);
855     gtk_box_pack_start (GTK_BOX (top_pane_vbox), hbox26, FALSE, FALSE, 0);
856     gtk_container_set_border_width (GTK_CONTAINER (hbox26), 2);
857 
858     GtkWidget *vbox8 = rfm_vbox_new (FALSE, 5);
859     gtk_widget_show (vbox8);
860     gtk_box_pack_start (GTK_BOX (hbox26), vbox8, TRUE, TRUE, 0);
861     gtk_container_set_border_width (GTK_CONTAINER (vbox8), 5);
862 
863     GtkWidget *grep_box = rfm_hbox_new (FALSE, 0);
864     gtk_box_pack_start (GTK_BOX (vbox8), grep_box, FALSE, FALSE, 0);
865 
866     t=g_strdup_printf("%s: ",_("Contains the text"));
867     GtkWidget *grep_label = gtk_label_new (t);
868     g_free(t);
869     gtk_widget_show (grep_label);
870     gtk_box_pack_start (GTK_BOX (grep_box), grep_label, FALSE, FALSE, 0);
871 
872 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
873     GtkWidget *grep_combo = gtk_combo_box_entry_new ();
874 #else
875     GtkWidget *grep_combo = gtk_combo_box_new_with_entry ();
876 #endif
877     g_object_set_data (G_OBJECT (grep_combo), "GladeParentKey", grep_combo);
878     gtk_widget_show (grep_combo);
879     gtk_box_pack_start (GTK_BOX (grep_box), grep_combo, FALSE, FALSE, 5);
880     gtk_widget_set_sensitive (grep_combo, have_grep);
881     g_object_set_data(G_OBJECT(dialog), "grep_combo", grep_combo);
882 
883     GtkWidget *togglebutton3 = rfm_toggle_button ("xffm/stock_dialog-question", "");
884     gtk_box_pack_start (GTK_BOX (grep_box), togglebutton3, FALSE, FALSE, 0);
885     g_object_set_data(G_OBJECT(dialog), "togglebutton3", togglebutton3);
886     rfm_add_custom_tooltip(togglebutton3, NULL, _(grep_text_help));
887     g_signal_connect (togglebutton3,
888                       "toggled", G_CALLBACK (on_help_grep),
889 		      (gpointer) dialog);
890 
891     GtkWidget *hbox20 = rfm_hbox_new (FALSE, 0);
892     gtk_widget_show (hbox20);
893     gtk_box_pack_start (GTK_BOX (vbox8), hbox20, FALSE, FALSE, 0);
894 
895     GtkWidget *vbox13 = rfm_vbox_new (FALSE, 0);
896     gtk_box_pack_start (GTK_BOX (hbox20), vbox13, TRUE, TRUE, 0);
897 
898     GtkWidget *case_sensitive = gtk_check_button_new_with_mnemonic (_("Case Sensitive"));
899     gtk_widget_show (case_sensitive);
900     gtk_box_pack_start (GTK_BOX (vbox13), case_sensitive, FALSE, FALSE, 0);
901     gtk_widget_set_sensitive (case_sensitive, FALSE);
902     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (case_sensitive), default_case_sensitive);
903     g_object_set_data(G_OBJECT(dialog), "case_sensitive", case_sensitive);
904 
905     GtkWidget *ext_regexp = gtk_check_button_new_with_mnemonic (_("Extended regexp"));
906     gtk_widget_show (ext_regexp);
907     gtk_box_pack_start (GTK_BOX (vbox13), ext_regexp, FALSE, FALSE, 0);
908     gtk_widget_set_sensitive (ext_regexp, FALSE);
909     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ext_regexp), default_ext_regexp);
910     g_object_set_data(G_OBJECT(dialog), "ext_regexp", ext_regexp);
911 
912     GtkWidget *look_in_binaries = gtk_check_button_new_with_mnemonic (_("Include binary files"));
913     gtk_widget_show (look_in_binaries);
914     gtk_box_pack_start (GTK_BOX (vbox13), look_in_binaries, FALSE, FALSE, 0);
915     gtk_widget_set_sensitive (look_in_binaries, FALSE);
916     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (look_in_binaries), default_look_in_binaries);
917     g_object_set_data(G_OBJECT(dialog), "look_in_binaries", look_in_binaries);
918 
919     GtkWidget *line_count = gtk_check_button_new_with_mnemonic (_("Line Count"));
920     // XXX: (FIXME) this option (-c) does not work in fgr...
921     //    gtk_widget_show (line_count);
922     gtk_box_pack_start (GTK_BOX (vbox13), line_count, FALSE, FALSE, 0);
923     gtk_widget_set_sensitive (line_count, FALSE);
924     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (line_count), default_line_count);
925     g_object_set_data(G_OBJECT(dialog), "line_count", line_count);
926 
927 
928     GtkWidget *hbox28 = rfm_hbox_new (FALSE, 0);
929     gtk_box_pack_start (GTK_BOX (top_pane_vbox), hbox28, TRUE, TRUE, 0);
930     gtk_container_set_border_width (GTK_CONTAINER (hbox28), 2);
931 
932     GtkWidget *vbox11 = rfm_vbox_new (FALSE, 0);
933     gtk_widget_show (vbox11);
934     gtk_box_pack_start (GTK_BOX (hbox28), vbox11, TRUE, TRUE, 0);
935 
936 
937 
938     GtkWidget *hbox24 = rfm_hbox_new (FALSE, 0);
939     gtk_box_pack_start (GTK_BOX (vbox11), hbox24, FALSE, FALSE, 0);
940     gtk_container_set_border_width (GTK_CONTAINER (hbox24), 5);
941 
942     GtkWidget *label40 = gtk_label_new ("");
943     t=g_strdup_printf("<b>%s</b>: ", _("Match"));
944     gtk_label_set_markup (GTK_LABEL(label40), t);
945     g_free(t);
946     gtk_widget_show (label40);
947     gtk_box_pack_start (GTK_BOX (hbox24), label40, FALSE, FALSE, 0);
948     gtk_widget_set_sensitive (label40, FALSE);
949     g_object_set_data(G_OBJECT(dialog), "label40", label40);
950 
951     GSList *anywhere_group = NULL;
952     GtkWidget *anywhere = gtk_radio_button_new_with_mnemonic (NULL, _("Anywhere"));
953     gtk_widget_show (anywhere);
954     gtk_box_pack_start (GTK_BOX (hbox24), anywhere, FALSE, FALSE, 0);
955     gtk_radio_button_set_group (GTK_RADIO_BUTTON (anywhere), anywhere_group);
956     g_object_set_data(G_OBJECT(dialog), "anywhere", anywhere);
957     anywhere_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (anywhere));
958     gtk_widget_set_sensitive (anywhere, FALSE);
959     if (default_anywhere) {
960 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (anywhere), default_anywhere);
961     }
962 
963 
964     GtkWidget *match_words = gtk_radio_button_new_with_mnemonic (NULL, _("Whole words only"));
965     gtk_widget_show (match_words);
966     gtk_box_pack_start (GTK_BOX (hbox24), match_words, FALSE, FALSE, 0);
967     gtk_radio_button_set_group (GTK_RADIO_BUTTON (match_words), anywhere_group);
968     g_object_set_data(G_OBJECT(dialog), "match_words", match_words);
969     anywhere_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (match_words));
970     gtk_widget_set_sensitive (match_words, FALSE);
971     if (default_match_words) {
972 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (match_words), default_match_words);
973     }
974 
975 
976     GtkWidget *match_lines = gtk_radio_button_new_with_mnemonic (NULL, _("lines"));
977     gtk_widget_show (match_lines);
978     gtk_box_pack_start (GTK_BOX (hbox24), match_lines, FALSE, FALSE, 0);
979     gtk_radio_button_set_group (GTK_RADIO_BUTTON (match_lines), anywhere_group);
980     g_object_set_data(G_OBJECT(dialog), "match_lines", match_lines);
981     anywhere_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (match_lines));
982     gtk_widget_set_sensitive (match_lines, FALSE);
983     if (default_match_lines) {
984 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (match_lines), default_match_lines);
985     }
986 
987     GtkWidget *match_no_match = gtk_radio_button_new_with_mnemonic (NULL, _("No match"));
988     gtk_widget_show (match_no_match);
989     gtk_box_pack_start (GTK_BOX (hbox24), match_no_match, FALSE, FALSE, 0);
990     gtk_radio_button_set_group (GTK_RADIO_BUTTON (match_no_match), anywhere_group);
991     g_object_set_data(G_OBJECT(dialog), "match_no_match", match_no_match);
992     anywhere_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (match_no_match));
993     gtk_widget_set_sensitive (match_no_match, FALSE);
994     if (default_match_no_match) {
995 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (match_no_match), default_match_no_match);
996     }
997 
998     gtk_widget_show(hbox);
999     gtk_widget_show (path_box);
1000     gtk_widget_show (filter_box);
1001     gtk_widget_show (right_options_vbox);
1002     gtk_widget_show (center_options_vbox);
1003     gtk_widget_show (left_options_vbox);
1004     gtk_widget_show (grep_box);
1005     gtk_widget_show (vbox13);
1006     gtk_widget_show (hbox28);
1007     gtk_widget_show (hbox24);
1008     gtk_widget_show(top_pane_vbox);
1009 
1010 
1011     GtkWidget *hbuttonbox2 = rfm_hbutton_box_new ();
1012     gtk_widget_show (hbuttonbox2);
1013     gtk_box_pack_start (GTK_BOX (main_vbox), hbuttonbox2, FALSE, TRUE, 0);
1014     gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox2), 3);
1015     gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_EDGE);
1016 
1017     GtkWidget *button_image;
1018     gchar *g=g_strdup_printf("%s/%s", _("Find"), _("Close"));
1019     GtkWidget *find_button =
1020         rfm_dialog_button("xffm/stock_find", g);
1021     g_free(g);
1022     g_object_set_data(G_OBJECT(dialog), "find_button", find_button);
1023     g_object_set_data(G_OBJECT(find_button), "dialog", dialog);
1024 
1025     GtkWidget *apply_button =
1026         rfm_dialog_button("xffm/stock_find", _("Find"));
1027     g_object_set_data(G_OBJECT(dialog), "apply_button", apply_button);
1028     g_object_set_data(G_OBJECT(apply_button), "dialog", dialog);
1029 
1030     GtkWidget *cancel_button =
1031         rfm_dialog_button("xffm/stock_cancel", _("Cancel"));
1032     g_object_set_data(G_OBJECT(dialog), "cancel_button", cancel_button);
1033     g_object_set_data(G_OBJECT(cancel_button), "dialog", dialog);
1034     gtk_widget_set_sensitive(cancel_button, FALSE);
1035 
1036 
1037     GtkWidget *clear_button =
1038         rfm_dialog_button("xffm/stock_clear", _("Clear"));
1039     g_object_set_data(G_OBJECT(dialog), "clear_button", clear_button);
1040     g_object_set_data(G_OBJECT(clear_button), "dialog", dialog);
1041     g_signal_connect (G_OBJECT (clear_button), "clicked",
1042 	    G_CALLBACK (clear_text), NULL);
1043 
1044     GtkWidget *close_button =
1045         rfm_dialog_button("xffm/stock_close", _("Close"));
1046     g_object_set_data(G_OBJECT(dialog), "close_button", close_button);
1047     g_object_set_data(G_OBJECT(close_button), "dialog", dialog);
1048 
1049 
1050     gtk_widget_show (find_button);
1051     gtk_container_add (GTK_CONTAINER (hbuttonbox2), find_button);
1052     gtk_widget_set_can_default(find_button, TRUE);
1053 
1054     gtk_widget_show (apply_button);
1055     gtk_container_add (GTK_CONTAINER (hbuttonbox2), apply_button);
1056     gtk_widget_set_can_default(apply_button, TRUE);
1057 
1058     gtk_widget_show (clear_button);
1059     gtk_container_add (GTK_CONTAINER (hbuttonbox2), clear_button);
1060 
1061     gtk_widget_show (cancel_button);
1062     gtk_container_add (GTK_CONTAINER (hbuttonbox2), cancel_button);
1063 
1064     const gchar *editor = getenv("EDITOR");
1065     if (editor && strlen(editor)){
1066 	gchar *basename = g_strdup(editor);
1067 	if (strchr(basename, ' ')) *strchr(basename, ' ') = 0;
1068 	gchar *editor_path = g_find_program_in_path(basename);
1069 	if (editor_path){
1070 	    gchar *iconpath=g_strdup(basename);
1071 	    GdkPixbuf *pix = rfm_get_pixbuf (iconpath, SMALL_ICON_SIZE); //refs
1072 	    if (!pix) iconpath = g_strdup("xffm/stock_edit");
1073             else g_object_unref(pix);
1074 
1075 	    GtkWidget *edit_button =
1076                 rfm_dialog_button(iconpath, _("Edit"));
1077  	    g_free(iconpath);
1078 	    g_object_set_data(G_OBJECT(dialog), "edit_button", edit_button);
1079 	    g_object_set_data(G_OBJECT(edit_button), "dialog", dialog);
1080 	    g_signal_connect (G_OBJECT (edit_button), "clicked", G_CALLBACK (edit_command), NULL);
1081 	    gtk_widget_show(edit_button);
1082 	    gtk_container_add (GTK_CONTAINER (hbuttonbox2), edit_button);
1083 	    g_free(editor_path);
1084 	}
1085 	g_free(basename);
1086     } else {
1087 	NOOP("getenv(\"EDITOR\") = %s\n", editor);
1088     }
1089 
1090 
1091     gtk_widget_show (close_button);
1092     gtk_container_add (GTK_CONTAINER (hbuttonbox2), close_button);
1093     gtk_widget_add_accelerator (close_button, "clicked", accel_group, GDK_KEY_Escape, 0, GTK_ACCEL_VISIBLE);
1094 
1095     gtk_widget_grab_default (find_button);
1096     gtk_window_add_accel_group (GTK_WINDOW (dialog), accel_group);
1097 
1098     gtk_widget_realize(dialog);
1099 
1100     GtkAllocation label_allocation;
1101     GtkAllocation allocation;
1102     gtk_widget_get_allocation(top_pane_vbox, &allocation);
1103     gtk_widget_get_allocation(path_label, &label_allocation);
1104     // width will be the smaller of the two.
1105     gint width = (geometry.max_width < allocation.width)?
1106 	geometry.max_width: allocation.width;
1107     NOOP(stderr, "max w= %d, top_pane w= %d, label w=%d\n",
1108 	    geometry.max_width,
1109 	     allocation.width,
1110 	    label_allocation.width);
1111     gint combo_width;
1112     combo_width = width - label_allocation.width - 120;
1113     if (combo_width > 100){
1114 	gtk_widget_set_size_request (path_combo, combo_width, -1);
1115     }
1116     gtk_widget_get_allocation(filter_label, &label_allocation);
1117     combo_width = width - label_allocation.width - 120;
1118     if (combo_width > 100){
1119 	gtk_widget_set_size_request (filter_combo, combo_width, -1);
1120     }
1121     gtk_widget_get_allocation(grep_label, &label_allocation);
1122     combo_width = width - label_allocation.width - 120;
1123     if (combo_width > 100){
1124 	gtk_widget_set_size_request (grep_combo, combo_width, -1);
1125     }
1126 
1127     // This will be constrained to the maximum width set by geometry hints:
1128 
1129 #if GTK_MAJOR_VERSION==2
1130     gtk_window_set_default_size (GTK_WINDOW (dialog), allocation.width+50,  allocation.height+75);
1131 #else
1132     gtk_window_set_default_geometry(GTK_WINDOW (dialog),  allocation.width+50,  allocation.height+75);
1133 #endif
1134 
1135 
1136     gtk_paned_set_position (GTK_PANED (vpane), 1000);
1137 
1138 
1139     return dialog;
1140 }
1141