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
;
277 options
.file_case_sens
=
278 mc_config_get_bool (mc_main_config
, "FindFile", "file_case_sens", TRUE
);
279 options
.file_pattern
=
280 mc_config_get_bool (mc_main_config
, "FindFile", "file_shell_pattern", TRUE
);
281 options
.find_recurs
= mc_config_get_bool (mc_main_config
, "FindFile", "file_find_recurs", TRUE
);
282 options
.skip_hidden
=
283 mc_config_get_bool (mc_main_config
, "FindFile", "file_skip_hidden", FALSE
);
284 options
.file_all_charsets
=
285 mc_config_get_bool (mc_main_config
, "FindFile", "file_all_charsets", FALSE
);
286 options
.content_use
= mc_config_get_bool (mc_main_config
, "FindFile", "content_use", TRUE
);
287 options
.content_case_sens
=
288 mc_config_get_bool (mc_main_config
, "FindFile", "content_case_sens", TRUE
);
289 options
.content_regexp
=
290 mc_config_get_bool (mc_main_config
, "FindFile", "content_regexp", FALSE
);
291 options
.content_first_hit
=
292 mc_config_get_bool (mc_main_config
, "FindFile", "content_first_hit", FALSE
);
293 options
.content_whole_words
=
294 mc_config_get_bool (mc_main_config
, "FindFile", "content_whole_words", FALSE
);
295 options
.content_all_charsets
=
296 mc_config_get_bool (mc_main_config
, "FindFile", "content_all_charsets", FALSE
);
297 options
.ignore_dirs_enable
=
298 mc_config_get_bool (mc_main_config
, "FindFile", "ignore_dirs_enable", TRUE
);
300 /* Back compatibility: try load old parameter at first */
301 ignore_dirs
= mc_config_get_string (mc_main_config
, "Misc", "find_ignore_dirs", "");
302 mc_config_del_key (mc_main_config
, "Misc", "find_ignore_dirs");
304 /* Then load new parameters */
305 options
.ignore_dirs
= mc_config_get_string (mc_main_config
, "FindFile", "ignore_dirs", "");
306 if (options
.ignore_dirs
[0] != '\0')
307 g_free (ignore_dirs
);
310 g_free (options
.ignore_dirs
);
311 options
.ignore_dirs
= ignore_dirs
;
314 if (options
.ignore_dirs
[0] == '\0')
316 g_free (options
.ignore_dirs
);
317 options
.ignore_dirs
= NULL
;
321 /* --------------------------------------------------------------------------------------------- */
324 find_save_options (void)
326 mc_config_set_bool (mc_main_config
, "FindFile", "file_case_sens", options
.file_case_sens
);
327 mc_config_set_bool (mc_main_config
, "FindFile", "file_shell_pattern", options
.file_pattern
);
328 mc_config_set_bool (mc_main_config
, "FindFile", "file_find_recurs", options
.find_recurs
);
329 mc_config_set_bool (mc_main_config
, "FindFile", "file_skip_hidden", options
.skip_hidden
);
330 mc_config_set_bool (mc_main_config
, "FindFile", "file_all_charsets", options
.file_all_charsets
);
331 mc_config_set_bool (mc_main_config
, "FindFile", "content_use", options
.content_use
);
332 mc_config_set_bool (mc_main_config
, "FindFile", "content_case_sens", options
.content_case_sens
);
333 mc_config_set_bool (mc_main_config
, "FindFile", "content_regexp", options
.content_regexp
);
334 mc_config_set_bool (mc_main_config
, "FindFile", "content_first_hit", options
.content_first_hit
);
335 mc_config_set_bool (mc_main_config
, "FindFile", "content_whole_words",
336 options
.content_whole_words
);
337 mc_config_set_bool (mc_main_config
, "FindFile", "content_all_charsets",
338 options
.content_all_charsets
);
339 mc_config_set_bool (mc_main_config
, "FindFile", "ignore_dirs_enable",
340 options
.ignore_dirs_enable
);
341 mc_config_set_string (mc_main_config
, "FindFile", "ignore_dirs", options
.ignore_dirs
);
344 /* --------------------------------------------------------------------------------------------- */
347 add_to_list (const char *text
, void *data
)
349 return listbox_add_item (find_list
, LISTBOX_APPEND_AT_END
, 0, text
, data
);
352 /* --------------------------------------------------------------------------------------------- */
355 stop_idle (void *data
)
357 set_idle_proc (data
, 0);
360 /* --------------------------------------------------------------------------------------------- */
363 status_update (const char *text
)
365 label_set_text (status_label
, text
);
368 /* --------------------------------------------------------------------------------------------- */
371 found_num_update (void)
373 char buffer
[BUF_TINY
];
374 g_snprintf (buffer
, sizeof (buffer
), _("Found: %ld"), matches
);
375 label_set_text (found_num_label
, buffer
);
378 /* --------------------------------------------------------------------------------------------- */
381 get_list_info (char **file
, char **dir
)
383 listbox_get_current (find_list
, file
, (void **) dir
);
386 /* --------------------------------------------------------------------------------------------- */
387 /** check regular expression */
390 find_check_regexp (const char *r
)
393 gboolean regexp_ok
= FALSE
;
395 search
= mc_search_new (r
, -1);
399 search
->search_type
= MC_SEARCH_T_REGEX
;
400 regexp_ok
= mc_search_prepare (search
);
401 mc_search_free (search
);
407 /* --------------------------------------------------------------------------------------------- */
409 * Callback for the parameter dialog.
410 * Validate regex, prevent closing the dialog if it's invalid.
414 find_parm_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
419 if (sender
== (Widget
*) content_use_cbox
)
421 gboolean disable
= !(content_use_cbox
->state
& C_BOOL
);
423 widget_disable (content_label
->widget
, disable
);
424 send_message ((Widget
*) content_label
, WIDGET_DRAW
, 0);
425 widget_disable (in_with
->widget
, disable
);
426 send_message ((Widget
*) in_with
, WIDGET_DRAW
, 0);
427 widget_disable (content_first_hit_cbox
->widget
, disable
);
428 send_message ((Widget
*) content_first_hit_cbox
, WIDGET_DRAW
, 0);
429 widget_disable (content_regexp_cbox
->widget
, disable
);
430 send_message ((Widget
*) content_regexp_cbox
, WIDGET_DRAW
, 0);
431 widget_disable (content_case_sens_cbox
->widget
, disable
);
432 send_message ((Widget
*) content_case_sens_cbox
, WIDGET_DRAW
, 0);
434 widget_disable (content_all_charsets_cbox
->widget
, disable
);
435 send_message ((Widget
*) content_all_charsets_cbox
, WIDGET_DRAW
, 0);
437 widget_disable (content_whole_words_cbox
->widget
, disable
);
438 send_message ((Widget
*) content_whole_words_cbox
, WIDGET_DRAW
, 0);
443 if (sender
== (Widget
*) ignore_dirs_cbox
)
445 gboolean disable
= !(ignore_dirs_cbox
->state
& C_BOOL
);
447 widget_disable (in_ignore
->widget
, disable
);
448 send_message ((Widget
*) in_ignore
, WIDGET_DRAW
, 0);
453 return MSG_NOT_HANDLED
;
457 if (h
->ret_value
!= B_ENTER
)
460 /* check filename regexp */
461 if (!(file_pattern_cbox
->state
& C_BOOL
)
462 && (in_name
->buffer
[0] != '\0') && !find_check_regexp (in_name
->buffer
))
464 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
465 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
466 dlg_select_widget (in_name
);
470 /* check content regexp */
471 if ((content_use_cbox
->state
& C_BOOL
) && (content_regexp_cbox
->state
& C_BOOL
)
472 && (in_with
->buffer
[0] != '\0') && !find_check_regexp (in_with
->buffer
))
474 h
->state
= DLG_ACTIVE
; /* Don't stop the dialog */
475 message (D_ERROR
, MSG_ERROR
, _("Malformed regular expression"));
476 dlg_select_widget (in_with
);
483 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
487 /* --------------------------------------------------------------------------------------------- */
489 * find_parameters: gets information from the user
491 * If the return value is TRUE, then the following holds:
493 * start_dir, ignore_dirs, pattern and content contain the information provided by the user.
494 * They are newly allocated strings and must be freed when uneeded.
496 * start_dir_len is -1 when user entered an absolute path, otherwise it is a length
497 * of start_dir (which is absolute). It is used to get a relative pats of find results.
501 find_parameters (char **start_dir
, ssize_t
* start_dir_len
,
502 char **ignore_dirs
, char **pattern
, char **content
)
504 gboolean return_value
;
507 const char *file_case_label
= N_("Cas&e sensitive");
508 const char *file_pattern_label
= N_("&Using shell patterns");
509 const char *file_recurs_label
= N_("&Find recursively");
510 const char *file_skip_hidden_label
= N_("S&kip hidden");
512 const char *file_all_charsets_label
= N_("&All charsets");
516 const char *content_use_label
= N_("Sea&rch for content");
517 const char *content_case_label
= N_("Case sens&itive");
518 const char *content_regexp_label
= N_("Re&gular expression");
519 const char *content_first_hit_label
= N_("Fir&st hit");
520 const char *content_whole_words_label
= N_("&Whole words");
522 const char *content_all_charsets_label
= N_("A&ll charsets");
525 const char *buts
[] = { N_("&OK"), N_("&Cancel"), N_("&Tree") };
534 int i
= sizeof (buts
) / sizeof (buts
[0]);
536 buts
[i
] = _(buts
[i
]);
538 file_case_label
= _(file_case_label
);
539 file_pattern_label
= _(file_pattern_label
);
540 file_recurs_label
= _(file_recurs_label
);
541 file_skip_hidden_label
= _(file_skip_hidden_label
);
543 file_all_charsets_label
= _(file_all_charsets_label
);
544 content_all_charsets_label
= _(content_all_charsets_label
);
546 content_use_label
= _(content_use_label
);
547 content_case_label
= _(content_case_label
);
548 content_regexp_label
= _(content_regexp_label
);
549 content_first_hit_label
= _(content_first_hit_label
);
550 content_whole_words_label
= _(content_whole_words_label
);
552 #endif /* ENABLE_NLS */
554 b0
= str_term_width1 (buts
[0]) + 6; /* default button */
555 b1
= str_term_width1 (buts
[1]) + 4;
556 b2
= str_term_width1 (buts
[2]) + 4;
558 find_load_options ();
560 if (in_start_dir
== NULL
)
561 in_start_dir
= g_strdup (".");
563 disable
= !options
.content_use
;
566 create_dlg (TRUE
, 0, 0, FIND_Y
, FIND_X
, dialog_colors
,
567 find_parm_callback
, "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
569 add_widget (find_dlg
,
570 button_new (FIND_Y
- 3, FIND_X
* 3 / 4 - b1
/ 2, B_CANCEL
, NORMAL_BUTTON
, buts
[1],
572 add_widget (find_dlg
,
573 button_new (FIND_Y
- 3, FIND_X
/ 4 - b0
/ 2, B_ENTER
, DEFPUSH_BUTTON
, buts
[0], 0));
575 cbox_position
= FIND_Y
- 5;
577 content_first_hit_cbox
=
578 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_first_hit
,
579 content_first_hit_label
);
580 widget_disable (content_first_hit_cbox
->widget
, disable
);
581 add_widget (find_dlg
, content_first_hit_cbox
);
583 content_whole_words_cbox
=
584 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_whole_words
,
585 content_whole_words_label
);
586 widget_disable (content_whole_words_cbox
->widget
, disable
);
587 add_widget (find_dlg
, content_whole_words_cbox
);
590 content_all_charsets_cbox
= check_new (cbox_position
--, FIND_X
/ 2 + 1,
591 options
.content_all_charsets
,
592 content_all_charsets_label
);
593 widget_disable (content_all_charsets_cbox
->widget
, disable
);
594 add_widget (find_dlg
, content_all_charsets_cbox
);
597 content_case_sens_cbox
=
598 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_case_sens
, content_case_label
);
599 widget_disable (content_case_sens_cbox
->widget
, disable
);
600 add_widget (find_dlg
, content_case_sens_cbox
);
602 content_regexp_cbox
=
603 check_new (cbox_position
--, FIND_X
/ 2 + 1, options
.content_regexp
, content_regexp_label
);
604 widget_disable (content_regexp_cbox
->widget
, disable
);
605 add_widget (find_dlg
, content_regexp_cbox
);
607 cbox_position
= FIND_Y
- 6;
609 skip_hidden_cbox
= check_new (cbox_position
--, 3, options
.skip_hidden
, file_skip_hidden_label
);
610 add_widget (find_dlg
, skip_hidden_cbox
);
613 file_all_charsets_cbox
=
614 check_new (cbox_position
--, 3, options
.file_all_charsets
, file_all_charsets_label
);
615 add_widget (find_dlg
, file_all_charsets_cbox
);
618 file_case_sens_cbox
= check_new (cbox_position
--, 3, options
.file_case_sens
, file_case_label
);
619 add_widget (find_dlg
, file_case_sens_cbox
);
621 file_pattern_cbox
= check_new (cbox_position
--, 3, options
.file_pattern
, file_pattern_label
);
622 add_widget (find_dlg
, file_pattern_cbox
);
624 recursively_cbox
= check_new (cbox_position
, 3, options
.find_recurs
, file_recurs_label
);
625 add_widget (find_dlg
, recursively_cbox
);
627 /* This checkbox is located in the second column */
629 check_new (cbox_position
, FIND_X
/ 2 + 1, options
.content_use
, content_use_label
);
630 add_widget (find_dlg
, content_use_cbox
);
633 input_new (8, FIND_X
/ 2 + 1, input_get_default_colors (), FIND_X
/ 2 - 4, INPUT_LAST_TEXT
,
634 MC_HISTORY_SHARED_SEARCH
, INPUT_COMPLETE_DEFAULT
);
635 widget_disable (in_with
->widget
, disable
);
636 add_widget (find_dlg
, in_with
);
638 content_label
= label_new (7, FIND_X
/ 2 + 1, _("Content:"));
639 widget_disable (content_label
->widget
, disable
);
640 add_widget (find_dlg
, content_label
);
642 in_name
= input_new (8, 3, input_get_default_colors (),
643 FIND_X
/ 2 - 4, INPUT_LAST_TEXT
, "name", INPUT_COMPLETE_DEFAULT
);
644 add_widget (find_dlg
, in_name
);
645 add_widget (find_dlg
, label_new (7, 3, _("File name:")));
647 in_ignore
= input_new (5, 3, input_get_default_colors (), FIND_X
- 6,
648 options
.ignore_dirs
!= NULL
? options
.ignore_dirs
: "",
649 "ignoredirs", INPUT_COMPLETE_DEFAULT
);
650 widget_disable (in_ignore
->widget
, !options
.ignore_dirs_enable
);
651 add_widget (find_dlg
, in_ignore
);
654 check_new (4, 3, options
.ignore_dirs_enable
, _("Ena&ble ignore directories:"));
655 add_widget (find_dlg
, ignore_dirs_cbox
);
657 add_widget (find_dlg
, button_new (3, FIND_X
- b2
- 2, B_TREE
, NORMAL_BUTTON
, buts
[2], 0));
659 in_start
= input_new (3, 3, input_get_default_colors (),
660 FIND_X
- b2
- 6, in_start_dir
, "start", INPUT_COMPLETE_DEFAULT
);
661 add_widget (find_dlg
, in_start
);
662 add_widget (find_dlg
, label_new (2, 3, _("Start at:")));
665 dlg_select_widget (in_name
);
667 switch (run_dlg (find_dlg
))
670 return_value
= FALSE
;
677 temp_dir
= in_start
->buffer
;
678 if ((temp_dir
[0] == '\0') || ((temp_dir
[0] == '.') && (temp_dir
[1] == '\0')))
679 temp_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
681 temp_dir
= g_strdup (temp_dir
);
683 if (in_start_dir
!= INPUT_LAST_TEXT
)
684 g_free (in_start_dir
);
685 in_start_dir
= tree_box (temp_dir
);
686 if (in_start_dir
== NULL
)
687 in_start_dir
= temp_dir
;
691 input_assign_text (in_start
, in_start_dir
);
693 /* Warning: Dreadful goto */
702 options
.file_all_charsets
= file_all_charsets_cbox
->state
& C_BOOL
;
703 options
.content_all_charsets
= content_all_charsets_cbox
->state
& C_BOOL
;
705 options
.content_use
= content_use_cbox
->state
& C_BOOL
;
706 options
.content_case_sens
= content_case_sens_cbox
->state
& C_BOOL
;
707 options
.content_regexp
= content_regexp_cbox
->state
& C_BOOL
;
708 options
.content_first_hit
= content_first_hit_cbox
->state
& C_BOOL
;
709 options
.content_whole_words
= content_whole_words_cbox
->state
& C_BOOL
;
710 options
.find_recurs
= recursively_cbox
->state
& C_BOOL
;
711 options
.file_pattern
= file_pattern_cbox
->state
& C_BOOL
;
712 options
.file_case_sens
= file_case_sens_cbox
->state
& C_BOOL
;
713 options
.skip_hidden
= skip_hidden_cbox
->state
& C_BOOL
;
714 options
.ignore_dirs_enable
= ignore_dirs_cbox
->state
& C_BOOL
;
715 g_free (options
.ignore_dirs
);
716 options
.ignore_dirs
= g_strdup (in_ignore
->buffer
);
718 *content
= (options
.content_use
&& in_with
->buffer
[0] != '\0')
719 ? g_strdup (in_with
->buffer
) : NULL
;
720 *start_dir
= in_start
->buffer
[0] != '\0' ? in_start
->buffer
: (char *) ".";
721 *pattern
= g_strdup (in_name
->buffer
);
722 if (in_start_dir
!= INPUT_LAST_TEXT
)
723 g_free (in_start_dir
);
724 in_start_dir
= g_strdup (*start_dir
);
726 s
= tilde_expand (*start_dir
);
727 canonicalize_pathname (s
);
729 if (s
[0] == '.' && s
[1] == '\0')
731 *start_dir
= vfs_path_to_str (current_panel
->cwd_vpath
);
732 /* FIXME: is current_panel->cwd_vpath canonicalized? */
733 /* relative paths will be used in panelization */
734 *start_dir_len
= (ssize_t
) strlen (*start_dir
);
737 else if (g_path_is_absolute (s
))
744 /* relative paths will be used in panelization */
747 cwd_str
= vfs_path_to_str (current_panel
->cwd_vpath
);
748 *start_dir
= mc_build_filename (cwd_str
, s
, (char *) NULL
);
749 *start_dir_len
= (ssize_t
) strlen (cwd_str
);
754 if (!options
.ignore_dirs_enable
|| in_ignore
->buffer
[0] == '\0'
755 || (in_ignore
->buffer
[0] == '.' && in_ignore
->buffer
[1] == '\0'))
758 *ignore_dirs
= g_strdup (in_ignore
->buffer
);
760 find_save_options ();
766 destroy_dlg (find_dlg
);
771 /* --------------------------------------------------------------------------------------------- */
773 #if GLIB_CHECK_VERSION (2, 14, 0)
775 push_directory (const vfs_path_t
* dir
)
777 g_queue_push_head (&dir_queue
, (void *) dir
);
780 /* --------------------------------------------------------------------------------------------- */
782 static inline vfs_path_t
*
785 return (vfs_path_t
*) g_queue_pop_tail (&dir_queue
);
788 /* --------------------------------------------------------------------------------------------- */
789 /** Remove all the items from the stack */
794 g_queue_foreach (&dir_queue
, (GFunc
) vfs_path_free
, NULL
);
795 g_queue_clear (&dir_queue
);
798 /* --------------------------------------------------------------------------------------------- */
800 #else /* GLIB_CHECK_VERSION */
802 push_directory (const vfs_path_t
* dir
)
806 new = g_new (dir_stack
, 1);
807 new->name
= (vfs_path_t
*) dir
;
808 new->prev
= dir_stack_base
;
809 dir_stack_base
= new;
812 /* --------------------------------------------------------------------------------------------- */
817 vfs_path_t
*name
= NULL
;
819 if (dir_stack_base
!= NULL
)
822 name
= dir_stack_base
->name
;
823 next
= dir_stack_base
->prev
;
824 g_free (dir_stack_base
);
825 dir_stack_base
= next
;
831 /* --------------------------------------------------------------------------------------------- */
832 /** Remove all the items from the stack */
837 vfs_path_t
*dir
= NULL
;
839 while ((dir
= pop_directory ()) != NULL
)
842 #endif /* GLIB_CHECK_VERSION */
844 /* --------------------------------------------------------------------------------------------- */
847 insert_file (const char *dir
, const char *file
)
849 char *tmp_name
= NULL
;
850 static char *dirname
= NULL
;
852 while (dir
[0] == PATH_SEP
&& dir
[1] == PATH_SEP
)
857 if (strcmp (old_dir
, dir
))
860 old_dir
= g_strdup (dir
);
861 dirname
= add_to_list (dir
, NULL
);
866 old_dir
= g_strdup (dir
);
867 dirname
= add_to_list (dir
, NULL
);
870 tmp_name
= g_strdup_printf (" %s", file
);
871 add_to_list (tmp_name
, dirname
);
875 /* --------------------------------------------------------------------------------------------- */
878 find_add_match (const char *dir
, const char *file
)
880 insert_file (dir
, file
);
884 listbox_select_first (find_list
);
885 send_message (&find_list
->widget
, WIDGET_DRAW
, 0);
891 /* --------------------------------------------------------------------------------------------- */
895 * Returns malloced null-terminated line from file file_fd.
896 * Input is buffered in buf_size long buffer.
897 * Current pos in buf is stored in pos.
898 * n_read - number of read chars.
899 * has_newline - is there newline ?
903 get_line_at (int file_fd
, char *buf
, int buf_size
, int *pos
, int *n_read
, gboolean
* has_newline
)
915 *n_read
= mc_read (file_fd
, buf
, buf_size
);
923 /* skip possible leading zero(s) */
929 if (i
>= buffer_size
- 1)
930 buffer
= g_realloc (buffer
, buffer_size
+= 80);
939 *has_newline
= (ch
!= '\0');
947 /* --------------------------------------------------------------------------------------------- */
949 static FindProgressStatus
950 check_find_events (Dlg_head
* h
)
956 c
= tty_get_event (&event
, h
->mouse_status
== MOU_REPEAT
, FALSE
);
959 dlg_process_event (h
, c
, &event
);
960 if (h
->ret_value
== B_ENTER
961 || h
->ret_value
== B_CANCEL
|| h
->ret_value
== B_AGAIN
|| h
->ret_value
== B_PANELIZE
)
963 /* dialog terminated */
966 if (!(h
->flags
& DLG_WANT_IDLE
))
968 /* searching suspended */
976 /* --------------------------------------------------------------------------------------------- */
980 * Search the content_pattern string in the DIRECTORY/FILE.
981 * It will add the found entries to the find listbox.
983 * returns FALSE if do_search should look for another file
984 * TRUE if do_search should exit and proceed to the event handler
988 search_content (Dlg_head
* h
, const char *directory
, const char *filename
)
993 gboolean ret_val
= FALSE
;
996 vpath
= vfs_path_build_filename (directory
, filename
, (char *) NULL
);
998 if (mc_stat (vpath
, &s
) != 0 || !S_ISREG (s
.st_mode
))
1000 vfs_path_free (vpath
);
1004 file_fd
= mc_open (vpath
, O_RDONLY
);
1005 vfs_path_free (vpath
);
1010 g_snprintf (buffer
, sizeof (buffer
), _("Grepping in %s"), str_trunc (filename
, FIND2_X_USE
));
1012 status_update (buffer
);
1015 tty_enable_interrupt_key ();
1016 tty_got_interrupt ();
1022 gboolean has_newline
;
1024 gboolean found
= FALSE
;
1026 char result
[BUF_MEDIUM
];
1030 /* We've been previously suspended, start from the previous position */
1036 && (p
= get_line_at (file_fd
, buffer
, sizeof (buffer
),
1037 &pos
, &n_read
, &has_newline
)) != NULL
)
1039 if (!found
/* Search in binary line once */
1040 && mc_search_run (search_content_handle
,
1041 (const void *) p
, 0, strlen (p
), &found_len
))
1043 g_snprintf (result
, sizeof (result
), "%d:%s", line
, filename
);
1044 find_add_match (directory
, result
);
1049 if (found
&& options
.content_first_hit
)
1058 if ((line
& 0xff) == 0)
1060 FindProgressStatus res
;
1061 res
= check_find_events (h
);
1080 tty_disable_interrupt_key ();
1085 /* --------------------------------------------------------------------------------------------- */
1088 If dir is absolute, this means we're within dir and searching file here.
1089 If dir is relative, this means we're going to add dir to the directory stack.
1092 find_ignore_dir_search (const char *dir
)
1094 if (find_ignore_dirs
!= NULL
)
1096 const size_t dlen
= strlen (dir
);
1097 const unsigned char dabs
= g_path_is_absolute (dir
) ? 1 : 0;
1101 for (ignore_dir
= find_ignore_dirs
; *ignore_dir
!= NULL
; ignore_dir
++)
1103 const size_t ilen
= strlen (*ignore_dir
);
1104 const unsigned char iabs
= g_path_is_absolute (*ignore_dir
) ? 2 : 0;
1106 /* ignore dir is too long -- skip it */
1110 /* handle absolute and relative paths */
1111 switch (iabs
| dabs
)
1113 case 0: /* both paths are relative */
1114 case 3: /* both paths are abolute */
1115 /* if ignore dir is not a path of dir -- skip it */
1116 if (strncmp (dir
, *ignore_dir
, ilen
) == 0)
1118 /* be sure that ignore dir is not a part of dir like:
1119 ignore dir is "h", dir is "home" */
1120 if (dir
[ilen
] == '\0' || dir
[ilen
] == PATH_SEP
)
1124 case 1: /* dir is absolute, ignore_dir is relative */
1128 d
= strstr (dir
, *ignore_dir
);
1129 if (d
!= NULL
&& d
[-1] == PATH_SEP
&& (d
[ilen
] == '\0' || d
[ilen
] == PATH_SEP
))
1133 case 2: /* dir is relative, ignore_dir is absolute */
1134 /* FIXME: skip this case */
1136 default: /* this cannot occurs */
1145 /* --------------------------------------------------------------------------------------------- */
1148 find_rotate_dash (const Dlg_head
* h
, gboolean finish
)
1150 static const char rotating_dash
[] = "|/-\\";
1151 static unsigned int pos
= 0;
1155 pos
= (pos
+ 1) % 4;
1156 tty_setcolor (h
->color
[DLG_COLOR_NORMAL
]);
1157 dlg_move (h
, FIND2_Y
- 7, FIND2_X
- 4);
1158 tty_print_char (finish
? ' ' : rotating_dash
[pos
]);
1163 /* --------------------------------------------------------------------------------------------- */
1166 do_search (Dlg_head
* h
)
1168 static struct dirent
*dp
= NULL
;
1169 static DIR *dirp
= NULL
;
1170 static char *directory
= NULL
;
1171 struct stat tmp_stat
;
1172 static int subdirs_left
= 0;
1174 unsigned short count
;
1177 { /* someone forces me to close dirp */
1189 for (count
= 0; count
< 32; count
++)
1199 while (dirp
== NULL
)
1201 vfs_path_t
*tmp_vpath
= NULL
;
1203 tty_setcolor (REVERSE_COLOR
);
1207 tmp_vpath
= pop_directory ();
1208 if (tmp_vpath
== NULL
)
1211 if (ignore_count
== 0)
1212 status_update (_("Finished"));
1215 char msg
[BUF_SMALL
];
1216 g_snprintf (msg
, sizeof (msg
),
1217 ngettext ("Finished (ignored %zd directory)",
1218 "Finished (ignored %zd directories)",
1219 ignore_count
), ignore_count
);
1220 status_update (msg
);
1222 find_rotate_dash (h
, TRUE
);
1227 /* handle absolute ignore dirs here */
1232 tmp
= vfs_path_to_str (tmp_vpath
);
1233 ok
= find_ignore_dir_search (tmp
);
1239 vfs_path_free (tmp_vpath
);
1244 directory
= vfs_path_to_str (tmp_vpath
);
1248 char buffer
[BUF_SMALL
];
1250 g_snprintf (buffer
, sizeof (buffer
), _("Searching %s"),
1251 str_trunc (directory
, FIND2_X_USE
));
1252 status_update (buffer
);
1254 /* mc_stat should not be called after mc_opendir
1255 because vfs_s_opendir modifies the st_nlink
1257 if (mc_stat (tmp_vpath
, &tmp_stat
) == 0)
1258 subdirs_left
= tmp_stat
.st_nlink
- 2;
1262 dirp
= mc_opendir (tmp_vpath
);
1263 vfs_path_free (tmp_vpath
);
1264 } /* while (!dirp) */
1266 /* skip invalid filenames */
1267 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1271 if (strcmp (dp
->d_name
, ".") == 0 || strcmp (dp
->d_name
, "..") == 0)
1273 /* skip invalid filenames */
1274 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1280 if (!(options
.skip_hidden
&& (dp
->d_name
[0] == '.')))
1284 if ((subdirs_left
!= 0) && options
.find_recurs
&& (directory
!= NULL
))
1285 { /* Can directory be NULL ? */
1286 /* handle relative ignore dirs here */
1287 if (options
.ignore_dirs_enable
&& find_ignore_dir_search (dp
->d_name
))
1291 vfs_path_t
*tmp_vpath
;
1293 tmp_vpath
= vfs_path_build_filename (directory
, dp
->d_name
, (char *) NULL
);
1295 if (mc_lstat (tmp_vpath
, &tmp_stat
) == 0 && S_ISDIR (tmp_stat
.st_mode
))
1297 push_directory (tmp_vpath
);
1301 vfs_path_free (tmp_vpath
);
1305 search_ok
= mc_search_run (search_file_handle
, dp
->d_name
,
1306 0, strlen (dp
->d_name
), &bytes_found
);
1310 if (content_pattern
== NULL
)
1311 find_add_match (directory
, dp
->d_name
);
1312 else if (search_content (h
, directory
, dp
->d_name
))
1317 /* skip invalid filenames */
1318 while ((dp
= mc_readdir (dirp
)) != NULL
&& !str_is_valid_string (dp
->d_name
))
1322 find_rotate_dash (h
, FALSE
);
1327 /* --------------------------------------------------------------------------------------------- */
1330 init_find_vars (void)
1337 /* Remove all the items from the stack */
1340 g_strfreev (find_ignore_dirs
);
1341 find_ignore_dirs
= NULL
;
1344 /* --------------------------------------------------------------------------------------------- */
1347 find_do_view_edit (int unparsed_view
, int edit
, char *dir
, char *file
)
1349 char *fullname
= NULL
;
1350 const char *filename
= NULL
;
1353 if (content_pattern
!= NULL
)
1355 filename
= strchr (file
+ 4, ':') + 1;
1356 line
= atoi (file
+ 4);
1360 filename
= file
+ 4;
1364 fullname
= mc_build_filename (dir
, filename
, (char *) NULL
);
1366 do_edit_at_line (fullname
, use_internal_edit
, line
);
1368 view_file_at_line (fullname
, unparsed_view
, use_internal_view
, line
);
1372 /* --------------------------------------------------------------------------------------------- */
1375 view_edit_currently_selected_file (int unparsed_view
, int edit
)
1380 listbox_get_current (find_list
, &text
, (void **) &dir
);
1382 if ((text
== NULL
) || (dir
== NULL
))
1383 return MSG_NOT_HANDLED
;
1385 find_do_view_edit (unparsed_view
, edit
, dir
, text
);
1389 /* --------------------------------------------------------------------------------------------- */
1392 find_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
1397 if (parm
== KEY_F (3) || parm
== KEY_F (13))
1399 int unparsed_view
= (parm
== KEY_F (13));
1400 return view_edit_currently_selected_file (unparsed_view
, 0);
1402 if (parm
== KEY_F (4))
1404 return view_edit_currently_selected_file (0, 1);
1406 return MSG_NOT_HANDLED
;
1413 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
1417 /* --------------------------------------------------------------------------------------------- */
1418 /** Handles the Stop/Start button in the find window */
1421 start_stop (WButton
* button
, int action
)
1427 set_idle_proc (find_dlg
, running
);
1428 is_start
= !is_start
;
1430 status_update (is_start
? _("Stopped") : _("Searching"));
1431 button_set_text (stop_button
, fbuts
[is_start
? 1 : 0].text
);
1436 /* --------------------------------------------------------------------------------------------- */
1437 /** Handle view command, when invoked as a button */
1440 find_do_view_file (WButton
* button
, int action
)
1445 view_edit_currently_selected_file (0, 0);
1449 /* --------------------------------------------------------------------------------------------- */
1450 /** Handle edit command, when invoked as a button */
1453 find_do_edit_file (WButton
* button
, int action
)
1458 view_edit_currently_selected_file (0, 1);
1462 /* --------------------------------------------------------------------------------------------- */
1468 static gboolean i18n_flag
= FALSE
;
1472 int i
= sizeof (fbuts
) / sizeof (fbuts
[0]);
1475 fbuts
[i
].text
= _(fbuts
[i
].text
);
1476 fbuts
[i
].len
= str_term_width1 (fbuts
[i
].text
) + 3;
1479 fbuts
[2].len
+= 2; /* DEFPUSH_BUTTON */
1482 #endif /* ENABLE_NLS */
1485 * Dynamically place buttons centered within current window size
1488 int l0
= max (fbuts
[0].len
, fbuts
[1].len
);
1489 int l1
= fbuts
[2].len
+ fbuts
[3].len
+ l0
+ fbuts
[4].len
;
1490 int l2
= fbuts
[5].len
+ fbuts
[6].len
+ fbuts
[7].len
;
1493 /* Check, if both button rows fit within FIND2_X */
1494 FIND2_X
= max (l1
+ 9, COLS
- 16);
1495 FIND2_X
= max (l2
+ 8, FIND2_X
);
1497 /* compute amount of space between buttons for each row */
1498 r1
= (FIND2_X
- 4 - l1
) % 5;
1499 l1
= (FIND2_X
- 4 - l1
) / 5;
1500 r2
= (FIND2_X
- 4 - l2
) % 4;
1501 l2
= (FIND2_X
- 4 - l2
) / 4;
1503 /* ...and finally, place buttons */
1504 fbuts
[2].x
= 2 + r1
/ 2 + l1
;
1505 fbuts
[3].x
= fbuts
[2].x
+ fbuts
[2].len
+ l1
;
1506 fbuts
[0].x
= fbuts
[3].x
+ fbuts
[3].len
+ l1
;
1507 fbuts
[4].x
= fbuts
[0].x
+ l0
+ l1
;
1508 fbuts
[5].x
= 2 + r2
/ 2 + l2
;
1509 fbuts
[6].x
= fbuts
[5].x
+ fbuts
[5].len
+ l2
;
1510 fbuts
[7].x
= fbuts
[6].x
+ fbuts
[6].len
+ l2
;
1514 create_dlg (TRUE
, 0, 0, FIND2_Y
, FIND2_X
, dialog_colors
, find_callback
,
1515 "[Find File]", _("Find File"), DLG_CENTER
| DLG_REVERSE
);
1517 add_widget (find_dlg
,
1518 button_new (FIND2_Y
- 3, fbuts
[7].x
, B_VIEW
, NORMAL_BUTTON
,
1519 fbuts
[7].text
, find_do_edit_file
));
1520 add_widget (find_dlg
,
1521 button_new (FIND2_Y
- 3, fbuts
[6].x
, B_VIEW
, NORMAL_BUTTON
,
1522 fbuts
[6].text
, find_do_view_file
));
1523 add_widget (find_dlg
,
1524 button_new (FIND2_Y
- 3, fbuts
[5].x
, B_PANELIZE
, NORMAL_BUTTON
, fbuts
[5].text
,
1527 add_widget (find_dlg
,
1528 button_new (FIND2_Y
- 4, fbuts
[4].x
, B_CANCEL
, NORMAL_BUTTON
, fbuts
[4].text
, NULL
));
1530 button_new (FIND2_Y
- 4, fbuts
[0].x
, B_STOP
, NORMAL_BUTTON
, fbuts
[0].text
, start_stop
);
1531 add_widget (find_dlg
, stop_button
);
1532 add_widget (find_dlg
,
1533 button_new (FIND2_Y
- 4, fbuts
[3].x
, B_AGAIN
, NORMAL_BUTTON
, fbuts
[3].text
, NULL
));
1534 add_widget (find_dlg
,
1535 button_new (FIND2_Y
- 4, fbuts
[2].x
, B_ENTER
, DEFPUSH_BUTTON
, fbuts
[2].text
, NULL
));
1537 status_label
= label_new (FIND2_Y
- 7, 4, _("Searching"));
1538 add_widget (find_dlg
, status_label
);
1540 found_num_label
= label_new (FIND2_Y
- 6, 4, "");
1541 add_widget (find_dlg
, found_num_label
);
1543 find_list
= listbox_new (2, 2, FIND2_Y
- 10, FIND2_X
- 4, FALSE
, NULL
);
1544 add_widget (find_dlg
, find_list
);
1547 /* --------------------------------------------------------------------------------------------- */
1554 search_content_handle
= mc_search_new (content_pattern
, -1);
1555 if (search_content_handle
)
1557 search_content_handle
->search_type
=
1558 options
.content_regexp
? MC_SEARCH_T_REGEX
: MC_SEARCH_T_NORMAL
;
1559 search_content_handle
->is_case_sensitive
= options
.content_case_sens
;
1560 search_content_handle
->whole_words
= options
.content_whole_words
;
1561 search_content_handle
->is_all_charsets
= options
.content_all_charsets
;
1563 search_file_handle
= mc_search_new (find_pattern
, -1);
1564 search_file_handle
->search_type
= options
.file_pattern
? MC_SEARCH_T_GLOB
: MC_SEARCH_T_REGEX
;
1565 search_file_handle
->is_case_sensitive
= options
.file_case_sens
;
1566 search_file_handle
->is_all_charsets
= options
.file_all_charsets
;
1567 search_file_handle
->is_entire_line
= options
.file_pattern
;
1571 set_idle_proc (find_dlg
, 1);
1572 ret
= run_dlg (find_dlg
);
1574 mc_search_free (search_file_handle
);
1575 search_file_handle
= NULL
;
1576 mc_search_free (search_content_handle
);
1577 search_content_handle
= NULL
;
1582 /* --------------------------------------------------------------------------------------------- */
1587 set_idle_proc (find_dlg
, 0);
1588 destroy_dlg (find_dlg
);
1591 /* --------------------------------------------------------------------------------------------- */
1594 do_find (const char *start_dir
, ssize_t start_dir_len
, const char *ignore_dirs
,
1595 const char *pattern
, const char *content
, char **dirname
, char **filename
)
1597 int return_value
= 0;
1598 char *dir_tmp
= NULL
, *file_tmp
= NULL
;
1602 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
1603 find_pattern
= (char *) pattern
;
1605 content_pattern
= NULL
;
1606 if (options
.content_use
&& content
!= NULL
&& str_is_valid_string (content
))
1607 content_pattern
= g_strdup (content
);
1610 parse_ignore_dirs (ignore_dirs
);
1611 push_directory (vfs_path_from_str (start_dir
));
1613 return_value
= run_process ();
1615 /* Clear variables */
1618 get_list_info (&file_tmp
, &dir_tmp
);
1621 *dirname
= g_strdup (dir_tmp
);
1623 *filename
= g_strdup (file_tmp
);
1625 if (return_value
== B_PANELIZE
&& *filename
)
1627 int status
, link_to_dir
, stale_link
;
1632 dir_list
*list
= ¤t_panel
->dir
;
1635 if (set_zero_dir (list
))
1638 for (i
= 0, entry
= find_list
->list
; entry
!= NULL
; i
++, entry
= g_list_next (entry
))
1640 const char *lc_filename
= NULL
;
1641 WLEntry
*le
= (WLEntry
*) entry
->data
;
1644 if ((le
->text
== NULL
) || (le
->data
== NULL
))
1647 if (content_pattern
!= NULL
)
1648 lc_filename
= strchr (le
->text
+ 4, ':') + 1;
1650 lc_filename
= le
->text
+ 4;
1652 name
= mc_build_filename (le
->data
, lc_filename
, (char *) NULL
);
1653 /* skip initial start dir */
1654 if (start_dir_len
< 0)
1658 p
= name
+ (size_t) start_dir_len
;
1663 status
= handle_path (list
, p
, &st
, next_free
, &link_to_dir
, &stale_link
);
1675 /* don't add files more than once to the panel */
1676 if (content_pattern
!= NULL
&& next_free
> 0
1677 && strcmp (list
->list
[next_free
- 1].fname
, p
) == 0)
1683 if (next_free
== 0) /* first turn i.e clean old list */
1684 panel_clean_dir (current_panel
);
1685 list
->list
[next_free
].fnamelen
= strlen (p
);
1686 list
->list
[next_free
].fname
= g_strndup (p
, list
->list
[next_free
].fnamelen
);
1687 list
->list
[next_free
].f
.marked
= 0;
1688 list
->list
[next_free
].f
.link_to_dir
= link_to_dir
;
1689 list
->list
[next_free
].f
.stale_link
= stale_link
;
1690 list
->list
[next_free
].f
.dir_size_computed
= 0;
1691 list
->list
[next_free
].st
= st
;
1692 list
->list
[next_free
].sort_key
= NULL
;
1693 list
->list
[next_free
].second_sort_key
= NULL
;
1696 if (!(next_free
& 15))
1702 current_panel
->count
= next_free
;
1703 current_panel
->is_panelized
= TRUE
;
1706 if (start_dir_len
< 0)
1709 vfs_path_free (current_panel
->cwd_vpath
);
1710 current_panel
->cwd_vpath
= vfs_path_from_str (PATH_SEP_STR
);
1711 ret
= chdir (PATH_SEP_STR
);
1713 panelize_save_panel (current_panel
);
1717 g_free (content_pattern
);
1719 do_search (NULL
); /* force do_search to release resources */
1723 return return_value
;
1726 /* --------------------------------------------------------------------------------------------- */
1727 /*** public functions ****************************************************************************/
1728 /* --------------------------------------------------------------------------------------------- */
1733 char *start_dir
= NULL
, *pattern
= NULL
, *content
= NULL
, *ignore_dirs
= NULL
;
1734 ssize_t start_dir_len
;
1735 char *filename
= NULL
, *dirname
= NULL
;
1738 while (find_parameters (&start_dir
, &start_dir_len
, &ignore_dirs
, &pattern
, &content
))
1740 if (pattern
[0] == '\0')
1741 break; /* nothing search */
1743 dirname
= filename
= NULL
;
1745 v
= do_find (start_dir
, start_dir_len
, ignore_dirs
, pattern
, content
, &dirname
, &filename
);
1746 g_free (ignore_dirs
);
1751 if (dirname
!= NULL
)
1753 do_cd (dirname
, cd_exact
);
1754 if (filename
!= NULL
)
1755 try_to_select (current_panel
,
1756 filename
+ (content
!= NULL
1757 ? strchr (filename
+ 4, ':') - filename
+ 1 : 4));
1759 else if (filename
!= NULL
)
1760 do_cd (filename
, cd_exact
);
1774 if (v
== B_PANELIZE
)
1776 panel_re_sort (current_panel
);
1777 try_to_select (current_panel
, NULL
);
1783 /* --------------------------------------------------------------------------------------------- */