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/vfs/vfs.h"
43 #include "lib/strutil.h"
44 #include "lib/widget.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 */
58 /*** global variables ****************************************************************************/
60 /*** file scope macro definitions ****************************************************************/
62 /* Size of the find window */
63 #define FIND2_Y (LINES - 4)
65 #define FIND2_X_USE (FIND2_X - 20)
67 /*** file scope type declarations ****************************************************************/
69 /* A couple of extra messages we need */
86 /* find file options */
89 /* file name options */
90 gboolean file_case_sens
;
91 gboolean file_pattern
;
94 gboolean file_all_charsets
;
96 /* file content options */
98 gboolean content_case_sens
;
99 gboolean content_regexp
;
100 gboolean content_first_hit
;
101 gboolean content_whole_words
;
102 gboolean content_all_charsets
;
104 /* whether use ignore dirs or not */
105 gboolean ignore_dirs_enable
;
106 /* list of directories to be ignored, separated by ':' */
108 } find_file_options_t
;
110 /*** file scope variables ************************************************************************/
112 /* Parsed ignore dirs */
113 static char **find_ignore_dirs
= NULL
;
115 /* Size of the find parameters window */
117 static int FIND_Y
= 19;
119 static int FIND_Y
= 18;
121 static int FIND_X
= 68;
123 static int FIND2_X
= 64;
125 /* static variables to remember find parameters */
126 static WInput
*in_start
; /* Start path */
127 static WInput
*in_name
; /* Filename */
128 static WInput
*in_with
; /* Text */
129 static WInput
*in_ignore
;
130 static WLabel
*content_label
; /* 'Content:' label */
131 static WCheck
*file_case_sens_cbox
; /* "case sensitive" checkbox */
132 static WCheck
*file_pattern_cbox
; /* File name is glob or regexp */
133 static WCheck
*recursively_cbox
;
134 static WCheck
*skip_hidden_cbox
;
135 static WCheck
*content_use_cbox
; /* Take into account the Content field */
136 static WCheck
*content_case_sens_cbox
; /* "case sensitive" checkbox */
137 static WCheck
*content_regexp_cbox
; /* "find regular expression" checkbox */
138 static WCheck
*content_first_hit_cbox
; /* "First hit" checkbox" */
139 static WCheck
*content_whole_words_cbox
; /* "whole words" checkbox */
141 static WCheck
*file_all_charsets_cbox
;
142 static WCheck
*content_all_charsets_cbox
;
144 static WCheck
*ignore_dirs_cbox
;
146 static gboolean running
= FALSE
; /* nice flag */
147 static char *find_pattern
= NULL
; /* Pattern to search */
148 static char *content_pattern
= NULL
; /* pattern to search inside files; if
149 content_regexp_flag is true, it contains the
150 regex pattern, else the search string. */
151 static unsigned long matches
; /* Number of matches */
152 static gboolean is_start
= FALSE
; /* Status of the start/stop toggle button */
153 static char *old_dir
= NULL
;
155 /* Where did we stop */
157 static int last_line
;
160 static size_t ignore_count
= 0;
162 static Dlg_head
*find_dlg
; /* The dialog */
163 static WButton
*stop_button
; /* pointer to the stop button */
164 static WLabel
*status_label
; /* Finished, Searching etc. */
165 static WLabel
*found_num_label
; /* Number of found items */
166 static WListbox
*find_list
; /* Listbox with the file list */
168 /* This keeps track of the directory stack */
169 #if GLIB_CHECK_VERSION (2, 14, 0)
170 static GQueue dir_queue
= G_QUEUE_INIT
;
172 typedef struct dir_stack
175 struct dir_stack
*prev
;
178 static dir_stack
*dir_stack_base
= 0;
179 #endif /* GLIB_CHECK_VERSION */
185 int len
; /* length including space and brackets */
189 {N_("&Suspend"), 11, 29},
190 {N_("Con&tinue"), 12, 29},
191 {N_("&Chdir"), 11, 3},
192 {N_("&Again"), 9, 17},
193 {N_("&Quit"), 8, 43},
194 {N_("Pane&lize"), 12, 3},
195 {N_("&View - F3"), 13, 20},
196 {N_("&Edit - F4"), 13, 38}
200 static find_file_options_t options
= {
201 TRUE
, TRUE
, TRUE
, FALSE
, FALSE
,
202 FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
205 static char *in_start_dir
= INPUT_LAST_TEXT
;
207 static mc_search_t
*search_file_handle
= NULL
;
208 static mc_search_t
*search_content_handle
= NULL
;
210 /*** file scope functions ************************************************************************/
213 parse_ignore_dirs (const char *ignore_dirs
)
215 size_t r
= 0, w
= 0; /* read and write iterators */
217 if (!options
.ignore_dirs_enable
|| ignore_dirs
== NULL
|| ignore_dirs
[0] == '\0')
220 find_ignore_dirs
= g_strsplit (ignore_dirs
, ":", -1);
222 /* Values like '/foo::/bar: produce holes in list.
223 * Find and remove them */
224 for (; find_ignore_dirs
[r
] != NULL
; r
++)
226 if (find_ignore_dirs
[r
][0] == '\0')
228 /* empty entry -- skip it */
229 g_free (find_ignore_dirs
[r
]);
230 find_ignore_dirs
[r
] = NULL
;
236 /* copy entry to the previous free array cell */
237 find_ignore_dirs
[w
] = find_ignore_dirs
[r
];
238 find_ignore_dirs
[r
] = NULL
;
241 canonicalize_pathname (find_ignore_dirs
[w
]);
242 if (find_ignore_dirs
[w
][0] != '\0')
246 g_free (find_ignore_dirs
[w
]);
247 find_ignore_dirs
[w
] = NULL
;
251 if (find_ignore_dirs
[0] == NULL
)
253 g_strfreev (find_ignore_dirs
);
254 find_ignore_dirs
= NULL
;
258 /* --------------------------------------------------------------------------------------------- */
261 find_load_options (void)
263 static gboolean loaded
= FALSE
;
271 options
.file_case_sens
=
272 mc_config_get_bool (mc_main_config
, "FindFile", "file_case_sens", TRUE
);
273 options
.file_pattern
=
274 mc_config_get_bool (mc_main_config
, "FindFile", "file_shell_pattern", TRUE
);
275 options
.find_recurs
= mc_config_get_bool (mc_main_config
, "FindFile", "file_find_recurs", TRUE
);
276 options
.skip_hidden
=
277 mc_config_get_bool (mc_main_config
, "FindFile", "file_skip_hidden", FALSE
);
278 options
.file_all_charsets
=
279 mc_config_get_bool (mc_main_config
, "FindFile", "file_all_charsets", FALSE
);
280 options
.content_use
= mc_config_get_bool (mc_main_config
, "FindFile", "content_use", TRUE
);
281 options
.content_case_sens
=
282 mc_config_get_bool (mc_main_config
, "FindFile", "content_case_sens", TRUE
);
283 options
.content_regexp
=
284 mc_config_get_bool (mc_main_config
, "FindFile", "content_regexp", FALSE
);
285 options
.content_first_hit
=
286 mc_config_get_bool (mc_main_config
, "FindFile", "content_first_hit", FALSE
);
287 options
.content_whole_words
=
288 mc_config_get_bool (mc_main_config
, "FindFile", "content_whole_words", FALSE
);
289 options
.content_all_charsets
=
290 mc_config_get_bool (mc_main_config
, "FindFile", "content_all_charsets", FALSE
);
291 options
.ignore_dirs_enable
=
292 mc_config_get_bool (mc_main_config
, "FindFile", "ignore_dirs_enable", TRUE
);
294 /* Back compatibility: try load old parameter at first */
295 ignore_dirs
= mc_config_get_string (mc_main_config
, "Misc", "find_ignore_dirs", "");
296 mc_config_del_key (mc_main_config
, "Misc", "find_ignore_dirs");
298 /* Then load new parameters */
299 options
.ignore_dirs
= mc_config_get_string (mc_main_config
, "FindFile", "ignore_dirs", "");
300 if (options
.ignore_dirs
[0] != '\0')
301 g_free (ignore_dirs
);
304 g_free (options
.ignore_dirs
);
305 options
.ignore_dirs
= ignore_dirs
;
308 if (options
.ignore_dirs
[0] == '\0')
310 g_free (options
.ignore_dirs
);
311 options
.ignore_dirs
= NULL
;
315 /* --------------------------------------------------------------------------------------------- */
318 find_save_options (void)
320 mc_config_set_bool (mc_main_config
, "FindFile", "file_case_sens", options
.file_case_sens
);
321 mc_config_set_bool (mc_main_config
, "FindFile", "file_shell_pattern", options
.file_pattern
);
322 mc_config_set_bool (mc_main_config
, "FindFile", "file_find_recurs", options
.find_recurs
);
323 mc_config_set_bool (mc_main_config
, "FindFile", "file_skip_hidden", options
.skip_hidden
);
324 mc_config_set_bool (mc_main_config
, "FindFile", "file_all_charsets", options
.file_all_charsets
);
325 mc_config_set_bool (mc_main_config
, "FindFile", "content_use", options
.content_use
);
326 mc_config_set_bool (mc_main_config
, "FindFile", "content_case_sens", options
.content_case_sens
);
327 mc_config_set_bool (mc_main_config
, "FindFile", "content_regexp", options
.content_regexp
);
328 mc_config_set_bool (mc_main_config
, "FindFile", "content_first_hit", options
.content_first_hit
);
329 mc_config_set_bool (mc_main_config
, "FindFile", "content_whole_words",
330 options
.content_whole_words
);
331 mc_config_set_bool (mc_main_config
, "FindFile", "content_all_charsets",
332 options
.content_all_charsets
);
333 mc_config_set_bool (mc_main_config
, "FindFile", "ignore_dirs_enable",
334 options
.ignore_dirs_enable
);
335 mc_config_set_string (mc_main_config
, "FindFile", "ignore_dirs", options
.ignore_dirs
);
338 /* --------------------------------------------------------------------------------------------- */
341 add_to_list (const char *text
, void *data
)
343 return listbox_add_item (find_list
, LISTBOX_APPEND_AT_END
, 0, text
, data
);
346 /* --------------------------------------------------------------------------------------------- */
349 stop_idle (void *data
)
351 set_idle_proc (data
, 0);
354 /* --------------------------------------------------------------------------------------------- */
357 status_update (const char *text
)
359 label_set_text (status_label
, text
);
362 /* --------------------------------------------------------------------------------------------- */
365 found_num_update (void)
367 char buffer
[BUF_TINY
];
368 g_snprintf (buffer
, sizeof (buffer
), _("Found: %ld"), matches
);
369 label_set_text (found_num_label
, buffer
);
372 /* --------------------------------------------------------------------------------------------- */
375 get_list_info (char **file
, char **dir
)
377 listbox_get_current (find_list
, file
, (void **) dir
);
380 /* --------------------------------------------------------------------------------------------- */
381 /** check regular expression */
384 find_check_regexp (const char *r
)
387 gboolean regexp_ok
= FALSE
;
389 search
= mc_search_new (r
, -1);
393 search
->search_type
= MC_SEARCH_T_REGEX
;
394 regexp_ok
= mc_search_prepare (search
);
395 mc_search_free (search
);
401 /* --------------------------------------------------------------------------------------------- */
403 * Callback for the parameter dialog.
404 * Validate regex, prevent closing the dialog if it's invalid.
408 find_parm_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
413 if (sender
== (Widget
*) content_use_cbox
)
415 gboolean disable
= !(content_use_cbox
->state
& C_BOOL
);
417 widget_disable (content_label
->widget
, disable
);
418 send_message ((Widget
*) content_label
, WIDGET_DRAW
, 0);
419 widget_disable (in_with
->widget
, disable
);
420 send_message ((Widget
*) in_with
, WIDGET_DRAW
, 0);
421 widget_disable (content_first_hit_cbox
->widget
, disable
);
422 send_message ((Widget
*) content_first_hit_cbox
, WIDGET_DRAW
, 0);
423 widget_disable (content_regexp_cbox
->widget
, disable
);
424 send_message ((Widget
*) content_regexp_cbox
, WIDGET_DRAW
, 0);
425 widget_disable (content_case_sens_cbox
->widget
, disable
);
426 send_message ((Widget
*) content_case_sens_cbox
, WIDGET_DRAW
, 0);
428 widget_disable (content_all_charsets_cbox
->widget
, disable
);
429 send_message ((Widget
*) content_all_charsets_cbox
, WIDGET_DRAW
, 0);
431 widget_disable (content_whole_words_cbox
->widget
, disable
);
432 send_message ((Widget
*) content_whole_words_cbox
, WIDGET_DRAW
, 0);
437 if (sender
== (Widget
*) ignore_dirs_cbox
)
439 gboolean disable
= !(ignore_dirs_cbox
->state
& C_BOOL
);
441 widget_disable (in_ignore
->widget
, disable
);
442 send_message ((Widget
*) in_ignore
, WIDGET_DRAW
, 0);
447 return MSG_NOT_HANDLED
;
451 if (h
->ret_value
!= B_ENTER
)
454 /* check filename regexp */
455 if (!(file_pattern_cbox
->state
& C_BOOL
)
456 && (in_name
->buffer
[0] != '\0') && !find_check_regexp (in_name
->buffer
))
458 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
459 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
460 dlg_select_widget (in_name
);
464 /* check content regexp */
465 if ((content_use_cbox
->state
& C_BOOL
) && (content_regexp_cbox
->state
& C_BOOL
)
466 && (in_with
->buffer
[0] != '\0') && !find_check_regexp (in_with
->buffer
))
468 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
469 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
470 dlg_select_widget (in_with
);
477 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
481 /* --------------------------------------------------------------------------------------------- */
483 * find_parameters: gets information from the user
485 * If the return value is TRUE, then the following holds:
487 * START_DIR, IGNORE_FIR and PATTERN are pointers to char * and upon return they
488 * contain the information provided by the user.
490 * CONTENT holds a strdup of the contents specified by the user if he
491 * asked for them or 0 if not (note, this is different from the
492 * behavior for the other two parameters.
497 find_parameters (char **start_dir
, char **ignore_dirs
, char **pattern
, char **content
)
499 gboolean return_value
;
502 const char *file_case_label
= N_("Cas&e sensitive");
503 const char *file_pattern_label
= N_("&Using shell patterns");
504 const char *file_recurs_label
= N_("&Find recursively");
505 const char *file_skip_hidden_label
= N_("S&kip hidden");
507 const char *file_all_charsets_label
= N_("&All charsets");
511 const char *content_use_label
= N_("Sea&rch for content");
512 const char *content_case_label
= N_("Case sens&itive");
513 const char *content_regexp_label
= N_("Re&gular expression");
514 const char *content_first_hit_label
= N_("Fir&st hit");
515 const char *content_whole_words_label
= N_("&Whole words");
517 const char *content_all_charsets_label
= N_("A&ll charsets");
520 const char *buts
[] = { N_("&OK"), N_("&Cancel"), N_("&Tree") };
529 int i
= sizeof (buts
) / sizeof (buts
[0]);
531 buts
[i
] = _(buts
[i
]);
533 file_case_label
= _(file_case_label
);
534 file_pattern_label
= _(file_pattern_label
);
535 file_recurs_label
= _(file_recurs_label
);
536 file_skip_hidden_label
= _(file_skip_hidden_label
);
538 file_all_charsets_label
= _(file_all_charsets_label
);
539 content_all_charsets_label
= _(content_all_charsets_label
);
541 content_use_label
= _(content_use_label
);
542 content_case_label
= _(content_case_label
);
543 content_regexp_label
= _(content_regexp_label
);
544 content_first_hit_label
= _(content_first_hit_label
);
545 content_whole_words_label
= _(content_whole_words_label
);
547 #endif /* ENABLE_NLS */
549 b0
= str_term_width1 (buts
[0]) + 6; /* default button */
550 b1
= str_term_width1 (buts
[1]) + 4;
551 b2
= str_term_width1 (buts
[2]) + 4;
553 find_load_options ();
555 if (in_start_dir
== NULL
)
556 in_start_dir
= g_strdup (".");
558 disable
= !options
.content_use
;
561 create_dlg (TRUE
, 0, 0, FIND_Y
, FIND_X
, dialog_colors
,
562 find_parm_callback
, "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
564 add_widget (find_dlg
,
565 button_new (FIND_Y
- 3, FIND_X
* 3 / 4 - b1
/ 2, B_CANCEL
, NORMAL_BUTTON
, buts
[1],
567 add_widget (find_dlg
,
568 button_new (FIND_Y
- 3, FIND_X
/ 4 - b0
/ 2, B_ENTER
, DEFPUSH_BUTTON
, buts
[0], 0));
570 cbox_position
= FIND_Y
- 5;
572 content_first_hit_cbox
=
573 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_first_hit
,
574 content_first_hit_label
);
575 widget_disable (content_first_hit_cbox
->widget
, disable
);
576 add_widget (find_dlg
, content_first_hit_cbox
);
578 content_whole_words_cbox
=
579 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_whole_words
,
580 content_whole_words_label
);
581 widget_disable (content_whole_words_cbox
->widget
, disable
);
582 add_widget (find_dlg
, content_whole_words_cbox
);
585 content_all_charsets_cbox
= check_new (cbox_position
--, FIND_X
/ 2 + 1,
586 options
.content_all_charsets
,
587 content_all_charsets_label
);
588 widget_disable (content_all_charsets_cbox
->widget
, disable
);
589 add_widget (find_dlg
, content_all_charsets_cbox
);
592 content_case_sens_cbox
=
593 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_case_sens
, content_case_label
);
594 widget_disable (content_case_sens_cbox
->widget
, disable
);
595 add_widget (find_dlg
, content_case_sens_cbox
);
597 content_regexp_cbox
=
598 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_regexp
, content_regexp_label
);
599 widget_disable (content_regexp_cbox
->widget
, disable
);
600 add_widget (find_dlg
, content_regexp_cbox
);
602 cbox_position
= FIND_Y
- 6;
604 skip_hidden_cbox
= check_new (cbox_position
--, 3, options
.skip_hidden
, file_skip_hidden_label
);
605 add_widget (find_dlg
, skip_hidden_cbox
);
608 file_all_charsets_cbox
=
609 check_new (cbox_position
--, 3, options
.file_all_charsets
, file_all_charsets_label
);
610 add_widget (find_dlg
, file_all_charsets_cbox
);
613 file_case_sens_cbox
= check_new (cbox_position
--, 3, options
.file_case_sens
, file_case_label
);
614 add_widget (find_dlg
, file_case_sens_cbox
);
616 file_pattern_cbox
= check_new (cbox_position
--, 3, options
.file_pattern
, file_pattern_label
);
617 add_widget (find_dlg
, file_pattern_cbox
);
619 recursively_cbox
= check_new (cbox_position
, 3, options
.find_recurs
, file_recurs_label
);
620 add_widget (find_dlg
, recursively_cbox
);
622 /* This checkbox is located in the second column */
624 check_new (cbox_position
, FIND_X
/ 2 + 1, options
.content_use
, content_use_label
);
625 add_widget (find_dlg
, content_use_cbox
);
628 input_new (8, FIND_X
/ 2 + 1, input_get_default_colors (), FIND_X
/ 2 - 4, INPUT_LAST_TEXT
,
629 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
630 widget_disable (in_with
->widget
, disable
);
631 add_widget (find_dlg
, in_with
);
633 content_label
= label_new (7, FIND_X
/ 2 + 1, _("Content:"));
634 widget_disable (content_label
->widget
, disable
);
635 add_widget (find_dlg
, content_label
);
637 in_name
= input_new (8, 3, input_get_default_colors (),
638 FIND_X
/ 2 - 4, INPUT_LAST_TEXT
, "name", INPUT_COMPLETE_DEFAULT
);
639 add_widget (find_dlg
, in_name
);
640 add_widget (find_dlg
, label_new (7, 3, _("File name:")));
642 in_ignore
= input_new (5, 3, input_get_default_colors (), FIND_X
- 6,
643 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "",
644 "ignoredirs", INPUT_COMPLETE_DEFAULT
);
645 widget_disable (in_ignore
->widget
, !options
.ignore_dirs_enable
);
646 add_widget (find_dlg
, in_ignore
);
649 check_new (4, 3, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
650 add_widget (find_dlg
, ignore_dirs_cbox
);
652 add_widget (find_dlg
, button_new (3, FIND_X
- b2
- 2, B_TREE
, NORMAL_BUTTON
, buts
[2], 0));
654 in_start
= input_new (3, 3, input_get_default_colors (),
655 FIND_X
- b2
- 6, in_start_dir
, "start", INPUT_COMPLETE_DEFAULT
);
656 add_widget (find_dlg
, in_start
);
657 add_widget (find_dlg
, label_new (2, 3, _("Start at:")));
660 dlg_select_widget (in_name
);
662 switch (run_dlg (find_dlg
))
665 return_value
= FALSE
;
670 const char *temp_dir
= in_start
->buffer
;
672 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
673 temp_dir
= current_panel
->cwd
;
675 if (in_start_dir
!= INPUT_LAST_TEXT
)
676 g_free (in_start_dir
);
677 in_start_dir
= tree_box (temp_dir
);
678 if (in_start_dir
== NULL
)
679 in_start_dir
= g_strdup (temp_dir
);
681 input_assign_text (in_start
, in_start_dir
);
683 /* Warning: Dreadful goto */
689 options
.file_all_charsets
= file_all_charsets_cbox
->state
& C_BOOL
;
690 options
.content_all_charsets
= content_all_charsets_cbox
->state
& C_BOOL
;
692 options
.content_use
= content_use_cbox
->state
& C_BOOL
;
693 options
.content_case_sens
= content_case_sens_cbox
->state
& C_BOOL
;
694 options
.content_regexp
= content_regexp_cbox
->state
& C_BOOL
;
695 options
.content_first_hit
= content_first_hit_cbox
->state
& C_BOOL
;
696 options
.content_whole_words
= content_whole_words_cbox
->state
& C_BOOL
;
697 options
.find_recurs
= recursively_cbox
->state
& C_BOOL
;
698 options
.file_pattern
= file_pattern_cbox
->state
& C_BOOL
;
699 options
.file_case_sens
= file_case_sens_cbox
->state
& C_BOOL
;
700 options
.skip_hidden
= skip_hidden_cbox
->state
& C_BOOL
;
701 options
.ignore_dirs_enable
= ignore_dirs_cbox
->state
& C_BOOL
;
702 g_free (options
.ignore_dirs
);
703 options
.ignore_dirs
= g_strdup (in_ignore
->buffer
);
705 *content
= (options
.content_use
&& in_with
->buffer
[0] != '\0')
706 ? g_strdup (in_with
->buffer
) : NULL
;
707 *start_dir
= in_start
->buffer
[0] != '\0' ? in_start
->buffer
: (char *) ".";
708 *pattern
= g_strdup (in_name
->buffer
);
709 if (in_start_dir
!= INPUT_LAST_TEXT
)
710 g_free (in_start_dir
);
711 in_start_dir
= g_strdup (*start_dir
);
712 if ((*start_dir
)[0] == '.' && (*start_dir
)[1] == '\0')
713 *start_dir
= g_strdup (current_panel
->cwd
);
714 else if (g_path_is_absolute (*start_dir
))
715 *start_dir
= g_strdup (*start_dir
);
717 *start_dir
= mc_build_filename (current_panel
->cwd
, *start_dir
, (char *) NULL
);
719 canonicalize_pathname (*start_dir
);
721 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
722 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
725 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
727 find_save_options ();
732 destroy_dlg (find_dlg
);
737 /* --------------------------------------------------------------------------------------------- */
739 #if GLIB_CHECK_VERSION (2, 14, 0)
741 push_directory (const char *dir
)
743 g_queue_push_head (&dir_queue
, (void *) dir
);
746 /* --------------------------------------------------------------------------------------------- */
751 return (char *) g_queue_pop_tail (&dir_queue
);
754 /* --------------------------------------------------------------------------------------------- */
755 /** Remove all the items from the stack */
760 g_queue_foreach (&dir_queue
, (GFunc
) g_free
, NULL
);
761 g_queue_clear (&dir_queue
);
764 /* --------------------------------------------------------------------------------------------- */
766 #else /* GLIB_CHECK_VERSION */
768 push_directory (const char *dir
)
772 new = g_new (dir_stack
, 1);
773 new->name
= (char *) dir
;
774 new->prev
= dir_stack_base
;
775 dir_stack_base
= new;
778 /* --------------------------------------------------------------------------------------------- */
785 if (dir_stack_base
!= NULL
)
788 name
= dir_stack_base
->name
;
789 next
= dir_stack_base
->prev
;
790 g_free (dir_stack_base
);
791 dir_stack_base
= next
;
797 /* --------------------------------------------------------------------------------------------- */
798 /** Remove all the items from the stack */
804 while ((dir
= pop_directory ()) != NULL
)
807 #endif /* GLIB_CHECK_VERSION */
809 /* --------------------------------------------------------------------------------------------- */
812 insert_file (const char *dir
, const char *file
)
814 char *tmp_name
= NULL
;
815 static char *dirname
= NULL
;
817 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
822 if (strcmp (old_dir
, dir
))
825 old_dir
= g_strdup (dir
);
826 dirname
= add_to_list (dir
, NULL
);
831 old_dir
= g_strdup (dir
);
832 dirname
= add_to_list (dir
, NULL
);
835 tmp_name
= g_strdup_printf (" %s", file
);
836 add_to_list (tmp_name
, dirname
);
840 /* --------------------------------------------------------------------------------------------- */
843 find_add_match (const char *dir
, const char *file
)
845 insert_file (dir
, file
);
849 listbox_select_first (find_list
);
850 send_message (&find_list
->widget
, WIDGET_DRAW
, 0);
856 /* --------------------------------------------------------------------------------------------- */
860 * Returns malloced null-terminated line from file file_fd.
861 * Input is buffered in buf_size long buffer.
862 * Current pos in buf is stored in pos.
863 * n_read - number of read chars.
864 * has_newline - is there newline ?
868 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
880 *n_read
= mc_read (file_fd
, buf
, buf_size
);
888 /* skip possible leading zero(s) */
894 if (i
>= buffer_size
- 1)
895 buffer
= g_realloc (buffer
, buffer_size
+= 80);
904 *has_newline
= (ch
!= '\0');
912 /* --------------------------------------------------------------------------------------------- */
914 static FindProgressStatus
915 check_find_events (Dlg_head
* h
)
921 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
924 dlg_process_event (h
, c
, &event
);
925 if (h
->ret_value
== B_ENTER
926 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
928 /* dialog terminated */
931 if (!(h
->flags
& DLG_WANT_IDLE
))
933 /* searching suspended */
941 /* --------------------------------------------------------------------------------------------- */
945 * Search the content_pattern string in the DIRECTORY/FILE.
946 * It will add the found entries to the find listbox.
948 * returns FALSE if do_search should look for another file
949 * TRUE if do_search should exit and proceed to the event handler
953 search_content (Dlg_head
* h
, const char *directory
, const char *filename
)
959 gboolean ret_val
= FALSE
;
961 fname
= concat_dir_and_file (directory
, filename
);
963 if (mc_stat (fname
, &s
) != 0 || !S_ISREG (s
.st_mode
))
969 file_fd
= mc_open (fname
, O_RDONLY
);
975 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), str_trunc (filename
, FIND2_X_USE
));
977 status_update (buffer
);
980 tty_enable_interrupt_key ();
981 tty_got_interrupt ();
987 gboolean has_newline
;
989 gboolean found
= FALSE
;
991 char result
[BUF_MEDIUM
];
995 /* We've been previously suspended, start from the previous position */
1001 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1002 &pos
, &n_read
, &has_newline
)) != NULL
)
1004 if (!found
/* Search in binary line once */
1005 && mc_search_run (search_content_handle
,
1006 (const void *) p
, 0, strlen (p
), &found_len
))
1008 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1009 find_add_match (directory
, result
);
1014 if (found
&& options
.content_first_hit
)
1023 if ((line
& 0xff) == 0)
1025 FindProgressStatus res
;
1026 res
= check_find_events (h
);
1045 tty_disable_interrupt_key ();
1050 /* --------------------------------------------------------------------------------------------- */
1053 If dir is absolute, this means we're within dir and searching file here.
1054 If dir is relative, this means we're going to add dir to the directory stack.
1057 find_ignore_dir_search (const char *dir
)
1059 if (find_ignore_dirs
!= NULL
)
1061 const size_t dlen
= strlen (dir
);
1062 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1066 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1068 const size_t ilen
= strlen (*ignore_dir
);
1069 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1071 /* ignore dir is too long -- skip it */
1075 /* handle absolute and relative paths */
1076 switch (iabs
| dabs
)
1078 case 0: /* both paths are relative */
1079 case 3: /* both paths are abolute */
1080 /* if ignore dir is not a path of dir -- skip it */
1081 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1083 /* be sure that ignore dir is not a part of dir like:
1084 ignore dir is "h", dir is "home" */
1085 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1089 case 1: /* dir is absolute, ignore_dir is relative */
1093 d
= strstr (dir
, *ignore_dir
);
1094 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1098 case 2: /* dir is relative, ignore_dir is absolute */
1099 /* FIXME: skip this case */
1101 default: /* this cannot occurs */
1110 /* --------------------------------------------------------------------------------------------- */
1113 find_rotate_dash (const Dlg_head
* h
, gboolean finish
)
1115 static const char rotating_dash
[] = "|/-\\";
1116 static unsigned int pos
= 0;
1120 pos
= (pos
+ 1) % 4;
1121 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1122 dlg_move (h
, FIND2_Y
- 7, FIND2_X
- 4);
1123 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1128 /* --------------------------------------------------------------------------------------------- */
1131 do_search (Dlg_head
* h
)
1133 static struct dirent
*dp
= NULL
;
1134 static DIR *dirp
= NULL
;
1135 static char *directory
= NULL
;
1136 struct stat tmp_stat
;
1137 static int subdirs_left
= 0;
1139 unsigned short count
;
1142 { /* someone forces me to close dirp */
1154 for (count
= 0; count
< 32; count
++)
1164 while (dirp
== NULL
)
1168 tty_setcolor (REVERSE_COLOR
);
1172 tmp
= pop_directory ();
1176 if (ignore_count
== 0)
1177 status_update (_("Finished"));
1180 char msg
[BUF_SMALL
];
1181 g_snprintf (msg
, sizeof (msg
),
1182 ngettext ("Finished (ignored %zd directory)",
1183 "Finished (ignored %zd directories)",
1184 ignore_count
), ignore_count
);
1185 status_update (msg
);
1187 find_rotate_dash (h
, TRUE
);
1192 /* handle absolute ignore dirs here */
1193 if (!find_ignore_dir_search (tmp
))
1205 char buffer
[BUF_SMALL
];
1207 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"),
1208 str_trunc (directory
, FIND2_X_USE
));
1209 status_update (buffer
);
1211 /* mc_stat should not be called after mc_opendir
1212 because vfs_s_opendir modifies the st_nlink
1214 if (mc_stat (directory
, &tmp_stat
) == 0)
1215 subdirs_left
= tmp_stat
.st_nlink
- 2;
1219 dirp
= mc_opendir (directory
);
1220 } /* while (!dirp) */
1222 /* skip invalid filenames */
1223 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1227 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1229 /* skip invalid filenames */
1230 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1236 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1240 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1241 { /* Can directory be NULL ? */
1242 /* handle relative ignore dirs here */
1243 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1249 tmp_name
= mc_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1251 if (mc_lstat (tmp_name
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1253 push_directory (tmp_name
);
1261 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1262 0, strlen (dp
->d_name
), &bytes_found
);
1266 if (content_pattern
== NULL
)
1267 find_add_match (directory
, dp
->d_name
);
1268 else if (search_content (h
, directory
, dp
->d_name
))
1273 /* skip invalid filenames */
1274 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1278 find_rotate_dash (h
, FALSE
);
1283 /* --------------------------------------------------------------------------------------------- */
1286 init_find_vars (void)
1293 /* Remove all the items from the stack */
1296 g_strfreev (find_ignore_dirs
);
1297 find_ignore_dirs
= NULL
;
1300 /* --------------------------------------------------------------------------------------------- */
1303 make_fullname (const char *dirname
, const char *filename
)
1306 if (strcmp (dirname
, ".") == 0 || strcmp (dirname
, "." PATH_SEP_STR
) == 0)
1307 return g_strdup (filename
);
1308 if (strncmp (dirname
, "." PATH_SEP_STR
, 2) == 0)
1309 return concat_dir_and_file (dirname
+ 2, filename
);
1310 return concat_dir_and_file (dirname
, filename
);
1313 /* --------------------------------------------------------------------------------------------- */
1316 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1318 char *fullname
= NULL
;
1319 const char *filename
= NULL
;
1322 if (content_pattern
!= NULL
)
1324 filename
= strchr (file
+ 4, ':') + 1;
1325 line
= atoi (file
+ 4);
1329 filename
= file
+ 4;
1333 fullname
= make_fullname (dir
, filename
);
1335 do_edit_at_line (fullname
, use_internal_edit
, line
);
1337 view_file_at_line (fullname
, unparsed_view
, use_internal_view
, line
);
1341 /* --------------------------------------------------------------------------------------------- */
1344 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1349 listbox_get_current (find_list
, &text
, (void **) &dir
);
1351 if ((text
== NULL
) || (dir
== NULL
))
1352 return MSG_NOT_HANDLED
;
1354 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1358 /* --------------------------------------------------------------------------------------------- */
1361 find_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
1366 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1368 int unparsed_view
= (parm
== KEY_F (13));
1369 return view_edit_currently_selected_file (unparsed_view
, 0);
1371 if (parm
== KEY_F (4))
1373 return view_edit_currently_selected_file (0, 1);
1375 return MSG_NOT_HANDLED
;
1382 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
1386 /* --------------------------------------------------------------------------------------------- */
1387 /** Handles the Stop/Start button in the find window */
1390 start_stop (WButton
* button
, int action
)
1396 set_idle_proc (find_dlg
, running
);
1397 is_start
= !is_start
;
1399 status_update (is_start
? _("Stopped") : _("Searching"));
1400 button_set_text (stop_button
, fbuts
[is_start
? 1 : 0].text
);
1405 /* --------------------------------------------------------------------------------------------- */
1406 /** Handle view command, when invoked as a button */
1409 find_do_view_file (WButton
* button
, int action
)
1414 view_edit_currently_selected_file (0, 0);
1418 /* --------------------------------------------------------------------------------------------- */
1419 /** Handle edit command, when invoked as a button */
1422 find_do_edit_file (WButton
* button
, int action
)
1427 view_edit_currently_selected_file (0, 1);
1431 /* --------------------------------------------------------------------------------------------- */
1437 static gboolean i18n_flag
= FALSE
;
1441 int i
= sizeof (fbuts
) / sizeof (fbuts
[0]);
1444 fbuts
[i
].text
= _(fbuts
[i
].text
);
1445 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1448 fbuts
[2].len
+= 2; /* DEFPUSH_BUTTON */
1451 #endif /* ENABLE_NLS */
1454 * Dynamically place buttons centered within current window size
1457 int l0
= max (fbuts
[0].len
, fbuts
[1].len
);
1458 int l1
= fbuts
[2].len
+ fbuts
[3].len
+ l0
+ fbuts
[4].len
;
1459 int l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
;
1462 /* Check, if both button rows fit within FIND2_X */
1463 FIND2_X
= max (l1
+ 9, COLS
- 16);
1464 FIND2_X
= max (l2
+ 8, FIND2_X
);
1466 /* compute amount of space between buttons for each row */
1467 r1
= (FIND2_X
- 4 - l1
) % 5;
1468 l1
= (FIND2_X
- 4 - l1
) / 5;
1469 r2
= (FIND2_X
- 4 - l2
) % 4;
1470 l2
= (FIND2_X
- 4 - l2
) / 4;
1472 /* ...and finally, place buttons */
1473 fbuts
[2].x
= 2 + r1
/ 2 + l1
;
1474 fbuts
[3].x
= fbuts
[2].x
+ fbuts
[2].len
+ l1
;
1475 fbuts
[0].x
= fbuts
[3].x
+ fbuts
[3].len
+ l1
;
1476 fbuts
[4].x
= fbuts
[0].x
+ l0
+ l1
;
1477 fbuts
[5].x
= 2 + r2
/ 2 + l2
;
1478 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ l2
;
1479 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ l2
;
1483 create_dlg (TRUE
, 0, 0, FIND2_Y
, FIND2_X
, dialog_colors
, find_callback
,
1484 "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
1486 add_widget (find_dlg
,
1487 button_new (FIND2_Y
- 3, fbuts
[7].x
, B_VIEW
, NORMAL_BUTTON
,
1488 fbuts
[7].text
, find_do_edit_file
));
1489 add_widget (find_dlg
,
1490 button_new (FIND2_Y
- 3, fbuts
[6].x
, B_VIEW
, NORMAL_BUTTON
,
1491 fbuts
[6].text
, find_do_view_file
));
1492 add_widget (find_dlg
,
1493 button_new (FIND2_Y
- 3, fbuts
[5].x
, B_PANELIZE
, NORMAL_BUTTON
, fbuts
[5].text
,
1496 add_widget (find_dlg
,
1497 button_new (FIND2_Y
- 4, fbuts
[4].x
, B_CANCEL
, NORMAL_BUTTON
, fbuts
[4].text
, NULL
));
1499 button_new (FIND2_Y
- 4, fbuts
[0].x
, B_STOP
, NORMAL_BUTTON
, fbuts
[0].text
, start_stop
);
1500 add_widget (find_dlg
, stop_button
);
1501 add_widget (find_dlg
,
1502 button_new (FIND2_Y
- 4, fbuts
[3].x
, B_AGAIN
, NORMAL_BUTTON
, fbuts
[3].text
, NULL
));
1503 add_widget (find_dlg
,
1504 button_new (FIND2_Y
- 4, fbuts
[2].x
, B_ENTER
, DEFPUSH_BUTTON
, fbuts
[2].text
, NULL
));
1506 status_label
= label_new (FIND2_Y
- 7, 4, _("Searching"));
1507 add_widget (find_dlg
, status_label
);
1509 found_num_label
= label_new (FIND2_Y
- 6, 4, "");
1510 add_widget (find_dlg
, found_num_label
);
1512 find_list
= listbox_new (2, 2, FIND2_Y
- 10, FIND2_X
- 4, FALSE
, NULL
);
1513 add_widget (find_dlg
, find_list
);
1516 /* --------------------------------------------------------------------------------------------- */
1523 search_content_handle
= mc_search_new (content_pattern
, -1);
1524 if (search_content_handle
)
1526 search_content_handle
->search_type
=
1527 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1528 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1529 search_content_handle
->whole_words
= options
.content_whole_words
;
1530 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1532 search_file_handle
= mc_search_new (find_pattern
, -1);
1533 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1534 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1535 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1536 search_file_handle
->is_entire_line
= options
.file_pattern
;
1540 set_idle_proc (find_dlg
, 1);
1541 ret
= run_dlg (find_dlg
);
1543 mc_search_free (search_file_handle
);
1544 search_file_handle
= NULL
;
1545 mc_search_free (search_content_handle
);
1546 search_content_handle
= NULL
;
1551 /* --------------------------------------------------------------------------------------------- */
1556 set_idle_proc (find_dlg
, 0);
1557 destroy_dlg (find_dlg
);
1560 /* --------------------------------------------------------------------------------------------- */
1563 find_file (const char *start_dir
, const char *ignore_dirs
, const char *pattern
, const char *content
,
1564 char **dirname
, char **filename
)
1566 int return_value
= 0;
1567 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1571 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1572 find_pattern
= (char *) pattern
;
1574 content_pattern
= NULL
;
1575 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1576 content_pattern
= g_strdup (content
);
1579 parse_ignore_dirs (ignore_dirs
);
1580 push_directory (start_dir
);
1582 return_value
= run_process ();
1584 /* Clear variables */
1587 get_list_info (&file_tmp
, &dir_tmp
);
1590 *dirname
= g_strdup (dir_tmp
);
1592 *filename
= g_strdup (file_tmp
);
1594 if (return_value
== B_PANELIZE
&& *filename
)
1596 int status
, link_to_dir
, stale_link
;
1601 dir_list
*list
= ¤t_panel
->dir
;
1604 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1606 const char *lc_filename
= NULL
;
1607 WLEntry
*le
= (WLEntry
*) entry
->data
;
1609 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1612 if (content_pattern
!= NULL
)
1613 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1615 lc_filename
= le
->text
+ 4;
1617 name
= make_fullname (le
->data
, lc_filename
);
1618 status
= handle_path (list
, name
, &st
, next_free
, &link_to_dir
, &stale_link
);
1630 /* don't add files more than once to the panel */
1631 if (content_pattern
!= NULL
&& next_free
> 0
1632 && strcmp (list
->list
[next_free
- 1].fname
, name
) == 0)
1638 if (!next_free
) /* first turn i.e clean old list */
1639 panel_clean_dir (current_panel
);
1640 list
->list
[next_free
].fnamelen
= strlen (name
);
1641 list
->list
[next_free
].fname
= name
;
1642 list
->list
[next_free
].f
.marked
= 0;
1643 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1644 list
->list
[next_free
].f
.stale_link
= stale_link
;
1645 list
->list
[next_free
].f
.dir_size_computed
= 0;
1646 list
->list
[next_free
].st
= st
;
1647 list
->list
[next_free
].sort_key
= NULL
;
1648 list
->list
[next_free
].second_sort_key
= NULL
;
1650 if (!(next_free
& 15))
1656 current_panel
->count
= next_free
;
1657 current_panel
->is_panelized
= 1;
1659 if (start_dir
[0] == PATH_SEP
)
1662 strcpy (current_panel
->cwd
, PATH_SEP_STR
);
1663 ret
= chdir (PATH_SEP_STR
);
1668 g_free (content_pattern
);
1670 do_search (NULL
); /* force do_search to release resources */
1674 return return_value
;
1677 /* --------------------------------------------------------------------------------------------- */
1678 /*** public functions ****************************************************************************/
1679 /* --------------------------------------------------------------------------------------------- */
1684 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1685 char *filename
= NULL
, *dirname
= NULL
;
1687 gboolean dir_and_file_set
;
1689 while (find_parameters (&start_dir
, &ignore_dirs
, &pattern
, &content
))
1691 if (pattern
[0] == '\0')
1692 break; /* nothing search */
1694 dirname
= filename
= NULL
;
1696 v
= find_file (start_dir
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1697 g_free (ignore_dirs
);
1702 if (dirname
!= NULL
)
1704 do_cd (dirname
, cd_exact
);
1705 if (filename
!= NULL
)
1706 try_to_select (current_panel
,
1707 filename
+ (content
!= NULL
1708 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1710 else if (filename
!= NULL
)
1711 do_cd (filename
, cd_exact
);
1719 dir_and_file_set
= (dirname
!= NULL
) && (filename
!= NULL
);
1726 if (v
== B_PANELIZE
)
1728 if (dir_and_file_set
)
1730 try_to_select (current_panel
, NULL
);
1731 panel_re_sort (current_panel
);
1732 try_to_select (current_panel
, NULL
);
1739 /* --------------------------------------------------------------------------------------------- */