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
;
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
);
298 options
.ignore_dirs
= mc_config_get_string (mc_main_config
, "FindFile", "ignore_dirs", "");
300 if (options
.ignore_dirs
[0] == '\0')
302 g_free (options
.ignore_dirs
);
303 options
.ignore_dirs
= NULL
;
307 /* --------------------------------------------------------------------------------------------- */
310 find_save_options (void)
312 mc_config_set_bool (mc_main_config
, "FindFile", "file_case_sens", options
.file_case_sens
);
313 mc_config_set_bool (mc_main_config
, "FindFile", "file_shell_pattern", options
.file_pattern
);
314 mc_config_set_bool (mc_main_config
, "FindFile", "file_find_recurs", options
.find_recurs
);
315 mc_config_set_bool (mc_main_config
, "FindFile", "file_skip_hidden", options
.skip_hidden
);
316 mc_config_set_bool (mc_main_config
, "FindFile", "file_all_charsets", options
.file_all_charsets
);
317 mc_config_set_bool (mc_main_config
, "FindFile", "content_use", options
.content_use
);
318 mc_config_set_bool (mc_main_config
, "FindFile", "content_case_sens", options
.content_case_sens
);
319 mc_config_set_bool (mc_main_config
, "FindFile", "content_regexp", options
.content_regexp
);
320 mc_config_set_bool (mc_main_config
, "FindFile", "content_first_hit", options
.content_first_hit
);
321 mc_config_set_bool (mc_main_config
, "FindFile", "content_whole_words",
322 options
.content_whole_words
);
323 mc_config_set_bool (mc_main_config
, "FindFile", "content_all_charsets",
324 options
.content_all_charsets
);
325 mc_config_set_bool (mc_main_config
, "FindFile", "ignore_dirs_enable",
326 options
.ignore_dirs_enable
);
327 mc_config_set_string (mc_main_config
, "FindFile", "ignore_dirs", options
.ignore_dirs
);
330 /* --------------------------------------------------------------------------------------------- */
333 add_to_list (const char *text
, void *data
)
335 return listbox_add_item (find_list
, LISTBOX_APPEND_AT_END
, 0, text
, data
);
338 /* --------------------------------------------------------------------------------------------- */
341 stop_idle (void *data
)
343 set_idle_proc (data
, 0);
346 /* --------------------------------------------------------------------------------------------- */
349 status_update (const char *text
)
351 label_set_text (status_label
, text
);
354 /* --------------------------------------------------------------------------------------------- */
357 found_num_update (void)
359 char buffer
[BUF_TINY
];
360 g_snprintf (buffer
, sizeof (buffer
), _("Found: %ld"), matches
);
361 label_set_text (found_num_label
, buffer
);
364 /* --------------------------------------------------------------------------------------------- */
367 get_list_info (char **file
, char **dir
)
369 listbox_get_current (find_list
, file
, (void **) dir
);
372 /* --------------------------------------------------------------------------------------------- */
373 /** check regular expression */
376 find_check_regexp (const char *r
)
379 gboolean regexp_ok
= FALSE
;
381 search
= mc_search_new (r
, -1);
385 search
->search_type
= MC_SEARCH_T_REGEX
;
386 regexp_ok
= mc_search_prepare (search
);
387 mc_search_free (search
);
393 /* --------------------------------------------------------------------------------------------- */
395 * Callback for the parameter dialog.
396 * Validate regex, prevent closing the dialog if it's invalid.
400 find_parm_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
405 if (sender
== (Widget
*) content_use_cbox
)
407 gboolean disable
= !(content_use_cbox
->state
& C_BOOL
);
409 widget_disable (content_label
->widget
, disable
);
410 send_message ((Widget
*) content_label
, WIDGET_DRAW
, 0);
411 widget_disable (in_with
->widget
, disable
);
412 send_message ((Widget
*) in_with
, WIDGET_DRAW
, 0);
413 widget_disable (content_first_hit_cbox
->widget
, disable
);
414 send_message ((Widget
*) content_first_hit_cbox
, WIDGET_DRAW
, 0);
415 widget_disable (content_regexp_cbox
->widget
, disable
);
416 send_message ((Widget
*) content_regexp_cbox
, WIDGET_DRAW
, 0);
417 widget_disable (content_case_sens_cbox
->widget
, disable
);
418 send_message ((Widget
*) content_case_sens_cbox
, WIDGET_DRAW
, 0);
420 widget_disable (content_all_charsets_cbox
->widget
, disable
);
421 send_message ((Widget
*) content_all_charsets_cbox
, WIDGET_DRAW
, 0);
423 widget_disable (content_whole_words_cbox
->widget
, disable
);
424 send_message ((Widget
*) content_whole_words_cbox
, WIDGET_DRAW
, 0);
429 if (sender
== (Widget
*) ignore_dirs_cbox
)
431 gboolean disable
= !(ignore_dirs_cbox
->state
& C_BOOL
);
433 widget_disable (in_ignore
->widget
, disable
);
434 send_message ((Widget
*) in_ignore
, WIDGET_DRAW
, 0);
439 return MSG_NOT_HANDLED
;
443 if (h
->ret_value
!= B_ENTER
)
446 /* check filename regexp */
447 if (!(file_pattern_cbox
->state
& C_BOOL
)
448 && (in_name
->buffer
[0] != '\0') && !find_check_regexp (in_name
->buffer
))
450 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
451 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
452 dlg_select_widget (in_name
);
456 /* check content regexp */
457 if ((content_use_cbox
->state
& C_BOOL
) && (content_regexp_cbox
->state
& C_BOOL
)
458 && (in_with
->buffer
[0] != '\0') && !find_check_regexp (in_with
->buffer
))
460 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
461 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
462 dlg_select_widget (in_with
);
469 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
473 /* --------------------------------------------------------------------------------------------- */
475 * find_parameters: gets information from the user
477 * If the return value is TRUE, then the following holds:
479 * start_dir, ignore_dirs, pattern and content contain the information provided by the user.
480 * They are newly allocated strings and must be freed when uneeded.
482 * start_dir_len is -1 when user entered an absolute path, otherwise it is a length
483 * of start_dir (which is absolute). It is used to get a relative pats of find results.
487 find_parameters (char **start_dir
, ssize_t
* start_dir_len
,
488 char **ignore_dirs
, char **pattern
, char **content
)
490 gboolean return_value
;
493 const char *file_case_label
= N_("Cas&e sensitive");
494 const char *file_pattern_label
= N_("&Using shell patterns");
495 const char *file_recurs_label
= N_("&Find recursively");
496 const char *file_skip_hidden_label
= N_("S&kip hidden");
498 const char *file_all_charsets_label
= N_("&All charsets");
502 const char *content_use_label
= N_("Sea&rch for content");
503 const char *content_case_label
= N_("Case sens&itive");
504 const char *content_regexp_label
= N_("Re&gular expression");
505 const char *content_first_hit_label
= N_("Fir&st hit");
506 const char *content_whole_words_label
= N_("&Whole words");
508 const char *content_all_charsets_label
= N_("A&ll charsets");
511 const char *buts
[] = { N_("&OK"), N_("&Cancel"), N_("&Tree") };
520 int i
= sizeof (buts
) / sizeof (buts
[0]);
522 buts
[i
] = _(buts
[i
]);
524 file_case_label
= _(file_case_label
);
525 file_pattern_label
= _(file_pattern_label
);
526 file_recurs_label
= _(file_recurs_label
);
527 file_skip_hidden_label
= _(file_skip_hidden_label
);
529 file_all_charsets_label
= _(file_all_charsets_label
);
530 content_all_charsets_label
= _(content_all_charsets_label
);
532 content_use_label
= _(content_use_label
);
533 content_case_label
= _(content_case_label
);
534 content_regexp_label
= _(content_regexp_label
);
535 content_first_hit_label
= _(content_first_hit_label
);
536 content_whole_words_label
= _(content_whole_words_label
);
538 #endif /* ENABLE_NLS */
540 b0
= str_term_width1 (buts
[0]) + 6; /* default button */
541 b1
= str_term_width1 (buts
[1]) + 4;
542 b2
= str_term_width1 (buts
[2]) + 4;
544 find_load_options ();
546 if (in_start_dir
== NULL
)
547 in_start_dir
= g_strdup (".");
549 disable
= !options
.content_use
;
552 create_dlg (TRUE
, 0, 0, FIND_Y
, FIND_X
, dialog_colors
,
553 find_parm_callback
, NULL
, "[Find File]", _("Find File"),
554 DLG_CENTER
| DLG_REVERSE
);
556 add_widget (find_dlg
,
557 button_new (FIND_Y
- 3, FIND_X
* 3 / 4 - b1
/ 2, B_CANCEL
, NORMAL_BUTTON
, buts
[1],
559 add_widget (find_dlg
,
560 button_new (FIND_Y
- 3, FIND_X
/ 4 - b0
/ 2, B_ENTER
, DEFPUSH_BUTTON
, buts
[0], 0));
562 cbox_position
= FIND_Y
- 5;
564 content_first_hit_cbox
=
565 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_first_hit
,
566 content_first_hit_label
);
567 widget_disable (content_first_hit_cbox
->widget
, disable
);
568 add_widget (find_dlg
, content_first_hit_cbox
);
570 content_whole_words_cbox
=
571 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_whole_words
,
572 content_whole_words_label
);
573 widget_disable (content_whole_words_cbox
->widget
, disable
);
574 add_widget (find_dlg
, content_whole_words_cbox
);
577 content_all_charsets_cbox
= check_new (cbox_position
--, FIND_X
/ 2 + 1,
578 options
.content_all_charsets
,
579 content_all_charsets_label
);
580 widget_disable (content_all_charsets_cbox
->widget
, disable
);
581 add_widget (find_dlg
, content_all_charsets_cbox
);
584 content_case_sens_cbox
=
585 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_case_sens
, content_case_label
);
586 widget_disable (content_case_sens_cbox
->widget
, disable
);
587 add_widget (find_dlg
, content_case_sens_cbox
);
589 content_regexp_cbox
=
590 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_regexp
, content_regexp_label
);
591 widget_disable (content_regexp_cbox
->widget
, disable
);
592 add_widget (find_dlg
, content_regexp_cbox
);
594 cbox_position
= FIND_Y
- 6;
596 skip_hidden_cbox
= check_new (cbox_position
--, 3, options
.skip_hidden
, file_skip_hidden_label
);
597 add_widget (find_dlg
, skip_hidden_cbox
);
600 file_all_charsets_cbox
=
601 check_new (cbox_position
--, 3, options
.file_all_charsets
, file_all_charsets_label
);
602 add_widget (find_dlg
, file_all_charsets_cbox
);
605 file_case_sens_cbox
= check_new (cbox_position
--, 3, options
.file_case_sens
, file_case_label
);
606 add_widget (find_dlg
, file_case_sens_cbox
);
608 file_pattern_cbox
= check_new (cbox_position
--, 3, options
.file_pattern
, file_pattern_label
);
609 add_widget (find_dlg
, file_pattern_cbox
);
611 recursively_cbox
= check_new (cbox_position
, 3, options
.find_recurs
, file_recurs_label
);
612 add_widget (find_dlg
, recursively_cbox
);
614 /* This checkbox is located in the second column */
616 check_new (cbox_position
, FIND_X
/ 2 + 1, options
.content_use
, content_use_label
);
617 add_widget (find_dlg
, content_use_cbox
);
620 input_new (8, FIND_X
/ 2 + 1, input_get_default_colors (), FIND_X
/ 2 - 4, INPUT_LAST_TEXT
,
621 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
622 widget_disable (in_with
->widget
, disable
);
623 add_widget (find_dlg
, in_with
);
625 content_label
= label_new (7, FIND_X
/ 2 + 1, _("Content:"));
626 widget_disable (content_label
->widget
, disable
);
627 add_widget (find_dlg
, content_label
);
629 in_name
= input_new (8, 3, input_get_default_colors (),
630 FIND_X
/ 2 - 4, INPUT_LAST_TEXT
, "name", INPUT_COMPLETE_DEFAULT
);
631 add_widget (find_dlg
, in_name
);
632 add_widget (find_dlg
, label_new (7, 3, _("File name:")));
634 in_ignore
= input_new (5, 3, input_get_default_colors (), FIND_X
- 6,
635 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "",
636 "ignoredirs", INPUT_COMPLETE_DEFAULT
);
637 widget_disable (in_ignore
->widget
, !options
.ignore_dirs_enable
);
638 add_widget (find_dlg
, in_ignore
);
641 check_new (4, 3, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
642 add_widget (find_dlg
, ignore_dirs_cbox
);
644 add_widget (find_dlg
, button_new (3, FIND_X
- b2
- 2, B_TREE
, NORMAL_BUTTON
, buts
[2], 0));
646 in_start
= input_new (3, 3, input_get_default_colors (),
647 FIND_X
- b2
- 6, in_start_dir
, "start", INPUT_COMPLETE_DEFAULT
);
648 add_widget (find_dlg
, in_start
);
649 add_widget (find_dlg
, label_new (2, 3, _("Start at:")));
652 dlg_select_widget (in_name
);
654 switch (run_dlg (find_dlg
))
657 return_value
= FALSE
;
664 temp_dir
= in_start
->buffer
;
665 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
666 temp_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
668 temp_dir
= g_strdup (temp_dir
);
670 if (in_start_dir
!= INPUT_LAST_TEXT
)
671 g_free (in_start_dir
);
672 in_start_dir
= tree_box (temp_dir
);
673 if (in_start_dir
== NULL
)
674 in_start_dir
= temp_dir
;
678 input_assign_text (in_start
, in_start_dir
);
680 /* 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
);
713 s
= tilde_expand (*start_dir
);
714 canonicalize_pathname (s
);
716 if (s
[0] == '.' && s
[1] == '\0')
718 *start_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
719 /* FIXME: is current_panel->cwd_vpath canonicalized? */
720 /* relative paths will be used in panelization */
721 *start_dir_len
= (ssize_t
) strlen (*start_dir
);
724 else if (g_path_is_absolute (s
))
731 /* relative paths will be used in panelization */
734 cwd_str
= vfs_path_to_str (current_panel
->cwd_vpath
);
735 *start_dir
= mc_build_filename (cwd_str
, s
, (char *) NULL
);
736 *start_dir_len
= (ssize_t
) strlen (cwd_str
);
741 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
742 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
745 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
747 find_save_options ();
753 destroy_dlg (find_dlg
);
758 /* --------------------------------------------------------------------------------------------- */
760 #if GLIB_CHECK_VERSION (2, 14, 0)
762 push_directory (const vfs_path_t
* dir
)
764 g_queue_push_head (&dir_queue
, (void *) dir
);
767 /* --------------------------------------------------------------------------------------------- */
769 static inline vfs_path_t
*
772 return (vfs_path_t
*) g_queue_pop_tail (&dir_queue
);
775 /* --------------------------------------------------------------------------------------------- */
776 /** Remove all the items from the stack */
781 g_queue_foreach (&dir_queue
, (GFunc
) vfs_path_free
, NULL
);
782 g_queue_clear (&dir_queue
);
785 /* --------------------------------------------------------------------------------------------- */
787 #else /* GLIB_CHECK_VERSION */
789 push_directory (const vfs_path_t
* dir
)
793 new = g_new (dir_stack
, 1);
794 new->name
= (vfs_path_t
*) dir
;
795 new->prev
= dir_stack_base
;
796 dir_stack_base
= new;
799 /* --------------------------------------------------------------------------------------------- */
804 vfs_path_t
*name
= NULL
;
806 if (dir_stack_base
!= NULL
)
809 name
= dir_stack_base
->name
;
810 next
= dir_stack_base
->prev
;
811 g_free (dir_stack_base
);
812 dir_stack_base
= next
;
818 /* --------------------------------------------------------------------------------------------- */
819 /** Remove all the items from the stack */
824 vfs_path_t
*dir
= NULL
;
826 while ((dir
= pop_directory ()) != NULL
)
829 #endif /* GLIB_CHECK_VERSION */
831 /* --------------------------------------------------------------------------------------------- */
834 insert_file (const char *dir
, const char *file
)
836 char *tmp_name
= NULL
;
837 static char *dirname
= NULL
;
839 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
844 if (strcmp (old_dir
, dir
))
847 old_dir
= g_strdup (dir
);
848 dirname
= add_to_list (dir
, NULL
);
853 old_dir
= g_strdup (dir
);
854 dirname
= add_to_list (dir
, NULL
);
857 tmp_name
= g_strdup_printf (" %s", file
);
858 add_to_list (tmp_name
, dirname
);
862 /* --------------------------------------------------------------------------------------------- */
865 find_add_match (const char *dir
, const char *file
)
867 insert_file (dir
, file
);
871 listbox_select_first (find_list
);
872 send_message (&find_list
->widget
, WIDGET_DRAW
, 0);
878 /* --------------------------------------------------------------------------------------------- */
882 * Returns malloced null-terminated line from file file_fd.
883 * Input is buffered in buf_size long buffer.
884 * Current pos in buf is stored in pos.
885 * n_read - number of read chars.
886 * has_newline - is there newline ?
890 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
902 *n_read
= mc_read (file_fd
, buf
, buf_size
);
910 /* skip possible leading zero(s) */
916 if (i
>= buffer_size
- 1)
917 buffer
= g_realloc (buffer
, buffer_size
+= 80);
926 *has_newline
= (ch
!= '\0');
934 /* --------------------------------------------------------------------------------------------- */
936 static FindProgressStatus
937 check_find_events (Dlg_head
* h
)
943 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
946 dlg_process_event (h
, c
, &event
);
947 if (h
->ret_value
== B_ENTER
948 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
950 /* dialog terminated */
953 if (!(h
->flags
& DLG_WANT_IDLE
))
955 /* searching suspended */
963 /* --------------------------------------------------------------------------------------------- */
967 * Search the content_pattern string in the DIRECTORY/FILE.
968 * It will add the found entries to the find listbox.
970 * returns FALSE if do_search should look for another file
971 * TRUE if do_search should exit and proceed to the event handler
975 search_content (Dlg_head
* h
, const char *directory
, const char *filename
)
980 gboolean ret_val
= FALSE
;
983 vpath
= vfs_path_build_filename (directory
, filename
, (char *) NULL
);
985 if (mc_stat (vpath
, &s
) != 0 || !S_ISREG (s
.st_mode
))
987 vfs_path_free (vpath
);
991 file_fd
= mc_open (vpath
, O_RDONLY
);
992 vfs_path_free (vpath
);
997 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), str_trunc (filename
, FIND2_X_USE
));
999 status_update (buffer
);
1002 tty_enable_interrupt_key ();
1003 tty_got_interrupt ();
1009 gboolean has_newline
;
1011 gboolean found
= FALSE
;
1013 char result
[BUF_MEDIUM
];
1017 /* We've been previously suspended, start from the previous position */
1023 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1024 &pos
, &n_read
, &has_newline
)) != NULL
)
1026 if (!found
/* Search in binary line once */
1027 && mc_search_run (search_content_handle
,
1028 (const void *) p
, 0, strlen (p
), &found_len
))
1030 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1031 find_add_match (directory
, result
);
1036 if (found
&& options
.content_first_hit
)
1045 if ((line
& 0xff) == 0)
1047 FindProgressStatus res
;
1048 res
= check_find_events (h
);
1067 tty_disable_interrupt_key ();
1072 /* --------------------------------------------------------------------------------------------- */
1075 If dir is absolute, this means we're within dir and searching file here.
1076 If dir is relative, this means we're going to add dir to the directory stack.
1079 find_ignore_dir_search (const char *dir
)
1081 if (find_ignore_dirs
!= NULL
)
1083 const size_t dlen
= strlen (dir
);
1084 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1088 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1090 const size_t ilen
= strlen (*ignore_dir
);
1091 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1093 /* ignore dir is too long -- skip it */
1097 /* handle absolute and relative paths */
1098 switch (iabs
| dabs
)
1100 case 0: /* both paths are relative */
1101 case 3: /* both paths are abolute */
1102 /* if ignore dir is not a path of dir -- skip it */
1103 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1105 /* be sure that ignore dir is not a part of dir like:
1106 ignore dir is "h", dir is "home" */
1107 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1111 case 1: /* dir is absolute, ignore_dir is relative */
1115 d
= strstr (dir
, *ignore_dir
);
1116 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1120 case 2: /* dir is relative, ignore_dir is absolute */
1121 /* FIXME: skip this case */
1123 default: /* this cannot occurs */
1132 /* --------------------------------------------------------------------------------------------- */
1135 find_rotate_dash (const Dlg_head
* h
, gboolean finish
)
1137 static const char rotating_dash
[] = "|/-\\";
1138 static unsigned int pos
= 0;
1142 pos
= (pos
+ 1) % 4;
1143 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1144 dlg_move (h
, FIND2_Y
- 7, FIND2_X
- 4);
1145 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1150 /* --------------------------------------------------------------------------------------------- */
1153 do_search (Dlg_head
* h
)
1155 static struct dirent
*dp
= NULL
;
1156 static DIR *dirp
= NULL
;
1157 static char *directory
= NULL
;
1158 struct stat tmp_stat
;
1159 static int subdirs_left
= 0;
1161 unsigned short count
;
1164 { /* someone forces me to close dirp */
1176 for (count
= 0; count
< 32; count
++)
1186 while (dirp
== NULL
)
1188 vfs_path_t
*tmp_vpath
= NULL
;
1190 tty_setcolor (REVERSE_COLOR
);
1194 tmp_vpath
= pop_directory ();
1195 if (tmp_vpath
== NULL
)
1198 if (ignore_count
== 0)
1199 status_update (_("Finished"));
1202 char msg
[BUF_SMALL
];
1203 g_snprintf (msg
, sizeof (msg
),
1204 ngettext ("Finished (ignored %zd directory)",
1205 "Finished (ignored %zd directories)",
1206 ignore_count
), ignore_count
);
1207 status_update (msg
);
1209 find_rotate_dash (h
, TRUE
);
1214 /* handle absolute ignore dirs here */
1219 tmp
= vfs_path_to_str (tmp_vpath
);
1220 ok
= find_ignore_dir_search (tmp
);
1226 vfs_path_free (tmp_vpath
);
1231 directory
= vfs_path_to_str (tmp_vpath
);
1235 char buffer
[BUF_SMALL
];
1237 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"),
1238 str_trunc (directory
, FIND2_X_USE
));
1239 status_update (buffer
);
1241 /* mc_stat should not be called after mc_opendir
1242 because vfs_s_opendir modifies the st_nlink
1244 if (mc_stat (tmp_vpath
, &tmp_stat
) == 0)
1245 subdirs_left
= tmp_stat
.st_nlink
- 2;
1249 dirp
= mc_opendir (tmp_vpath
);
1250 vfs_path_free (tmp_vpath
);
1251 } /* while (!dirp) */
1253 /* skip invalid filenames */
1254 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1258 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1260 /* skip invalid filenames */
1261 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1267 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1271 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1272 { /* Can directory be NULL ? */
1273 /* handle relative ignore dirs here */
1274 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1278 vfs_path_t
*tmp_vpath
;
1280 tmp_vpath
= vfs_path_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1282 if (mc_lstat (tmp_vpath
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1284 push_directory (tmp_vpath
);
1288 vfs_path_free (tmp_vpath
);
1292 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1293 0, strlen (dp
->d_name
), &bytes_found
);
1297 if (content_pattern
== NULL
)
1298 find_add_match (directory
, dp
->d_name
);
1299 else if (search_content (h
, directory
, dp
->d_name
))
1304 /* skip invalid filenames */
1305 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1309 find_rotate_dash (h
, FALSE
);
1314 /* --------------------------------------------------------------------------------------------- */
1317 init_find_vars (void)
1324 /* Remove all the items from the stack */
1327 g_strfreev (find_ignore_dirs
);
1328 find_ignore_dirs
= NULL
;
1331 /* --------------------------------------------------------------------------------------------- */
1334 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1336 char *fullname
= NULL
;
1337 const char *filename
= NULL
;
1339 vfs_path_t
*fullname_vpath
;
1341 if (content_pattern
!= NULL
)
1343 filename
= strchr (file
+ 4, ':') + 1;
1344 line
= atoi (file
+ 4);
1348 filename
= file
+ 4;
1352 fullname_vpath
= vfs_path_build_filename (dir
, filename
, (char *) NULL
);
1354 do_edit_at_line (fullname_vpath
, use_internal_edit
, line
);
1356 view_file_at_line (fullname_vpath
, unparsed_view
, use_internal_view
, line
);
1357 vfs_path_free (fullname_vpath
);
1361 /* --------------------------------------------------------------------------------------------- */
1364 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1369 listbox_get_current (find_list
, &text
, (void **) &dir
);
1371 if ((text
== NULL
) || (dir
== NULL
))
1372 return MSG_NOT_HANDLED
;
1374 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1378 /* --------------------------------------------------------------------------------------------- */
1381 find_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
1386 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1388 int unparsed_view
= (parm
== KEY_F (13));
1389 return view_edit_currently_selected_file (unparsed_view
, 0);
1391 if (parm
== KEY_F (4))
1393 return view_edit_currently_selected_file (0, 1);
1395 return MSG_NOT_HANDLED
;
1402 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
1406 /* --------------------------------------------------------------------------------------------- */
1407 /** Handles the Stop/Start button in the find window */
1410 start_stop (WButton
* button
, int action
)
1416 set_idle_proc (find_dlg
, running
);
1417 is_start
= !is_start
;
1419 status_update (is_start
? _("Stopped") : _("Searching"));
1420 button_set_text (stop_button
, fbuts
[is_start
? 1 : 0].text
);
1425 /* --------------------------------------------------------------------------------------------- */
1426 /** Handle view command, when invoked as a button */
1429 find_do_view_file (WButton
* button
, int action
)
1434 view_edit_currently_selected_file (0, 0);
1438 /* --------------------------------------------------------------------------------------------- */
1439 /** Handle edit command, when invoked as a button */
1442 find_do_edit_file (WButton
* button
, int action
)
1447 view_edit_currently_selected_file (0, 1);
1451 /* --------------------------------------------------------------------------------------------- */
1457 static gboolean i18n_flag
= FALSE
;
1461 int i
= sizeof (fbuts
) / sizeof (fbuts
[0]);
1464 fbuts
[i
].text
= _(fbuts
[i
].text
);
1465 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1468 fbuts
[2].len
+= 2; /* DEFPUSH_BUTTON */
1471 #endif /* ENABLE_NLS */
1474 * Dynamically place buttons centered within current window size
1477 int l0
= max (fbuts
[0].len
, fbuts
[1].len
);
1478 int l1
= fbuts
[2].len
+ fbuts
[3].len
+ l0
+ fbuts
[4].len
;
1479 int l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
;
1482 /* Check, if both button rows fit within FIND2_X */
1483 FIND2_X
= max (l1
+ 9, COLS
- 16);
1484 FIND2_X
= max (l2
+ 8, FIND2_X
);
1486 /* compute amount of space between buttons for each row */
1487 r1
= (FIND2_X
- 4 - l1
) % 5;
1488 l1
= (FIND2_X
- 4 - l1
) / 5;
1489 r2
= (FIND2_X
- 4 - l2
) % 4;
1490 l2
= (FIND2_X
- 4 - l2
) / 4;
1492 /* ...and finally, place buttons */
1493 fbuts
[2].x
= 2 + r1
/ 2 + l1
;
1494 fbuts
[3].x
= fbuts
[2].x
+ fbuts
[2].len
+ l1
;
1495 fbuts
[0].x
= fbuts
[3].x
+ fbuts
[3].len
+ l1
;
1496 fbuts
[4].x
= fbuts
[0].x
+ l0
+ l1
;
1497 fbuts
[5].x
= 2 + r2
/ 2 + l2
;
1498 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ l2
;
1499 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ l2
;
1503 create_dlg (TRUE
, 0, 0, FIND2_Y
, FIND2_X
, dialog_colors
, find_callback
, NULL
,
1504 "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
1506 add_widget (find_dlg
,
1507 button_new (FIND2_Y
- 3, fbuts
[7].x
, B_VIEW
, NORMAL_BUTTON
,
1508 fbuts
[7].text
, find_do_edit_file
));
1509 add_widget (find_dlg
,
1510 button_new (FIND2_Y
- 3, fbuts
[6].x
, B_VIEW
, NORMAL_BUTTON
,
1511 fbuts
[6].text
, find_do_view_file
));
1512 add_widget (find_dlg
,
1513 button_new (FIND2_Y
- 3, fbuts
[5].x
, B_PANELIZE
, NORMAL_BUTTON
, fbuts
[5].text
,
1516 add_widget (find_dlg
,
1517 button_new (FIND2_Y
- 4, fbuts
[4].x
, B_CANCEL
, NORMAL_BUTTON
, fbuts
[4].text
, NULL
));
1519 button_new (FIND2_Y
- 4, fbuts
[0].x
, B_STOP
, NORMAL_BUTTON
, fbuts
[0].text
, start_stop
);
1520 add_widget (find_dlg
, stop_button
);
1521 add_widget (find_dlg
,
1522 button_new (FIND2_Y
- 4, fbuts
[3].x
, B_AGAIN
, NORMAL_BUTTON
, fbuts
[3].text
, NULL
));
1523 add_widget (find_dlg
,
1524 button_new (FIND2_Y
- 4, fbuts
[2].x
, B_ENTER
, DEFPUSH_BUTTON
, fbuts
[2].text
, NULL
));
1526 status_label
= label_new (FIND2_Y
- 7, 4, _("Searching"));
1527 add_widget (find_dlg
, status_label
);
1529 found_num_label
= label_new (FIND2_Y
- 6, 4, "");
1530 add_widget (find_dlg
, found_num_label
);
1532 find_list
= listbox_new (2, 2, FIND2_Y
- 10, FIND2_X
- 4, FALSE
, NULL
);
1533 add_widget (find_dlg
, find_list
);
1536 /* --------------------------------------------------------------------------------------------- */
1543 search_content_handle
= mc_search_new (content_pattern
, -1);
1544 if (search_content_handle
)
1546 search_content_handle
->search_type
=
1547 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1548 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1549 search_content_handle
->whole_words
= options
.content_whole_words
;
1550 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1552 search_file_handle
= mc_search_new (find_pattern
, -1);
1553 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1554 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1555 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1556 search_file_handle
->is_entire_line
= options
.file_pattern
;
1560 set_idle_proc (find_dlg
, 1);
1561 ret
= run_dlg (find_dlg
);
1563 mc_search_free (search_file_handle
);
1564 search_file_handle
= NULL
;
1565 mc_search_free (search_content_handle
);
1566 search_content_handle
= NULL
;
1571 /* --------------------------------------------------------------------------------------------- */
1576 set_idle_proc (find_dlg
, 0);
1577 destroy_dlg (find_dlg
);
1580 /* --------------------------------------------------------------------------------------------- */
1583 do_find (const char *start_dir
, ssize_t start_dir_len
, const char *ignore_dirs
,
1584 const char *pattern
, const char *content
, char **dirname
, char **filename
)
1586 int return_value
= 0;
1587 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1591 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1592 find_pattern
= (char *) pattern
;
1594 content_pattern
= NULL
;
1595 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1596 content_pattern
= g_strdup (content
);
1599 parse_ignore_dirs (ignore_dirs
);
1600 push_directory (vfs_path_from_str (start_dir
));
1602 return_value
= run_process ();
1604 /* Clear variables */
1607 get_list_info (&file_tmp
, &dir_tmp
);
1610 *dirname
= g_strdup (dir_tmp
);
1612 *filename
= g_strdup (file_tmp
);
1614 if (return_value
== B_PANELIZE
&& *filename
)
1616 int status
, link_to_dir
, stale_link
;
1621 dir_list
*list
= ¤t_panel
->dir
;
1624 if (set_zero_dir (list
))
1627 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1629 const char *lc_filename
= NULL
;
1630 WLEntry
*le
= (WLEntry
*) entry
->data
;
1633 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1636 if (content_pattern
!= NULL
)
1637 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1639 lc_filename
= le
->text
+ 4;
1641 name
= mc_build_filename (le
->data
, lc_filename
, (char *) NULL
);
1642 /* skip initial start dir */
1643 if (start_dir_len
< 0)
1647 p
= name
+ (size_t) start_dir_len
;
1652 status
= handle_path (list
, p
, &st
, next_free
, &link_to_dir
, &stale_link
);
1664 /* don't add files more than once to the panel */
1665 if (content_pattern
!= NULL
&& next_free
> 0
1666 && strcmp (list
->list
[next_free
- 1].fname
, p
) == 0)
1672 if (next_free
== 0) /* first turn i.e clean old list */
1673 panel_clean_dir (current_panel
);
1674 list
->list
[next_free
].fnamelen
= strlen (p
);
1675 list
->list
[next_free
].fname
= g_strndup (p
, list
->list
[next_free
].fnamelen
);
1676 list
->list
[next_free
].f
.marked
= 0;
1677 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1678 list
->list
[next_free
].f
.stale_link
= stale_link
;
1679 list
->list
[next_free
].f
.dir_size_computed
= 0;
1680 list
->list
[next_free
].st
= st
;
1681 list
->list
[next_free
].sort_key
= NULL
;
1682 list
->list
[next_free
].second_sort_key
= NULL
;
1685 if (!(next_free
& 15))
1691 current_panel
->count
= next_free
;
1692 current_panel
->is_panelized
= TRUE
;
1695 if (start_dir_len
< 0)
1698 vfs_path_free (current_panel
->cwd_vpath
);
1699 current_panel
->cwd_vpath
= vfs_path_from_str (PATH_SEP_STR
);
1700 ret
= chdir (PATH_SEP_STR
);
1702 panelize_save_panel (current_panel
);
1706 g_free (content_pattern
);
1708 do_search (NULL
); /* force do_search to release resources */
1712 return return_value
;
1715 /* --------------------------------------------------------------------------------------------- */
1716 /*** public functions ****************************************************************************/
1717 /* --------------------------------------------------------------------------------------------- */
1722 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1723 ssize_t start_dir_len
;
1724 char *filename
= NULL
, *dirname
= NULL
;
1727 while (find_parameters (&start_dir
, &start_dir_len
, &ignore_dirs
, &pattern
, &content
))
1729 if (pattern
[0] == '\0')
1730 break; /* nothing search */
1732 dirname
= filename
= NULL
;
1734 v
= do_find (start_dir
, start_dir_len
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1735 g_free (ignore_dirs
);
1740 if (dirname
!= NULL
)
1742 vfs_path_t
*dirname_vpath
;
1744 dirname_vpath
= vfs_path_from_str (dirname
);
1745 do_cd (dirname_vpath
, cd_exact
);
1746 vfs_path_free (dirname_vpath
);
1747 if (filename
!= NULL
)
1748 try_to_select (current_panel
,
1749 filename
+ (content
!= NULL
1750 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1752 else if (filename
!= NULL
)
1754 vfs_path_t
*filename_vpath
;
1756 filename_vpath
= vfs_path_from_str (filename
);
1757 do_cd (filename_vpath
, cd_exact
);
1758 vfs_path_free (filename_vpath
);
1773 if (v
== B_PANELIZE
)
1775 panel_re_sort (current_panel
);
1776 try_to_select (current_panel
, NULL
);
1782 /* --------------------------------------------------------------------------------------------- */