2 Find file command for the Midnight Commander
4 Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
6 The Free Software Foundation, Inc.
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 * \brief Source: Find file command
40 #include "lib/global.h"
42 #include "lib/tty/tty.h"
43 #include "lib/tty/key.h"
45 #include "lib/search.h"
46 #include "lib/mcconfig.h"
47 #include "lib/vfs/vfs.h"
48 #include "lib/strutil.h"
49 #include "lib/widget.h"
50 #include "lib/util.h" /* canonicalize_pathname() */
52 #include "src/setup.h" /* verbose */
53 #include "src/history.h" /* MC_HISTORY_SHARED_SEARCH */
54 #include "src/main.h" /* do_cd */
57 #include "cmd.h" /* view_file_at_line */
58 #include "midnight.h" /* current_panel */
63 /*** global variables ****************************************************************************/
65 /*** file scope macro definitions ****************************************************************/
67 /* Size of the find window */
68 #define FIND2_Y (LINES - 4)
70 #define FIND2_X_USE (FIND2_X - 20)
72 /*** file scope type declarations ****************************************************************/
74 /* A couple of extra messages we need */
91 /* find file options */
94 /* file name options */
95 gboolean file_case_sens
;
96 gboolean file_pattern
;
99 gboolean file_all_charsets
;
101 /* file content options */
102 gboolean content_use
;
103 gboolean content_case_sens
;
104 gboolean content_regexp
;
105 gboolean content_first_hit
;
106 gboolean content_whole_words
;
107 gboolean content_all_charsets
;
109 /* whether use ignore dirs or not */
110 gboolean ignore_dirs_enable
;
111 /* list of directories to be ignored, separated by ':' */
113 } find_file_options_t
;
115 /*** file scope variables ************************************************************************/
117 /* Parsed ignore dirs */
118 static char **find_ignore_dirs
= NULL
;
120 /* Size of the find parameters window */
122 static int FIND_Y
= 19;
124 static int FIND_Y
= 18;
126 static int FIND_X
= 68;
128 static int FIND2_X
= 64;
130 /* static variables to remember find parameters */
131 static WInput
*in_start
; /* Start path */
132 static WInput
*in_name
; /* Filename */
133 static WInput
*in_with
; /* Text */
134 static WInput
*in_ignore
;
135 static WLabel
*content_label
; /* 'Content:' label */
136 static WCheck
*file_case_sens_cbox
; /* "case sensitive" checkbox */
137 static WCheck
*file_pattern_cbox
; /* File name is glob or regexp */
138 static WCheck
*recursively_cbox
;
139 static WCheck
*skip_hidden_cbox
;
140 static WCheck
*content_use_cbox
; /* Take into account the Content field */
141 static WCheck
*content_case_sens_cbox
; /* "case sensitive" checkbox */
142 static WCheck
*content_regexp_cbox
; /* "find regular expression" checkbox */
143 static WCheck
*content_first_hit_cbox
; /* "First hit" checkbox" */
144 static WCheck
*content_whole_words_cbox
; /* "whole words" checkbox */
146 static WCheck
*file_all_charsets_cbox
;
147 static WCheck
*content_all_charsets_cbox
;
149 static WCheck
*ignore_dirs_cbox
;
151 static gboolean running
= FALSE
; /* nice flag */
152 static char *find_pattern
= NULL
; /* Pattern to search */
153 static char *content_pattern
= NULL
; /* pattern to search inside files; if
154 content_regexp_flag is true, it contains the
155 regex pattern, else the search string. */
156 static unsigned long matches
; /* Number of matches */
157 static gboolean is_start
= FALSE
; /* Status of the start/stop toggle button */
158 static char *old_dir
= NULL
;
160 /* Where did we stop */
162 static int last_line
;
165 static size_t ignore_count
= 0;
167 static Dlg_head
*find_dlg
; /* The dialog */
168 static WButton
*stop_button
; /* pointer to the stop button */
169 static WLabel
*status_label
; /* Finished, Searching etc. */
170 static WLabel
*found_num_label
; /* Number of found items */
171 static WListbox
*find_list
; /* Listbox with the file list */
173 /* This keeps track of the directory stack */
174 #if GLIB_CHECK_VERSION (2, 14, 0)
175 static GQueue dir_queue
= G_QUEUE_INIT
;
177 typedef struct dir_stack
180 struct dir_stack
*prev
;
183 static dir_stack
*dir_stack_base
= 0;
184 #endif /* GLIB_CHECK_VERSION */
190 int len
; /* length including space and brackets */
194 {N_("&Suspend"), 11, 29},
195 {N_("Con&tinue"), 12, 29},
196 {N_("&Chdir"), 11, 3},
197 {N_("&Again"), 9, 17},
198 {N_("&Quit"), 8, 43},
199 {N_("Pane&lize"), 12, 3},
200 {N_("&View - F3"), 13, 20},
201 {N_("&Edit - F4"), 13, 38}
205 static find_file_options_t options
= {
206 TRUE
, TRUE
, TRUE
, FALSE
, FALSE
,
207 FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
210 static char *in_start_dir
= INPUT_LAST_TEXT
;
212 static mc_search_t
*search_file_handle
= NULL
;
213 static mc_search_t
*search_content_handle
= NULL
;
215 /*** file scope functions ************************************************************************/
218 parse_ignore_dirs (const char *ignore_dirs
)
220 size_t r
= 0, w
= 0; /* read and write iterators */
222 if (!options
.ignore_dirs_enable
|| ignore_dirs
== NULL
|| ignore_dirs
[0] == '\0')
225 find_ignore_dirs
= g_strsplit (ignore_dirs
, ":", -1);
227 /* Values like '/foo::/bar: produce holes in list.
228 * Find and remove them */
229 for (; find_ignore_dirs
[r
] != NULL
; r
++)
231 if (find_ignore_dirs
[r
][0] == '\0')
233 /* empty entry -- skip it */
234 g_free (find_ignore_dirs
[r
]);
235 find_ignore_dirs
[r
] = NULL
;
241 /* copy entry to the previous free array cell */
242 find_ignore_dirs
[w
] = find_ignore_dirs
[r
];
243 find_ignore_dirs
[r
] = NULL
;
246 canonicalize_pathname (find_ignore_dirs
[w
]);
247 if (find_ignore_dirs
[w
][0] != '\0')
251 g_free (find_ignore_dirs
[w
]);
252 find_ignore_dirs
[w
] = NULL
;
256 if (find_ignore_dirs
[0] == NULL
)
258 g_strfreev (find_ignore_dirs
);
259 find_ignore_dirs
= NULL
;
263 /* --------------------------------------------------------------------------------------------- */
266 find_load_options (void)
268 static gboolean loaded
= FALSE
;
276 options
.file_case_sens
=
277 mc_config_get_bool (mc_main_config
, "FindFile", "file_case_sens", TRUE
);
278 options
.file_pattern
=
279 mc_config_get_bool (mc_main_config
, "FindFile", "file_shell_pattern", TRUE
);
280 options
.find_recurs
= mc_config_get_bool (mc_main_config
, "FindFile", "file_find_recurs", TRUE
);
281 options
.skip_hidden
=
282 mc_config_get_bool (mc_main_config
, "FindFile", "file_skip_hidden", FALSE
);
283 options
.file_all_charsets
=
284 mc_config_get_bool (mc_main_config
, "FindFile", "file_all_charsets", FALSE
);
285 options
.content_use
= mc_config_get_bool (mc_main_config
, "FindFile", "content_use", TRUE
);
286 options
.content_case_sens
=
287 mc_config_get_bool (mc_main_config
, "FindFile", "content_case_sens", TRUE
);
288 options
.content_regexp
=
289 mc_config_get_bool (mc_main_config
, "FindFile", "content_regexp", FALSE
);
290 options
.content_first_hit
=
291 mc_config_get_bool (mc_main_config
, "FindFile", "content_first_hit", FALSE
);
292 options
.content_whole_words
=
293 mc_config_get_bool (mc_main_config
, "FindFile", "content_whole_words", FALSE
);
294 options
.content_all_charsets
=
295 mc_config_get_bool (mc_main_config
, "FindFile", "content_all_charsets", FALSE
);
296 options
.ignore_dirs_enable
=
297 mc_config_get_bool (mc_main_config
, "FindFile", "ignore_dirs_enable", TRUE
);
299 /* Back compatibility: try load old parameter at first */
300 ignore_dirs
= mc_config_get_string (mc_main_config
, "Misc", "find_ignore_dirs", "");
301 mc_config_del_key (mc_main_config
, "Misc", "find_ignore_dirs");
303 /* Then load new parameters */
304 options
.ignore_dirs
= mc_config_get_string (mc_main_config
, "FindFile", "ignore_dirs", "");
305 if (options
.ignore_dirs
[0] != '\0')
306 g_free (ignore_dirs
);
309 g_free (options
.ignore_dirs
);
310 options
.ignore_dirs
= ignore_dirs
;
313 if (options
.ignore_dirs
[0] == '\0')
315 g_free (options
.ignore_dirs
);
316 options
.ignore_dirs
= NULL
;
320 /* --------------------------------------------------------------------------------------------- */
323 find_save_options (void)
325 mc_config_set_bool (mc_main_config
, "FindFile", "file_case_sens", options
.file_case_sens
);
326 mc_config_set_bool (mc_main_config
, "FindFile", "file_shell_pattern", options
.file_pattern
);
327 mc_config_set_bool (mc_main_config
, "FindFile", "file_find_recurs", options
.find_recurs
);
328 mc_config_set_bool (mc_main_config
, "FindFile", "file_skip_hidden", options
.skip_hidden
);
329 mc_config_set_bool (mc_main_config
, "FindFile", "file_all_charsets", options
.file_all_charsets
);
330 mc_config_set_bool (mc_main_config
, "FindFile", "content_use", options
.content_use
);
331 mc_config_set_bool (mc_main_config
, "FindFile", "content_case_sens", options
.content_case_sens
);
332 mc_config_set_bool (mc_main_config
, "FindFile", "content_regexp", options
.content_regexp
);
333 mc_config_set_bool (mc_main_config
, "FindFile", "content_first_hit", options
.content_first_hit
);
334 mc_config_set_bool (mc_main_config
, "FindFile", "content_whole_words",
335 options
.content_whole_words
);
336 mc_config_set_bool (mc_main_config
, "FindFile", "content_all_charsets",
337 options
.content_all_charsets
);
338 mc_config_set_bool (mc_main_config
, "FindFile", "ignore_dirs_enable",
339 options
.ignore_dirs_enable
);
340 mc_config_set_string (mc_main_config
, "FindFile", "ignore_dirs", options
.ignore_dirs
);
343 /* --------------------------------------------------------------------------------------------- */
346 add_to_list (const char *text
, void *data
)
348 return listbox_add_item (find_list
, LISTBOX_APPEND_AT_END
, 0, text
, data
);
351 /* --------------------------------------------------------------------------------------------- */
354 stop_idle (void *data
)
356 set_idle_proc (data
, 0);
359 /* --------------------------------------------------------------------------------------------- */
362 status_update (const char *text
)
364 label_set_text (status_label
, text
);
367 /* --------------------------------------------------------------------------------------------- */
370 found_num_update (void)
372 char buffer
[BUF_TINY
];
373 g_snprintf (buffer
, sizeof (buffer
), _("Found: %ld"), matches
);
374 label_set_text (found_num_label
, buffer
);
377 /* --------------------------------------------------------------------------------------------- */
380 get_list_info (char **file
, char **dir
)
382 listbox_get_current (find_list
, file
, (void **) dir
);
385 /* --------------------------------------------------------------------------------------------- */
386 /** check regular expression */
389 find_check_regexp (const char *r
)
392 gboolean regexp_ok
= FALSE
;
394 search
= mc_search_new (r
, -1);
398 search
->search_type
= MC_SEARCH_T_REGEX
;
399 regexp_ok
= mc_search_prepare (search
);
400 mc_search_free (search
);
406 /* --------------------------------------------------------------------------------------------- */
408 * Callback for the parameter dialog.
409 * Validate regex, prevent closing the dialog if it's invalid.
413 find_parm_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
418 if (sender
== (Widget
*) content_use_cbox
)
420 gboolean disable
= !(content_use_cbox
->state
& C_BOOL
);
422 widget_disable (content_label
->widget
, disable
);
423 send_message ((Widget
*) content_label
, WIDGET_DRAW
, 0);
424 widget_disable (in_with
->widget
, disable
);
425 send_message ((Widget
*) in_with
, WIDGET_DRAW
, 0);
426 widget_disable (content_first_hit_cbox
->widget
, disable
);
427 send_message ((Widget
*) content_first_hit_cbox
, WIDGET_DRAW
, 0);
428 widget_disable (content_regexp_cbox
->widget
, disable
);
429 send_message ((Widget
*) content_regexp_cbox
, WIDGET_DRAW
, 0);
430 widget_disable (content_case_sens_cbox
->widget
, disable
);
431 send_message ((Widget
*) content_case_sens_cbox
, WIDGET_DRAW
, 0);
433 widget_disable (content_all_charsets_cbox
->widget
, disable
);
434 send_message ((Widget
*) content_all_charsets_cbox
, WIDGET_DRAW
, 0);
436 widget_disable (content_whole_words_cbox
->widget
, disable
);
437 send_message ((Widget
*) content_whole_words_cbox
, WIDGET_DRAW
, 0);
442 if (sender
== (Widget
*) ignore_dirs_cbox
)
444 gboolean disable
= !(ignore_dirs_cbox
->state
& C_BOOL
);
446 widget_disable (in_ignore
->widget
, disable
);
447 send_message ((Widget
*) in_ignore
, WIDGET_DRAW
, 0);
452 return MSG_NOT_HANDLED
;
456 if (h
->ret_value
!= B_ENTER
)
459 /* check filename regexp */
460 if (!(file_pattern_cbox
->state
& C_BOOL
)
461 && (in_name
->buffer
[0] != '\0') && !find_check_regexp (in_name
->buffer
))
463 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
464 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
465 dlg_select_widget (in_name
);
469 /* check content regexp */
470 if ((content_use_cbox
->state
& C_BOOL
) && (content_regexp_cbox
->state
& C_BOOL
)
471 && (in_with
->buffer
[0] != '\0') && !find_check_regexp (in_with
->buffer
))
473 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
474 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
475 dlg_select_widget (in_with
);
482 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
486 /* --------------------------------------------------------------------------------------------- */
488 * find_parameters: gets information from the user
490 * If the return value is TRUE, then the following holds:
492 * start_dir, ignore_dirs, pattern and content contain the information provided by the user.
493 * They are newly allocated strings and must be freed when uneeded.
495 * start_dir_len is -1 when user entered an absolute path, otherwise it is a length
496 * of start_dir (which is absolute). It is used to get a relative pats of find results.
500 find_parameters (char **start_dir
, ssize_t
* start_dir_len
,
501 char **ignore_dirs
, char **pattern
, char **content
)
503 gboolean return_value
;
506 const char *file_case_label
= N_("Cas&e sensitive");
507 const char *file_pattern_label
= N_("&Using shell patterns");
508 const char *file_recurs_label
= N_("&Find recursively");
509 const char *file_skip_hidden_label
= N_("S&kip hidden");
511 const char *file_all_charsets_label
= N_("&All charsets");
515 const char *content_use_label
= N_("Sea&rch for content");
516 const char *content_case_label
= N_("Case sens&itive");
517 const char *content_regexp_label
= N_("Re&gular expression");
518 const char *content_first_hit_label
= N_("Fir&st hit");
519 const char *content_whole_words_label
= N_("&Whole words");
521 const char *content_all_charsets_label
= N_("A&ll charsets");
524 const char *buts
[] = { N_("&OK"), N_("&Cancel"), N_("&Tree") };
533 int i
= sizeof (buts
) / sizeof (buts
[0]);
535 buts
[i
] = _(buts
[i
]);
537 file_case_label
= _(file_case_label
);
538 file_pattern_label
= _(file_pattern_label
);
539 file_recurs_label
= _(file_recurs_label
);
540 file_skip_hidden_label
= _(file_skip_hidden_label
);
542 file_all_charsets_label
= _(file_all_charsets_label
);
543 content_all_charsets_label
= _(content_all_charsets_label
);
545 content_use_label
= _(content_use_label
);
546 content_case_label
= _(content_case_label
);
547 content_regexp_label
= _(content_regexp_label
);
548 content_first_hit_label
= _(content_first_hit_label
);
549 content_whole_words_label
= _(content_whole_words_label
);
551 #endif /* ENABLE_NLS */
553 b0
= str_term_width1 (buts
[0]) + 6; /* default button */
554 b1
= str_term_width1 (buts
[1]) + 4;
555 b2
= str_term_width1 (buts
[2]) + 4;
557 find_load_options ();
559 if (in_start_dir
== NULL
)
560 in_start_dir
= g_strdup (".");
562 disable
= !options
.content_use
;
565 create_dlg (TRUE
, 0, 0, FIND_Y
, FIND_X
, dialog_colors
,
566 find_parm_callback
, "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
568 add_widget (find_dlg
,
569 button_new (FIND_Y
- 3, FIND_X
* 3 / 4 - b1
/ 2, B_CANCEL
, NORMAL_BUTTON
, buts
[1],
571 add_widget (find_dlg
,
572 button_new (FIND_Y
- 3, FIND_X
/ 4 - b0
/ 2, B_ENTER
, DEFPUSH_BUTTON
, buts
[0], 0));
574 cbox_position
= FIND_Y
- 5;
576 content_first_hit_cbox
=
577 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_first_hit
,
578 content_first_hit_label
);
579 widget_disable (content_first_hit_cbox
->widget
, disable
);
580 add_widget (find_dlg
, content_first_hit_cbox
);
582 content_whole_words_cbox
=
583 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_whole_words
,
584 content_whole_words_label
);
585 widget_disable (content_whole_words_cbox
->widget
, disable
);
586 add_widget (find_dlg
, content_whole_words_cbox
);
589 content_all_charsets_cbox
= check_new (cbox_position
--, FIND_X
/ 2 + 1,
590 options
.content_all_charsets
,
591 content_all_charsets_label
);
592 widget_disable (content_all_charsets_cbox
->widget
, disable
);
593 add_widget (find_dlg
, content_all_charsets_cbox
);
596 content_case_sens_cbox
=
597 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_case_sens
, content_case_label
);
598 widget_disable (content_case_sens_cbox
->widget
, disable
);
599 add_widget (find_dlg
, content_case_sens_cbox
);
601 content_regexp_cbox
=
602 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_regexp
, content_regexp_label
);
603 widget_disable (content_regexp_cbox
->widget
, disable
);
604 add_widget (find_dlg
, content_regexp_cbox
);
606 cbox_position
= FIND_Y
- 6;
608 skip_hidden_cbox
= check_new (cbox_position
--, 3, options
.skip_hidden
, file_skip_hidden_label
);
609 add_widget (find_dlg
, skip_hidden_cbox
);
612 file_all_charsets_cbox
=
613 check_new (cbox_position
--, 3, options
.file_all_charsets
, file_all_charsets_label
);
614 add_widget (find_dlg
, file_all_charsets_cbox
);
617 file_case_sens_cbox
= check_new (cbox_position
--, 3, options
.file_case_sens
, file_case_label
);
618 add_widget (find_dlg
, file_case_sens_cbox
);
620 file_pattern_cbox
= check_new (cbox_position
--, 3, options
.file_pattern
, file_pattern_label
);
621 add_widget (find_dlg
, file_pattern_cbox
);
623 recursively_cbox
= check_new (cbox_position
, 3, options
.find_recurs
, file_recurs_label
);
624 add_widget (find_dlg
, recursively_cbox
);
626 /* This checkbox is located in the second column */
628 check_new (cbox_position
, FIND_X
/ 2 + 1, options
.content_use
, content_use_label
);
629 add_widget (find_dlg
, content_use_cbox
);
632 input_new (8, FIND_X
/ 2 + 1, input_get_default_colors (), FIND_X
/ 2 - 4, INPUT_LAST_TEXT
,
633 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
634 widget_disable (in_with
->widget
, disable
);
635 add_widget (find_dlg
, in_with
);
637 content_label
= label_new (7, FIND_X
/ 2 + 1, _("Content:"));
638 widget_disable (content_label
->widget
, disable
);
639 add_widget (find_dlg
, content_label
);
641 in_name
= input_new (8, 3, input_get_default_colors (),
642 FIND_X
/ 2 - 4, INPUT_LAST_TEXT
, "name", INPUT_COMPLETE_DEFAULT
);
643 add_widget (find_dlg
, in_name
);
644 add_widget (find_dlg
, label_new (7, 3, _("File name:")));
646 in_ignore
= input_new (5, 3, input_get_default_colors (), FIND_X
- 6,
647 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "",
648 "ignoredirs", INPUT_COMPLETE_DEFAULT
);
649 widget_disable (in_ignore
->widget
, !options
.ignore_dirs_enable
);
650 add_widget (find_dlg
, in_ignore
);
653 check_new (4, 3, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
654 add_widget (find_dlg
, ignore_dirs_cbox
);
656 add_widget (find_dlg
, button_new (3, FIND_X
- b2
- 2, B_TREE
, NORMAL_BUTTON
, buts
[2], 0));
658 in_start
= input_new (3, 3, input_get_default_colors (),
659 FIND_X
- b2
- 6, in_start_dir
, "start", INPUT_COMPLETE_DEFAULT
);
660 add_widget (find_dlg
, in_start
);
661 add_widget (find_dlg
, label_new (2, 3, _("Start at:")));
664 dlg_select_widget (in_name
);
666 switch (run_dlg (find_dlg
))
669 return_value
= FALSE
;
674 const char *temp_dir
= in_start
->buffer
;
676 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
677 temp_dir
= current_panel
->cwd
;
679 if (in_start_dir
!= INPUT_LAST_TEXT
)
680 g_free (in_start_dir
);
681 in_start_dir
= tree_box (temp_dir
);
682 if (in_start_dir
== NULL
)
683 in_start_dir
= g_strdup (temp_dir
);
685 input_assign_text (in_start
, in_start_dir
);
687 /* Warning: Dreadful goto */
696 options
.file_all_charsets
= file_all_charsets_cbox
->state
& C_BOOL
;
697 options
.content_all_charsets
= content_all_charsets_cbox
->state
& C_BOOL
;
699 options
.content_use
= content_use_cbox
->state
& C_BOOL
;
700 options
.content_case_sens
= content_case_sens_cbox
->state
& C_BOOL
;
701 options
.content_regexp
= content_regexp_cbox
->state
& C_BOOL
;
702 options
.content_first_hit
= content_first_hit_cbox
->state
& C_BOOL
;
703 options
.content_whole_words
= content_whole_words_cbox
->state
& C_BOOL
;
704 options
.find_recurs
= recursively_cbox
->state
& C_BOOL
;
705 options
.file_pattern
= file_pattern_cbox
->state
& C_BOOL
;
706 options
.file_case_sens
= file_case_sens_cbox
->state
& C_BOOL
;
707 options
.skip_hidden
= skip_hidden_cbox
->state
& C_BOOL
;
708 options
.ignore_dirs_enable
= ignore_dirs_cbox
->state
& C_BOOL
;
709 g_free (options
.ignore_dirs
);
710 options
.ignore_dirs
= g_strdup (in_ignore
->buffer
);
712 *content
= (options
.content_use
&& in_with
->buffer
[0] != '\0')
713 ? g_strdup (in_with
->buffer
) : NULL
;
714 *start_dir
= in_start
->buffer
[0] != '\0' ? in_start
->buffer
: (char *) ".";
715 *pattern
= g_strdup (in_name
->buffer
);
716 if (in_start_dir
!= INPUT_LAST_TEXT
)
717 g_free (in_start_dir
);
718 in_start_dir
= g_strdup (*start_dir
);
720 s
= g_strdup (*start_dir
);
721 canonicalize_pathname (s
);
723 if (s
[0] == '.' && s
[1] == '\0')
725 *start_dir
= g_strdup (current_panel
->cwd
);
726 /* FIXME: is current_panel->cwd canonicalized? */
727 /* relative paths will be used in panelization */
728 *start_dir_len
= (ssize_t
) strlen (current_panel
->cwd
);
731 else if (g_path_is_absolute (s
))
738 /* relative paths will be used in panelization */
739 *start_dir
= mc_build_filename (current_panel
->cwd
, s
, (char *) NULL
);
740 *start_dir_len
= (ssize_t
) strlen (current_panel
->cwd
);
744 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
745 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
748 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
750 find_save_options ();
756 destroy_dlg (find_dlg
);
761 /* --------------------------------------------------------------------------------------------- */
763 #if GLIB_CHECK_VERSION (2, 14, 0)
765 push_directory (const char *dir
)
767 g_queue_push_head (&dir_queue
, (void *) dir
);
770 /* --------------------------------------------------------------------------------------------- */
775 return (char *) g_queue_pop_tail (&dir_queue
);
778 /* --------------------------------------------------------------------------------------------- */
779 /** Remove all the items from the stack */
784 g_queue_foreach (&dir_queue
, (GFunc
) g_free
, NULL
);
785 g_queue_clear (&dir_queue
);
788 /* --------------------------------------------------------------------------------------------- */
790 #else /* GLIB_CHECK_VERSION */
792 push_directory (const char *dir
)
796 new = g_new (dir_stack
, 1);
797 new->name
= (char *) dir
;
798 new->prev
= dir_stack_base
;
799 dir_stack_base
= new;
802 /* --------------------------------------------------------------------------------------------- */
809 if (dir_stack_base
!= NULL
)
812 name
= dir_stack_base
->name
;
813 next
= dir_stack_base
->prev
;
814 g_free (dir_stack_base
);
815 dir_stack_base
= next
;
821 /* --------------------------------------------------------------------------------------------- */
822 /** Remove all the items from the stack */
828 while ((dir
= pop_directory ()) != NULL
)
831 #endif /* GLIB_CHECK_VERSION */
833 /* --------------------------------------------------------------------------------------------- */
836 insert_file (const char *dir
, const char *file
)
838 char *tmp_name
= NULL
;
839 static char *dirname
= NULL
;
841 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
846 if (strcmp (old_dir
, dir
))
849 old_dir
= g_strdup (dir
);
850 dirname
= add_to_list (dir
, NULL
);
855 old_dir
= g_strdup (dir
);
856 dirname
= add_to_list (dir
, NULL
);
859 tmp_name
= g_strdup_printf (" %s", file
);
860 add_to_list (tmp_name
, dirname
);
864 /* --------------------------------------------------------------------------------------------- */
867 find_add_match (const char *dir
, const char *file
)
869 insert_file (dir
, file
);
873 listbox_select_first (find_list
);
874 send_message (&find_list
->widget
, WIDGET_DRAW
, 0);
880 /* --------------------------------------------------------------------------------------------- */
884 * Returns malloced null-terminated line from file file_fd.
885 * Input is buffered in buf_size long buffer.
886 * Current pos in buf is stored in pos.
887 * n_read - number of read chars.
888 * has_newline - is there newline ?
892 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
904 *n_read
= mc_read (file_fd
, buf
, buf_size
);
912 /* skip possible leading zero(s) */
918 if (i
>= buffer_size
- 1)
919 buffer
= g_realloc (buffer
, buffer_size
+= 80);
928 *has_newline
= (ch
!= '\0');
936 /* --------------------------------------------------------------------------------------------- */
938 static FindProgressStatus
939 check_find_events (Dlg_head
* h
)
945 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
948 dlg_process_event (h
, c
, &event
);
949 if (h
->ret_value
== B_ENTER
950 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
952 /* dialog terminated */
955 if (!(h
->flags
& DLG_WANT_IDLE
))
957 /* searching suspended */
965 /* --------------------------------------------------------------------------------------------- */
969 * Search the content_pattern string in the DIRECTORY/FILE.
970 * It will add the found entries to the find listbox.
972 * returns FALSE if do_search should look for another file
973 * TRUE if do_search should exit and proceed to the event handler
977 search_content (Dlg_head
* h
, const char *directory
, const char *filename
)
983 gboolean ret_val
= FALSE
;
985 fname
= mc_build_filename (directory
, filename
, (char *) NULL
);
987 if (mc_stat (fname
, &s
) != 0 || !S_ISREG (s
.st_mode
))
993 file_fd
= mc_open (fname
, O_RDONLY
);
999 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), str_trunc (filename
, FIND2_X_USE
));
1001 status_update (buffer
);
1004 tty_enable_interrupt_key ();
1005 tty_got_interrupt ();
1011 gboolean has_newline
;
1013 gboolean found
= FALSE
;
1015 char result
[BUF_MEDIUM
];
1019 /* We've been previously suspended, start from the previous position */
1025 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1026 &pos
, &n_read
, &has_newline
)) != NULL
)
1028 if (!found
/* Search in binary line once */
1029 && mc_search_run (search_content_handle
,
1030 (const void *) p
, 0, strlen (p
), &found_len
))
1032 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1033 find_add_match (directory
, result
);
1038 if (found
&& options
.content_first_hit
)
1047 if ((line
& 0xff) == 0)
1049 FindProgressStatus res
;
1050 res
= check_find_events (h
);
1069 tty_disable_interrupt_key ();
1074 /* --------------------------------------------------------------------------------------------- */
1077 If dir is absolute, this means we're within dir and searching file here.
1078 If dir is relative, this means we're going to add dir to the directory stack.
1081 find_ignore_dir_search (const char *dir
)
1083 if (find_ignore_dirs
!= NULL
)
1085 const size_t dlen
= strlen (dir
);
1086 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1090 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1092 const size_t ilen
= strlen (*ignore_dir
);
1093 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1095 /* ignore dir is too long -- skip it */
1099 /* handle absolute and relative paths */
1100 switch (iabs
| dabs
)
1102 case 0: /* both paths are relative */
1103 case 3: /* both paths are abolute */
1104 /* if ignore dir is not a path of dir -- skip it */
1105 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1107 /* be sure that ignore dir is not a part of dir like:
1108 ignore dir is "h", dir is "home" */
1109 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1113 case 1: /* dir is absolute, ignore_dir is relative */
1117 d
= strstr (dir
, *ignore_dir
);
1118 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1122 case 2: /* dir is relative, ignore_dir is absolute */
1123 /* FIXME: skip this case */
1125 default: /* this cannot occurs */
1134 /* --------------------------------------------------------------------------------------------- */
1137 find_rotate_dash (const Dlg_head
* h
, gboolean finish
)
1139 static const char rotating_dash
[] = "|/-\\";
1140 static unsigned int pos
= 0;
1144 pos
= (pos
+ 1) % 4;
1145 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1146 dlg_move (h
, FIND2_Y
- 7, FIND2_X
- 4);
1147 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1152 /* --------------------------------------------------------------------------------------------- */
1155 do_search (Dlg_head
* h
)
1157 static struct dirent
*dp
= NULL
;
1158 static DIR *dirp
= NULL
;
1159 static char *directory
= NULL
;
1160 struct stat tmp_stat
;
1161 static int subdirs_left
= 0;
1163 unsigned short count
;
1166 { /* someone forces me to close dirp */
1178 for (count
= 0; count
< 32; count
++)
1188 while (dirp
== NULL
)
1192 tty_setcolor (REVERSE_COLOR
);
1196 tmp
= pop_directory ();
1200 if (ignore_count
== 0)
1201 status_update (_("Finished"));
1204 char msg
[BUF_SMALL
];
1205 g_snprintf (msg
, sizeof (msg
),
1206 ngettext ("Finished (ignored %zd directory)",
1207 "Finished (ignored %zd directories)",
1208 ignore_count
), ignore_count
);
1209 status_update (msg
);
1211 find_rotate_dash (h
, TRUE
);
1216 /* handle absolute ignore dirs here */
1217 if (!find_ignore_dir_search (tmp
))
1229 char buffer
[BUF_SMALL
];
1231 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"),
1232 str_trunc (directory
, FIND2_X_USE
));
1233 status_update (buffer
);
1235 /* mc_stat should not be called after mc_opendir
1236 because vfs_s_opendir modifies the st_nlink
1238 if (mc_stat (directory
, &tmp_stat
) == 0)
1239 subdirs_left
= tmp_stat
.st_nlink
- 2;
1243 dirp
= mc_opendir (directory
);
1244 } /* while (!dirp) */
1246 /* skip invalid filenames */
1247 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1251 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1253 /* skip invalid filenames */
1254 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1260 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1264 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1265 { /* Can directory be NULL ? */
1266 /* handle relative ignore dirs here */
1267 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1273 tmp_name
= mc_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1275 if (mc_lstat (tmp_name
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1277 push_directory (tmp_name
);
1285 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1286 0, strlen (dp
->d_name
), &bytes_found
);
1290 if (content_pattern
== NULL
)
1291 find_add_match (directory
, dp
->d_name
);
1292 else if (search_content (h
, directory
, dp
->d_name
))
1297 /* skip invalid filenames */
1298 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1302 find_rotate_dash (h
, FALSE
);
1307 /* --------------------------------------------------------------------------------------------- */
1310 init_find_vars (void)
1317 /* Remove all the items from the stack */
1320 g_strfreev (find_ignore_dirs
);
1321 find_ignore_dirs
= NULL
;
1324 /* --------------------------------------------------------------------------------------------- */
1327 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1329 char *fullname
= NULL
;
1330 const char *filename
= NULL
;
1333 if (content_pattern
!= NULL
)
1335 filename
= strchr (file
+ 4, ':') + 1;
1336 line
= atoi (file
+ 4);
1340 filename
= file
+ 4;
1344 fullname
= mc_build_filename (dir
, filename
, (char *) NULL
);
1346 do_edit_at_line (fullname
, use_internal_edit
, line
);
1348 view_file_at_line (fullname
, unparsed_view
, use_internal_view
, line
);
1352 /* --------------------------------------------------------------------------------------------- */
1355 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1360 listbox_get_current (find_list
, &text
, (void **) &dir
);
1362 if ((text
== NULL
) || (dir
== NULL
))
1363 return MSG_NOT_HANDLED
;
1365 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1369 /* --------------------------------------------------------------------------------------------- */
1372 find_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
1377 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1379 int unparsed_view
= (parm
== KEY_F (13));
1380 return view_edit_currently_selected_file (unparsed_view
, 0);
1382 if (parm
== KEY_F (4))
1384 return view_edit_currently_selected_file (0, 1);
1386 return MSG_NOT_HANDLED
;
1393 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
1397 /* --------------------------------------------------------------------------------------------- */
1398 /** Handles the Stop/Start button in the find window */
1401 start_stop (WButton
* button
, int action
)
1407 set_idle_proc (find_dlg
, running
);
1408 is_start
= !is_start
;
1410 status_update (is_start
? _("Stopped") : _("Searching"));
1411 button_set_text (stop_button
, fbuts
[is_start
? 1 : 0].text
);
1416 /* --------------------------------------------------------------------------------------------- */
1417 /** Handle view command, when invoked as a button */
1420 find_do_view_file (WButton
* button
, int action
)
1425 view_edit_currently_selected_file (0, 0);
1429 /* --------------------------------------------------------------------------------------------- */
1430 /** Handle edit command, when invoked as a button */
1433 find_do_edit_file (WButton
* button
, int action
)
1438 view_edit_currently_selected_file (0, 1);
1442 /* --------------------------------------------------------------------------------------------- */
1448 static gboolean i18n_flag
= FALSE
;
1452 int i
= sizeof (fbuts
) / sizeof (fbuts
[0]);
1455 fbuts
[i
].text
= _(fbuts
[i
].text
);
1456 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1459 fbuts
[2].len
+= 2; /* DEFPUSH_BUTTON */
1462 #endif /* ENABLE_NLS */
1465 * Dynamically place buttons centered within current window size
1468 int l0
= max (fbuts
[0].len
, fbuts
[1].len
);
1469 int l1
= fbuts
[2].len
+ fbuts
[3].len
+ l0
+ fbuts
[4].len
;
1470 int l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
;
1473 /* Check, if both button rows fit within FIND2_X */
1474 FIND2_X
= max (l1
+ 9, COLS
- 16);
1475 FIND2_X
= max (l2
+ 8, FIND2_X
);
1477 /* compute amount of space between buttons for each row */
1478 r1
= (FIND2_X
- 4 - l1
) % 5;
1479 l1
= (FIND2_X
- 4 - l1
) / 5;
1480 r2
= (FIND2_X
- 4 - l2
) % 4;
1481 l2
= (FIND2_X
- 4 - l2
) / 4;
1483 /* ...and finally, place buttons */
1484 fbuts
[2].x
= 2 + r1
/ 2 + l1
;
1485 fbuts
[3].x
= fbuts
[2].x
+ fbuts
[2].len
+ l1
;
1486 fbuts
[0].x
= fbuts
[3].x
+ fbuts
[3].len
+ l1
;
1487 fbuts
[4].x
= fbuts
[0].x
+ l0
+ l1
;
1488 fbuts
[5].x
= 2 + r2
/ 2 + l2
;
1489 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ l2
;
1490 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ l2
;
1494 create_dlg (TRUE
, 0, 0, FIND2_Y
, FIND2_X
, dialog_colors
, find_callback
,
1495 "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
1497 add_widget (find_dlg
,
1498 button_new (FIND2_Y
- 3, fbuts
[7].x
, B_VIEW
, NORMAL_BUTTON
,
1499 fbuts
[7].text
, find_do_edit_file
));
1500 add_widget (find_dlg
,
1501 button_new (FIND2_Y
- 3, fbuts
[6].x
, B_VIEW
, NORMAL_BUTTON
,
1502 fbuts
[6].text
, find_do_view_file
));
1503 add_widget (find_dlg
,
1504 button_new (FIND2_Y
- 3, fbuts
[5].x
, B_PANELIZE
, NORMAL_BUTTON
, fbuts
[5].text
,
1507 add_widget (find_dlg
,
1508 button_new (FIND2_Y
- 4, fbuts
[4].x
, B_CANCEL
, NORMAL_BUTTON
, fbuts
[4].text
, NULL
));
1510 button_new (FIND2_Y
- 4, fbuts
[0].x
, B_STOP
, NORMAL_BUTTON
, fbuts
[0].text
, start_stop
);
1511 add_widget (find_dlg
, stop_button
);
1512 add_widget (find_dlg
,
1513 button_new (FIND2_Y
- 4, fbuts
[3].x
, B_AGAIN
, NORMAL_BUTTON
, fbuts
[3].text
, NULL
));
1514 add_widget (find_dlg
,
1515 button_new (FIND2_Y
- 4, fbuts
[2].x
, B_ENTER
, DEFPUSH_BUTTON
, fbuts
[2].text
, NULL
));
1517 status_label
= label_new (FIND2_Y
- 7, 4, _("Searching"));
1518 add_widget (find_dlg
, status_label
);
1520 found_num_label
= label_new (FIND2_Y
- 6, 4, "");
1521 add_widget (find_dlg
, found_num_label
);
1523 find_list
= listbox_new (2, 2, FIND2_Y
- 10, FIND2_X
- 4, FALSE
, NULL
);
1524 add_widget (find_dlg
, find_list
);
1527 /* --------------------------------------------------------------------------------------------- */
1534 search_content_handle
= mc_search_new (content_pattern
, -1);
1535 if (search_content_handle
)
1537 search_content_handle
->search_type
=
1538 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1539 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1540 search_content_handle
->whole_words
= options
.content_whole_words
;
1541 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1543 search_file_handle
= mc_search_new (find_pattern
, -1);
1544 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1545 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1546 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1547 search_file_handle
->is_entire_line
= options
.file_pattern
;
1551 set_idle_proc (find_dlg
, 1);
1552 ret
= run_dlg (find_dlg
);
1554 mc_search_free (search_file_handle
);
1555 search_file_handle
= NULL
;
1556 mc_search_free (search_content_handle
);
1557 search_content_handle
= NULL
;
1562 /* --------------------------------------------------------------------------------------------- */
1567 set_idle_proc (find_dlg
, 0);
1568 destroy_dlg (find_dlg
);
1571 /* --------------------------------------------------------------------------------------------- */
1574 do_find (const char *start_dir
, ssize_t start_dir_len
, const char *ignore_dirs
,
1575 const char *pattern
, const char *content
, char **dirname
, char **filename
)
1577 int return_value
= 0;
1578 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1582 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1583 find_pattern
= (char *) pattern
;
1585 content_pattern
= NULL
;
1586 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1587 content_pattern
= g_strdup (content
);
1590 parse_ignore_dirs (ignore_dirs
);
1591 push_directory (start_dir
);
1593 return_value
= run_process ();
1595 /* Clear variables */
1598 get_list_info (&file_tmp
, &dir_tmp
);
1601 *dirname
= g_strdup (dir_tmp
);
1603 *filename
= g_strdup (file_tmp
);
1605 if (return_value
== B_PANELIZE
&& *filename
)
1607 int status
, link_to_dir
, stale_link
;
1612 dir_list
*list
= ¤t_panel
->dir
;
1615 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1617 const char *lc_filename
= NULL
;
1618 WLEntry
*le
= (WLEntry
*) entry
->data
;
1621 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1624 if (content_pattern
!= NULL
)
1625 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1627 lc_filename
= le
->text
+ 4;
1629 name
= mc_build_filename (le
->data
, lc_filename
, (char *) NULL
);
1630 /* skip initial start dir */
1631 if (start_dir_len
< 0)
1635 p
= name
+ (size_t) start_dir_len
;
1640 status
= handle_path (list
, p
, &st
, next_free
, &link_to_dir
, &stale_link
);
1652 /* don't add files more than once to the panel */
1653 if (content_pattern
!= NULL
&& next_free
> 0
1654 && strcmp (list
->list
[next_free
- 1].fname
, p
) == 0)
1660 if (next_free
== 0) /* first turn i.e clean old list */
1661 panel_clean_dir (current_panel
);
1662 list
->list
[next_free
].fnamelen
= strlen (p
);
1663 list
->list
[next_free
].fname
= g_strdup (p
);
1664 list
->list
[next_free
].f
.marked
= 0;
1665 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1666 list
->list
[next_free
].f
.stale_link
= stale_link
;
1667 list
->list
[next_free
].f
.dir_size_computed
= 0;
1668 list
->list
[next_free
].st
= st
;
1669 list
->list
[next_free
].sort_key
= NULL
;
1670 list
->list
[next_free
].second_sort_key
= NULL
;
1673 if (!(next_free
& 15))
1679 current_panel
->count
= next_free
;
1680 current_panel
->is_panelized
= 1;
1683 if (start_dir_len
< 0)
1687 strcpy (current_panel
->cwd
, PATH_SEP_STR
);
1688 ret
= chdir (PATH_SEP_STR
);
1693 g_free (content_pattern
);
1695 do_search (NULL
); /* force do_search to release resources */
1699 return return_value
;
1702 /* --------------------------------------------------------------------------------------------- */
1703 /*** public functions ****************************************************************************/
1704 /* --------------------------------------------------------------------------------------------- */
1709 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1710 ssize_t start_dir_len
;
1711 char *filename
= NULL
, *dirname
= NULL
;
1714 while (find_parameters (&start_dir
, &start_dir_len
, &ignore_dirs
, &pattern
, &content
))
1716 if (pattern
[0] == '\0')
1717 break; /* nothing search */
1719 dirname
= filename
= NULL
;
1721 v
= do_find (start_dir
, start_dir_len
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1722 g_free (ignore_dirs
);
1727 if (dirname
!= NULL
)
1729 do_cd (dirname
, cd_exact
);
1730 if (filename
!= NULL
)
1731 try_to_select (current_panel
,
1732 filename
+ (content
!= NULL
1733 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1735 else if (filename
!= NULL
)
1736 do_cd (filename
, cd_exact
);
1750 if (v
== B_PANELIZE
)
1752 panel_re_sort (current_panel
);
1753 try_to_select (current_panel
, NULL
);
1759 /* --------------------------------------------------------------------------------------------- */