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 */
64 /*** global variables ****************************************************************************/
66 /*** file scope macro definitions ****************************************************************/
68 /* Size of the find window */
69 #define FIND2_Y (LINES - 4)
71 #define FIND2_X_USE (FIND2_X - 20)
73 /*** file scope type declarations ****************************************************************/
75 /* A couple of extra messages we need */
92 /* find file options */
95 /* file name options */
96 gboolean file_case_sens
;
97 gboolean file_pattern
;
100 gboolean file_all_charsets
;
102 /* file content options */
103 gboolean content_use
;
104 gboolean content_case_sens
;
105 gboolean content_regexp
;
106 gboolean content_first_hit
;
107 gboolean content_whole_words
;
108 gboolean content_all_charsets
;
110 /* whether use ignore dirs or not */
111 gboolean ignore_dirs_enable
;
112 /* list of directories to be ignored, separated by ':' */
114 } find_file_options_t
;
116 /*** file scope variables ************************************************************************/
118 /* Parsed ignore dirs */
119 static char **find_ignore_dirs
= NULL
;
121 /* Size of the find parameters window */
123 static int FIND_Y
= 19;
125 static int FIND_Y
= 18;
127 static int FIND_X
= 68;
129 static int FIND2_X
= 64;
131 /* static variables to remember find parameters */
132 static WInput
*in_start
; /* Start path */
133 static WInput
*in_name
; /* Filename */
134 static WInput
*in_with
; /* Text */
135 static WInput
*in_ignore
;
136 static WLabel
*content_label
; /* 'Content:' label */
137 static WCheck
*file_case_sens_cbox
; /* "case sensitive" checkbox */
138 static WCheck
*file_pattern_cbox
; /* File name is glob or regexp */
139 static WCheck
*recursively_cbox
;
140 static WCheck
*skip_hidden_cbox
;
141 static WCheck
*content_use_cbox
; /* Take into account the Content field */
142 static WCheck
*content_case_sens_cbox
; /* "case sensitive" checkbox */
143 static WCheck
*content_regexp_cbox
; /* "find regular expression" checkbox */
144 static WCheck
*content_first_hit_cbox
; /* "First hit" checkbox" */
145 static WCheck
*content_whole_words_cbox
; /* "whole words" checkbox */
147 static WCheck
*file_all_charsets_cbox
;
148 static WCheck
*content_all_charsets_cbox
;
150 static WCheck
*ignore_dirs_cbox
;
152 static gboolean running
= FALSE
; /* nice flag */
153 static char *find_pattern
= NULL
; /* Pattern to search */
154 static char *content_pattern
= NULL
; /* pattern to search inside files; if
155 content_regexp_flag is true, it contains the
156 regex pattern, else the search string. */
157 static unsigned long matches
; /* Number of matches */
158 static gboolean is_start
= FALSE
; /* Status of the start/stop toggle button */
159 static char *old_dir
= NULL
;
161 /* Where did we stop */
163 static int last_line
;
166 static size_t ignore_count
= 0;
168 static Dlg_head
*find_dlg
; /* The dialog */
169 static WButton
*stop_button
; /* pointer to the stop button */
170 static WLabel
*status_label
; /* Finished, Searching etc. */
171 static WLabel
*found_num_label
; /* Number of found items */
172 static WListbox
*find_list
; /* Listbox with the file list */
174 /* This keeps track of the directory stack */
175 #if GLIB_CHECK_VERSION (2, 14, 0)
176 static GQueue dir_queue
= G_QUEUE_INIT
;
178 typedef struct dir_stack
181 struct dir_stack
*prev
;
184 static dir_stack
*dir_stack_base
= 0;
185 #endif /* GLIB_CHECK_VERSION */
191 int len
; /* length including space and brackets */
195 {N_("&Suspend"), 11, 29},
196 {N_("Con&tinue"), 12, 29},
197 {N_("&Chdir"), 11, 3},
198 {N_("&Again"), 9, 17},
199 {N_("&Quit"), 8, 43},
200 {N_("Pane&lize"), 12, 3},
201 {N_("&View - F3"), 13, 20},
202 {N_("&Edit - F4"), 13, 38}
206 static find_file_options_t options
= {
207 TRUE
, TRUE
, TRUE
, FALSE
, FALSE
,
208 FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
211 static char *in_start_dir
= INPUT_LAST_TEXT
;
213 static mc_search_t
*search_file_handle
= NULL
;
214 static mc_search_t
*search_content_handle
= NULL
;
216 /*** file scope functions ************************************************************************/
219 parse_ignore_dirs (const char *ignore_dirs
)
221 size_t r
= 0, w
= 0; /* read and write iterators */
223 if (!options
.ignore_dirs_enable
|| ignore_dirs
== NULL
|| ignore_dirs
[0] == '\0')
226 find_ignore_dirs
= g_strsplit (ignore_dirs
, ":", -1);
228 /* Values like '/foo::/bar: produce holes in list.
229 * Find and remove them */
230 for (; find_ignore_dirs
[r
] != NULL
; r
++)
232 if (find_ignore_dirs
[r
][0] == '\0')
234 /* empty entry -- skip it */
235 g_free (find_ignore_dirs
[r
]);
236 find_ignore_dirs
[r
] = NULL
;
242 /* copy entry to the previous free array cell */
243 find_ignore_dirs
[w
] = find_ignore_dirs
[r
];
244 find_ignore_dirs
[r
] = NULL
;
247 canonicalize_pathname (find_ignore_dirs
[w
]);
248 if (find_ignore_dirs
[w
][0] != '\0')
252 g_free (find_ignore_dirs
[w
]);
253 find_ignore_dirs
[w
] = NULL
;
257 if (find_ignore_dirs
[0] == NULL
)
259 g_strfreev (find_ignore_dirs
);
260 find_ignore_dirs
= NULL
;
264 /* --------------------------------------------------------------------------------------------- */
267 find_load_options (void)
269 static gboolean loaded
= FALSE
;
277 options
.file_case_sens
=
278 mc_config_get_bool (mc_main_config
, "FindFile", "file_case_sens", TRUE
);
279 options
.file_pattern
=
280 mc_config_get_bool (mc_main_config
, "FindFile", "file_shell_pattern", TRUE
);
281 options
.find_recurs
= mc_config_get_bool (mc_main_config
, "FindFile", "file_find_recurs", TRUE
);
282 options
.skip_hidden
=
283 mc_config_get_bool (mc_main_config
, "FindFile", "file_skip_hidden", FALSE
);
284 options
.file_all_charsets
=
285 mc_config_get_bool (mc_main_config
, "FindFile", "file_all_charsets", FALSE
);
286 options
.content_use
= mc_config_get_bool (mc_main_config
, "FindFile", "content_use", TRUE
);
287 options
.content_case_sens
=
288 mc_config_get_bool (mc_main_config
, "FindFile", "content_case_sens", TRUE
);
289 options
.content_regexp
=
290 mc_config_get_bool (mc_main_config
, "FindFile", "content_regexp", FALSE
);
291 options
.content_first_hit
=
292 mc_config_get_bool (mc_main_config
, "FindFile", "content_first_hit", FALSE
);
293 options
.content_whole_words
=
294 mc_config_get_bool (mc_main_config
, "FindFile", "content_whole_words", FALSE
);
295 options
.content_all_charsets
=
296 mc_config_get_bool (mc_main_config
, "FindFile", "content_all_charsets", FALSE
);
297 options
.ignore_dirs_enable
=
298 mc_config_get_bool (mc_main_config
, "FindFile", "ignore_dirs_enable", TRUE
);
300 /* Back compatibility: try load old parameter at first */
301 ignore_dirs
= mc_config_get_string (mc_main_config
, CONFIG_MISC_SECTION
, "find_ignore_dirs", "");
302 mc_config_del_key (mc_main_config
, CONFIG_MISC_SECTION
, "find_ignore_dirs");
304 /* Then load new parameters */
305 options
.ignore_dirs
= mc_config_get_string (mc_main_config
, "FindFile", "ignore_dirs", "");
306 if (options
.ignore_dirs
[0] != '\0')
307 g_free (ignore_dirs
);
310 g_free (options
.ignore_dirs
);
311 options
.ignore_dirs
= ignore_dirs
;
314 if (options
.ignore_dirs
[0] == '\0')
316 g_free (options
.ignore_dirs
);
317 options
.ignore_dirs
= NULL
;
321 /* --------------------------------------------------------------------------------------------- */
324 find_save_options (void)
326 mc_config_set_bool (mc_main_config
, "FindFile", "file_case_sens", options
.file_case_sens
);
327 mc_config_set_bool (mc_main_config
, "FindFile", "file_shell_pattern", options
.file_pattern
);
328 mc_config_set_bool (mc_main_config
, "FindFile", "file_find_recurs", options
.find_recurs
);
329 mc_config_set_bool (mc_main_config
, "FindFile", "file_skip_hidden", options
.skip_hidden
);
330 mc_config_set_bool (mc_main_config
, "FindFile", "file_all_charsets", options
.file_all_charsets
);
331 mc_config_set_bool (mc_main_config
, "FindFile", "content_use", options
.content_use
);
332 mc_config_set_bool (mc_main_config
, "FindFile", "content_case_sens", options
.content_case_sens
);
333 mc_config_set_bool (mc_main_config
, "FindFile", "content_regexp", options
.content_regexp
);
334 mc_config_set_bool (mc_main_config
, "FindFile", "content_first_hit", options
.content_first_hit
);
335 mc_config_set_bool (mc_main_config
, "FindFile", "content_whole_words",
336 options
.content_whole_words
);
337 mc_config_set_bool (mc_main_config
, "FindFile", "content_all_charsets",
338 options
.content_all_charsets
);
339 mc_config_set_bool (mc_main_config
, "FindFile", "ignore_dirs_enable",
340 options
.ignore_dirs_enable
);
341 mc_config_set_string (mc_main_config
, "FindFile", "ignore_dirs", options
.ignore_dirs
);
344 /* --------------------------------------------------------------------------------------------- */
347 add_to_list (const char *text
, void *data
)
349 return listbox_add_item (find_list
, LISTBOX_APPEND_AT_END
, 0, text
, data
);
352 /* --------------------------------------------------------------------------------------------- */
355 stop_idle (void *data
)
357 set_idle_proc (data
, 0);
360 /* --------------------------------------------------------------------------------------------- */
363 status_update (const char *text
)
365 label_set_text (status_label
, text
);
368 /* --------------------------------------------------------------------------------------------- */
371 found_num_update (void)
373 char buffer
[BUF_TINY
];
374 g_snprintf (buffer
, sizeof (buffer
), _("Found: %ld"), matches
);
375 label_set_text (found_num_label
, buffer
);
378 /* --------------------------------------------------------------------------------------------- */
381 get_list_info (char **file
, char **dir
)
383 listbox_get_current (find_list
, file
, (void **) dir
);
386 /* --------------------------------------------------------------------------------------------- */
387 /** check regular expression */
390 find_check_regexp (const char *r
)
393 gboolean regexp_ok
= FALSE
;
395 search
= mc_search_new (r
, -1);
399 search
->search_type
= MC_SEARCH_T_REGEX
;
400 regexp_ok
= mc_search_prepare (search
);
401 mc_search_free (search
);
407 /* --------------------------------------------------------------------------------------------- */
409 * Callback for the parameter dialog.
410 * Validate regex, prevent closing the dialog if it's invalid.
414 find_parm_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
419 if (sender
== (Widget
*) content_use_cbox
)
421 gboolean disable
= !(content_use_cbox
->state
& C_BOOL
);
423 widget_disable (content_label
->widget
, disable
);
424 send_message ((Widget
*) content_label
, WIDGET_DRAW
, 0);
425 widget_disable (in_with
->widget
, disable
);
426 send_message ((Widget
*) in_with
, WIDGET_DRAW
, 0);
427 widget_disable (content_first_hit_cbox
->widget
, disable
);
428 send_message ((Widget
*) content_first_hit_cbox
, WIDGET_DRAW
, 0);
429 widget_disable (content_regexp_cbox
->widget
, disable
);
430 send_message ((Widget
*) content_regexp_cbox
, WIDGET_DRAW
, 0);
431 widget_disable (content_case_sens_cbox
->widget
, disable
);
432 send_message ((Widget
*) content_case_sens_cbox
, WIDGET_DRAW
, 0);
434 widget_disable (content_all_charsets_cbox
->widget
, disable
);
435 send_message ((Widget
*) content_all_charsets_cbox
, WIDGET_DRAW
, 0);
437 widget_disable (content_whole_words_cbox
->widget
, disable
);
438 send_message ((Widget
*) content_whole_words_cbox
, WIDGET_DRAW
, 0);
443 if (sender
== (Widget
*) ignore_dirs_cbox
)
445 gboolean disable
= !(ignore_dirs_cbox
->state
& C_BOOL
);
447 widget_disable (in_ignore
->widget
, disable
);
448 send_message ((Widget
*) in_ignore
, WIDGET_DRAW
, 0);
453 return MSG_NOT_HANDLED
;
457 if (h
->ret_value
!= B_ENTER
)
460 /* check filename regexp */
461 if (!(file_pattern_cbox
->state
& C_BOOL
)
462 && (in_name
->buffer
[0] != '\0') && !find_check_regexp (in_name
->buffer
))
464 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
465 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
466 dlg_select_widget (in_name
);
470 /* check content regexp */
471 if ((content_use_cbox
->state
& C_BOOL
) && (content_regexp_cbox
->state
& C_BOOL
)
472 && (in_with
->buffer
[0] != '\0') && !find_check_regexp (in_with
->buffer
))
474 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
475 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
476 dlg_select_widget (in_with
);
483 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
487 /* --------------------------------------------------------------------------------------------- */
489 * find_parameters: gets information from the user
491 * If the return value is TRUE, then the following holds:
493 * start_dir, ignore_dirs, pattern and content contain the information provided by the user.
494 * They are newly allocated strings and must be freed when uneeded.
496 * start_dir_len is -1 when user entered an absolute path, otherwise it is a length
497 * of start_dir (which is absolute). It is used to get a relative pats of find results.
501 find_parameters (char **start_dir
, ssize_t
* start_dir_len
,
502 char **ignore_dirs
, char **pattern
, char **content
)
504 gboolean return_value
;
507 const char *file_case_label
= N_("Cas&e sensitive");
508 const char *file_pattern_label
= N_("&Using shell patterns");
509 const char *file_recurs_label
= N_("&Find recursively");
510 const char *file_skip_hidden_label
= N_("S&kip hidden");
512 const char *file_all_charsets_label
= N_("&All charsets");
516 const char *content_use_label
= N_("Sea&rch for content");
517 const char *content_case_label
= N_("Case sens&itive");
518 const char *content_regexp_label
= N_("Re&gular expression");
519 const char *content_first_hit_label
= N_("Fir&st hit");
520 const char *content_whole_words_label
= N_("&Whole words");
522 const char *content_all_charsets_label
= N_("A&ll charsets");
525 const char *buts
[] = { N_("&OK"), N_("&Cancel"), N_("&Tree") };
534 int i
= sizeof (buts
) / sizeof (buts
[0]);
536 buts
[i
] = _(buts
[i
]);
538 file_case_label
= _(file_case_label
);
539 file_pattern_label
= _(file_pattern_label
);
540 file_recurs_label
= _(file_recurs_label
);
541 file_skip_hidden_label
= _(file_skip_hidden_label
);
543 file_all_charsets_label
= _(file_all_charsets_label
);
544 content_all_charsets_label
= _(content_all_charsets_label
);
546 content_use_label
= _(content_use_label
);
547 content_case_label
= _(content_case_label
);
548 content_regexp_label
= _(content_regexp_label
);
549 content_first_hit_label
= _(content_first_hit_label
);
550 content_whole_words_label
= _(content_whole_words_label
);
552 #endif /* ENABLE_NLS */
554 b0
= str_term_width1 (buts
[0]) + 6; /* default button */
555 b1
= str_term_width1 (buts
[1]) + 4;
556 b2
= str_term_width1 (buts
[2]) + 4;
558 find_load_options ();
560 if (in_start_dir
== NULL
)
561 in_start_dir
= g_strdup (".");
563 disable
= !options
.content_use
;
566 create_dlg (TRUE
, 0, 0, FIND_Y
, FIND_X
, dialog_colors
,
567 find_parm_callback
, "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
569 add_widget (find_dlg
,
570 button_new (FIND_Y
- 3, FIND_X
* 3 / 4 - b1
/ 2, B_CANCEL
, NORMAL_BUTTON
, buts
[1],
572 add_widget (find_dlg
,
573 button_new (FIND_Y
- 3, FIND_X
/ 4 - b0
/ 2, B_ENTER
, DEFPUSH_BUTTON
, buts
[0], 0));
575 cbox_position
= FIND_Y
- 5;
577 content_first_hit_cbox
=
578 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_first_hit
,
579 content_first_hit_label
);
580 widget_disable (content_first_hit_cbox
->widget
, disable
);
581 add_widget (find_dlg
, content_first_hit_cbox
);
583 content_whole_words_cbox
=
584 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_whole_words
,
585 content_whole_words_label
);
586 widget_disable (content_whole_words_cbox
->widget
, disable
);
587 add_widget (find_dlg
, content_whole_words_cbox
);
590 content_all_charsets_cbox
= check_new (cbox_position
--, FIND_X
/ 2 + 1,
591 options
.content_all_charsets
,
592 content_all_charsets_label
);
593 widget_disable (content_all_charsets_cbox
->widget
, disable
);
594 add_widget (find_dlg
, content_all_charsets_cbox
);
597 content_case_sens_cbox
=
598 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_case_sens
, content_case_label
);
599 widget_disable (content_case_sens_cbox
->widget
, disable
);
600 add_widget (find_dlg
, content_case_sens_cbox
);
602 content_regexp_cbox
=
603 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_regexp
, content_regexp_label
);
604 widget_disable (content_regexp_cbox
->widget
, disable
);
605 add_widget (find_dlg
, content_regexp_cbox
);
607 cbox_position
= FIND_Y
- 6;
609 skip_hidden_cbox
= check_new (cbox_position
--, 3, options
.skip_hidden
, file_skip_hidden_label
);
610 add_widget (find_dlg
, skip_hidden_cbox
);
613 file_all_charsets_cbox
=
614 check_new (cbox_position
--, 3, options
.file_all_charsets
, file_all_charsets_label
);
615 add_widget (find_dlg
, file_all_charsets_cbox
);
618 file_case_sens_cbox
= check_new (cbox_position
--, 3, options
.file_case_sens
, file_case_label
);
619 add_widget (find_dlg
, file_case_sens_cbox
);
621 file_pattern_cbox
= check_new (cbox_position
--, 3, options
.file_pattern
, file_pattern_label
);
622 add_widget (find_dlg
, file_pattern_cbox
);
624 recursively_cbox
= check_new (cbox_position
, 3, options
.find_recurs
, file_recurs_label
);
625 add_widget (find_dlg
, recursively_cbox
);
627 /* This checkbox is located in the second column */
629 check_new (cbox_position
, FIND_X
/ 2 + 1, options
.content_use
, content_use_label
);
630 add_widget (find_dlg
, content_use_cbox
);
633 input_new (8, FIND_X
/ 2 + 1, input_get_default_colors (), FIND_X
/ 2 - 4, INPUT_LAST_TEXT
,
634 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
635 widget_disable (in_with
->widget
, disable
);
636 add_widget (find_dlg
, in_with
);
638 content_label
= label_new (7, FIND_X
/ 2 + 1, _("Content:"));
639 widget_disable (content_label
->widget
, disable
);
640 add_widget (find_dlg
, content_label
);
642 in_name
= input_new (8, 3, input_get_default_colors (),
643 FIND_X
/ 2 - 4, INPUT_LAST_TEXT
, "name", INPUT_COMPLETE_DEFAULT
);
644 add_widget (find_dlg
, in_name
);
645 add_widget (find_dlg
, label_new (7, 3, _("File name:")));
647 in_ignore
= input_new (5, 3, input_get_default_colors (), FIND_X
- 6,
648 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "",
649 "ignoredirs", INPUT_COMPLETE_DEFAULT
);
650 widget_disable (in_ignore
->widget
, !options
.ignore_dirs_enable
);
651 add_widget (find_dlg
, in_ignore
);
654 check_new (4, 3, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
655 add_widget (find_dlg
, ignore_dirs_cbox
);
657 add_widget (find_dlg
, button_new (3, FIND_X
- b2
- 2, B_TREE
, NORMAL_BUTTON
, buts
[2], 0));
659 in_start
= input_new (3, 3, input_get_default_colors (),
660 FIND_X
- b2
- 6, in_start_dir
, "start", INPUT_COMPLETE_DEFAULT
);
661 add_widget (find_dlg
, in_start
);
662 add_widget (find_dlg
, label_new (2, 3, _("Start at:")));
665 dlg_select_widget (in_name
);
667 switch (run_dlg (find_dlg
))
670 return_value
= FALSE
;
675 const char *temp_dir
= in_start
->buffer
;
677 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
678 temp_dir
= current_panel
->cwd
;
680 if (in_start_dir
!= INPUT_LAST_TEXT
)
681 g_free (in_start_dir
);
682 in_start_dir
= tree_box (temp_dir
);
683 if (in_start_dir
== NULL
)
684 in_start_dir
= g_strdup (temp_dir
);
686 input_assign_text (in_start
, in_start_dir
);
688 /* Warning: Dreadful goto */
697 options
.file_all_charsets
= file_all_charsets_cbox
->state
& C_BOOL
;
698 options
.content_all_charsets
= content_all_charsets_cbox
->state
& C_BOOL
;
700 options
.content_use
= content_use_cbox
->state
& C_BOOL
;
701 options
.content_case_sens
= content_case_sens_cbox
->state
& C_BOOL
;
702 options
.content_regexp
= content_regexp_cbox
->state
& C_BOOL
;
703 options
.content_first_hit
= content_first_hit_cbox
->state
& C_BOOL
;
704 options
.content_whole_words
= content_whole_words_cbox
->state
& C_BOOL
;
705 options
.find_recurs
= recursively_cbox
->state
& C_BOOL
;
706 options
.file_pattern
= file_pattern_cbox
->state
& C_BOOL
;
707 options
.file_case_sens
= file_case_sens_cbox
->state
& C_BOOL
;
708 options
.skip_hidden
= skip_hidden_cbox
->state
& C_BOOL
;
709 options
.ignore_dirs_enable
= ignore_dirs_cbox
->state
& C_BOOL
;
710 g_free (options
.ignore_dirs
);
711 options
.ignore_dirs
= g_strdup (in_ignore
->buffer
);
713 *content
= (options
.content_use
&& in_with
->buffer
[0] != '\0')
714 ? g_strdup (in_with
->buffer
) : NULL
;
715 *start_dir
= in_start
->buffer
[0] != '\0' ? in_start
->buffer
: (char *) ".";
716 *pattern
= g_strdup (in_name
->buffer
);
717 if (in_start_dir
!= INPUT_LAST_TEXT
)
718 g_free (in_start_dir
);
719 in_start_dir
= g_strdup (*start_dir
);
721 s
= tilde_expand (*start_dir
);
722 canonicalize_pathname (s
);
724 if (s
[0] == '.' && s
[1] == '\0')
726 *start_dir
= g_strdup (current_panel
->cwd
);
727 /* FIXME: is current_panel->cwd canonicalized? */
728 /* relative paths will be used in panelization */
729 *start_dir_len
= (ssize_t
) strlen (current_panel
->cwd
);
732 else if (g_path_is_absolute (s
))
739 /* relative paths will be used in panelization */
740 *start_dir
= mc_build_filename (current_panel
->cwd
, s
, (char *) NULL
);
741 *start_dir_len
= (ssize_t
) strlen (current_panel
->cwd
);
745 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
746 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
749 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
751 find_save_options ();
757 destroy_dlg (find_dlg
);
762 /* --------------------------------------------------------------------------------------------- */
764 #if GLIB_CHECK_VERSION (2, 14, 0)
766 push_directory (const char *dir
)
768 g_queue_push_head (&dir_queue
, (void *) dir
);
771 /* --------------------------------------------------------------------------------------------- */
776 return (char *) g_queue_pop_tail (&dir_queue
);
779 /* --------------------------------------------------------------------------------------------- */
780 /** Remove all the items from the stack */
785 g_queue_foreach (&dir_queue
, (GFunc
) g_free
, NULL
);
786 g_queue_clear (&dir_queue
);
789 /* --------------------------------------------------------------------------------------------- */
791 #else /* GLIB_CHECK_VERSION */
793 push_directory (const char *dir
)
797 new = g_new (dir_stack
, 1);
798 new->name
= (char *) dir
;
799 new->prev
= dir_stack_base
;
800 dir_stack_base
= new;
803 /* --------------------------------------------------------------------------------------------- */
810 if (dir_stack_base
!= NULL
)
813 name
= dir_stack_base
->name
;
814 next
= dir_stack_base
->prev
;
815 g_free (dir_stack_base
);
816 dir_stack_base
= next
;
822 /* --------------------------------------------------------------------------------------------- */
823 /** Remove all the items from the stack */
829 while ((dir
= pop_directory ()) != NULL
)
832 #endif /* GLIB_CHECK_VERSION */
834 /* --------------------------------------------------------------------------------------------- */
837 insert_file (const char *dir
, const char *file
)
839 char *tmp_name
= NULL
;
840 static char *dirname
= NULL
;
842 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
847 if (strcmp (old_dir
, dir
))
850 old_dir
= g_strdup (dir
);
851 dirname
= add_to_list (dir
, NULL
);
856 old_dir
= g_strdup (dir
);
857 dirname
= add_to_list (dir
, NULL
);
860 tmp_name
= g_strdup_printf (" %s", file
);
861 add_to_list (tmp_name
, dirname
);
865 /* --------------------------------------------------------------------------------------------- */
868 find_add_match (const char *dir
, const char *file
)
870 insert_file (dir
, file
);
874 listbox_select_first (find_list
);
875 send_message (&find_list
->widget
, WIDGET_DRAW
, 0);
881 /* --------------------------------------------------------------------------------------------- */
885 * Returns malloced null-terminated line from file file_fd.
886 * Input is buffered in buf_size long buffer.
887 * Current pos in buf is stored in pos.
888 * n_read - number of read chars.
889 * has_newline - is there newline ?
893 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
905 *n_read
= mc_read (file_fd
, buf
, buf_size
);
913 /* skip possible leading zero(s) */
919 if (i
>= buffer_size
- 1)
920 buffer
= g_realloc (buffer
, buffer_size
+= 80);
929 *has_newline
= (ch
!= '\0');
937 /* --------------------------------------------------------------------------------------------- */
939 static FindProgressStatus
940 check_find_events (Dlg_head
* h
)
946 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
949 dlg_process_event (h
, c
, &event
);
950 if (h
->ret_value
== B_ENTER
951 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
953 /* dialog terminated */
956 if (!(h
->flags
& DLG_WANT_IDLE
))
958 /* searching suspended */
966 /* --------------------------------------------------------------------------------------------- */
970 * Search the content_pattern string in the DIRECTORY/FILE.
971 * It will add the found entries to the find listbox.
973 * returns FALSE if do_search should look for another file
974 * TRUE if do_search should exit and proceed to the event handler
978 search_content (Dlg_head
* h
, const char *directory
, const char *filename
)
984 gboolean ret_val
= FALSE
;
986 fname
= mc_build_filename (directory
, filename
, (char *) NULL
);
988 if (mc_stat (fname
, &s
) != 0 || !S_ISREG (s
.st_mode
))
994 file_fd
= mc_open (fname
, O_RDONLY
);
1000 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), str_trunc (filename
, FIND2_X_USE
));
1002 status_update (buffer
);
1005 tty_enable_interrupt_key ();
1006 tty_got_interrupt ();
1012 gboolean has_newline
;
1014 gboolean found
= FALSE
;
1016 char result
[BUF_MEDIUM
];
1020 /* We've been previously suspended, start from the previous position */
1026 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1027 &pos
, &n_read
, &has_newline
)) != NULL
)
1029 if (!found
/* Search in binary line once */
1030 && mc_search_run (search_content_handle
,
1031 (const void *) p
, 0, strlen (p
), &found_len
))
1033 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1034 find_add_match (directory
, result
);
1039 if (found
&& options
.content_first_hit
)
1048 if ((line
& 0xff) == 0)
1050 FindProgressStatus res
;
1051 res
= check_find_events (h
);
1070 tty_disable_interrupt_key ();
1075 /* --------------------------------------------------------------------------------------------- */
1078 If dir is absolute, this means we're within dir and searching file here.
1079 If dir is relative, this means we're going to add dir to the directory stack.
1082 find_ignore_dir_search (const char *dir
)
1084 if (find_ignore_dirs
!= NULL
)
1086 const size_t dlen
= strlen (dir
);
1087 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1091 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1093 const size_t ilen
= strlen (*ignore_dir
);
1094 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1096 /* ignore dir is too long -- skip it */
1100 /* handle absolute and relative paths */
1101 switch (iabs
| dabs
)
1103 case 0: /* both paths are relative */
1104 case 3: /* both paths are abolute */
1105 /* if ignore dir is not a path of dir -- skip it */
1106 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1108 /* be sure that ignore dir is not a part of dir like:
1109 ignore dir is "h", dir is "home" */
1110 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1114 case 1: /* dir is absolute, ignore_dir is relative */
1118 d
= strstr (dir
, *ignore_dir
);
1119 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1123 case 2: /* dir is relative, ignore_dir is absolute */
1124 /* FIXME: skip this case */
1126 default: /* this cannot occurs */
1135 /* --------------------------------------------------------------------------------------------- */
1138 find_rotate_dash (const Dlg_head
* h
, gboolean finish
)
1140 static const char rotating_dash
[] = "|/-\\";
1141 static unsigned int pos
= 0;
1145 pos
= (pos
+ 1) % 4;
1146 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1147 dlg_move (h
, FIND2_Y
- 7, FIND2_X
- 4);
1148 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1153 /* --------------------------------------------------------------------------------------------- */
1156 do_search (Dlg_head
* h
)
1158 static struct dirent
*dp
= NULL
;
1159 static DIR *dirp
= NULL
;
1160 static char *directory
= NULL
;
1161 struct stat tmp_stat
;
1162 static int subdirs_left
= 0;
1164 unsigned short count
;
1167 { /* someone forces me to close dirp */
1179 for (count
= 0; count
< 32; count
++)
1189 while (dirp
== NULL
)
1193 tty_setcolor (REVERSE_COLOR
);
1197 tmp
= pop_directory ();
1201 if (ignore_count
== 0)
1202 status_update (_("Finished"));
1205 char msg
[BUF_SMALL
];
1206 g_snprintf (msg
, sizeof (msg
),
1207 ngettext ("Finished (ignored %zd directory)",
1208 "Finished (ignored %zd directories)",
1209 ignore_count
), ignore_count
);
1210 status_update (msg
);
1212 find_rotate_dash (h
, TRUE
);
1217 /* handle absolute ignore dirs here */
1218 if (!find_ignore_dir_search (tmp
))
1230 char buffer
[BUF_SMALL
];
1232 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"),
1233 str_trunc (directory
, FIND2_X_USE
));
1234 status_update (buffer
);
1236 /* mc_stat should not be called after mc_opendir
1237 because vfs_s_opendir modifies the st_nlink
1239 if (mc_stat (directory
, &tmp_stat
) == 0)
1240 subdirs_left
= tmp_stat
.st_nlink
- 2;
1244 dirp
= mc_opendir (directory
);
1245 } /* while (!dirp) */
1247 /* skip invalid filenames */
1248 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1252 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1254 /* skip invalid filenames */
1255 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1261 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1265 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1266 { /* Can directory be NULL ? */
1267 /* handle relative ignore dirs here */
1268 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1274 tmp_name
= mc_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1276 if (mc_lstat (tmp_name
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1278 push_directory (tmp_name
);
1286 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1287 0, strlen (dp
->d_name
), &bytes_found
);
1291 if (content_pattern
== NULL
)
1292 find_add_match (directory
, dp
->d_name
);
1293 else if (search_content (h
, directory
, dp
->d_name
))
1298 /* skip invalid filenames */
1299 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1303 find_rotate_dash (h
, FALSE
);
1308 /* --------------------------------------------------------------------------------------------- */
1311 init_find_vars (void)
1318 /* Remove all the items from the stack */
1321 g_strfreev (find_ignore_dirs
);
1322 find_ignore_dirs
= NULL
;
1325 /* --------------------------------------------------------------------------------------------- */
1328 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1330 char *fullname
= NULL
;
1331 const char *filename
= NULL
;
1334 if (content_pattern
!= NULL
)
1336 filename
= strchr (file
+ 4, ':') + 1;
1337 line
= atoi (file
+ 4);
1341 filename
= file
+ 4;
1345 fullname
= mc_build_filename (dir
, filename
, (char *) NULL
);
1347 do_edit_at_line (fullname
, use_internal_edit
, line
);
1349 view_file_at_line (fullname
, unparsed_view
, use_internal_view
, line
);
1353 /* --------------------------------------------------------------------------------------------- */
1356 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1361 listbox_get_current (find_list
, &text
, (void **) &dir
);
1363 if ((text
== NULL
) || (dir
== NULL
))
1364 return MSG_NOT_HANDLED
;
1366 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1370 /* --------------------------------------------------------------------------------------------- */
1373 find_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
1378 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1380 int unparsed_view
= (parm
== KEY_F (13));
1381 return view_edit_currently_selected_file (unparsed_view
, 0);
1383 if (parm
== KEY_F (4))
1385 return view_edit_currently_selected_file (0, 1);
1387 return MSG_NOT_HANDLED
;
1394 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
1398 /* --------------------------------------------------------------------------------------------- */
1399 /** Handles the Stop/Start button in the find window */
1402 start_stop (WButton
* button
, int action
)
1408 set_idle_proc (find_dlg
, running
);
1409 is_start
= !is_start
;
1411 status_update (is_start
? _("Stopped") : _("Searching"));
1412 button_set_text (stop_button
, fbuts
[is_start
? 1 : 0].text
);
1417 /* --------------------------------------------------------------------------------------------- */
1418 /** Handle view command, when invoked as a button */
1421 find_do_view_file (WButton
* button
, int action
)
1426 view_edit_currently_selected_file (0, 0);
1430 /* --------------------------------------------------------------------------------------------- */
1431 /** Handle edit command, when invoked as a button */
1434 find_do_edit_file (WButton
* button
, int action
)
1439 view_edit_currently_selected_file (0, 1);
1443 /* --------------------------------------------------------------------------------------------- */
1449 static gboolean i18n_flag
= FALSE
;
1453 int i
= sizeof (fbuts
) / sizeof (fbuts
[0]);
1456 fbuts
[i
].text
= _(fbuts
[i
].text
);
1457 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1460 fbuts
[2].len
+= 2; /* DEFPUSH_BUTTON */
1463 #endif /* ENABLE_NLS */
1466 * Dynamically place buttons centered within current window size
1469 int l0
= max (fbuts
[0].len
, fbuts
[1].len
);
1470 int l1
= fbuts
[2].len
+ fbuts
[3].len
+ l0
+ fbuts
[4].len
;
1471 int l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
;
1474 /* Check, if both button rows fit within FIND2_X */
1475 FIND2_X
= max (l1
+ 9, COLS
- 16);
1476 FIND2_X
= max (l2
+ 8, FIND2_X
);
1478 /* compute amount of space between buttons for each row */
1479 r1
= (FIND2_X
- 4 - l1
) % 5;
1480 l1
= (FIND2_X
- 4 - l1
) / 5;
1481 r2
= (FIND2_X
- 4 - l2
) % 4;
1482 l2
= (FIND2_X
- 4 - l2
) / 4;
1484 /* ...and finally, place buttons */
1485 fbuts
[2].x
= 2 + r1
/ 2 + l1
;
1486 fbuts
[3].x
= fbuts
[2].x
+ fbuts
[2].len
+ l1
;
1487 fbuts
[0].x
= fbuts
[3].x
+ fbuts
[3].len
+ l1
;
1488 fbuts
[4].x
= fbuts
[0].x
+ l0
+ l1
;
1489 fbuts
[5].x
= 2 + r2
/ 2 + l2
;
1490 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ l2
;
1491 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ l2
;
1495 create_dlg (TRUE
, 0, 0, FIND2_Y
, FIND2_X
, dialog_colors
, find_callback
,
1496 "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
1498 add_widget (find_dlg
,
1499 button_new (FIND2_Y
- 3, fbuts
[7].x
, B_VIEW
, NORMAL_BUTTON
,
1500 fbuts
[7].text
, find_do_edit_file
));
1501 add_widget (find_dlg
,
1502 button_new (FIND2_Y
- 3, fbuts
[6].x
, B_VIEW
, NORMAL_BUTTON
,
1503 fbuts
[6].text
, find_do_view_file
));
1504 add_widget (find_dlg
,
1505 button_new (FIND2_Y
- 3, fbuts
[5].x
, B_PANELIZE
, NORMAL_BUTTON
, fbuts
[5].text
,
1508 add_widget (find_dlg
,
1509 button_new (FIND2_Y
- 4, fbuts
[4].x
, B_CANCEL
, NORMAL_BUTTON
, fbuts
[4].text
, NULL
));
1511 button_new (FIND2_Y
- 4, fbuts
[0].x
, B_STOP
, NORMAL_BUTTON
, fbuts
[0].text
, start_stop
);
1512 add_widget (find_dlg
, stop_button
);
1513 add_widget (find_dlg
,
1514 button_new (FIND2_Y
- 4, fbuts
[3].x
, B_AGAIN
, NORMAL_BUTTON
, fbuts
[3].text
, NULL
));
1515 add_widget (find_dlg
,
1516 button_new (FIND2_Y
- 4, fbuts
[2].x
, B_ENTER
, DEFPUSH_BUTTON
, fbuts
[2].text
, NULL
));
1518 status_label
= label_new (FIND2_Y
- 7, 4, _("Searching"));
1519 add_widget (find_dlg
, status_label
);
1521 found_num_label
= label_new (FIND2_Y
- 6, 4, "");
1522 add_widget (find_dlg
, found_num_label
);
1524 find_list
= listbox_new (2, 2, FIND2_Y
- 10, FIND2_X
- 4, FALSE
, NULL
);
1525 add_widget (find_dlg
, find_list
);
1528 /* --------------------------------------------------------------------------------------------- */
1535 search_content_handle
= mc_search_new (content_pattern
, -1);
1536 if (search_content_handle
)
1538 search_content_handle
->search_type
=
1539 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1540 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1541 search_content_handle
->whole_words
= options
.content_whole_words
;
1542 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1544 search_file_handle
= mc_search_new (find_pattern
, -1);
1545 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1546 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1547 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1548 search_file_handle
->is_entire_line
= options
.file_pattern
;
1552 set_idle_proc (find_dlg
, 1);
1553 ret
= run_dlg (find_dlg
);
1555 mc_search_free (search_file_handle
);
1556 search_file_handle
= NULL
;
1557 mc_search_free (search_content_handle
);
1558 search_content_handle
= NULL
;
1563 /* --------------------------------------------------------------------------------------------- */
1568 set_idle_proc (find_dlg
, 0);
1569 destroy_dlg (find_dlg
);
1572 /* --------------------------------------------------------------------------------------------- */
1575 do_find (const char *start_dir
, ssize_t start_dir_len
, const char *ignore_dirs
,
1576 const char *pattern
, const char *content
, char **dirname
, char **filename
)
1578 int return_value
= 0;
1579 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1583 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1584 find_pattern
= (char *) pattern
;
1586 content_pattern
= NULL
;
1587 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1588 content_pattern
= g_strdup (content
);
1591 parse_ignore_dirs (ignore_dirs
);
1592 push_directory (start_dir
);
1594 return_value
= run_process ();
1596 /* Clear variables */
1599 get_list_info (&file_tmp
, &dir_tmp
);
1602 *dirname
= g_strdup (dir_tmp
);
1604 *filename
= g_strdup (file_tmp
);
1606 if (return_value
== B_PANELIZE
&& *filename
)
1608 int status
, link_to_dir
, stale_link
;
1613 dir_list
*list
= ¤t_panel
->dir
;
1616 if (set_zero_dir (list
))
1619 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1621 const char *lc_filename
= NULL
;
1622 WLEntry
*le
= (WLEntry
*) entry
->data
;
1625 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1628 if (content_pattern
!= NULL
)
1629 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1631 lc_filename
= le
->text
+ 4;
1633 name
= mc_build_filename (le
->data
, lc_filename
, (char *) NULL
);
1634 /* skip initial start dir */
1635 if (start_dir_len
< 0)
1639 p
= name
+ (size_t) start_dir_len
;
1644 status
= handle_path (list
, p
, &st
, next_free
, &link_to_dir
, &stale_link
);
1656 /* don't add files more than once to the panel */
1657 if (content_pattern
!= NULL
&& next_free
> 0
1658 && strcmp (list
->list
[next_free
- 1].fname
, p
) == 0)
1664 if (next_free
== 0) /* first turn i.e clean old list */
1665 panel_clean_dir (current_panel
);
1666 list
->list
[next_free
].fnamelen
= strlen (p
);
1667 list
->list
[next_free
].fname
= g_strndup (p
, list
->list
[next_free
].fnamelen
);
1668 list
->list
[next_free
].f
.marked
= 0;
1669 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1670 list
->list
[next_free
].f
.stale_link
= stale_link
;
1671 list
->list
[next_free
].f
.dir_size_computed
= 0;
1672 list
->list
[next_free
].st
= st
;
1673 list
->list
[next_free
].sort_key
= NULL
;
1674 list
->list
[next_free
].second_sort_key
= NULL
;
1677 if (!(next_free
& 15))
1683 current_panel
->count
= next_free
;
1684 current_panel
->is_panelized
= TRUE
;
1687 if (start_dir_len
< 0)
1691 strcpy (current_panel
->cwd
, PATH_SEP_STR
);
1692 ret
= chdir (PATH_SEP_STR
);
1694 panelize_save_panel (current_panel
);
1698 g_free (content_pattern
);
1700 do_search (NULL
); /* force do_search to release resources */
1704 return return_value
;
1707 /* --------------------------------------------------------------------------------------------- */
1708 /*** public functions ****************************************************************************/
1709 /* --------------------------------------------------------------------------------------------- */
1714 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1715 ssize_t start_dir_len
;
1716 char *filename
= NULL
, *dirname
= NULL
;
1719 while (find_parameters (&start_dir
, &start_dir_len
, &ignore_dirs
, &pattern
, &content
))
1721 if (pattern
[0] == '\0')
1722 break; /* nothing search */
1724 dirname
= filename
= NULL
;
1726 v
= do_find (start_dir
, start_dir_len
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1727 g_free (ignore_dirs
);
1732 if (dirname
!= NULL
)
1734 do_cd (dirname
, cd_exact
);
1735 if (filename
!= NULL
)
1736 try_to_select (current_panel
,
1737 filename
+ (content
!= NULL
1738 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1740 else if (filename
!= NULL
)
1741 do_cd (filename
, cd_exact
);
1755 if (v
== B_PANELIZE
)
1757 panel_re_sort (current_panel
);
1758 try_to_select (current_panel
, NULL
);
1764 /* --------------------------------------------------------------------------------------------- */