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 Dlg_head
*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_("&Suspend"), 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 set_idle_proc (data
, 0);
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 (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
415 if (sender
== WIDGET (content_use_cbox
))
417 gboolean disable
= !(content_use_cbox
->state
& C_BOOL
);
419 widget_disable (WIDGET (in_with
), disable
);
420 widget_disable (WIDGET (content_first_hit_cbox
), disable
);
421 widget_disable (WIDGET (content_regexp_cbox
), disable
);
422 widget_disable (WIDGET (content_case_sens_cbox
), disable
);
424 widget_disable (WIDGET (content_all_charsets_cbox
), disable
);
426 widget_disable (WIDGET (content_whole_words_cbox
), disable
);
431 if (sender
== WIDGET (ignore_dirs_cbox
))
433 gboolean disable
= !(ignore_dirs_cbox
->state
& C_BOOL
);
435 widget_disable (WIDGET (in_ignore
), disable
);
440 return MSG_NOT_HANDLED
;
444 if (h
->ret_value
!= B_ENTER
)
447 /* check filename regexp */
448 if (!(file_pattern_cbox
->state
& C_BOOL
)
449 && (in_name
->buffer
[0] != '\0') && !find_check_regexp (in_name
->buffer
))
451 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
452 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
453 dlg_select_widget (in_name
);
457 /* check content regexp */
458 if ((content_use_cbox
->state
& C_BOOL
) && (content_regexp_cbox
->state
& C_BOOL
)
459 && (in_with
->buffer
[0] != '\0') && !find_check_regexp (in_with
->buffer
))
461 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
462 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
463 dlg_select_widget (in_with
);
470 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
474 /* --------------------------------------------------------------------------------------------- */
476 * find_parameters: gets information from the user
478 * If the return value is TRUE, then the following holds:
480 * start_dir, ignore_dirs, pattern and content contain the information provided by the user.
481 * They are newly allocated strings and must be freed when uneeded.
483 * start_dir_len is -1 when user entered an absolute path, otherwise it is a length
484 * of start_dir (which is absolute). It is used to get a relative pats of find results.
488 find_parameters (char **start_dir
, ssize_t
* start_dir_len
,
489 char **ignore_dirs
, char **pattern
, char **content
)
491 /* Size of the find parameters window */
493 const int lines
= 19;
495 const int lines
= 18;
499 gboolean return_value
;
502 const char *file_name_label
= N_("File name:");
503 const char *file_recurs_label
= N_("&Find recursively");
504 const char *file_pattern_label
= N_("&Using shell patterns");
506 const char *file_all_charsets_label
= N_("&All charsets");
508 const char *file_case_label
= N_("Cas&e sensitive");
509 const char *file_skip_hidden_label
= N_("S&kip hidden");
512 const char *content_content_label
= N_("Content:");
513 const char *content_use_label
= N_("Sea&rch for content");
514 const char *content_regexp_label
= N_("Re&gular expression");
515 const char *content_case_label
= N_("Case sens&itive");
517 const char *content_all_charsets_label
= N_("A&ll charsets");
519 const char *content_whole_words_label
= N_("&Whole words");
520 const char *content_first_hit_label
= N_("Fir&st hit");
522 const char *buts
[] = { N_("&Tree"), N_("&OK"), N_("&Cancel") };
536 file_name_label
= _(file_name_label
);
537 file_recurs_label
= _(file_recurs_label
);
538 file_pattern_label
= _(file_pattern_label
);
540 file_all_charsets_label
= _(file_all_charsets_label
);
542 file_case_label
= _(file_case_label
);
543 file_skip_hidden_label
= _(file_skip_hidden_label
);
546 content_content_label
= _(content_content_label
);
547 content_use_label
= _(content_use_label
);
548 content_regexp_label
= _(content_regexp_label
);
549 content_case_label
= _(content_case_label
);
551 content_all_charsets_label
= _(content_all_charsets_label
);
553 content_whole_words_label
= _(content_whole_words_label
);
554 content_first_hit_label
= _(content_first_hit_label
);
556 for (i
= 0; i
< G_N_ELEMENTS (buts
); i
++)
557 buts
[i
] = _(buts
[i
]);
559 #endif /* ENABLE_NLS */
561 /* caclulate dialog width */
564 cw
= str_term_width1 (file_name_label
);
565 cw
= max (cw
, str_term_width1 (file_recurs_label
) + 4);
566 cw
= max (cw
, str_term_width1 (file_pattern_label
) + 4);
568 cw
= max (cw
, str_term_width1 (file_all_charsets_label
) + 4);
570 cw
= max (cw
, str_term_width1 (file_case_label
) + 4);
571 cw
= max (cw
, str_term_width1 (file_skip_hidden_label
) + 4);
573 cw
= max (cw
, str_term_width1 (content_content_label
) + 4);
574 cw
= max (cw
, str_term_width1 (content_use_label
) + 4);
575 cw
= max (cw
, str_term_width1 (content_regexp_label
) + 4);
576 cw
= max (cw
, str_term_width1 (content_case_label
) + 4);
578 cw
= max (cw
, str_term_width1 (content_all_charsets_label
) + 4);
580 cw
= max (cw
, str_term_width1 (content_whole_words_label
) + 4);
581 cw
= max (cw
, str_term_width1 (content_first_hit_label
) + 4);
584 b0
= str_term_width1 (buts
[0]) + 3;
585 b1
= str_term_width1 (buts
[1]) + 5; /* default button */
586 b2
= str_term_width1 (buts
[2]) + 3;
589 cols
= max (cols
, max (b12
, cw
* 2 + 1) + 6);
591 find_load_options ();
593 if (in_start_dir
== NULL
)
594 in_start_dir
= g_strdup (".");
596 disable
= !options
.content_use
;
599 create_dlg (TRUE
, 0, 0, lines
, cols
, dialog_colors
, find_parm_callback
, NULL
, "[Find File]",
600 _("Find File"), DLG_CENTER
);
607 add_widget (find_dlg
, label_new (y1
++, x1
, _("Start at:")));
609 input_new (y1
, x1
, input_get_default_colors (), cols
- b0
- 7, in_start_dir
, "start",
610 INPUT_COMPLETE_DEFAULT
);
611 add_widget (find_dlg
, in_start
);
613 add_widget (find_dlg
, button_new (y1
++, cols
- b0
- 3, B_TREE
, NORMAL_BUTTON
, buts
[0], NULL
));
616 check_new (y1
++, x1
, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
617 add_widget (find_dlg
, ignore_dirs_cbox
);
620 input_new (y1
++, x1
, input_get_default_colors (), cols
- 6,
621 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "", "ignoredirs",
622 INPUT_COMPLETE_DEFAULT
);
623 widget_disable (WIDGET (in_ignore
), !options
.ignore_dirs_enable
);
624 add_widget (find_dlg
, in_ignore
);
626 add_widget (find_dlg
, hline_new (y1
++, -1, -1));
630 /* Start 1st column */
631 add_widget (find_dlg
, label_new (y1
++, x1
, file_name_label
));
633 input_new (y1
++, x1
, input_get_default_colors (), cw
, INPUT_LAST_TEXT
, "name",
634 INPUT_COMPLETE_DEFAULT
);
635 add_widget (find_dlg
, in_name
);
637 /* Start 2nd column */
638 content_label
= label_new (y2
++, x2
, content_content_label
);
639 add_widget (find_dlg
, content_label
);
641 input_new (y2
++, x2
, input_get_default_colors (), cw
, INPUT_LAST_TEXT
,
642 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
643 in_with
->label
= content_label
;
644 widget_disable (WIDGET (in_with
), disable
);
645 add_widget (find_dlg
, in_with
);
647 content_use_cbox
= check_new (y2
++, x2
, options
.content_use
, content_use_label
);
648 add_widget (find_dlg
, content_use_cbox
);
650 /* Continue 1st column */
651 recursively_cbox
= check_new (y1
++, x1
, options
.find_recurs
, file_recurs_label
);
652 add_widget (find_dlg
, recursively_cbox
);
654 file_pattern_cbox
= check_new (y1
++, x1
, options
.file_pattern
, file_pattern_label
);
655 add_widget (find_dlg
, file_pattern_cbox
);
657 file_case_sens_cbox
= check_new (y1
++, x1
, options
.file_case_sens
, file_case_label
);
658 add_widget (find_dlg
, file_case_sens_cbox
);
661 file_all_charsets_cbox
=
662 check_new (y1
++, x1
, options
.file_all_charsets
, file_all_charsets_label
);
663 add_widget (find_dlg
, file_all_charsets_cbox
);
666 skip_hidden_cbox
= check_new (y1
++, x1
, options
.skip_hidden
, file_skip_hidden_label
);
667 add_widget (find_dlg
, skip_hidden_cbox
);
669 /* Continue 2nd column */
670 content_regexp_cbox
= check_new (y2
++, x2
, options
.content_regexp
, content_regexp_label
);
671 widget_disable (WIDGET (content_regexp_cbox
), disable
);
672 add_widget (find_dlg
, content_regexp_cbox
);
674 content_case_sens_cbox
= check_new (y2
++, x2
, options
.content_case_sens
, content_case_label
);
675 widget_disable (WIDGET (content_case_sens_cbox
), disable
);
676 add_widget (find_dlg
, content_case_sens_cbox
);
679 content_all_charsets_cbox
=
680 check_new (y2
++, x2
, options
.content_all_charsets
, content_all_charsets_label
);
681 widget_disable (WIDGET (content_all_charsets_cbox
), disable
);
682 add_widget (find_dlg
, content_all_charsets_cbox
);
685 content_whole_words_cbox
=
686 check_new (y2
++, x2
, options
.content_whole_words
, content_whole_words_label
);
687 widget_disable (WIDGET (content_whole_words_cbox
), disable
);
688 add_widget (find_dlg
, content_whole_words_cbox
);
690 content_first_hit_cbox
=
691 check_new (y2
++, x2
, options
.content_first_hit
, content_first_hit_label
);
692 widget_disable (WIDGET (content_first_hit_cbox
), disable
);
693 add_widget (find_dlg
, content_first_hit_cbox
);
697 x1
= (cols
- b12
) / 2;
698 add_widget (find_dlg
, hline_new (y1
++, -1, -1));
699 add_widget (find_dlg
, button_new (y1
, x1
, B_ENTER
, DEFPUSH_BUTTON
, buts
[1], NULL
));
700 add_widget (find_dlg
, button_new (y1
, x1
+ b1
+ 1, B_CANCEL
, NORMAL_BUTTON
, buts
[2], NULL
));
703 dlg_select_widget (in_name
);
705 switch (run_dlg (find_dlg
))
708 return_value
= FALSE
;
715 temp_dir
= in_start
->buffer
;
716 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
717 temp_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
719 temp_dir
= g_strdup (temp_dir
);
721 if (in_start_dir
!= INPUT_LAST_TEXT
)
722 g_free (in_start_dir
);
723 in_start_dir
= tree_box (temp_dir
);
724 if (in_start_dir
== NULL
)
725 in_start_dir
= temp_dir
;
729 input_assign_text (in_start
, in_start_dir
);
731 /* Warning: Dreadful goto */
740 options
.file_all_charsets
= file_all_charsets_cbox
->state
& C_BOOL
;
741 options
.content_all_charsets
= content_all_charsets_cbox
->state
& C_BOOL
;
743 options
.content_use
= content_use_cbox
->state
& C_BOOL
;
744 options
.content_case_sens
= content_case_sens_cbox
->state
& C_BOOL
;
745 options
.content_regexp
= content_regexp_cbox
->state
& C_BOOL
;
746 options
.content_first_hit
= content_first_hit_cbox
->state
& C_BOOL
;
747 options
.content_whole_words
= content_whole_words_cbox
->state
& C_BOOL
;
748 options
.find_recurs
= recursively_cbox
->state
& C_BOOL
;
749 options
.file_pattern
= file_pattern_cbox
->state
& C_BOOL
;
750 options
.file_case_sens
= file_case_sens_cbox
->state
& C_BOOL
;
751 options
.skip_hidden
= skip_hidden_cbox
->state
& C_BOOL
;
752 options
.ignore_dirs_enable
= ignore_dirs_cbox
->state
& C_BOOL
;
753 g_free (options
.ignore_dirs
);
754 options
.ignore_dirs
= g_strdup (in_ignore
->buffer
);
756 *content
= (options
.content_use
&& in_with
->buffer
[0] != '\0')
757 ? g_strdup (in_with
->buffer
) : NULL
;
758 *start_dir
= in_start
->buffer
[0] != '\0' ? in_start
->buffer
: (char *) ".";
759 *pattern
= g_strdup (in_name
->buffer
);
760 if (in_start_dir
!= INPUT_LAST_TEXT
)
761 g_free (in_start_dir
);
762 in_start_dir
= g_strdup (*start_dir
);
764 s
= tilde_expand (*start_dir
);
765 canonicalize_pathname (s
);
767 if (s
[0] == '.' && s
[1] == '\0')
769 *start_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
770 /* FIXME: is current_panel->cwd_vpath canonicalized? */
771 /* relative paths will be used in panelization */
772 *start_dir_len
= (ssize_t
) strlen (*start_dir
);
775 else if (g_path_is_absolute (s
))
782 /* relative paths will be used in panelization */
785 cwd_str
= vfs_path_to_str (current_panel
->cwd_vpath
);
786 *start_dir
= mc_build_filename (cwd_str
, s
, (char *) NULL
);
787 *start_dir_len
= (ssize_t
) strlen (cwd_str
);
792 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
793 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
796 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
798 find_save_options ();
804 destroy_dlg (find_dlg
);
809 /* --------------------------------------------------------------------------------------------- */
811 #if GLIB_CHECK_VERSION (2, 14, 0)
813 push_directory (const vfs_path_t
* dir
)
815 g_queue_push_head (&dir_queue
, (void *) dir
);
818 /* --------------------------------------------------------------------------------------------- */
820 static inline vfs_path_t
*
823 return (vfs_path_t
*) g_queue_pop_tail (&dir_queue
);
826 /* --------------------------------------------------------------------------------------------- */
827 /** Remove all the items from the stack */
832 g_queue_foreach (&dir_queue
, (GFunc
) vfs_path_free
, NULL
);
833 g_queue_clear (&dir_queue
);
836 /* --------------------------------------------------------------------------------------------- */
838 #else /* GLIB_CHECK_VERSION */
840 push_directory (const vfs_path_t
* dir
)
844 new = g_new (dir_stack
, 1);
845 new->name
= (vfs_path_t
*) dir
;
846 new->prev
= dir_stack_base
;
847 dir_stack_base
= new;
850 /* --------------------------------------------------------------------------------------------- */
855 vfs_path_t
*name
= NULL
;
857 if (dir_stack_base
!= NULL
)
860 name
= dir_stack_base
->name
;
861 next
= dir_stack_base
->prev
;
862 g_free (dir_stack_base
);
863 dir_stack_base
= next
;
869 /* --------------------------------------------------------------------------------------------- */
870 /** Remove all the items from the stack */
875 vfs_path_t
*dir
= NULL
;
877 while ((dir
= pop_directory ()) != NULL
)
880 #endif /* GLIB_CHECK_VERSION */
882 /* --------------------------------------------------------------------------------------------- */
885 insert_file (const char *dir
, const char *file
)
887 char *tmp_name
= NULL
;
888 static char *dirname
= NULL
;
890 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
895 if (strcmp (old_dir
, dir
))
898 old_dir
= g_strdup (dir
);
899 dirname
= add_to_list (dir
, NULL
);
904 old_dir
= g_strdup (dir
);
905 dirname
= add_to_list (dir
, NULL
);
908 tmp_name
= g_strdup_printf (" %s", file
);
909 add_to_list (tmp_name
, dirname
);
913 /* --------------------------------------------------------------------------------------------- */
916 find_add_match (const char *dir
, const char *file
)
918 insert_file (dir
, file
);
922 listbox_select_first (find_list
);
923 send_message (WIDGET (find_list
), NULL
, WIDGET_DRAW
, 0, NULL
);
929 /* --------------------------------------------------------------------------------------------- */
933 * Returns malloced null-terminated line from file file_fd.
934 * Input is buffered in buf_size long buffer.
935 * Current pos in buf is stored in pos.
936 * n_read - number of read chars.
937 * has_newline - is there newline ?
941 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
953 *n_read
= mc_read (file_fd
, buf
, buf_size
);
961 /* skip possible leading zero(s) */
967 if (i
>= buffer_size
- 1)
968 buffer
= g_realloc (buffer
, buffer_size
+= 80);
977 *has_newline
= (ch
!= '\0');
985 /* --------------------------------------------------------------------------------------------- */
987 static FindProgressStatus
988 check_find_events (Dlg_head
* h
)
994 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
997 dlg_process_event (h
, c
, &event
);
998 if (h
->ret_value
== B_ENTER
999 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
1001 /* dialog terminated */
1004 if (!(h
->flags
& DLG_WANT_IDLE
))
1006 /* searching suspended */
1007 return FIND_SUSPEND
;
1014 /* --------------------------------------------------------------------------------------------- */
1018 * Search the content_pattern string in the DIRECTORY/FILE.
1019 * It will add the found entries to the find listbox.
1021 * returns FALSE if do_search should look for another file
1022 * TRUE if do_search should exit and proceed to the event handler
1026 search_content (Dlg_head
* h
, const char *directory
, const char *filename
)
1029 char buffer
[BUF_4K
];
1031 gboolean ret_val
= FALSE
;
1034 vpath
= vfs_path_build_filename (directory
, filename
, (char *) NULL
);
1036 if (mc_stat (vpath
, &s
) != 0 || !S_ISREG (s
.st_mode
))
1038 vfs_path_free (vpath
);
1042 file_fd
= mc_open (vpath
, O_RDONLY
);
1043 vfs_path_free (vpath
);
1048 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), filename
);
1049 status_update (str_trunc (buffer
, WIDGET (h
)->cols
- 8));
1053 tty_enable_interrupt_key ();
1054 tty_got_interrupt ();
1060 gboolean has_newline
;
1062 gboolean found
= FALSE
;
1064 char result
[BUF_MEDIUM
];
1068 /* We've been previously suspended, start from the previous position */
1074 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1075 &pos
, &n_read
, &has_newline
)) != NULL
)
1077 if (!found
/* Search in binary line once */
1078 && mc_search_run (search_content_handle
,
1079 (const void *) p
, 0, strlen (p
), &found_len
))
1081 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1082 find_add_match (directory
, result
);
1087 if (found
&& options
.content_first_hit
)
1096 if ((line
& 0xff) == 0)
1098 FindProgressStatus res
;
1099 res
= check_find_events (h
);
1118 tty_disable_interrupt_key ();
1123 /* --------------------------------------------------------------------------------------------- */
1126 If dir is absolute, this means we're within dir and searching file here.
1127 If dir is relative, this means we're going to add dir to the directory stack.
1130 find_ignore_dir_search (const char *dir
)
1132 if (find_ignore_dirs
!= NULL
)
1134 const size_t dlen
= strlen (dir
);
1135 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1139 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1141 const size_t ilen
= strlen (*ignore_dir
);
1142 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1144 /* ignore dir is too long -- skip it */
1148 /* handle absolute and relative paths */
1149 switch (iabs
| dabs
)
1151 case 0: /* both paths are relative */
1152 case 3: /* both paths are abolute */
1153 /* if ignore dir is not a path of dir -- skip it */
1154 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1156 /* be sure that ignore dir is not a part of dir like:
1157 ignore dir is "h", dir is "home" */
1158 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1162 case 1: /* dir is absolute, ignore_dir is relative */
1166 d
= strstr (dir
, *ignore_dir
);
1167 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1171 case 2: /* dir is relative, ignore_dir is absolute */
1172 /* FIXME: skip this case */
1174 default: /* this cannot occurs */
1183 /* --------------------------------------------------------------------------------------------- */
1186 find_rotate_dash (const Dlg_head
* h
, gboolean finish
)
1188 static const char rotating_dash
[] = "|/-\\";
1189 static unsigned int pos
= 0;
1193 const Widget
*w
= WIDGET (h
);
1195 pos
= (pos
+ 1) % 4;
1196 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1197 widget_move (h
, w
->lines
- 7, w
->cols
- 4);
1198 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1203 /* --------------------------------------------------------------------------------------------- */
1206 do_search (Dlg_head
* h
)
1208 static struct dirent
*dp
= NULL
;
1209 static DIR *dirp
= NULL
;
1210 static char *directory
= NULL
;
1211 struct stat tmp_stat
;
1212 static int subdirs_left
= 0;
1214 unsigned short count
;
1217 { /* someone forces me to close dirp */
1229 for (count
= 0; count
< 32; count
++)
1239 while (dirp
== NULL
)
1241 vfs_path_t
*tmp_vpath
= NULL
;
1243 tty_setcolor (REVERSE_COLOR
);
1247 tmp_vpath
= pop_directory ();
1248 if (tmp_vpath
== NULL
)
1251 if (ignore_count
== 0)
1252 status_update (_("Finished"));
1255 char msg
[BUF_SMALL
];
1256 g_snprintf (msg
, sizeof (msg
),
1257 ngettext ("Finished (ignored %zd directory)",
1258 "Finished (ignored %zd directories)",
1259 ignore_count
), ignore_count
);
1260 status_update (msg
);
1262 find_rotate_dash (h
, TRUE
);
1267 /* handle absolute ignore dirs here */
1272 tmp
= vfs_path_to_str (tmp_vpath
);
1273 ok
= find_ignore_dir_search (tmp
);
1279 vfs_path_free (tmp_vpath
);
1284 directory
= vfs_path_to_str (tmp_vpath
);
1288 char buffer
[BUF_MEDIUM
];
1290 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"), directory
);
1291 status_update (str_trunc (directory
, WIDGET (h
)->cols
- 8));
1293 /* mc_stat should not be called after mc_opendir
1294 because vfs_s_opendir modifies the st_nlink
1296 if (mc_stat (tmp_vpath
, &tmp_stat
) == 0)
1297 subdirs_left
= tmp_stat
.st_nlink
- 2;
1301 dirp
= mc_opendir (tmp_vpath
);
1302 vfs_path_free (tmp_vpath
);
1303 } /* while (!dirp) */
1305 /* skip invalid filenames */
1306 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1310 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1312 /* skip invalid filenames */
1313 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1319 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1323 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1324 { /* Can directory be NULL ? */
1325 /* handle relative ignore dirs here */
1326 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1330 vfs_path_t
*tmp_vpath
;
1332 tmp_vpath
= vfs_path_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1334 if (mc_lstat (tmp_vpath
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1336 push_directory (tmp_vpath
);
1340 vfs_path_free (tmp_vpath
);
1344 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1345 0, strlen (dp
->d_name
), &bytes_found
);
1349 if (content_pattern
== NULL
)
1350 find_add_match (directory
, dp
->d_name
);
1351 else if (search_content (h
, directory
, dp
->d_name
))
1356 /* skip invalid filenames */
1357 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1361 find_rotate_dash (h
, FALSE
);
1366 /* --------------------------------------------------------------------------------------------- */
1369 init_find_vars (void)
1376 /* Remove all the items from the stack */
1379 g_strfreev (find_ignore_dirs
);
1380 find_ignore_dirs
= NULL
;
1383 /* --------------------------------------------------------------------------------------------- */
1386 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1388 char *fullname
= NULL
;
1389 const char *filename
= NULL
;
1391 vfs_path_t
*fullname_vpath
;
1393 if (content_pattern
!= NULL
)
1395 filename
= strchr (file
+ 4, ':') + 1;
1396 line
= atoi (file
+ 4);
1400 filename
= file
+ 4;
1404 fullname_vpath
= vfs_path_build_filename (dir
, filename
, (char *) NULL
);
1406 do_edit_at_line (fullname_vpath
, use_internal_edit
, line
);
1408 view_file_at_line (fullname_vpath
, unparsed_view
, use_internal_view
, line
);
1409 vfs_path_free (fullname_vpath
);
1413 /* --------------------------------------------------------------------------------------------- */
1416 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1421 listbox_get_current (find_list
, &text
, (void **) &dir
);
1423 if ((text
== NULL
) || (dir
== NULL
))
1424 return MSG_NOT_HANDLED
;
1426 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1430 /* --------------------------------------------------------------------------------------------- */
1433 find_calc_button_locations (const Dlg_head
* h
, gboolean all_buttons
)
1435 const int cols
= WIDGET (h
)->cols
;
1439 l1
= fbuts
[0].len
+ fbuts
[1].len
+ fbuts
[is_start
? 3 : 2].len
+ fbuts
[4].len
+ 3;
1440 l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
+ 2;
1442 fbuts
[0].x
= (cols
- l1
) / 2;
1443 fbuts
[1].x
= fbuts
[0].x
+ fbuts
[0].len
+ 1;
1444 fbuts
[2].x
= fbuts
[1].x
+ fbuts
[1].len
+ 1;
1445 fbuts
[3].x
= fbuts
[2].x
;
1446 fbuts
[4].x
= fbuts
[2].x
+ fbuts
[is_start
? 3 : 2].len
+ 1;
1450 fbuts
[5].x
= (cols
- l2
) / 2;
1451 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ 1;
1452 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ 1;
1456 /* --------------------------------------------------------------------------------------------- */
1459 find_relocate_buttons (const Dlg_head
* h
, gboolean all_buttons
)
1463 find_calc_button_locations (h
, all_buttons
);
1465 for (i
= 0; i
< fbuts_num
; i
++)
1466 fbuts
[i
].button
->x
= WIDGET (h
)->x
+ fbuts
[i
].x
;
1469 /* --------------------------------------------------------------------------------------------- */
1472 find_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
1477 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1479 int unparsed_view
= (parm
== KEY_F (13));
1480 return view_edit_currently_selected_file (unparsed_view
, 0);
1482 if (parm
== KEY_F (4))
1483 return view_edit_currently_selected_file (0, 1);
1484 return MSG_NOT_HANDLED
;
1487 dlg_set_size (h
, LINES
- 4, COLS
- 16);
1488 find_relocate_buttons (h
, TRUE
);
1496 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
1500 /* --------------------------------------------------------------------------------------------- */
1501 /** Handles the Stop/Start button in the find window */
1504 start_stop (WButton
* button
, int action
)
1506 Widget
*w
= WIDGET (button
);
1511 set_idle_proc (find_dlg
, running
);
1512 is_start
= !is_start
;
1514 status_update (is_start
? _("Stopped") : _("Searching"));
1515 button_set_text (button
, fbuts
[is_start
? 3 : 2].text
);
1517 find_relocate_buttons (w
->owner
, FALSE
);
1518 dlg_redraw (w
->owner
);
1523 /* --------------------------------------------------------------------------------------------- */
1524 /** Handle view command, when invoked as a button */
1527 find_do_view_file (WButton
* button
, int action
)
1532 view_edit_currently_selected_file (0, 0);
1536 /* --------------------------------------------------------------------------------------------- */
1537 /** Handle edit command, when invoked as a button */
1540 find_do_edit_file (WButton
* button
, int action
)
1545 view_edit_currently_selected_file (0, 1);
1549 /* --------------------------------------------------------------------------------------------- */
1559 static gboolean i18n_flag
= FALSE
;
1563 for (i
= 0; i
< fbuts_num
; i
++)
1565 fbuts
[i
].text
= _(fbuts
[i
].text
);
1566 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1567 if (fbuts
[i
].flags
== DEFPUSH_BUTTON
)
1573 #endif /* ENABLE_NLS */
1579 create_dlg (TRUE
, 0, 0, lines
, cols
, dialog_colors
, find_callback
, NULL
, "[Find File]",
1580 _("Find File"), DLG_CENTER
);
1582 find_calc_button_locations (find_dlg
, TRUE
);
1585 find_list
= listbox_new (y
, 2, lines
- 10, cols
- 4, FALSE
, NULL
);
1586 add_widget_autopos (find_dlg
, find_list
, WPOS_KEEP_ALL
, NULL
);
1587 y
+= WIDGET (find_list
)->lines
;
1589 add_widget_autopos (find_dlg
, hline_new (y
++, -1, -1), WPOS_KEEP_BOTTOM
, NULL
);
1591 found_num_label
= label_new (y
++, 4, "");
1592 add_widget_autopos (find_dlg
, found_num_label
, WPOS_KEEP_BOTTOM
, NULL
);
1594 status_label
= label_new (y
++, 4, _("Searching"));
1595 add_widget_autopos (find_dlg
, status_label
, WPOS_KEEP_BOTTOM
, NULL
);
1597 add_widget_autopos (find_dlg
, hline_new (y
++, -1, -1), WPOS_KEEP_BOTTOM
, NULL
);
1599 for (i
= 0; i
< fbuts_num
; i
++)
1602 fbuts
[3].button
= fbuts
[2].button
;
1607 (y
, fbuts
[i
].x
, fbuts
[i
].ret_cmd
, fbuts
[i
].flags
, fbuts
[i
].text
,
1608 fbuts
[i
].callback
));
1609 add_widget_autopos (find_dlg
, fbuts
[i
].button
, WPOS_KEEP_BOTTOM
, NULL
);
1612 if (i
== quit_button
)
1616 dlg_select_widget (find_list
);
1619 /* --------------------------------------------------------------------------------------------- */
1626 search_content_handle
= mc_search_new (content_pattern
, -1);
1627 if (search_content_handle
)
1629 search_content_handle
->search_type
=
1630 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1631 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1632 search_content_handle
->whole_words
= options
.content_whole_words
;
1633 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1635 search_file_handle
= mc_search_new (find_pattern
, -1);
1636 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1637 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1638 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1639 search_file_handle
->is_entire_line
= options
.file_pattern
;
1643 set_idle_proc (find_dlg
, 1);
1644 ret
= run_dlg (find_dlg
);
1646 mc_search_free (search_file_handle
);
1647 search_file_handle
= NULL
;
1648 mc_search_free (search_content_handle
);
1649 search_content_handle
= NULL
;
1654 /* --------------------------------------------------------------------------------------------- */
1659 set_idle_proc (find_dlg
, 0);
1660 destroy_dlg (find_dlg
);
1663 /* --------------------------------------------------------------------------------------------- */
1666 do_find (const char *start_dir
, ssize_t start_dir_len
, const char *ignore_dirs
,
1667 const char *pattern
, const char *content
, char **dirname
, char **filename
)
1669 int return_value
= 0;
1670 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1674 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1675 find_pattern
= (char *) pattern
;
1677 content_pattern
= NULL
;
1678 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1679 content_pattern
= g_strdup (content
);
1682 parse_ignore_dirs (ignore_dirs
);
1683 push_directory (vfs_path_from_str (start_dir
));
1685 return_value
= run_process ();
1687 /* Clear variables */
1690 get_list_info (&file_tmp
, &dir_tmp
);
1693 *dirname
= g_strdup (dir_tmp
);
1695 *filename
= g_strdup (file_tmp
);
1697 if (return_value
== B_PANELIZE
&& *filename
)
1699 int status
, link_to_dir
, stale_link
;
1704 dir_list
*list
= ¤t_panel
->dir
;
1707 if (set_zero_dir (list
))
1710 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1712 const char *lc_filename
= NULL
;
1713 WLEntry
*le
= (WLEntry
*) entry
->data
;
1716 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1719 if (content_pattern
!= NULL
)
1720 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1722 lc_filename
= le
->text
+ 4;
1724 name
= mc_build_filename (le
->data
, lc_filename
, (char *) NULL
);
1725 /* skip initial start dir */
1726 if (start_dir_len
< 0)
1730 p
= name
+ (size_t) start_dir_len
;
1735 status
= handle_path (list
, p
, &st
, next_free
, &link_to_dir
, &stale_link
);
1747 /* don't add files more than once to the panel */
1748 if (content_pattern
!= NULL
&& next_free
> 0
1749 && strcmp (list
->list
[next_free
- 1].fname
, p
) == 0)
1755 if (next_free
== 0) /* first turn i.e clean old list */
1756 panel_clean_dir (current_panel
);
1757 list
->list
[next_free
].fnamelen
= strlen (p
);
1758 list
->list
[next_free
].fname
= g_strndup (p
, list
->list
[next_free
].fnamelen
);
1759 list
->list
[next_free
].f
.marked
= 0;
1760 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1761 list
->list
[next_free
].f
.stale_link
= stale_link
;
1762 list
->list
[next_free
].f
.dir_size_computed
= 0;
1763 list
->list
[next_free
].st
= st
;
1764 list
->list
[next_free
].sort_key
= NULL
;
1765 list
->list
[next_free
].second_sort_key
= NULL
;
1768 if (!(next_free
& 15))
1774 current_panel
->count
= next_free
;
1775 current_panel
->is_panelized
= TRUE
;
1778 if (start_dir_len
< 0)
1781 vfs_path_free (current_panel
->cwd_vpath
);
1782 current_panel
->cwd_vpath
= vfs_path_from_str (PATH_SEP_STR
);
1783 ret
= chdir (PATH_SEP_STR
);
1785 panelize_save_panel (current_panel
);
1789 g_free (content_pattern
);
1791 do_search (NULL
); /* force do_search to release resources */
1795 return return_value
;
1798 /* --------------------------------------------------------------------------------------------- */
1799 /*** public functions ****************************************************************************/
1800 /* --------------------------------------------------------------------------------------------- */
1805 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1806 ssize_t start_dir_len
;
1807 char *filename
= NULL
, *dirname
= NULL
;
1810 while (find_parameters (&start_dir
, &start_dir_len
, &ignore_dirs
, &pattern
, &content
))
1812 if (pattern
[0] == '\0')
1813 break; /* nothing search */
1815 dirname
= filename
= NULL
;
1817 v
= do_find (start_dir
, start_dir_len
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1818 g_free (ignore_dirs
);
1823 if (dirname
!= NULL
)
1825 vfs_path_t
*dirname_vpath
;
1827 dirname_vpath
= vfs_path_from_str (dirname
);
1828 do_cd (dirname_vpath
, cd_exact
);
1829 vfs_path_free (dirname_vpath
);
1830 if (filename
!= NULL
)
1831 try_to_select (current_panel
,
1832 filename
+ (content
!= NULL
1833 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1835 else if (filename
!= NULL
)
1837 vfs_path_t
*filename_vpath
;
1839 filename_vpath
= vfs_path_from_str (filename
);
1840 do_cd (filename_vpath
, cd_exact
);
1841 vfs_path_free (filename_vpath
);
1856 if (v
== B_PANELIZE
)
1858 panel_re_sort (current_panel
);
1859 try_to_select (current_panel
, NULL
);
1865 /* --------------------------------------------------------------------------------------------- */