1 /* Find file command for the Midnight Commander
2 Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2006, 2007 Free Software Foundation, Inc.
4 Written 1995 by Miguel de Icaza
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
23 * \brief Source: Find file command
35 #include "lib/global.h"
37 #include "lib/tty/tty.h"
38 #include "lib/tty/key.h"
40 #include "lib/search.h"
41 #include "lib/mcconfig.h"
42 #include "lib/strutil.h"
43 #include "lib/widget.h"
44 #include "lib/vfs/mc-vfs/vfs.h"
45 #include "lib/util.h" /* canonicalize_pathname() */
47 #include "src/setup.h" /* verbose */
48 #include "src/history.h" /* MC_HISTORY_SHARED_SEARCH */
49 #include "src/main.h" /* do_cd */
52 #include "cmd.h" /* view_file_at_line */
53 #include "midnight.h" /* current_panel */
55 #include "layout.h" /* mc_refresh() */
59 /*** global variables ****************************************************************************/
61 /*** file scope macro definitions ****************************************************************/
63 /* Size of the find window */
64 #define FIND2_Y (LINES - 4)
66 #define FIND2_X_USE (FIND2_X - 20)
68 /*** file scope type declarations ****************************************************************/
70 /* A couple of extra messages we need */
87 /* find file options */
90 /* file name options */
91 gboolean file_case_sens
;
92 gboolean file_pattern
;
95 gboolean file_all_charsets
;
97 /* file content options */
99 gboolean content_case_sens
;
100 gboolean content_regexp
;
101 gboolean content_first_hit
;
102 gboolean content_whole_words
;
103 gboolean content_all_charsets
;
105 /* whether use ignore dirs or not */
106 gboolean ignore_dirs_enable
;
107 /* list of directories to be ignored, separated by ':' */
109 } find_file_options_t
;
111 /*** file scope variables ************************************************************************/
113 /* Parsed ignore dirs */
114 static char **find_ignore_dirs
= NULL
;
116 /* Size of the find parameters window */
118 static int FIND_Y
= 19;
120 static int FIND_Y
= 18;
122 static int FIND_X
= 68;
124 static int FIND2_X
= 64;
126 /* static variables to remember find parameters */
127 static WInput
*in_start
; /* Start path */
128 static WInput
*in_name
; /* Filename */
129 static WInput
*in_with
; /* Text */
130 static WInput
*in_ignore
;
131 static WLabel
*content_label
; /* 'Content:' label */
132 static WCheck
*file_case_sens_cbox
; /* "case sensitive" checkbox */
133 static WCheck
*file_pattern_cbox
; /* File name is glob or regexp */
134 static WCheck
*recursively_cbox
;
135 static WCheck
*skip_hidden_cbox
;
136 static WCheck
*content_use_cbox
; /* Take into account the Content field */
137 static WCheck
*content_case_sens_cbox
; /* "case sensitive" checkbox */
138 static WCheck
*content_regexp_cbox
; /* "find regular expression" checkbox */
139 static WCheck
*content_first_hit_cbox
; /* "First hit" checkbox" */
140 static WCheck
*content_whole_words_cbox
; /* "whole words" checkbox */
142 static WCheck
*file_all_charsets_cbox
;
143 static WCheck
*content_all_charsets_cbox
;
145 static WCheck
*ignore_dirs_cbox
;
147 static gboolean running
= FALSE
; /* nice flag */
148 static char *find_pattern
= NULL
; /* Pattern to search */
149 static char *content_pattern
= NULL
; /* pattern to search inside files; if
150 content_regexp_flag is true, it contains the
151 regex pattern, else the search string. */
152 static unsigned long matches
; /* Number of matches */
153 static gboolean is_start
= FALSE
; /* Status of the start/stop toggle button */
154 static char *old_dir
= NULL
;
156 /* Where did we stop */
158 static int last_line
;
161 static size_t ignore_count
= 0;
163 static Dlg_head
*find_dlg
; /* The dialog */
164 static WButton
*stop_button
; /* pointer to the stop button */
165 static WLabel
*status_label
; /* Finished, Searching etc. */
166 static WLabel
*found_num_label
; /* Number of found items */
167 static WListbox
*find_list
; /* Listbox with the file list */
169 /* This keeps track of the directory stack */
170 #if GLIB_CHECK_VERSION (2, 14, 0)
171 static GQueue dir_queue
= G_QUEUE_INIT
;
173 typedef struct dir_stack
176 struct dir_stack
*prev
;
179 static dir_stack
*dir_stack_base
= 0;
180 #endif /* GLIB_CHECK_VERSION */
186 int len
; /* length including space and brackets */
190 {N_("&Suspend"), 11, 29},
191 {N_("Con&tinue"), 12, 29},
192 {N_("&Chdir"), 11, 3},
193 {N_("&Again"), 9, 17},
194 {N_("&Quit"), 8, 43},
195 {N_("Pane&lize"), 12, 3},
196 {N_("&View - F3"), 13, 20},
197 {N_("&Edit - F4"), 13, 38}
201 static find_file_options_t options
= {
202 TRUE
, TRUE
, TRUE
, FALSE
, FALSE
,
203 FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
206 static char *in_start_dir
= INPUT_LAST_TEXT
;
208 static mc_search_t
*search_file_handle
= NULL
;
209 static mc_search_t
*search_content_handle
= NULL
;
211 /*** file scope functions ************************************************************************/
214 parse_ignore_dirs (const char *ignore_dirs
)
216 size_t r
= 0, w
= 0; /* read and write iterators */
218 if (!options
.ignore_dirs_enable
|| ignore_dirs
== NULL
|| ignore_dirs
[0] == '\0')
221 find_ignore_dirs
= g_strsplit (ignore_dirs
, ":", -1);
223 /* Values like '/foo::/bar: produce holes in list.
224 * Find and remove them */
225 for (; find_ignore_dirs
[r
] != NULL
; r
++)
227 if (find_ignore_dirs
[r
][0] == '\0')
229 /* empty entry -- skip it */
230 g_free (find_ignore_dirs
[r
]);
231 find_ignore_dirs
[r
] = NULL
;
237 /* copy entry to the previous free array cell */
238 find_ignore_dirs
[w
] = find_ignore_dirs
[r
];
239 find_ignore_dirs
[r
] = NULL
;
242 canonicalize_pathname (find_ignore_dirs
[w
]);
243 if (find_ignore_dirs
[w
][0] != '\0')
247 g_free (find_ignore_dirs
[w
]);
248 find_ignore_dirs
[w
] = NULL
;
252 if (find_ignore_dirs
[0] == NULL
)
254 g_strfreev (find_ignore_dirs
);
255 find_ignore_dirs
= NULL
;
259 /* --------------------------------------------------------------------------------------------- */
262 find_load_options (void)
264 static gboolean loaded
= FALSE
;
272 options
.file_case_sens
=
273 mc_config_get_bool (mc_main_config
, "FindFile", "file_case_sens", TRUE
);
274 options
.file_pattern
=
275 mc_config_get_bool (mc_main_config
, "FindFile", "file_shell_pattern", TRUE
);
276 options
.find_recurs
= mc_config_get_bool (mc_main_config
, "FindFile", "file_find_recurs", TRUE
);
277 options
.skip_hidden
=
278 mc_config_get_bool (mc_main_config
, "FindFile", "file_skip_hidden", FALSE
);
279 options
.file_all_charsets
=
280 mc_config_get_bool (mc_main_config
, "FindFile", "file_all_charsets", FALSE
);
281 options
.content_use
= mc_config_get_bool (mc_main_config
, "FindFile", "content_use", TRUE
);
282 options
.content_case_sens
=
283 mc_config_get_bool (mc_main_config
, "FindFile", "content_case_sens", TRUE
);
284 options
.content_regexp
=
285 mc_config_get_bool (mc_main_config
, "FindFile", "content_regexp", FALSE
);
286 options
.content_first_hit
=
287 mc_config_get_bool (mc_main_config
, "FindFile", "content_first_hit", FALSE
);
288 options
.content_whole_words
=
289 mc_config_get_bool (mc_main_config
, "FindFile", "content_whole_words", FALSE
);
290 options
.content_all_charsets
=
291 mc_config_get_bool (mc_main_config
, "FindFile", "content_all_charsets", FALSE
);
292 options
.ignore_dirs_enable
=
293 mc_config_get_bool (mc_main_config
, "FindFile", "ignore_dirs_enable", TRUE
);
295 /* Back compatibility: try load old parameter at first */
296 ignore_dirs
= mc_config_get_string (mc_main_config
, "Misc", "find_ignore_dirs", "");
297 mc_config_del_key (mc_main_config
, "Misc", "find_ignore_dirs");
299 /* Then load new parameters */
300 options
.ignore_dirs
= mc_config_get_string (mc_main_config
, "FindFile", "ignore_dirs", "");
301 if (options
.ignore_dirs
[0] != '\0')
302 g_free (ignore_dirs
);
305 g_free (options
.ignore_dirs
);
306 options
.ignore_dirs
= ignore_dirs
;
309 if (options
.ignore_dirs
[0] == '\0')
311 g_free (options
.ignore_dirs
);
312 options
.ignore_dirs
= NULL
;
316 /* --------------------------------------------------------------------------------------------- */
319 find_save_options (void)
321 mc_config_set_bool (mc_main_config
, "FindFile", "file_case_sens", options
.file_case_sens
);
322 mc_config_set_bool (mc_main_config
, "FindFile", "file_shell_pattern", options
.file_pattern
);
323 mc_config_set_bool (mc_main_config
, "FindFile", "file_find_recurs", options
.find_recurs
);
324 mc_config_set_bool (mc_main_config
, "FindFile", "file_skip_hidden", options
.skip_hidden
);
325 mc_config_set_bool (mc_main_config
, "FindFile", "file_all_charsets", options
.file_all_charsets
);
326 mc_config_set_bool (mc_main_config
, "FindFile", "content_use", options
.content_use
);
327 mc_config_set_bool (mc_main_config
, "FindFile", "content_case_sens", options
.content_case_sens
);
328 mc_config_set_bool (mc_main_config
, "FindFile", "content_regexp", options
.content_regexp
);
329 mc_config_set_bool (mc_main_config
, "FindFile", "content_first_hit", options
.content_first_hit
);
330 mc_config_set_bool (mc_main_config
, "FindFile", "content_whole_words",
331 options
.content_whole_words
);
332 mc_config_set_bool (mc_main_config
, "FindFile", "content_all_charsets",
333 options
.content_all_charsets
);
334 mc_config_set_bool (mc_main_config
, "FindFile", "ignore_dirs_enable",
335 options
.ignore_dirs_enable
);
336 mc_config_set_string (mc_main_config
, "FindFile", "ignore_dirs", options
.ignore_dirs
);
339 /* --------------------------------------------------------------------------------------------- */
342 add_to_list (const char *text
, void *data
)
344 return listbox_add_item (find_list
, LISTBOX_APPEND_AT_END
, 0, text
, data
);
347 /* --------------------------------------------------------------------------------------------- */
350 stop_idle (void *data
)
352 set_idle_proc (data
, 0);
355 /* --------------------------------------------------------------------------------------------- */
358 status_update (const char *text
)
360 label_set_text (status_label
, text
);
363 /* --------------------------------------------------------------------------------------------- */
366 found_num_update (void)
368 char buffer
[BUF_TINY
];
369 g_snprintf (buffer
, sizeof (buffer
), _("Found: %ld"), matches
);
370 label_set_text (found_num_label
, buffer
);
373 /* --------------------------------------------------------------------------------------------- */
376 get_list_info (char **file
, char **dir
)
378 listbox_get_current (find_list
, file
, (void **) dir
);
381 /* --------------------------------------------------------------------------------------------- */
382 /** check regular expression */
385 find_check_regexp (const char *r
)
388 gboolean regexp_ok
= FALSE
;
390 search
= mc_search_new (r
, -1);
394 search
->search_type
= MC_SEARCH_T_REGEX
;
395 regexp_ok
= mc_search_prepare (search
);
396 mc_search_free (search
);
402 /* --------------------------------------------------------------------------------------------- */
404 * Callback for the parameter dialog.
405 * Validate regex, prevent closing the dialog if it's invalid.
409 find_parm_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
414 if (sender
== (Widget
*) content_use_cbox
)
416 gboolean disable
= !(content_use_cbox
->state
& C_BOOL
);
418 widget_disable (content_label
->widget
, disable
);
419 send_message ((Widget
*) content_label
, WIDGET_DRAW
, 0);
420 widget_disable (in_with
->widget
, disable
);
421 send_message ((Widget
*) in_with
, WIDGET_DRAW
, 0);
422 widget_disable (content_first_hit_cbox
->widget
, disable
);
423 send_message ((Widget
*) content_first_hit_cbox
, WIDGET_DRAW
, 0);
424 widget_disable (content_regexp_cbox
->widget
, disable
);
425 send_message ((Widget
*) content_regexp_cbox
, WIDGET_DRAW
, 0);
426 widget_disable (content_case_sens_cbox
->widget
, disable
);
427 send_message ((Widget
*) content_case_sens_cbox
, WIDGET_DRAW
, 0);
429 widget_disable (content_all_charsets_cbox
->widget
, disable
);
430 send_message ((Widget
*) content_all_charsets_cbox
, WIDGET_DRAW
, 0);
432 widget_disable (content_whole_words_cbox
->widget
, disable
);
433 send_message ((Widget
*) content_whole_words_cbox
, WIDGET_DRAW
, 0);
438 if (sender
== (Widget
*) ignore_dirs_cbox
)
440 gboolean disable
= !(ignore_dirs_cbox
->state
& C_BOOL
);
442 widget_disable (in_ignore
->widget
, disable
);
443 send_message ((Widget
*) in_ignore
, WIDGET_DRAW
, 0);
448 return MSG_NOT_HANDLED
;
452 if (h
->ret_value
!= B_ENTER
)
455 /* check filename regexp */
456 if (!(file_pattern_cbox
->state
& C_BOOL
)
457 && (in_name
->buffer
[0] != '\0') && !find_check_regexp (in_name
->buffer
))
459 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
460 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
461 dlg_select_widget (in_name
);
465 /* check content regexp */
466 if ((content_use_cbox
->state
& C_BOOL
) && (content_regexp_cbox
->state
& C_BOOL
)
467 && (in_with
->buffer
[0] != '\0') && !find_check_regexp (in_with
->buffer
))
469 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
470 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
471 dlg_select_widget (in_with
);
478 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
482 /* --------------------------------------------------------------------------------------------- */
484 * find_parameters: gets information from the user
486 * If the return value is TRUE, then the following holds:
488 * START_DIR, IGNORE_FIR and PATTERN are pointers to char * and upon return they
489 * contain the information provided by the user.
491 * CONTENT holds a strdup of the contents specified by the user if he
492 * asked for them or 0 if not (note, this is different from the
493 * behavior for the other two parameters.
498 find_parameters (char **start_dir
, char **ignore_dirs
, char **pattern
, char **content
)
500 gboolean return_value
;
503 const char *file_case_label
= N_("Cas&e sensitive");
504 const char *file_pattern_label
= N_("&Using shell patterns");
505 const char *file_recurs_label
= N_("&Find recursively");
506 const char *file_skip_hidden_label
= N_("S&kip hidden");
508 const char *file_all_charsets_label
= N_("&All charsets");
512 const char *content_use_label
= N_("Sea&rch for content");
513 const char *content_case_label
= N_("Case sens&itive");
514 const char *content_regexp_label
= N_("Re&gular expression");
515 const char *content_first_hit_label
= N_("Fir&st hit");
516 const char *content_whole_words_label
= N_("&Whole words");
518 const char *content_all_charsets_label
= N_("A&ll charsets");
521 const char *buts
[] = { N_("&OK"), N_("&Cancel"), N_("&Tree") };
530 int i
= sizeof (buts
) / sizeof (buts
[0]);
532 buts
[i
] = _(buts
[i
]);
534 file_case_label
= _(file_case_label
);
535 file_pattern_label
= _(file_pattern_label
);
536 file_recurs_label
= _(file_recurs_label
);
537 file_skip_hidden_label
= _(file_skip_hidden_label
);
539 file_all_charsets_label
= _(file_all_charsets_label
);
540 content_all_charsets_label
= _(content_all_charsets_label
);
542 content_use_label
= _(content_use_label
);
543 content_case_label
= _(content_case_label
);
544 content_regexp_label
= _(content_regexp_label
);
545 content_first_hit_label
= _(content_first_hit_label
);
546 content_whole_words_label
= _(content_whole_words_label
);
548 #endif /* ENABLE_NLS */
550 b0
= str_term_width1 (buts
[0]) + 6; /* default button */
551 b1
= str_term_width1 (buts
[1]) + 4;
552 b2
= str_term_width1 (buts
[2]) + 4;
554 find_load_options ();
556 if (in_start_dir
== NULL
)
557 in_start_dir
= g_strdup (".");
559 disable
= !options
.content_use
;
562 create_dlg (TRUE
, 0, 0, FIND_Y
, FIND_X
, dialog_colors
,
563 find_parm_callback
, "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
565 add_widget (find_dlg
,
566 button_new (FIND_Y
- 3, FIND_X
* 3 / 4 - b1
/ 2, B_CANCEL
, NORMAL_BUTTON
, buts
[1],
568 add_widget (find_dlg
,
569 button_new (FIND_Y
- 3, FIND_X
/ 4 - b0
/ 2, B_ENTER
, DEFPUSH_BUTTON
, buts
[0], 0));
571 cbox_position
= FIND_Y
- 5;
573 content_first_hit_cbox
=
574 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_first_hit
,
575 content_first_hit_label
);
576 widget_disable (content_first_hit_cbox
->widget
, disable
);
577 add_widget (find_dlg
, content_first_hit_cbox
);
579 content_whole_words_cbox
=
580 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_whole_words
,
581 content_whole_words_label
);
582 widget_disable (content_whole_words_cbox
->widget
, disable
);
583 add_widget (find_dlg
, content_whole_words_cbox
);
586 content_all_charsets_cbox
= check_new (cbox_position
--, FIND_X
/ 2 + 1,
587 options
.content_all_charsets
,
588 content_all_charsets_label
);
589 widget_disable (content_all_charsets_cbox
->widget
, disable
);
590 add_widget (find_dlg
, content_all_charsets_cbox
);
593 content_case_sens_cbox
=
594 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_case_sens
, content_case_label
);
595 widget_disable (content_case_sens_cbox
->widget
, disable
);
596 add_widget (find_dlg
, content_case_sens_cbox
);
598 content_regexp_cbox
=
599 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_regexp
, content_regexp_label
);
600 widget_disable (content_regexp_cbox
->widget
, disable
);
601 add_widget (find_dlg
, content_regexp_cbox
);
603 cbox_position
= FIND_Y
- 6;
605 skip_hidden_cbox
= check_new (cbox_position
--, 3, options
.skip_hidden
, file_skip_hidden_label
);
606 add_widget (find_dlg
, skip_hidden_cbox
);
609 file_all_charsets_cbox
=
610 check_new (cbox_position
--, 3, options
.file_all_charsets
, file_all_charsets_label
);
611 add_widget (find_dlg
, file_all_charsets_cbox
);
614 file_case_sens_cbox
= check_new (cbox_position
--, 3, options
.file_case_sens
, file_case_label
);
615 add_widget (find_dlg
, file_case_sens_cbox
);
617 file_pattern_cbox
= check_new (cbox_position
--, 3, options
.file_pattern
, file_pattern_label
);
618 add_widget (find_dlg
, file_pattern_cbox
);
620 recursively_cbox
= check_new (cbox_position
, 3, options
.find_recurs
, file_recurs_label
);
621 add_widget (find_dlg
, recursively_cbox
);
623 /* This checkbox is located in the second column */
625 check_new (cbox_position
, FIND_X
/ 2 + 1, options
.content_use
, content_use_label
);
626 add_widget (find_dlg
, content_use_cbox
);
629 input_new (8, FIND_X
/ 2 + 1, input_get_default_colors (), FIND_X
/ 2 - 4, INPUT_LAST_TEXT
,
630 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
631 widget_disable (in_with
->widget
, disable
);
632 add_widget (find_dlg
, in_with
);
634 content_label
= label_new (7, FIND_X
/ 2 + 1, _("Content:"));
635 widget_disable (content_label
->widget
, disable
);
636 add_widget (find_dlg
, content_label
);
638 in_name
= input_new (8, 3, input_get_default_colors (),
639 FIND_X
/ 2 - 4, INPUT_LAST_TEXT
, "name", INPUT_COMPLETE_DEFAULT
);
640 add_widget (find_dlg
, in_name
);
641 add_widget (find_dlg
, label_new (7, 3, _("File name:")));
643 in_ignore
= input_new (5, 3, input_get_default_colors (), FIND_X
- 6,
644 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "",
645 "ignoredirs", INPUT_COMPLETE_DEFAULT
);
646 widget_disable (in_ignore
->widget
, !options
.ignore_dirs_enable
);
647 add_widget (find_dlg
, in_ignore
);
650 check_new (4, 3, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
651 add_widget (find_dlg
, ignore_dirs_cbox
);
653 add_widget (find_dlg
, button_new (3, FIND_X
- b2
- 2, B_TREE
, NORMAL_BUTTON
, buts
[2], 0));
655 in_start
= input_new (3, 3, input_get_default_colors (),
656 FIND_X
- b2
- 6, in_start_dir
, "start", INPUT_COMPLETE_DEFAULT
);
657 add_widget (find_dlg
, in_start
);
658 add_widget (find_dlg
, label_new (2, 3, _("Start at:")));
661 dlg_select_widget (in_name
);
663 switch (run_dlg (find_dlg
))
666 return_value
= FALSE
;
671 const char *temp_dir
= in_start
->buffer
;
673 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
674 temp_dir
= current_panel
->cwd
;
676 if (in_start_dir
!= INPUT_LAST_TEXT
)
677 g_free (in_start_dir
);
678 in_start_dir
= tree_box (temp_dir
);
679 if (in_start_dir
== NULL
)
680 in_start_dir
= g_strdup (temp_dir
);
682 input_assign_text (in_start
, in_start_dir
);
684 /* Warning: Dreadful goto */
690 options
.file_all_charsets
= file_all_charsets_cbox
->state
& C_BOOL
;
691 options
.content_all_charsets
= content_all_charsets_cbox
->state
& C_BOOL
;
693 options
.content_use
= content_use_cbox
->state
& C_BOOL
;
694 options
.content_case_sens
= content_case_sens_cbox
->state
& C_BOOL
;
695 options
.content_regexp
= content_regexp_cbox
->state
& C_BOOL
;
696 options
.content_first_hit
= content_first_hit_cbox
->state
& C_BOOL
;
697 options
.content_whole_words
= content_whole_words_cbox
->state
& C_BOOL
;
698 options
.find_recurs
= recursively_cbox
->state
& C_BOOL
;
699 options
.file_pattern
= file_pattern_cbox
->state
& C_BOOL
;
700 options
.file_case_sens
= file_case_sens_cbox
->state
& C_BOOL
;
701 options
.skip_hidden
= skip_hidden_cbox
->state
& C_BOOL
;
702 options
.ignore_dirs_enable
= ignore_dirs_cbox
->state
& C_BOOL
;
703 g_free (options
.ignore_dirs
);
704 options
.ignore_dirs
= g_strdup (in_ignore
->buffer
);
706 *content
= (options
.content_use
&& in_with
->buffer
[0] != '\0')
707 ? g_strdup (in_with
->buffer
) : NULL
;
708 *start_dir
= in_start
->buffer
[0] != '\0' ? in_start
->buffer
: (char *) ".";
709 *pattern
= g_strdup (in_name
->buffer
);
710 if (in_start_dir
!= INPUT_LAST_TEXT
)
711 g_free (in_start_dir
);
712 in_start_dir
= g_strdup (*start_dir
);
713 if ((*start_dir
)[0] == '.' && (*start_dir
)[1] == '\0')
714 *start_dir
= g_strdup (current_panel
->cwd
);
715 else if (g_path_is_absolute (*start_dir
))
716 *start_dir
= g_strdup (*start_dir
);
718 *start_dir
= g_build_filename (current_panel
->cwd
, *start_dir
, (char *) NULL
);
720 canonicalize_pathname (*start_dir
);
722 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
723 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
726 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
728 find_save_options ();
733 destroy_dlg (find_dlg
);
738 /* --------------------------------------------------------------------------------------------- */
740 #if GLIB_CHECK_VERSION (2, 14, 0)
742 push_directory (const char *dir
)
744 g_queue_push_head (&dir_queue
, (void *) dir
);
747 /* --------------------------------------------------------------------------------------------- */
752 return (char *) g_queue_pop_tail (&dir_queue
);
755 /* --------------------------------------------------------------------------------------------- */
756 /** Remove all the items from the stack */
761 g_queue_foreach (&dir_queue
, (GFunc
) g_free
, NULL
);
762 g_queue_clear (&dir_queue
);
765 /* --------------------------------------------------------------------------------------------- */
767 #else /* GLIB_CHECK_VERSION */
769 push_directory (const char *dir
)
773 new = g_new (dir_stack
, 1);
774 new->name
= (char *) dir
;
775 new->prev
= dir_stack_base
;
776 dir_stack_base
= new;
779 /* --------------------------------------------------------------------------------------------- */
786 if (dir_stack_base
!= NULL
)
789 name
= dir_stack_base
->name
;
790 next
= dir_stack_base
->prev
;
791 g_free (dir_stack_base
);
792 dir_stack_base
= next
;
798 /* --------------------------------------------------------------------------------------------- */
799 /** Remove all the items from the stack */
805 while ((dir
= pop_directory ()) != NULL
)
808 #endif /* GLIB_CHECK_VERSION */
810 /* --------------------------------------------------------------------------------------------- */
813 insert_file (const char *dir
, const char *file
)
815 char *tmp_name
= NULL
;
816 static char *dirname
= NULL
;
818 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
823 if (strcmp (old_dir
, dir
))
826 old_dir
= g_strdup (dir
);
827 dirname
= add_to_list (dir
, NULL
);
832 old_dir
= g_strdup (dir
);
833 dirname
= add_to_list (dir
, NULL
);
836 tmp_name
= g_strdup_printf (" %s", file
);
837 add_to_list (tmp_name
, dirname
);
841 /* --------------------------------------------------------------------------------------------- */
844 find_add_match (const char *dir
, const char *file
)
846 insert_file (dir
, file
);
850 listbox_select_first (find_list
);
851 send_message (&find_list
->widget
, WIDGET_DRAW
, 0);
857 /* --------------------------------------------------------------------------------------------- */
861 * Returns malloced null-terminated line from file file_fd.
862 * Input is buffered in buf_size long buffer.
863 * Current pos in buf is stored in pos.
864 * n_read - number of read chars.
865 * has_newline - is there newline ?
869 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
881 *n_read
= mc_read (file_fd
, buf
, buf_size
);
889 /* skip possible leading zero(s) */
895 if (i
>= buffer_size
- 1)
896 buffer
= g_realloc (buffer
, buffer_size
+= 80);
905 *has_newline
= (ch
!= '\0');
913 /* --------------------------------------------------------------------------------------------- */
915 static FindProgressStatus
916 check_find_events (Dlg_head
* h
)
922 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
925 dlg_process_event (h
, c
, &event
);
926 if (h
->ret_value
== B_ENTER
927 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
929 /* dialog terminated */
932 if (!(h
->flags
& DLG_WANT_IDLE
))
934 /* searching suspended */
942 /* --------------------------------------------------------------------------------------------- */
946 * Search the content_pattern string in the DIRECTORY/FILE.
947 * It will add the found entries to the find listbox.
949 * returns FALSE if do_search should look for another file
950 * TRUE if do_search should exit and proceed to the event handler
954 search_content (Dlg_head
* h
, const char *directory
, const char *filename
)
960 gboolean ret_val
= FALSE
;
962 fname
= concat_dir_and_file (directory
, filename
);
964 if (mc_stat (fname
, &s
) != 0 || !S_ISREG (s
.st_mode
))
970 file_fd
= mc_open (fname
, O_RDONLY
);
976 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), str_trunc (filename
, FIND2_X_USE
));
978 status_update (buffer
);
981 tty_enable_interrupt_key ();
982 tty_got_interrupt ();
988 gboolean has_newline
;
990 gboolean found
= FALSE
;
992 char result
[BUF_MEDIUM
];
996 /* We've been previously suspended, start from the previous position */
1002 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1003 &pos
, &n_read
, &has_newline
)) != NULL
)
1005 if (!found
/* Search in binary line once */
1006 && mc_search_run (search_content_handle
,
1007 (const void *) p
, 0, strlen (p
), &found_len
))
1009 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1010 find_add_match (directory
, result
);
1015 if (found
&& options
.content_first_hit
)
1024 if ((line
& 0xff) == 0)
1026 FindProgressStatus res
;
1027 res
= check_find_events (h
);
1046 tty_disable_interrupt_key ();
1051 /* --------------------------------------------------------------------------------------------- */
1054 If dir is absolute, this means we're within dir and searching file here.
1055 If dir is relative, this means we're going to add dir to the directory stack.
1058 find_ignore_dir_search (const char *dir
)
1060 if (find_ignore_dirs
!= NULL
)
1062 const size_t dlen
= strlen (dir
);
1063 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1067 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1069 const size_t ilen
= strlen (*ignore_dir
);
1070 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1072 /* ignore dir is too long -- skip it */
1076 /* handle absolute and relative paths */
1077 switch (iabs
| dabs
)
1079 case 0: /* both paths are relative */
1080 case 3: /* both paths are abolute */
1081 /* if ignore dir is not a path of dir -- skip it */
1082 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1084 /* be sure that ignore dir is not a part of dir like:
1085 ignore dir is "h", dir is "home" */
1086 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1090 case 1: /* dir is absolute, ignore_dir is relative */
1094 d
= strstr (dir
, *ignore_dir
);
1095 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1099 case 2: /* dir is relative, ignore_dir is absolute */
1100 /* FIXME: skip this case */
1102 default: /* this cannot occurs */
1111 /* --------------------------------------------------------------------------------------------- */
1114 find_rotate_dash (const Dlg_head
* h
, gboolean finish
)
1116 static const char rotating_dash
[] = "|/-\\";
1117 static unsigned int pos
= 0;
1121 pos
= (pos
+ 1) % 4;
1122 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1123 dlg_move (h
, FIND2_Y
- 7, FIND2_X
- 4);
1124 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1129 /* --------------------------------------------------------------------------------------------- */
1132 do_search (Dlg_head
* h
)
1134 static struct dirent
*dp
= NULL
;
1135 static DIR *dirp
= NULL
;
1136 static char *directory
= NULL
;
1137 struct stat tmp_stat
;
1138 static int subdirs_left
= 0;
1140 unsigned short count
;
1143 { /* someone forces me to close dirp */
1155 for (count
= 0; count
< 32; count
++)
1165 while (dirp
== NULL
)
1169 tty_setcolor (REVERSE_COLOR
);
1173 tmp
= pop_directory ();
1177 if (ignore_count
== 0)
1178 status_update (_("Finished"));
1181 char msg
[BUF_SMALL
];
1182 g_snprintf (msg
, sizeof (msg
),
1183 ngettext ("Finished (ignored %zd directory)",
1184 "Finished (ignored %zd directories)",
1185 ignore_count
), ignore_count
);
1186 status_update (msg
);
1188 find_rotate_dash (h
, TRUE
);
1193 /* handle absolute ignore dirs here */
1194 if (!find_ignore_dir_search (tmp
))
1206 char buffer
[BUF_SMALL
];
1208 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"),
1209 str_trunc (directory
, FIND2_X_USE
));
1210 status_update (buffer
);
1212 /* mc_stat should not be called after mc_opendir
1213 because vfs_s_opendir modifies the st_nlink
1215 if (mc_stat (directory
, &tmp_stat
) == 0)
1216 subdirs_left
= tmp_stat
.st_nlink
- 2;
1220 dirp
= mc_opendir (directory
);
1221 } /* while (!dirp) */
1223 /* skip invalid filenames */
1224 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1228 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1230 /* skip invalid filenames */
1231 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1237 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1241 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1242 { /* Can directory be NULL ? */
1243 /* handle relative ignore dirs here */
1244 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1250 tmp_name
= g_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1252 if (mc_lstat (tmp_name
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1254 push_directory (tmp_name
);
1262 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1263 0, strlen (dp
->d_name
), &bytes_found
);
1267 if (content_pattern
== NULL
)
1268 find_add_match (directory
, dp
->d_name
);
1269 else if (search_content (h
, directory
, dp
->d_name
))
1274 /* skip invalid filenames */
1275 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1279 find_rotate_dash (h
, FALSE
);
1284 /* --------------------------------------------------------------------------------------------- */
1287 init_find_vars (void)
1294 /* Remove all the items from the stack */
1297 g_strfreev (find_ignore_dirs
);
1298 find_ignore_dirs
= NULL
;
1301 /* --------------------------------------------------------------------------------------------- */
1304 make_fullname (const char *dirname
, const char *filename
)
1307 if (strcmp (dirname
, ".") == 0 || strcmp (dirname
, "." PATH_SEP_STR
) == 0)
1308 return g_strdup (filename
);
1309 if (strncmp (dirname
, "." PATH_SEP_STR
, 2) == 0)
1310 return concat_dir_and_file (dirname
+ 2, filename
);
1311 return concat_dir_and_file (dirname
, filename
);
1314 /* --------------------------------------------------------------------------------------------- */
1317 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1319 char *fullname
= NULL
;
1320 const char *filename
= NULL
;
1323 if (content_pattern
!= NULL
)
1325 filename
= strchr (file
+ 4, ':') + 1;
1326 line
= atoi (file
+ 4);
1330 filename
= file
+ 4;
1334 fullname
= make_fullname (dir
, filename
);
1336 do_edit_at_line (fullname
, use_internal_edit
, line
);
1338 view_file_at_line (fullname
, unparsed_view
, use_internal_view
, line
);
1342 /* --------------------------------------------------------------------------------------------- */
1345 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1350 listbox_get_current (find_list
, &text
, (void **) &dir
);
1352 if ((text
== NULL
) || (dir
== NULL
))
1353 return MSG_NOT_HANDLED
;
1355 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1359 /* --------------------------------------------------------------------------------------------- */
1362 find_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
1367 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1369 int unparsed_view
= (parm
== KEY_F (13));
1370 return view_edit_currently_selected_file (unparsed_view
, 0);
1372 if (parm
== KEY_F (4))
1374 return view_edit_currently_selected_file (0, 1);
1376 return MSG_NOT_HANDLED
;
1383 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
1387 /* --------------------------------------------------------------------------------------------- */
1388 /** Handles the Stop/Start button in the find window */
1391 start_stop (WButton
* button
, int action
)
1397 set_idle_proc (find_dlg
, running
);
1398 is_start
= !is_start
;
1400 status_update (is_start
? _("Stopped") : _("Searching"));
1401 button_set_text (stop_button
, fbuts
[is_start
? 1 : 0].text
);
1406 /* --------------------------------------------------------------------------------------------- */
1407 /** Handle view command, when invoked as a button */
1410 find_do_view_file (WButton
* button
, int action
)
1415 view_edit_currently_selected_file (0, 0);
1419 /* --------------------------------------------------------------------------------------------- */
1420 /** Handle edit command, when invoked as a button */
1423 find_do_edit_file (WButton
* button
, int action
)
1428 view_edit_currently_selected_file (0, 1);
1432 /* --------------------------------------------------------------------------------------------- */
1438 static gboolean i18n_flag
= FALSE
;
1442 int i
= sizeof (fbuts
) / sizeof (fbuts
[0]);
1445 fbuts
[i
].text
= _(fbuts
[i
].text
);
1446 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1449 fbuts
[2].len
+= 2; /* DEFPUSH_BUTTON */
1452 #endif /* ENABLE_NLS */
1455 * Dynamically place buttons centered within current window size
1458 int l0
= max (fbuts
[0].len
, fbuts
[1].len
);
1459 int l1
= fbuts
[2].len
+ fbuts
[3].len
+ l0
+ fbuts
[4].len
;
1460 int l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
;
1463 /* Check, if both button rows fit within FIND2_X */
1464 FIND2_X
= max (l1
+ 9, COLS
- 16);
1465 FIND2_X
= max (l2
+ 8, FIND2_X
);
1467 /* compute amount of space between buttons for each row */
1468 r1
= (FIND2_X
- 4 - l1
) % 5;
1469 l1
= (FIND2_X
- 4 - l1
) / 5;
1470 r2
= (FIND2_X
- 4 - l2
) % 4;
1471 l2
= (FIND2_X
- 4 - l2
) / 4;
1473 /* ...and finally, place buttons */
1474 fbuts
[2].x
= 2 + r1
/ 2 + l1
;
1475 fbuts
[3].x
= fbuts
[2].x
+ fbuts
[2].len
+ l1
;
1476 fbuts
[0].x
= fbuts
[3].x
+ fbuts
[3].len
+ l1
;
1477 fbuts
[4].x
= fbuts
[0].x
+ l0
+ l1
;
1478 fbuts
[5].x
= 2 + r2
/ 2 + l2
;
1479 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ l2
;
1480 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ l2
;
1484 create_dlg (TRUE
, 0, 0, FIND2_Y
, FIND2_X
, dialog_colors
, find_callback
,
1485 "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
1487 add_widget (find_dlg
,
1488 button_new (FIND2_Y
- 3, fbuts
[7].x
, B_VIEW
, NORMAL_BUTTON
,
1489 fbuts
[7].text
, find_do_edit_file
));
1490 add_widget (find_dlg
,
1491 button_new (FIND2_Y
- 3, fbuts
[6].x
, B_VIEW
, NORMAL_BUTTON
,
1492 fbuts
[6].text
, find_do_view_file
));
1493 add_widget (find_dlg
,
1494 button_new (FIND2_Y
- 3, fbuts
[5].x
, B_PANELIZE
, NORMAL_BUTTON
, fbuts
[5].text
,
1497 add_widget (find_dlg
,
1498 button_new (FIND2_Y
- 4, fbuts
[4].x
, B_CANCEL
, NORMAL_BUTTON
, fbuts
[4].text
, NULL
));
1500 button_new (FIND2_Y
- 4, fbuts
[0].x
, B_STOP
, NORMAL_BUTTON
, fbuts
[0].text
, start_stop
);
1501 add_widget (find_dlg
, stop_button
);
1502 add_widget (find_dlg
,
1503 button_new (FIND2_Y
- 4, fbuts
[3].x
, B_AGAIN
, NORMAL_BUTTON
, fbuts
[3].text
, NULL
));
1504 add_widget (find_dlg
,
1505 button_new (FIND2_Y
- 4, fbuts
[2].x
, B_ENTER
, DEFPUSH_BUTTON
, fbuts
[2].text
, NULL
));
1507 status_label
= label_new (FIND2_Y
- 7, 4, _("Searching"));
1508 add_widget (find_dlg
, status_label
);
1510 found_num_label
= label_new (FIND2_Y
- 6, 4, "");
1511 add_widget (find_dlg
, found_num_label
);
1513 find_list
= listbox_new (2, 2, FIND2_Y
- 10, FIND2_X
- 4, FALSE
, NULL
);
1514 add_widget (find_dlg
, find_list
);
1517 /* --------------------------------------------------------------------------------------------- */
1524 search_content_handle
= mc_search_new (content_pattern
, -1);
1525 if (search_content_handle
)
1527 search_content_handle
->search_type
=
1528 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1529 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1530 search_content_handle
->whole_words
= options
.content_whole_words
;
1531 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1533 search_file_handle
= mc_search_new (find_pattern
, -1);
1534 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1535 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1536 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1537 search_file_handle
->is_entire_line
= options
.file_pattern
;
1541 set_idle_proc (find_dlg
, 1);
1542 ret
= run_dlg (find_dlg
);
1544 mc_search_free (search_file_handle
);
1545 search_file_handle
= NULL
;
1546 mc_search_free (search_content_handle
);
1547 search_content_handle
= NULL
;
1552 /* --------------------------------------------------------------------------------------------- */
1557 set_idle_proc (find_dlg
, 0);
1558 destroy_dlg (find_dlg
);
1561 /* --------------------------------------------------------------------------------------------- */
1564 find_file (const char *start_dir
, const char *ignore_dirs
, const char *pattern
, const char *content
,
1565 char **dirname
, char **filename
)
1567 int return_value
= 0;
1568 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1572 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1573 find_pattern
= (char *) pattern
;
1575 content_pattern
= NULL
;
1576 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1577 content_pattern
= g_strdup (content
);
1580 parse_ignore_dirs (ignore_dirs
);
1581 push_directory (start_dir
);
1583 return_value
= run_process ();
1585 /* Clear variables */
1588 get_list_info (&file_tmp
, &dir_tmp
);
1591 *dirname
= g_strdup (dir_tmp
);
1593 *filename
= g_strdup (file_tmp
);
1595 if (return_value
== B_PANELIZE
&& *filename
)
1597 int status
, link_to_dir
, stale_link
;
1602 dir_list
*list
= ¤t_panel
->dir
;
1605 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1607 const char *lc_filename
= NULL
;
1608 WLEntry
*le
= (WLEntry
*) entry
->data
;
1610 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1613 if (content_pattern
!= NULL
)
1614 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1616 lc_filename
= le
->text
+ 4;
1618 name
= make_fullname (le
->data
, lc_filename
);
1619 status
= handle_path (list
, name
, &st
, next_free
, &link_to_dir
, &stale_link
);
1631 /* don't add files more than once to the panel */
1632 if (content_pattern
!= NULL
&& next_free
> 0
1633 && strcmp (list
->list
[next_free
- 1].fname
, name
) == 0)
1639 if (!next_free
) /* first turn i.e clean old list */
1640 panel_clean_dir (current_panel
);
1641 list
->list
[next_free
].fnamelen
= strlen (name
);
1642 list
->list
[next_free
].fname
= name
;
1643 list
->list
[next_free
].f
.marked
= 0;
1644 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1645 list
->list
[next_free
].f
.stale_link
= stale_link
;
1646 list
->list
[next_free
].f
.dir_size_computed
= 0;
1647 list
->list
[next_free
].st
= st
;
1648 list
->list
[next_free
].sort_key
= NULL
;
1649 list
->list
[next_free
].second_sort_key
= NULL
;
1651 if (!(next_free
& 15))
1657 current_panel
->count
= next_free
;
1658 current_panel
->is_panelized
= 1;
1660 if (start_dir
[0] == PATH_SEP
)
1663 strcpy (current_panel
->cwd
, PATH_SEP_STR
);
1664 ret
= chdir (PATH_SEP_STR
);
1669 g_free (content_pattern
);
1671 do_search (NULL
); /* force do_search to release resources */
1675 return return_value
;
1678 /* --------------------------------------------------------------------------------------------- */
1679 /*** public functions ****************************************************************************/
1680 /* --------------------------------------------------------------------------------------------- */
1685 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1686 char *filename
= NULL
, *dirname
= NULL
;
1688 gboolean dir_and_file_set
;
1690 while (find_parameters (&start_dir
, &ignore_dirs
, &pattern
, &content
))
1692 if (pattern
[0] == '\0')
1693 break; /* nothing search */
1695 dirname
= filename
= NULL
;
1697 v
= find_file (start_dir
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1698 g_free (ignore_dirs
);
1703 if (dirname
!= NULL
)
1705 do_cd (dirname
, cd_exact
);
1706 if (filename
!= NULL
)
1707 try_to_select (current_panel
,
1708 filename
+ (content
!= NULL
1709 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1711 else if (filename
!= NULL
)
1712 do_cd (filename
, cd_exact
);
1720 dir_and_file_set
= (dirname
!= NULL
) && (filename
!= NULL
);
1727 if (v
== B_PANELIZE
)
1729 if (dir_and_file_set
)
1731 try_to_select (current_panel
, NULL
);
1732 panel_re_sort (current_panel
);
1733 try_to_select (current_panel
, NULL
);
1740 /* --------------------------------------------------------------------------------------------- */