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 */
56 #include "cmd.h" /* view_file_at_line */
57 #include "midnight.h" /* current_panel */
63 /*** global variables ****************************************************************************/
65 /*** file scope macro definitions ****************************************************************/
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 /* button callbacks */
113 static int start_stop (WButton
* button
, int action
);
114 static int find_do_view_file (WButton
* button
, int action
);
115 static int find_do_edit_file (WButton
* button
, int action
);
117 /* Parsed ignore dirs */
118 static char **find_ignore_dirs
= NULL
;
120 /* static variables to remember find parameters */
121 static WInput
*in_start
; /* Start path */
122 static WInput
*in_name
; /* Filename */
123 static WInput
*in_with
; /* Text */
124 static WInput
*in_ignore
;
125 static WLabel
*content_label
; /* 'Content:' label */
126 static WCheck
*file_case_sens_cbox
; /* "case sensitive" checkbox */
127 static WCheck
*file_pattern_cbox
; /* File name is glob or regexp */
128 static WCheck
*recursively_cbox
;
129 static WCheck
*skip_hidden_cbox
;
130 static WCheck
*content_use_cbox
; /* Take into account the Content field */
131 static WCheck
*content_case_sens_cbox
; /* "case sensitive" checkbox */
132 static WCheck
*content_regexp_cbox
; /* "find regular expression" checkbox */
133 static WCheck
*content_first_hit_cbox
; /* "First hit" checkbox" */
134 static WCheck
*content_whole_words_cbox
; /* "whole words" checkbox */
136 static WCheck
*file_all_charsets_cbox
;
137 static WCheck
*content_all_charsets_cbox
;
139 static WCheck
*ignore_dirs_cbox
;
141 static gboolean running
= FALSE
; /* nice flag */
142 static char *find_pattern
= NULL
; /* Pattern to search */
143 static char *content_pattern
= NULL
; /* pattern to search inside files; if
144 content_regexp_flag is true, it contains the
145 regex pattern, else the search string. */
146 static unsigned long matches
; /* Number of matches */
147 static gboolean is_start
= FALSE
; /* Status of the start/stop toggle button */
148 static char *old_dir
= NULL
;
150 /* Where did we stop */
152 static int last_line
;
155 static size_t ignore_count
= 0;
157 static WDialog
*find_dlg
; /* The dialog */
158 static WLabel
*status_label
; /* Finished, Searching etc. */
159 static WLabel
*found_num_label
; /* Number of found items */
161 /* This keeps track of the directory stack */
162 #if GLIB_CHECK_VERSION (2, 14, 0)
163 static GQueue dir_queue
= G_QUEUE_INIT
;
165 typedef struct dir_stack
168 struct dir_stack
*prev
;
171 static dir_stack
*dir_stack_base
= 0;
172 #endif /* GLIB_CHECK_VERSION */
178 button_flags_t flags
;
180 int len
; /* length including space and brackets */
186 { B_ENTER
, DEFPUSH_BUTTON
, N_("&Chdir"), 0, 0, NULL
, NULL
},
187 { B_AGAIN
, NORMAL_BUTTON
, N_("&Again"), 0, 0, NULL
, NULL
},
188 { B_STOP
, NORMAL_BUTTON
, N_("S&uspend"), 0, 0, NULL
, start_stop
},
189 { B_STOP
, NORMAL_BUTTON
, N_("Con&tinue"), 0, 0, NULL
, NULL
},
190 { B_CANCEL
, NORMAL_BUTTON
, N_("&Quit"), 0, 0, NULL
, NULL
},
192 { B_PANELIZE
, NORMAL_BUTTON
, N_("Pane&lize"), 0, 0, NULL
, NULL
},
193 { B_VIEW
, NORMAL_BUTTON
, N_("&View - F3"), 0, 0, NULL
, find_do_view_file
},
194 { B_VIEW
, NORMAL_BUTTON
, N_("&Edit - F4"), 0, 0, NULL
, find_do_edit_file
}
198 static const size_t fbuts_num
= G_N_ELEMENTS (fbuts
);
199 const size_t quit_button
= 4; /* index of "Quit" button */
201 static WListbox
*find_list
; /* Listbox with the file list */
203 static find_file_options_t options
= {
204 TRUE
, TRUE
, TRUE
, FALSE
, FALSE
,
205 FALSE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
208 static char *in_start_dir
= INPUT_LAST_TEXT
;
210 static mc_search_t
*search_file_handle
= NULL
;
211 static mc_search_t
*search_content_handle
= NULL
;
213 /* --------------------------------------------------------------------------------------------- */
214 /*** file scope functions ************************************************************************/
215 /* --------------------------------------------------------------------------------------------- */
217 /* don't use max macro to avoid double str_term_width1() call in widget length caclulation */
223 return (a
> b
? a
: b
);
226 /* --------------------------------------------------------------------------------------------- */
229 parse_ignore_dirs (const char *ignore_dirs
)
231 size_t r
= 0, w
= 0; /* read and write iterators */
233 if (!options
.ignore_dirs_enable
|| ignore_dirs
== NULL
|| ignore_dirs
[0] == '\0')
236 find_ignore_dirs
= g_strsplit (ignore_dirs
, ":", -1);
238 /* Values like '/foo::/bar: produce holes in list.
239 * Find and remove them */
240 for (; find_ignore_dirs
[r
] != NULL
; r
++)
242 if (find_ignore_dirs
[r
][0] == '\0')
244 /* empty entry -- skip it */
245 g_free (find_ignore_dirs
[r
]);
246 find_ignore_dirs
[r
] = NULL
;
252 /* copy entry to the previous free array cell */
253 find_ignore_dirs
[w
] = find_ignore_dirs
[r
];
254 find_ignore_dirs
[r
] = NULL
;
257 canonicalize_pathname (find_ignore_dirs
[w
]);
258 if (find_ignore_dirs
[w
][0] != '\0')
262 g_free (find_ignore_dirs
[w
]);
263 find_ignore_dirs
[w
] = NULL
;
267 if (find_ignore_dirs
[0] == NULL
)
269 g_strfreev (find_ignore_dirs
);
270 find_ignore_dirs
= NULL
;
274 /* --------------------------------------------------------------------------------------------- */
277 find_load_options (void)
279 static gboolean loaded
= FALSE
;
286 options
.file_case_sens
=
287 mc_config_get_bool (mc_main_config
, "FindFile", "file_case_sens", TRUE
);
288 options
.file_pattern
=
289 mc_config_get_bool (mc_main_config
, "FindFile", "file_shell_pattern", TRUE
);
290 options
.find_recurs
= mc_config_get_bool (mc_main_config
, "FindFile", "file_find_recurs", TRUE
);
291 options
.skip_hidden
=
292 mc_config_get_bool (mc_main_config
, "FindFile", "file_skip_hidden", FALSE
);
293 options
.file_all_charsets
=
294 mc_config_get_bool (mc_main_config
, "FindFile", "file_all_charsets", FALSE
);
295 options
.content_use
= mc_config_get_bool (mc_main_config
, "FindFile", "content_use", TRUE
);
296 options
.content_case_sens
=
297 mc_config_get_bool (mc_main_config
, "FindFile", "content_case_sens", TRUE
);
298 options
.content_regexp
=
299 mc_config_get_bool (mc_main_config
, "FindFile", "content_regexp", FALSE
);
300 options
.content_first_hit
=
301 mc_config_get_bool (mc_main_config
, "FindFile", "content_first_hit", FALSE
);
302 options
.content_whole_words
=
303 mc_config_get_bool (mc_main_config
, "FindFile", "content_whole_words", FALSE
);
304 options
.content_all_charsets
=
305 mc_config_get_bool (mc_main_config
, "FindFile", "content_all_charsets", FALSE
);
306 options
.ignore_dirs_enable
=
307 mc_config_get_bool (mc_main_config
, "FindFile", "ignore_dirs_enable", TRUE
);
308 options
.ignore_dirs
= mc_config_get_string (mc_main_config
, "FindFile", "ignore_dirs", "");
310 if (options
.ignore_dirs
[0] == '\0')
312 g_free (options
.ignore_dirs
);
313 options
.ignore_dirs
= NULL
;
317 /* --------------------------------------------------------------------------------------------- */
320 find_save_options (void)
322 mc_config_set_bool (mc_main_config
, "FindFile", "file_case_sens", options
.file_case_sens
);
323 mc_config_set_bool (mc_main_config
, "FindFile", "file_shell_pattern", options
.file_pattern
);
324 mc_config_set_bool (mc_main_config
, "FindFile", "file_find_recurs", options
.find_recurs
);
325 mc_config_set_bool (mc_main_config
, "FindFile", "file_skip_hidden", options
.skip_hidden
);
326 mc_config_set_bool (mc_main_config
, "FindFile", "file_all_charsets", options
.file_all_charsets
);
327 mc_config_set_bool (mc_main_config
, "FindFile", "content_use", options
.content_use
);
328 mc_config_set_bool (mc_main_config
, "FindFile", "content_case_sens", options
.content_case_sens
);
329 mc_config_set_bool (mc_main_config
, "FindFile", "content_regexp", options
.content_regexp
);
330 mc_config_set_bool (mc_main_config
, "FindFile", "content_first_hit", options
.content_first_hit
);
331 mc_config_set_bool (mc_main_config
, "FindFile", "content_whole_words",
332 options
.content_whole_words
);
333 mc_config_set_bool (mc_main_config
, "FindFile", "content_all_charsets",
334 options
.content_all_charsets
);
335 mc_config_set_bool (mc_main_config
, "FindFile", "ignore_dirs_enable",
336 options
.ignore_dirs_enable
);
337 mc_config_set_string (mc_main_config
, "FindFile", "ignore_dirs", options
.ignore_dirs
);
340 /* --------------------------------------------------------------------------------------------- */
343 add_to_list (const char *text
, void *data
)
345 return listbox_add_item (find_list
, LISTBOX_APPEND_AT_END
, 0, text
, data
);
348 /* --------------------------------------------------------------------------------------------- */
351 stop_idle (void *data
)
353 widget_want_idle (WIDGET (data
), FALSE
);
356 /* --------------------------------------------------------------------------------------------- */
359 status_update (const char *text
)
361 label_set_text (status_label
, text
);
364 /* --------------------------------------------------------------------------------------------- */
367 found_num_update (void)
369 char buffer
[BUF_TINY
];
370 g_snprintf (buffer
, sizeof (buffer
), _("Found: %ld"), matches
);
371 label_set_text (found_num_label
, buffer
);
374 /* --------------------------------------------------------------------------------------------- */
377 get_list_info (char **file
, char **dir
)
379 listbox_get_current (find_list
, file
, (void **) dir
);
382 /* --------------------------------------------------------------------------------------------- */
383 /** check regular expression */
386 find_check_regexp (const char *r
)
389 gboolean regexp_ok
= FALSE
;
391 search
= mc_search_new (r
, -1);
395 search
->search_type
= MC_SEARCH_T_REGEX
;
396 regexp_ok
= mc_search_prepare (search
);
397 mc_search_free (search
);
403 /* --------------------------------------------------------------------------------------------- */
405 * Callback for the parameter dialog.
406 * Validate regex, prevent closing the dialog if it's invalid.
410 find_parm_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
412 WDialog
*h
= DIALOG (w
);
417 if (sender
== WIDGET (content_use_cbox
))
419 gboolean disable
= !(content_use_cbox
->state
& C_BOOL
);
421 widget_disable (WIDGET (in_with
), disable
);
422 widget_disable (WIDGET (content_first_hit_cbox
), disable
);
423 widget_disable (WIDGET (content_regexp_cbox
), disable
);
424 widget_disable (WIDGET (content_case_sens_cbox
), disable
);
426 widget_disable (WIDGET (content_all_charsets_cbox
), disable
);
428 widget_disable (WIDGET (content_whole_words_cbox
), disable
);
433 if (sender
== WIDGET (ignore_dirs_cbox
))
435 gboolean disable
= !(ignore_dirs_cbox
->state
& C_BOOL
);
437 widget_disable (WIDGET (in_ignore
), disable
);
442 return MSG_NOT_HANDLED
;
446 if (h
->ret_value
!= B_ENTER
)
449 /* check filename regexp */
450 if (!(file_pattern_cbox
->state
& C_BOOL
)
451 && (in_name
->buffer
[0] != '\0') && !find_check_regexp (in_name
->buffer
))
453 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
454 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
455 dlg_select_widget (in_name
);
459 /* check content regexp */
460 if ((content_use_cbox
->state
& C_BOOL
) && (content_regexp_cbox
->state
& C_BOOL
)
461 && (in_with
->buffer
[0] != '\0') && !find_check_regexp (in_with
->buffer
))
463 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
464 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
465 dlg_select_widget (in_with
);
472 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
476 /* --------------------------------------------------------------------------------------------- */
478 * find_parameters: gets information from the user
480 * If the return value is TRUE, then the following holds:
482 * start_dir, ignore_dirs, pattern and content contain the information provided by the user.
483 * They are newly allocated strings and must be freed when uneeded.
485 * start_dir_len is -1 when user entered an absolute path, otherwise it is a length
486 * of start_dir (which is absolute). It is used to get a relative pats of find results.
490 find_parameters (char **start_dir
, ssize_t
* start_dir_len
,
491 char **ignore_dirs
, char **pattern
, char **content
)
493 /* Size of the find parameters window */
495 const int lines
= 19;
497 const int lines
= 18;
501 gboolean return_value
;
504 const char *file_name_label
= N_("File name:");
505 const char *file_recurs_label
= N_("&Find recursively");
506 const char *file_pattern_label
= N_("&Using shell patterns");
508 const char *file_all_charsets_label
= N_("&All charsets");
510 const char *file_case_label
= N_("Cas&e sensitive");
511 const char *file_skip_hidden_label
= N_("S&kip hidden");
514 const char *content_content_label
= N_("Content:");
515 const char *content_use_label
= N_("Sea&rch for content");
516 const char *content_regexp_label
= N_("Re&gular expression");
517 const char *content_case_label
= N_("Case sens&itive");
519 const char *content_all_charsets_label
= N_("A&ll charsets");
521 const char *content_whole_words_label
= N_("&Whole words");
522 const char *content_first_hit_label
= N_("Fir&st hit");
524 const char *buts
[] = { N_("&Tree"), N_("&OK"), N_("&Cancel") };
538 file_name_label
= _(file_name_label
);
539 file_recurs_label
= _(file_recurs_label
);
540 file_pattern_label
= _(file_pattern_label
);
542 file_all_charsets_label
= _(file_all_charsets_label
);
544 file_case_label
= _(file_case_label
);
545 file_skip_hidden_label
= _(file_skip_hidden_label
);
548 content_content_label
= _(content_content_label
);
549 content_use_label
= _(content_use_label
);
550 content_regexp_label
= _(content_regexp_label
);
551 content_case_label
= _(content_case_label
);
553 content_all_charsets_label
= _(content_all_charsets_label
);
555 content_whole_words_label
= _(content_whole_words_label
);
556 content_first_hit_label
= _(content_first_hit_label
);
558 for (i
= 0; i
< G_N_ELEMENTS (buts
); i
++)
559 buts
[i
] = _(buts
[i
]);
561 #endif /* ENABLE_NLS */
563 /* caclulate dialog width */
566 cw
= str_term_width1 (file_name_label
);
567 cw
= max (cw
, str_term_width1 (file_recurs_label
) + 4);
568 cw
= max (cw
, str_term_width1 (file_pattern_label
) + 4);
570 cw
= max (cw
, str_term_width1 (file_all_charsets_label
) + 4);
572 cw
= max (cw
, str_term_width1 (file_case_label
) + 4);
573 cw
= max (cw
, str_term_width1 (file_skip_hidden_label
) + 4);
575 cw
= max (cw
, str_term_width1 (content_content_label
) + 4);
576 cw
= max (cw
, str_term_width1 (content_use_label
) + 4);
577 cw
= max (cw
, str_term_width1 (content_regexp_label
) + 4);
578 cw
= max (cw
, str_term_width1 (content_case_label
) + 4);
580 cw
= max (cw
, str_term_width1 (content_all_charsets_label
) + 4);
582 cw
= max (cw
, str_term_width1 (content_whole_words_label
) + 4);
583 cw
= max (cw
, str_term_width1 (content_first_hit_label
) + 4);
586 b0
= str_term_width1 (buts
[0]) + 3;
587 b1
= str_term_width1 (buts
[1]) + 5; /* default button */
588 b2
= str_term_width1 (buts
[2]) + 3;
591 cols
= max (cols
, max (b12
, cw
* 2 + 1) + 6);
593 find_load_options ();
595 if (in_start_dir
== NULL
)
596 in_start_dir
= g_strdup (".");
598 disable
= !options
.content_use
;
601 create_dlg (TRUE
, 0, 0, lines
, cols
, dialog_colors
, find_parm_callback
, NULL
, "[Find File]",
602 _("Find File"), DLG_CENTER
);
609 add_widget (find_dlg
, label_new (y1
++, x1
, _("Start at:")));
611 input_new (y1
, x1
, input_get_default_colors (), cols
- b0
- 7, in_start_dir
, "start",
612 INPUT_COMPLETE_DEFAULT
);
613 add_widget (find_dlg
, in_start
);
615 add_widget (find_dlg
, button_new (y1
++, cols
- b0
- 3, B_TREE
, NORMAL_BUTTON
, buts
[0], NULL
));
618 check_new (y1
++, x1
, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
619 add_widget (find_dlg
, ignore_dirs_cbox
);
622 input_new (y1
++, x1
, input_get_default_colors (), cols
- 6,
623 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "", "ignoredirs",
624 INPUT_COMPLETE_DEFAULT
);
625 widget_disable (WIDGET (in_ignore
), !options
.ignore_dirs_enable
);
626 add_widget (find_dlg
, in_ignore
);
628 add_widget (find_dlg
, hline_new (y1
++, -1, -1));
632 /* Start 1st column */
633 add_widget (find_dlg
, label_new (y1
++, x1
, file_name_label
));
635 input_new (y1
++, x1
, input_get_default_colors (), cw
, INPUT_LAST_TEXT
, "name",
636 INPUT_COMPLETE_DEFAULT
);
637 add_widget (find_dlg
, in_name
);
639 /* Start 2nd column */
640 content_label
= label_new (y2
++, x2
, content_content_label
);
641 add_widget (find_dlg
, content_label
);
643 input_new (y2
++, x2
, input_get_default_colors (), cw
, INPUT_LAST_TEXT
,
644 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
645 in_with
->label
= content_label
;
646 widget_disable (WIDGET (in_with
), disable
);
647 add_widget (find_dlg
, in_with
);
649 content_use_cbox
= check_new (y2
++, x2
, options
.content_use
, content_use_label
);
650 add_widget (find_dlg
, content_use_cbox
);
652 /* Continue 1st column */
653 recursively_cbox
= check_new (y1
++, x1
, options
.find_recurs
, file_recurs_label
);
654 add_widget (find_dlg
, recursively_cbox
);
656 file_pattern_cbox
= check_new (y1
++, x1
, options
.file_pattern
, file_pattern_label
);
657 add_widget (find_dlg
, file_pattern_cbox
);
659 file_case_sens_cbox
= check_new (y1
++, x1
, options
.file_case_sens
, file_case_label
);
660 add_widget (find_dlg
, file_case_sens_cbox
);
663 file_all_charsets_cbox
=
664 check_new (y1
++, x1
, options
.file_all_charsets
, file_all_charsets_label
);
665 add_widget (find_dlg
, file_all_charsets_cbox
);
668 skip_hidden_cbox
= check_new (y1
++, x1
, options
.skip_hidden
, file_skip_hidden_label
);
669 add_widget (find_dlg
, skip_hidden_cbox
);
671 /* Continue 2nd column */
672 content_regexp_cbox
= check_new (y2
++, x2
, options
.content_regexp
, content_regexp_label
);
673 widget_disable (WIDGET (content_regexp_cbox
), disable
);
674 add_widget (find_dlg
, content_regexp_cbox
);
676 content_case_sens_cbox
= check_new (y2
++, x2
, options
.content_case_sens
, content_case_label
);
677 widget_disable (WIDGET (content_case_sens_cbox
), disable
);
678 add_widget (find_dlg
, content_case_sens_cbox
);
681 content_all_charsets_cbox
=
682 check_new (y2
++, x2
, options
.content_all_charsets
, content_all_charsets_label
);
683 widget_disable (WIDGET (content_all_charsets_cbox
), disable
);
684 add_widget (find_dlg
, content_all_charsets_cbox
);
687 content_whole_words_cbox
=
688 check_new (y2
++, x2
, options
.content_whole_words
, content_whole_words_label
);
689 widget_disable (WIDGET (content_whole_words_cbox
), disable
);
690 add_widget (find_dlg
, content_whole_words_cbox
);
692 content_first_hit_cbox
=
693 check_new (y2
++, x2
, options
.content_first_hit
, content_first_hit_label
);
694 widget_disable (WIDGET (content_first_hit_cbox
), disable
);
695 add_widget (find_dlg
, content_first_hit_cbox
);
699 x1
= (cols
- b12
) / 2;
700 add_widget (find_dlg
, hline_new (y1
++, -1, -1));
701 add_widget (find_dlg
, button_new (y1
, x1
, B_ENTER
, DEFPUSH_BUTTON
, buts
[1], NULL
));
702 add_widget (find_dlg
, button_new (y1
, x1
+ b1
+ 1, B_CANCEL
, NORMAL_BUTTON
, buts
[2], NULL
));
705 dlg_select_widget (in_name
);
707 switch (run_dlg (find_dlg
))
710 return_value
= FALSE
;
717 temp_dir
= in_start
->buffer
;
718 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
719 temp_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
721 temp_dir
= g_strdup (temp_dir
);
723 if (in_start_dir
!= INPUT_LAST_TEXT
)
724 g_free (in_start_dir
);
725 in_start_dir
= tree_box (temp_dir
);
726 if (in_start_dir
== NULL
)
727 in_start_dir
= temp_dir
;
731 input_assign_text (in_start
, in_start_dir
);
733 /* Warning: Dreadful goto */
742 options
.file_all_charsets
= file_all_charsets_cbox
->state
& C_BOOL
;
743 options
.content_all_charsets
= content_all_charsets_cbox
->state
& C_BOOL
;
745 options
.content_use
= content_use_cbox
->state
& C_BOOL
;
746 options
.content_case_sens
= content_case_sens_cbox
->state
& C_BOOL
;
747 options
.content_regexp
= content_regexp_cbox
->state
& C_BOOL
;
748 options
.content_first_hit
= content_first_hit_cbox
->state
& C_BOOL
;
749 options
.content_whole_words
= content_whole_words_cbox
->state
& C_BOOL
;
750 options
.find_recurs
= recursively_cbox
->state
& C_BOOL
;
751 options
.file_pattern
= file_pattern_cbox
->state
& C_BOOL
;
752 options
.file_case_sens
= file_case_sens_cbox
->state
& C_BOOL
;
753 options
.skip_hidden
= skip_hidden_cbox
->state
& C_BOOL
;
754 options
.ignore_dirs_enable
= ignore_dirs_cbox
->state
& C_BOOL
;
755 g_free (options
.ignore_dirs
);
756 options
.ignore_dirs
= g_strdup (in_ignore
->buffer
);
758 *content
= (options
.content_use
&& in_with
->buffer
[0] != '\0')
759 ? g_strdup (in_with
->buffer
) : NULL
;
760 *start_dir
= in_start
->buffer
[0] != '\0' ? in_start
->buffer
: (char *) ".";
761 *pattern
= g_strdup (in_name
->buffer
);
762 if (in_start_dir
!= INPUT_LAST_TEXT
)
763 g_free (in_start_dir
);
764 in_start_dir
= g_strdup (*start_dir
);
766 s
= tilde_expand (*start_dir
);
767 canonicalize_pathname (s
);
769 if (s
[0] == '.' && s
[1] == '\0')
771 *start_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
772 /* FIXME: is current_panel->cwd_vpath canonicalized? */
773 /* relative paths will be used in panelization */
774 *start_dir_len
= (ssize_t
) strlen (*start_dir
);
777 else if (g_path_is_absolute (s
))
784 /* relative paths will be used in panelization */
787 cwd_str
= vfs_path_to_str (current_panel
->cwd_vpath
);
788 *start_dir
= mc_build_filename (cwd_str
, s
, (char *) NULL
);
789 *start_dir_len
= (ssize_t
) strlen (cwd_str
);
794 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
795 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
798 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
800 find_save_options ();
806 destroy_dlg (find_dlg
);
811 /* --------------------------------------------------------------------------------------------- */
813 #if GLIB_CHECK_VERSION (2, 14, 0)
815 push_directory (const vfs_path_t
* dir
)
817 g_queue_push_head (&dir_queue
, (void *) dir
);
820 /* --------------------------------------------------------------------------------------------- */
822 static inline vfs_path_t
*
825 return (vfs_path_t
*) g_queue_pop_tail (&dir_queue
);
828 /* --------------------------------------------------------------------------------------------- */
829 /** Remove all the items from the stack */
834 g_queue_foreach (&dir_queue
, (GFunc
) vfs_path_free
, NULL
);
835 g_queue_clear (&dir_queue
);
838 /* --------------------------------------------------------------------------------------------- */
840 #else /* GLIB_CHECK_VERSION */
842 push_directory (const vfs_path_t
* dir
)
846 new = g_new (dir_stack
, 1);
847 new->name
= (vfs_path_t
*) dir
;
848 new->prev
= dir_stack_base
;
849 dir_stack_base
= new;
852 /* --------------------------------------------------------------------------------------------- */
857 vfs_path_t
*name
= NULL
;
859 if (dir_stack_base
!= NULL
)
862 name
= dir_stack_base
->name
;
863 next
= dir_stack_base
->prev
;
864 g_free (dir_stack_base
);
865 dir_stack_base
= next
;
871 /* --------------------------------------------------------------------------------------------- */
872 /** Remove all the items from the stack */
877 vfs_path_t
*dir
= NULL
;
879 while ((dir
= pop_directory ()) != NULL
)
882 #endif /* GLIB_CHECK_VERSION */
884 /* --------------------------------------------------------------------------------------------- */
887 insert_file (const char *dir
, const char *file
)
889 char *tmp_name
= NULL
;
890 static char *dirname
= NULL
;
892 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
897 if (strcmp (old_dir
, dir
))
900 old_dir
= g_strdup (dir
);
901 dirname
= add_to_list (dir
, NULL
);
906 old_dir
= g_strdup (dir
);
907 dirname
= add_to_list (dir
, NULL
);
910 tmp_name
= g_strdup_printf (" %s", file
);
911 add_to_list (tmp_name
, dirname
);
915 /* --------------------------------------------------------------------------------------------- */
918 find_add_match (const char *dir
, const char *file
)
920 insert_file (dir
, file
);
924 listbox_select_first (find_list
);
925 send_message (find_list
, NULL
, MSG_DRAW
, 0, NULL
);
931 /* --------------------------------------------------------------------------------------------- */
935 * Returns malloced null-terminated line from file file_fd.
936 * Input is buffered in buf_size long buffer.
937 * Current pos in buf is stored in pos.
938 * n_read - number of read chars.
939 * has_newline - is there newline ?
943 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
955 *n_read
= mc_read (file_fd
, buf
, buf_size
);
963 /* skip possible leading zero(s) */
969 if (i
>= buffer_size
- 1)
970 buffer
= g_realloc (buffer
, buffer_size
+= 80);
979 *has_newline
= (ch
!= '\0');
987 /* --------------------------------------------------------------------------------------------- */
989 static FindProgressStatus
990 check_find_events (WDialog
* h
)
996 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
999 dlg_process_event (h
, c
, &event
);
1000 if (h
->ret_value
== B_ENTER
1001 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
1003 /* dialog terminated */
1006 if ((WIDGET (h
)->options
& W_WANT_IDLE
) == 0)
1008 /* searching suspended */
1009 return FIND_SUSPEND
;
1016 /* --------------------------------------------------------------------------------------------- */
1020 * Search the content_pattern string in the DIRECTORY/FILE.
1021 * It will add the found entries to the find listbox.
1023 * returns FALSE if do_search should look for another file
1024 * TRUE if do_search should exit and proceed to the event handler
1028 search_content (WDialog
* h
, const char *directory
, const char *filename
)
1031 char buffer
[BUF_4K
];
1033 gboolean ret_val
= FALSE
;
1036 vpath
= vfs_path_build_filename (directory
, filename
, (char *) NULL
);
1038 if (mc_stat (vpath
, &s
) != 0 || !S_ISREG (s
.st_mode
))
1040 vfs_path_free (vpath
);
1044 file_fd
= mc_open (vpath
, O_RDONLY
);
1045 vfs_path_free (vpath
);
1050 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), filename
);
1051 status_update (str_trunc (buffer
, WIDGET (h
)->cols
- 8));
1055 tty_enable_interrupt_key ();
1056 tty_got_interrupt ();
1062 gboolean has_newline
;
1064 gboolean found
= FALSE
;
1066 char result
[BUF_MEDIUM
];
1070 /* We've been previously suspended, start from the previous position */
1076 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1077 &pos
, &n_read
, &has_newline
)) != NULL
)
1079 if (!found
/* Search in binary line once */
1080 && mc_search_run (search_content_handle
,
1081 (const void *) p
, 0, strlen (p
), &found_len
))
1083 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1084 find_add_match (directory
, result
);
1089 if (found
&& options
.content_first_hit
)
1098 if ((line
& 0xff) == 0)
1100 FindProgressStatus res
;
1101 res
= check_find_events (h
);
1120 tty_disable_interrupt_key ();
1125 /* --------------------------------------------------------------------------------------------- */
1128 If dir is absolute, this means we're within dir and searching file here.
1129 If dir is relative, this means we're going to add dir to the directory stack.
1132 find_ignore_dir_search (const char *dir
)
1134 if (find_ignore_dirs
!= NULL
)
1136 const size_t dlen
= strlen (dir
);
1137 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1141 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1143 const size_t ilen
= strlen (*ignore_dir
);
1144 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1146 /* ignore dir is too long -- skip it */
1150 /* handle absolute and relative paths */
1151 switch (iabs
| dabs
)
1153 case 0: /* both paths are relative */
1154 case 3: /* both paths are abolute */
1155 /* if ignore dir is not a path of dir -- skip it */
1156 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1158 /* be sure that ignore dir is not a part of dir like:
1159 ignore dir is "h", dir is "home" */
1160 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1164 case 1: /* dir is absolute, ignore_dir is relative */
1168 d
= strstr (dir
, *ignore_dir
);
1169 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1173 case 2: /* dir is relative, ignore_dir is absolute */
1174 /* FIXME: skip this case */
1176 default: /* this cannot occurs */
1185 /* --------------------------------------------------------------------------------------------- */
1188 find_rotate_dash (const WDialog
* h
, gboolean finish
)
1190 static const char rotating_dash
[] = "|/-\\";
1191 static unsigned int pos
= 0;
1195 const Widget
*w
= WIDGET (h
);
1197 pos
= (pos
+ 1) % 4;
1198 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1199 widget_move (h
, w
->lines
- 7, w
->cols
- 4);
1200 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1205 /* --------------------------------------------------------------------------------------------- */
1208 do_search (WDialog
* h
)
1210 static struct dirent
*dp
= NULL
;
1211 static DIR *dirp
= NULL
;
1212 static char *directory
= NULL
;
1213 struct stat tmp_stat
;
1214 static int subdirs_left
= 0;
1216 unsigned short count
;
1219 { /* someone forces me to close dirp */
1231 for (count
= 0; count
< 32; count
++)
1241 while (dirp
== NULL
)
1243 vfs_path_t
*tmp_vpath
= NULL
;
1245 tty_setcolor (REVERSE_COLOR
);
1249 tmp_vpath
= pop_directory ();
1250 if (tmp_vpath
== NULL
)
1253 if (ignore_count
== 0)
1254 status_update (_("Finished"));
1257 char msg
[BUF_SMALL
];
1258 g_snprintf (msg
, sizeof (msg
),
1259 ngettext ("Finished (ignored %zd directory)",
1260 "Finished (ignored %zd directories)",
1261 ignore_count
), ignore_count
);
1262 status_update (msg
);
1264 find_rotate_dash (h
, TRUE
);
1269 /* handle absolute ignore dirs here */
1274 tmp
= vfs_path_to_str (tmp_vpath
);
1275 ok
= find_ignore_dir_search (tmp
);
1281 vfs_path_free (tmp_vpath
);
1286 directory
= vfs_path_to_str (tmp_vpath
);
1290 char buffer
[BUF_MEDIUM
];
1292 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"), directory
);
1293 status_update (str_trunc (directory
, WIDGET (h
)->cols
- 8));
1295 /* mc_stat should not be called after mc_opendir
1296 because vfs_s_opendir modifies the st_nlink
1298 if (mc_stat (tmp_vpath
, &tmp_stat
) == 0)
1299 subdirs_left
= tmp_stat
.st_nlink
- 2;
1303 dirp
= mc_opendir (tmp_vpath
);
1304 vfs_path_free (tmp_vpath
);
1305 } /* while (!dirp) */
1307 /* skip invalid filenames */
1308 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1312 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1314 /* skip invalid filenames */
1315 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1321 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1325 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1326 { /* Can directory be NULL ? */
1327 /* handle relative ignore dirs here */
1328 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1332 vfs_path_t
*tmp_vpath
;
1334 tmp_vpath
= vfs_path_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1336 if (mc_lstat (tmp_vpath
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1338 push_directory (tmp_vpath
);
1342 vfs_path_free (tmp_vpath
);
1346 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1347 0, strlen (dp
->d_name
), &bytes_found
);
1351 if (content_pattern
== NULL
)
1352 find_add_match (directory
, dp
->d_name
);
1353 else if (search_content (h
, directory
, dp
->d_name
))
1358 /* skip invalid filenames */
1359 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1363 find_rotate_dash (h
, FALSE
);
1368 /* --------------------------------------------------------------------------------------------- */
1371 init_find_vars (void)
1378 /* Remove all the items from the stack */
1381 g_strfreev (find_ignore_dirs
);
1382 find_ignore_dirs
= NULL
;
1385 /* --------------------------------------------------------------------------------------------- */
1388 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1390 char *fullname
= NULL
;
1391 const char *filename
= NULL
;
1393 vfs_path_t
*fullname_vpath
;
1395 if (content_pattern
!= NULL
)
1397 filename
= strchr (file
+ 4, ':') + 1;
1398 line
= atoi (file
+ 4);
1402 filename
= file
+ 4;
1406 fullname_vpath
= vfs_path_build_filename (dir
, filename
, (char *) NULL
);
1408 do_edit_at_line (fullname_vpath
, use_internal_edit
, line
);
1410 view_file_at_line (fullname_vpath
, unparsed_view
, use_internal_view
, line
);
1411 vfs_path_free (fullname_vpath
);
1415 /* --------------------------------------------------------------------------------------------- */
1418 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1423 listbox_get_current (find_list
, &text
, (void **) &dir
);
1425 if ((text
== NULL
) || (dir
== NULL
))
1426 return MSG_NOT_HANDLED
;
1428 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1432 /* --------------------------------------------------------------------------------------------- */
1435 find_calc_button_locations (const WDialog
* h
, gboolean all_buttons
)
1437 const int cols
= WIDGET (h
)->cols
;
1441 l1
= fbuts
[0].len
+ fbuts
[1].len
+ fbuts
[is_start
? 3 : 2].len
+ fbuts
[4].len
+ 3;
1442 l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
+ 2;
1444 fbuts
[0].x
= (cols
- l1
) / 2;
1445 fbuts
[1].x
= fbuts
[0].x
+ fbuts
[0].len
+ 1;
1446 fbuts
[2].x
= fbuts
[1].x
+ fbuts
[1].len
+ 1;
1447 fbuts
[3].x
= fbuts
[2].x
;
1448 fbuts
[4].x
= fbuts
[2].x
+ fbuts
[is_start
? 3 : 2].len
+ 1;
1452 fbuts
[5].x
= (cols
- l2
) / 2;
1453 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ 1;
1454 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ 1;
1458 /* --------------------------------------------------------------------------------------------- */
1461 find_relocate_buttons (const WDialog
* h
, gboolean all_buttons
)
1465 find_calc_button_locations (h
, all_buttons
);
1467 for (i
= 0; i
< fbuts_num
; i
++)
1468 fbuts
[i
].button
->x
= WIDGET (h
)->x
+ fbuts
[i
].x
;
1471 /* --------------------------------------------------------------------------------------------- */
1474 find_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
1476 WDialog
*h
= DIALOG (w
);
1481 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1483 int unparsed_view
= (parm
== KEY_F (13));
1484 return view_edit_currently_selected_file (unparsed_view
, 0);
1486 if (parm
== KEY_F (4))
1487 return view_edit_currently_selected_file (0, 1);
1488 return MSG_NOT_HANDLED
;
1491 dlg_set_size (h
, LINES
- 4, COLS
- 16);
1492 find_relocate_buttons (h
, TRUE
);
1500 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
1504 /* --------------------------------------------------------------------------------------------- */
1505 /** Handles the Stop/Start button in the find window */
1508 start_stop (WButton
* button
, int action
)
1510 Widget
*w
= WIDGET (button
);
1515 widget_want_idle (WIDGET (find_dlg
), running
);
1516 is_start
= !is_start
;
1518 status_update (is_start
? _("Stopped") : _("Searching"));
1519 button_set_text (button
, fbuts
[is_start
? 3 : 2].text
);
1521 find_relocate_buttons (w
->owner
, FALSE
);
1522 dlg_redraw (w
->owner
);
1527 /* --------------------------------------------------------------------------------------------- */
1528 /** Handle view command, when invoked as a button */
1531 find_do_view_file (WButton
* button
, int action
)
1536 view_edit_currently_selected_file (0, 0);
1540 /* --------------------------------------------------------------------------------------------- */
1541 /** Handle edit command, when invoked as a button */
1544 find_do_edit_file (WButton
* button
, int action
)
1549 view_edit_currently_selected_file (0, 1);
1553 /* --------------------------------------------------------------------------------------------- */
1563 static gboolean i18n_flag
= FALSE
;
1567 for (i
= 0; i
< fbuts_num
; i
++)
1569 fbuts
[i
].text
= _(fbuts
[i
].text
);
1570 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1571 if (fbuts
[i
].flags
== DEFPUSH_BUTTON
)
1577 #endif /* ENABLE_NLS */
1583 create_dlg (TRUE
, 0, 0, lines
, cols
, dialog_colors
, find_callback
, NULL
, "[Find File]",
1584 _("Find File"), DLG_CENTER
);
1586 find_calc_button_locations (find_dlg
, TRUE
);
1589 find_list
= listbox_new (y
, 2, lines
- 10, cols
- 4, FALSE
, NULL
);
1590 add_widget_autopos (find_dlg
, find_list
, WPOS_KEEP_ALL
, NULL
);
1591 y
+= WIDGET (find_list
)->lines
;
1593 add_widget_autopos (find_dlg
, hline_new (y
++, -1, -1), WPOS_KEEP_BOTTOM
, NULL
);
1595 found_num_label
= label_new (y
++, 4, "");
1596 add_widget_autopos (find_dlg
, found_num_label
, WPOS_KEEP_BOTTOM
, NULL
);
1598 status_label
= label_new (y
++, 4, _("Searching"));
1599 add_widget_autopos (find_dlg
, status_label
, WPOS_KEEP_BOTTOM
, NULL
);
1601 add_widget_autopos (find_dlg
, hline_new (y
++, -1, -1), WPOS_KEEP_BOTTOM
, NULL
);
1603 for (i
= 0; i
< fbuts_num
; i
++)
1606 fbuts
[3].button
= fbuts
[2].button
;
1611 (y
, fbuts
[i
].x
, fbuts
[i
].ret_cmd
, fbuts
[i
].flags
, fbuts
[i
].text
,
1612 fbuts
[i
].callback
));
1613 add_widget_autopos (find_dlg
, fbuts
[i
].button
, WPOS_KEEP_BOTTOM
, NULL
);
1616 if (i
== quit_button
)
1620 dlg_select_widget (find_list
);
1623 /* --------------------------------------------------------------------------------------------- */
1630 search_content_handle
= mc_search_new (content_pattern
, -1);
1631 if (search_content_handle
)
1633 search_content_handle
->search_type
=
1634 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1635 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1636 search_content_handle
->whole_words
= options
.content_whole_words
;
1637 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1639 search_file_handle
= mc_search_new (find_pattern
, -1);
1640 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1641 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1642 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1643 search_file_handle
->is_entire_line
= options
.file_pattern
;
1647 widget_want_idle (WIDGET (find_dlg
), TRUE
);
1648 ret
= run_dlg (find_dlg
);
1650 mc_search_free (search_file_handle
);
1651 search_file_handle
= NULL
;
1652 mc_search_free (search_content_handle
);
1653 search_content_handle
= NULL
;
1658 /* --------------------------------------------------------------------------------------------- */
1663 widget_want_idle (WIDGET (find_dlg
), FALSE
);
1664 destroy_dlg (find_dlg
);
1667 /* --------------------------------------------------------------------------------------------- */
1670 do_find (const char *start_dir
, ssize_t start_dir_len
, const char *ignore_dirs
,
1671 const char *pattern
, const char *content
, char **dirname
, char **filename
)
1673 int return_value
= 0;
1674 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1678 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1679 find_pattern
= (char *) pattern
;
1681 content_pattern
= NULL
;
1682 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1683 content_pattern
= g_strdup (content
);
1686 parse_ignore_dirs (ignore_dirs
);
1687 push_directory (vfs_path_from_str (start_dir
));
1689 return_value
= run_process ();
1691 /* Clear variables */
1694 get_list_info (&file_tmp
, &dir_tmp
);
1697 *dirname
= g_strdup (dir_tmp
);
1699 *filename
= g_strdup (file_tmp
);
1701 if (return_value
== B_PANELIZE
&& *filename
)
1703 int status
, link_to_dir
, stale_link
;
1708 dir_list
*list
= ¤t_panel
->dir
;
1711 if (set_zero_dir (list
))
1714 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1716 const char *lc_filename
= NULL
;
1717 WLEntry
*le
= LENTRY (entry
->data
);
1720 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1723 if (content_pattern
!= NULL
)
1724 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1726 lc_filename
= le
->text
+ 4;
1728 name
= mc_build_filename (le
->data
, lc_filename
, (char *) NULL
);
1729 /* skip initial start dir */
1730 if (start_dir_len
< 0)
1734 p
= name
+ (size_t) start_dir_len
;
1739 status
= handle_path (list
, p
, &st
, next_free
, &link_to_dir
, &stale_link
);
1751 /* don't add files more than once to the panel */
1752 if (content_pattern
!= NULL
&& next_free
> 0
1753 && strcmp (list
->list
[next_free
- 1].fname
, p
) == 0)
1759 if (next_free
== 0) /* first turn i.e clean old list */
1760 panel_clean_dir (current_panel
);
1761 list
->list
[next_free
].fnamelen
= strlen (p
);
1762 list
->list
[next_free
].fname
= g_strndup (p
, list
->list
[next_free
].fnamelen
);
1763 list
->list
[next_free
].f
.marked
= 0;
1764 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1765 list
->list
[next_free
].f
.stale_link
= stale_link
;
1766 list
->list
[next_free
].f
.dir_size_computed
= 0;
1767 list
->list
[next_free
].st
= st
;
1768 list
->list
[next_free
].sort_key
= NULL
;
1769 list
->list
[next_free
].second_sort_key
= NULL
;
1772 if (!(next_free
& 15))
1778 current_panel
->count
= next_free
;
1779 current_panel
->is_panelized
= TRUE
;
1782 if (start_dir_len
< 0)
1785 vfs_path_free (current_panel
->cwd_vpath
);
1786 current_panel
->cwd_vpath
= vfs_path_from_str (PATH_SEP_STR
);
1787 ret
= chdir (PATH_SEP_STR
);
1790 panelize_save_panel (current_panel
);
1794 g_free (content_pattern
);
1796 do_search (NULL
); /* force do_search to release resources */
1800 return return_value
;
1803 /* --------------------------------------------------------------------------------------------- */
1804 /*** public functions ****************************************************************************/
1805 /* --------------------------------------------------------------------------------------------- */
1810 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1811 ssize_t start_dir_len
;
1812 char *filename
= NULL
, *dirname
= NULL
;
1815 while (find_parameters (&start_dir
, &start_dir_len
, &ignore_dirs
, &pattern
, &content
))
1817 if (pattern
[0] == '\0')
1818 break; /* nothing search */
1820 dirname
= filename
= NULL
;
1822 v
= do_find (start_dir
, start_dir_len
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1823 g_free (ignore_dirs
);
1828 if (dirname
!= NULL
)
1830 vfs_path_t
*dirname_vpath
;
1832 dirname_vpath
= vfs_path_from_str (dirname
);
1833 do_cd (dirname_vpath
, cd_exact
);
1834 vfs_path_free (dirname_vpath
);
1835 if (filename
!= NULL
)
1836 try_to_select (current_panel
,
1837 filename
+ (content
!= NULL
1838 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1840 else if (filename
!= NULL
)
1842 vfs_path_t
*filename_vpath
;
1844 filename_vpath
= vfs_path_from_str (filename
);
1845 do_cd (filename_vpath
, cd_exact
);
1846 vfs_path_free (filename_vpath
);
1861 if (v
== B_PANELIZE
)
1863 panel_re_sort (current_panel
);
1864 try_to_select (current_panel
, NULL
);
1870 /* --------------------------------------------------------------------------------------------- */