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
, "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
555 add_widget (find_dlg
,
556 button_new (FIND_Y
- 3, FIND_X
* 3 / 4 - b1
/ 2, B_CANCEL
, NORMAL_BUTTON
, buts
[1],
558 add_widget (find_dlg
,
559 button_new (FIND_Y
- 3, FIND_X
/ 4 - b0
/ 2, B_ENTER
, DEFPUSH_BUTTON
, buts
[0], 0));
561 cbox_position
= FIND_Y
- 5;
563 content_first_hit_cbox
=
564 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_first_hit
,
565 content_first_hit_label
);
566 widget_disable (content_first_hit_cbox
->widget
, disable
);
567 add_widget (find_dlg
, content_first_hit_cbox
);
569 content_whole_words_cbox
=
570 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_whole_words
,
571 content_whole_words_label
);
572 widget_disable (content_whole_words_cbox
->widget
, disable
);
573 add_widget (find_dlg
, content_whole_words_cbox
);
576 content_all_charsets_cbox
= check_new (cbox_position
--, FIND_X
/ 2 + 1,
577 options
.content_all_charsets
,
578 content_all_charsets_label
);
579 widget_disable (content_all_charsets_cbox
->widget
, disable
);
580 add_widget (find_dlg
, content_all_charsets_cbox
);
583 content_case_sens_cbox
=
584 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_case_sens
, content_case_label
);
585 widget_disable (content_case_sens_cbox
->widget
, disable
);
586 add_widget (find_dlg
, content_case_sens_cbox
);
588 content_regexp_cbox
=
589 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_regexp
, content_regexp_label
);
590 widget_disable (content_regexp_cbox
->widget
, disable
);
591 add_widget (find_dlg
, content_regexp_cbox
);
593 cbox_position
= FIND_Y
- 6;
595 skip_hidden_cbox
= check_new (cbox_position
--, 3, options
.skip_hidden
, file_skip_hidden_label
);
596 add_widget (find_dlg
, skip_hidden_cbox
);
599 file_all_charsets_cbox
=
600 check_new (cbox_position
--, 3, options
.file_all_charsets
, file_all_charsets_label
);
601 add_widget (find_dlg
, file_all_charsets_cbox
);
604 file_case_sens_cbox
= check_new (cbox_position
--, 3, options
.file_case_sens
, file_case_label
);
605 add_widget (find_dlg
, file_case_sens_cbox
);
607 file_pattern_cbox
= check_new (cbox_position
--, 3, options
.file_pattern
, file_pattern_label
);
608 add_widget (find_dlg
, file_pattern_cbox
);
610 recursively_cbox
= check_new (cbox_position
, 3, options
.find_recurs
, file_recurs_label
);
611 add_widget (find_dlg
, recursively_cbox
);
613 /* This checkbox is located in the second column */
615 check_new (cbox_position
, FIND_X
/ 2 + 1, options
.content_use
, content_use_label
);
616 add_widget (find_dlg
, content_use_cbox
);
619 input_new (8, FIND_X
/ 2 + 1, input_get_default_colors (), FIND_X
/ 2 - 4, INPUT_LAST_TEXT
,
620 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
621 widget_disable (in_with
->widget
, disable
);
622 add_widget (find_dlg
, in_with
);
624 content_label
= label_new (7, FIND_X
/ 2 + 1, _("Content:"));
625 widget_disable (content_label
->widget
, disable
);
626 add_widget (find_dlg
, content_label
);
628 in_name
= input_new (8, 3, input_get_default_colors (),
629 FIND_X
/ 2 - 4, INPUT_LAST_TEXT
, "name", INPUT_COMPLETE_DEFAULT
);
630 add_widget (find_dlg
, in_name
);
631 add_widget (find_dlg
, label_new (7, 3, _("File name:")));
633 in_ignore
= input_new (5, 3, input_get_default_colors (), FIND_X
- 6,
634 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "",
635 "ignoredirs", INPUT_COMPLETE_DEFAULT
);
636 widget_disable (in_ignore
->widget
, !options
.ignore_dirs_enable
);
637 add_widget (find_dlg
, in_ignore
);
640 check_new (4, 3, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
641 add_widget (find_dlg
, ignore_dirs_cbox
);
643 add_widget (find_dlg
, button_new (3, FIND_X
- b2
- 2, B_TREE
, NORMAL_BUTTON
, buts
[2], 0));
645 in_start
= input_new (3, 3, input_get_default_colors (),
646 FIND_X
- b2
- 6, in_start_dir
, "start", INPUT_COMPLETE_DEFAULT
);
647 add_widget (find_dlg
, in_start
);
648 add_widget (find_dlg
, label_new (2, 3, _("Start at:")));
651 dlg_select_widget (in_name
);
653 switch (run_dlg (find_dlg
))
656 return_value
= FALSE
;
663 temp_dir
= in_start
->buffer
;
664 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
665 temp_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
667 temp_dir
= g_strdup (temp_dir
);
669 if (in_start_dir
!= INPUT_LAST_TEXT
)
670 g_free (in_start_dir
);
671 in_start_dir
= tree_box (temp_dir
);
672 if (in_start_dir
== NULL
)
673 in_start_dir
= temp_dir
;
677 input_assign_text (in_start
, in_start_dir
);
679 /* Warning: Dreadful goto */
688 options
.file_all_charsets
= file_all_charsets_cbox
->state
& C_BOOL
;
689 options
.content_all_charsets
= content_all_charsets_cbox
->state
& C_BOOL
;
691 options
.content_use
= content_use_cbox
->state
& C_BOOL
;
692 options
.content_case_sens
= content_case_sens_cbox
->state
& C_BOOL
;
693 options
.content_regexp
= content_regexp_cbox
->state
& C_BOOL
;
694 options
.content_first_hit
= content_first_hit_cbox
->state
& C_BOOL
;
695 options
.content_whole_words
= content_whole_words_cbox
->state
& C_BOOL
;
696 options
.find_recurs
= recursively_cbox
->state
& C_BOOL
;
697 options
.file_pattern
= file_pattern_cbox
->state
& C_BOOL
;
698 options
.file_case_sens
= file_case_sens_cbox
->state
& C_BOOL
;
699 options
.skip_hidden
= skip_hidden_cbox
->state
& C_BOOL
;
700 options
.ignore_dirs_enable
= ignore_dirs_cbox
->state
& C_BOOL
;
701 g_free (options
.ignore_dirs
);
702 options
.ignore_dirs
= g_strdup (in_ignore
->buffer
);
704 *content
= (options
.content_use
&& in_with
->buffer
[0] != '\0')
705 ? g_strdup (in_with
->buffer
) : NULL
;
706 *start_dir
= in_start
->buffer
[0] != '\0' ? in_start
->buffer
: (char *) ".";
707 *pattern
= g_strdup (in_name
->buffer
);
708 if (in_start_dir
!= INPUT_LAST_TEXT
)
709 g_free (in_start_dir
);
710 in_start_dir
= g_strdup (*start_dir
);
712 s
= tilde_expand (*start_dir
);
713 canonicalize_pathname (s
);
715 if (s
[0] == '.' && s
[1] == '\0')
717 *start_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
718 /* FIXME: is current_panel->cwd_vpath canonicalized? */
719 /* relative paths will be used in panelization */
720 *start_dir_len
= (ssize_t
) strlen (*start_dir
);
723 else if (g_path_is_absolute (s
))
730 /* relative paths will be used in panelization */
733 cwd_str
= vfs_path_to_str (current_panel
->cwd_vpath
);
734 *start_dir
= mc_build_filename (cwd_str
, s
, (char *) NULL
);
735 *start_dir_len
= (ssize_t
) strlen (cwd_str
);
740 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
741 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
744 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
746 find_save_options ();
752 destroy_dlg (find_dlg
);
757 /* --------------------------------------------------------------------------------------------- */
759 #if GLIB_CHECK_VERSION (2, 14, 0)
761 push_directory (const vfs_path_t
* dir
)
763 g_queue_push_head (&dir_queue
, (void *) dir
);
766 /* --------------------------------------------------------------------------------------------- */
768 static inline vfs_path_t
*
771 return (vfs_path_t
*) g_queue_pop_tail (&dir_queue
);
774 /* --------------------------------------------------------------------------------------------- */
775 /** Remove all the items from the stack */
780 g_queue_foreach (&dir_queue
, (GFunc
) vfs_path_free
, NULL
);
781 g_queue_clear (&dir_queue
);
784 /* --------------------------------------------------------------------------------------------- */
786 #else /* GLIB_CHECK_VERSION */
788 push_directory (const vfs_path_t
* dir
)
792 new = g_new (dir_stack
, 1);
793 new->name
= (vfs_path_t
*) dir
;
794 new->prev
= dir_stack_base
;
795 dir_stack_base
= new;
798 /* --------------------------------------------------------------------------------------------- */
803 vfs_path_t
*name
= NULL
;
805 if (dir_stack_base
!= NULL
)
808 name
= dir_stack_base
->name
;
809 next
= dir_stack_base
->prev
;
810 g_free (dir_stack_base
);
811 dir_stack_base
= next
;
817 /* --------------------------------------------------------------------------------------------- */
818 /** Remove all the items from the stack */
823 vfs_path_t
*dir
= NULL
;
825 while ((dir
= pop_directory ()) != NULL
)
828 #endif /* GLIB_CHECK_VERSION */
830 /* --------------------------------------------------------------------------------------------- */
833 insert_file (const char *dir
, const char *file
)
835 char *tmp_name
= NULL
;
836 static char *dirname
= NULL
;
838 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
843 if (strcmp (old_dir
, dir
))
846 old_dir
= g_strdup (dir
);
847 dirname
= add_to_list (dir
, NULL
);
852 old_dir
= g_strdup (dir
);
853 dirname
= add_to_list (dir
, NULL
);
856 tmp_name
= g_strdup_printf (" %s", file
);
857 add_to_list (tmp_name
, dirname
);
861 /* --------------------------------------------------------------------------------------------- */
864 find_add_match (const char *dir
, const char *file
)
866 insert_file (dir
, file
);
870 listbox_select_first (find_list
);
871 send_message (&find_list
->widget
, WIDGET_DRAW
, 0);
877 /* --------------------------------------------------------------------------------------------- */
881 * Returns malloced null-terminated line from file file_fd.
882 * Input is buffered in buf_size long buffer.
883 * Current pos in buf is stored in pos.
884 * n_read - number of read chars.
885 * has_newline - is there newline ?
889 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
901 *n_read
= mc_read (file_fd
, buf
, buf_size
);
909 /* skip possible leading zero(s) */
915 if (i
>= buffer_size
- 1)
916 buffer
= g_realloc (buffer
, buffer_size
+= 80);
925 *has_newline
= (ch
!= '\0');
933 /* --------------------------------------------------------------------------------------------- */
935 static FindProgressStatus
936 check_find_events (Dlg_head
* h
)
942 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
945 dlg_process_event (h
, c
, &event
);
946 if (h
->ret_value
== B_ENTER
947 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
949 /* dialog terminated */
952 if (!(h
->flags
& DLG_WANT_IDLE
))
954 /* searching suspended */
962 /* --------------------------------------------------------------------------------------------- */
966 * Search the content_pattern string in the DIRECTORY/FILE.
967 * It will add the found entries to the find listbox.
969 * returns FALSE if do_search should look for another file
970 * TRUE if do_search should exit and proceed to the event handler
974 search_content (Dlg_head
* h
, const char *directory
, const char *filename
)
979 gboolean ret_val
= FALSE
;
982 vpath
= vfs_path_build_filename (directory
, filename
, (char *) NULL
);
984 if (mc_stat (vpath
, &s
) != 0 || !S_ISREG (s
.st_mode
))
986 vfs_path_free (vpath
);
990 file_fd
= mc_open (vpath
, O_RDONLY
);
991 vfs_path_free (vpath
);
996 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), str_trunc (filename
, FIND2_X_USE
));
998 status_update (buffer
);
1001 tty_enable_interrupt_key ();
1002 tty_got_interrupt ();
1008 gboolean has_newline
;
1010 gboolean found
= FALSE
;
1012 char result
[BUF_MEDIUM
];
1016 /* We've been previously suspended, start from the previous position */
1022 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1023 &pos
, &n_read
, &has_newline
)) != NULL
)
1025 if (!found
/* Search in binary line once */
1026 && mc_search_run (search_content_handle
,
1027 (const void *) p
, 0, strlen (p
), &found_len
))
1029 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1030 find_add_match (directory
, result
);
1035 if (found
&& options
.content_first_hit
)
1044 if ((line
& 0xff) == 0)
1046 FindProgressStatus res
;
1047 res
= check_find_events (h
);
1066 tty_disable_interrupt_key ();
1071 /* --------------------------------------------------------------------------------------------- */
1074 If dir is absolute, this means we're within dir and searching file here.
1075 If dir is relative, this means we're going to add dir to the directory stack.
1078 find_ignore_dir_search (const char *dir
)
1080 if (find_ignore_dirs
!= NULL
)
1082 const size_t dlen
= strlen (dir
);
1083 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1087 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1089 const size_t ilen
= strlen (*ignore_dir
);
1090 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1092 /* ignore dir is too long -- skip it */
1096 /* handle absolute and relative paths */
1097 switch (iabs
| dabs
)
1099 case 0: /* both paths are relative */
1100 case 3: /* both paths are abolute */
1101 /* if ignore dir is not a path of dir -- skip it */
1102 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1104 /* be sure that ignore dir is not a part of dir like:
1105 ignore dir is "h", dir is "home" */
1106 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1110 case 1: /* dir is absolute, ignore_dir is relative */
1114 d
= strstr (dir
, *ignore_dir
);
1115 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1119 case 2: /* dir is relative, ignore_dir is absolute */
1120 /* FIXME: skip this case */
1122 default: /* this cannot occurs */
1131 /* --------------------------------------------------------------------------------------------- */
1134 find_rotate_dash (const Dlg_head
* h
, gboolean finish
)
1136 static const char rotating_dash
[] = "|/-\\";
1137 static unsigned int pos
= 0;
1141 pos
= (pos
+ 1) % 4;
1142 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1143 dlg_move (h
, FIND2_Y
- 7, FIND2_X
- 4);
1144 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1149 /* --------------------------------------------------------------------------------------------- */
1152 do_search (Dlg_head
* h
)
1154 static struct dirent
*dp
= NULL
;
1155 static DIR *dirp
= NULL
;
1156 static char *directory
= NULL
;
1157 struct stat tmp_stat
;
1158 static int subdirs_left
= 0;
1160 unsigned short count
;
1163 { /* someone forces me to close dirp */
1175 for (count
= 0; count
< 32; count
++)
1185 while (dirp
== NULL
)
1187 vfs_path_t
*tmp_vpath
= NULL
;
1189 tty_setcolor (REVERSE_COLOR
);
1193 tmp_vpath
= pop_directory ();
1194 if (tmp_vpath
== NULL
)
1197 if (ignore_count
== 0)
1198 status_update (_("Finished"));
1201 char msg
[BUF_SMALL
];
1202 g_snprintf (msg
, sizeof (msg
),
1203 ngettext ("Finished (ignored %zd directory)",
1204 "Finished (ignored %zd directories)",
1205 ignore_count
), ignore_count
);
1206 status_update (msg
);
1208 find_rotate_dash (h
, TRUE
);
1213 /* handle absolute ignore dirs here */
1218 tmp
= vfs_path_to_str (tmp_vpath
);
1219 ok
= find_ignore_dir_search (tmp
);
1225 vfs_path_free (tmp_vpath
);
1230 directory
= vfs_path_to_str (tmp_vpath
);
1234 char buffer
[BUF_SMALL
];
1236 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"),
1237 str_trunc (directory
, FIND2_X_USE
));
1238 status_update (buffer
);
1240 /* mc_stat should not be called after mc_opendir
1241 because vfs_s_opendir modifies the st_nlink
1243 if (mc_stat (tmp_vpath
, &tmp_stat
) == 0)
1244 subdirs_left
= tmp_stat
.st_nlink
- 2;
1248 dirp
= mc_opendir (tmp_vpath
);
1249 vfs_path_free (tmp_vpath
);
1250 } /* while (!dirp) */
1252 /* skip invalid filenames */
1253 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1257 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1259 /* skip invalid filenames */
1260 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1266 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1270 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1271 { /* Can directory be NULL ? */
1272 /* handle relative ignore dirs here */
1273 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1277 vfs_path_t
*tmp_vpath
;
1279 tmp_vpath
= vfs_path_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1281 if (mc_lstat (tmp_vpath
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1283 push_directory (tmp_vpath
);
1287 vfs_path_free (tmp_vpath
);
1291 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1292 0, strlen (dp
->d_name
), &bytes_found
);
1296 if (content_pattern
== NULL
)
1297 find_add_match (directory
, dp
->d_name
);
1298 else if (search_content (h
, directory
, dp
->d_name
))
1303 /* skip invalid filenames */
1304 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1308 find_rotate_dash (h
, FALSE
);
1313 /* --------------------------------------------------------------------------------------------- */
1316 init_find_vars (void)
1323 /* Remove all the items from the stack */
1326 g_strfreev (find_ignore_dirs
);
1327 find_ignore_dirs
= NULL
;
1330 /* --------------------------------------------------------------------------------------------- */
1333 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1335 char *fullname
= NULL
;
1336 const char *filename
= NULL
;
1338 vfs_path_t
*fullname_vpath
;
1340 if (content_pattern
!= NULL
)
1342 filename
= strchr (file
+ 4, ':') + 1;
1343 line
= atoi (file
+ 4);
1347 filename
= file
+ 4;
1351 fullname_vpath
= vfs_path_build_filename (dir
, filename
, (char *) NULL
);
1353 do_edit_at_line (fullname_vpath
, use_internal_edit
, line
);
1355 view_file_at_line (fullname_vpath
, unparsed_view
, use_internal_view
, line
);
1356 vfs_path_free (fullname_vpath
);
1360 /* --------------------------------------------------------------------------------------------- */
1363 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1368 listbox_get_current (find_list
, &text
, (void **) &dir
);
1370 if ((text
== NULL
) || (dir
== NULL
))
1371 return MSG_NOT_HANDLED
;
1373 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1377 /* --------------------------------------------------------------------------------------------- */
1380 find_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
1385 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1387 int unparsed_view
= (parm
== KEY_F (13));
1388 return view_edit_currently_selected_file (unparsed_view
, 0);
1390 if (parm
== KEY_F (4))
1392 return view_edit_currently_selected_file (0, 1);
1394 return MSG_NOT_HANDLED
;
1401 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
1405 /* --------------------------------------------------------------------------------------------- */
1406 /** Handles the Stop/Start button in the find window */
1409 start_stop (WButton
* button
, int action
)
1415 set_idle_proc (find_dlg
, running
);
1416 is_start
= !is_start
;
1418 status_update (is_start
? _("Stopped") : _("Searching"));
1419 button_set_text (stop_button
, fbuts
[is_start
? 1 : 0].text
);
1424 /* --------------------------------------------------------------------------------------------- */
1425 /** Handle view command, when invoked as a button */
1428 find_do_view_file (WButton
* button
, int action
)
1433 view_edit_currently_selected_file (0, 0);
1437 /* --------------------------------------------------------------------------------------------- */
1438 /** Handle edit command, when invoked as a button */
1441 find_do_edit_file (WButton
* button
, int action
)
1446 view_edit_currently_selected_file (0, 1);
1450 /* --------------------------------------------------------------------------------------------- */
1456 static gboolean i18n_flag
= FALSE
;
1460 int i
= sizeof (fbuts
) / sizeof (fbuts
[0]);
1463 fbuts
[i
].text
= _(fbuts
[i
].text
);
1464 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1467 fbuts
[2].len
+= 2; /* DEFPUSH_BUTTON */
1470 #endif /* ENABLE_NLS */
1473 * Dynamically place buttons centered within current window size
1476 int l0
= max (fbuts
[0].len
, fbuts
[1].len
);
1477 int l1
= fbuts
[2].len
+ fbuts
[3].len
+ l0
+ fbuts
[4].len
;
1478 int l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
;
1481 /* Check, if both button rows fit within FIND2_X */
1482 FIND2_X
= max (l1
+ 9, COLS
- 16);
1483 FIND2_X
= max (l2
+ 8, FIND2_X
);
1485 /* compute amount of space between buttons for each row */
1486 r1
= (FIND2_X
- 4 - l1
) % 5;
1487 l1
= (FIND2_X
- 4 - l1
) / 5;
1488 r2
= (FIND2_X
- 4 - l2
) % 4;
1489 l2
= (FIND2_X
- 4 - l2
) / 4;
1491 /* ...and finally, place buttons */
1492 fbuts
[2].x
= 2 + r1
/ 2 + l1
;
1493 fbuts
[3].x
= fbuts
[2].x
+ fbuts
[2].len
+ l1
;
1494 fbuts
[0].x
= fbuts
[3].x
+ fbuts
[3].len
+ l1
;
1495 fbuts
[4].x
= fbuts
[0].x
+ l0
+ l1
;
1496 fbuts
[5].x
= 2 + r2
/ 2 + l2
;
1497 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ l2
;
1498 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ l2
;
1502 create_dlg (TRUE
, 0, 0, FIND2_Y
, FIND2_X
, dialog_colors
, find_callback
,
1503 "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
1505 add_widget (find_dlg
,
1506 button_new (FIND2_Y
- 3, fbuts
[7].x
, B_VIEW
, NORMAL_BUTTON
,
1507 fbuts
[7].text
, find_do_edit_file
));
1508 add_widget (find_dlg
,
1509 button_new (FIND2_Y
- 3, fbuts
[6].x
, B_VIEW
, NORMAL_BUTTON
,
1510 fbuts
[6].text
, find_do_view_file
));
1511 add_widget (find_dlg
,
1512 button_new (FIND2_Y
- 3, fbuts
[5].x
, B_PANELIZE
, NORMAL_BUTTON
, fbuts
[5].text
,
1515 add_widget (find_dlg
,
1516 button_new (FIND2_Y
- 4, fbuts
[4].x
, B_CANCEL
, NORMAL_BUTTON
, fbuts
[4].text
, NULL
));
1518 button_new (FIND2_Y
- 4, fbuts
[0].x
, B_STOP
, NORMAL_BUTTON
, fbuts
[0].text
, start_stop
);
1519 add_widget (find_dlg
, stop_button
);
1520 add_widget (find_dlg
,
1521 button_new (FIND2_Y
- 4, fbuts
[3].x
, B_AGAIN
, NORMAL_BUTTON
, fbuts
[3].text
, NULL
));
1522 add_widget (find_dlg
,
1523 button_new (FIND2_Y
- 4, fbuts
[2].x
, B_ENTER
, DEFPUSH_BUTTON
, fbuts
[2].text
, NULL
));
1525 status_label
= label_new (FIND2_Y
- 7, 4, _("Searching"));
1526 add_widget (find_dlg
, status_label
);
1528 found_num_label
= label_new (FIND2_Y
- 6, 4, "");
1529 add_widget (find_dlg
, found_num_label
);
1531 find_list
= listbox_new (2, 2, FIND2_Y
- 10, FIND2_X
- 4, FALSE
, NULL
);
1532 add_widget (find_dlg
, find_list
);
1535 /* --------------------------------------------------------------------------------------------- */
1542 search_content_handle
= mc_search_new (content_pattern
, -1);
1543 if (search_content_handle
)
1545 search_content_handle
->search_type
=
1546 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1547 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1548 search_content_handle
->whole_words
= options
.content_whole_words
;
1549 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1551 search_file_handle
= mc_search_new (find_pattern
, -1);
1552 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1553 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1554 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1555 search_file_handle
->is_entire_line
= options
.file_pattern
;
1559 set_idle_proc (find_dlg
, 1);
1560 ret
= run_dlg (find_dlg
);
1562 mc_search_free (search_file_handle
);
1563 search_file_handle
= NULL
;
1564 mc_search_free (search_content_handle
);
1565 search_content_handle
= NULL
;
1570 /* --------------------------------------------------------------------------------------------- */
1575 set_idle_proc (find_dlg
, 0);
1576 destroy_dlg (find_dlg
);
1579 /* --------------------------------------------------------------------------------------------- */
1582 do_find (const char *start_dir
, ssize_t start_dir_len
, const char *ignore_dirs
,
1583 const char *pattern
, const char *content
, char **dirname
, char **filename
)
1585 int return_value
= 0;
1586 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1590 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1591 find_pattern
= (char *) pattern
;
1593 content_pattern
= NULL
;
1594 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1595 content_pattern
= g_strdup (content
);
1598 parse_ignore_dirs (ignore_dirs
);
1599 push_directory (vfs_path_from_str (start_dir
));
1601 return_value
= run_process ();
1603 /* Clear variables */
1606 get_list_info (&file_tmp
, &dir_tmp
);
1609 *dirname
= g_strdup (dir_tmp
);
1611 *filename
= g_strdup (file_tmp
);
1613 if (return_value
== B_PANELIZE
&& *filename
)
1615 int status
, link_to_dir
, stale_link
;
1620 dir_list
*list
= ¤t_panel
->dir
;
1623 if (set_zero_dir (list
))
1626 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1628 const char *lc_filename
= NULL
;
1629 WLEntry
*le
= (WLEntry
*) entry
->data
;
1632 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1635 if (content_pattern
!= NULL
)
1636 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1638 lc_filename
= le
->text
+ 4;
1640 name
= mc_build_filename (le
->data
, lc_filename
, (char *) NULL
);
1641 /* skip initial start dir */
1642 if (start_dir_len
< 0)
1646 p
= name
+ (size_t) start_dir_len
;
1651 status
= handle_path (list
, p
, &st
, next_free
, &link_to_dir
, &stale_link
);
1663 /* don't add files more than once to the panel */
1664 if (content_pattern
!= NULL
&& next_free
> 0
1665 && strcmp (list
->list
[next_free
- 1].fname
, p
) == 0)
1671 if (next_free
== 0) /* first turn i.e clean old list */
1672 panel_clean_dir (current_panel
);
1673 list
->list
[next_free
].fnamelen
= strlen (p
);
1674 list
->list
[next_free
].fname
= g_strndup (p
, list
->list
[next_free
].fnamelen
);
1675 list
->list
[next_free
].f
.marked
= 0;
1676 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1677 list
->list
[next_free
].f
.stale_link
= stale_link
;
1678 list
->list
[next_free
].f
.dir_size_computed
= 0;
1679 list
->list
[next_free
].st
= st
;
1680 list
->list
[next_free
].sort_key
= NULL
;
1681 list
->list
[next_free
].second_sort_key
= NULL
;
1684 if (!(next_free
& 15))
1690 current_panel
->count
= next_free
;
1691 current_panel
->is_panelized
= TRUE
;
1694 if (start_dir_len
< 0)
1697 vfs_path_free (current_panel
->cwd_vpath
);
1698 current_panel
->cwd_vpath
= vfs_path_from_str (PATH_SEP_STR
);
1699 ret
= chdir (PATH_SEP_STR
);
1701 panelize_save_panel (current_panel
);
1705 g_free (content_pattern
);
1707 do_search (NULL
); /* force do_search to release resources */
1711 return return_value
;
1714 /* --------------------------------------------------------------------------------------------- */
1715 /*** public functions ****************************************************************************/
1716 /* --------------------------------------------------------------------------------------------- */
1721 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1722 ssize_t start_dir_len
;
1723 char *filename
= NULL
, *dirname
= NULL
;
1726 while (find_parameters (&start_dir
, &start_dir_len
, &ignore_dirs
, &pattern
, &content
))
1728 if (pattern
[0] == '\0')
1729 break; /* nothing search */
1731 dirname
= filename
= NULL
;
1733 v
= do_find (start_dir
, start_dir_len
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1734 g_free (ignore_dirs
);
1739 if (dirname
!= NULL
)
1741 vfs_path_t
*dirname_vpath
;
1743 dirname_vpath
= vfs_path_from_str (dirname
);
1744 do_cd (dirname_vpath
, cd_exact
);
1745 vfs_path_free (dirname_vpath
);
1746 if (filename
!= NULL
)
1747 try_to_select (current_panel
,
1748 filename
+ (content
!= NULL
1749 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1751 else if (filename
!= NULL
)
1753 vfs_path_t
*filename_vpath
;
1755 filename_vpath
= vfs_path_from_str (filename
);
1756 do_cd (filename_vpath
, cd_exact
);
1757 vfs_path_free (filename_vpath
);
1772 if (v
== B_PANELIZE
)
1774 panel_re_sort (current_panel
);
1775 try_to_select (current_panel
, NULL
);
1781 /* --------------------------------------------------------------------------------------------- */