* global.h: Include unix.h under "classical" QNX.
[midnight-commander.git] / src / find.c
blob354deaf6cda83638f6a254753b32c3d5d20af604
1 /* Find file command for the Midnight Commander
2 Copyright (C) The Free Software Foundation
3 Written 1995 by Miguel de Icaza
5 Complete rewrote.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include <config.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <ctype.h>
28 #include "global.h"
29 #include "tty.h"
30 #include "win.h"
31 #include "color.h"
32 #include "setup.h"
33 #include "find.h"
35 /* Dialog manager and widgets */
36 #include "dlg.h"
37 #include "widget.h"
39 #include "dialog.h" /* For do_refresh() */
40 #define DIR_H_INCLUDE_HANDLE_DIRENT
41 #include "dir.h"
42 #include "panel.h" /* current_panel */
43 #include "main.h" /* do_cd, try_to_select */
44 #include "wtools.h"
45 #include "cmd.h" /* view_file_at_line */
46 #include "boxes.h"
47 #include "../vfs/vfs.h"
49 #if defined(HAVE_RX_H) && defined(HAVE_REGCOMP)
50 # include <rx.h>
51 #else
52 # include <regex.h>
53 #endif
55 /* Size of the find parameters window */
56 #define FIND_Y 14
57 static int FIND_X = 50;
59 /* Size of the find window */
60 #define FIND2_Y LINES-4
62 static int FIND2_X = 64;
63 #define FIND2_X_USE FIND2_X-20
65 /* A couple of extra messages we need */
66 enum {
67 B_STOP = B_USER + 1,
68 B_AGAIN,
69 B_PANELIZE,
70 B_TREE,
71 B_VIEW
74 /* A list of directories to be ignores, separated with ':' */
75 char *find_ignore_dirs = 0;
77 static WInput *in_start; /* Start path */
78 static WInput *in_name; /* Pattern to search */
79 static WInput *in_with; /* text inside filename */
80 static int running = 0; /* nice flag */
81 static char *find_pattern; /* Pattern to search */
82 static char *content_pattern; /* pattern to search inside files */
83 static int count; /* Number of files displayed */
84 static int matches; /* Number of matches */
85 static int is_start; /* Status of the start/stop toggle button */
86 static char *old_dir;
88 static Dlg_head *find_dlg; /* The dialog */
90 static WButton *stop_button; /* pointer to the stop button */
91 static WLabel *status_label; /* Finished, Searching etc. */
92 static WListbox *find_list; /* Listbox with the file list */
94 /* This keeps track of the directory stack */
95 typedef struct dir_stack {
96 char *name;
97 struct dir_stack *prev;
98 } dir_stack ;
100 static dir_stack *dir_stack_base = 0;
102 static struct {
103 char* text;
104 int len; /* length including space and brackets */
105 int x;
106 } fbuts [] = {
107 { N_("&Suspend"), 11, 29 },
108 { N_("Con&tinue"), 12, 29 },
109 { N_("&Chdir"), 11, 3 },
110 { N_("&Again"), 9, 17 },
111 { N_("&Quit"), 8, 43 },
112 { N_("Pane&lize"), 12, 3 },
113 { N_("&View - F3"), 13, 20 },
114 { N_("&Edit - F4"), 13, 38 }
117 static char *add_to_list (char *text, void *closure);
118 static void stop_idle (void *data);
119 static void status_update (char *text);
120 static void get_list_info (char **file, char **dir);
123 * find_parameters: gets information from the user
125 * If the return value is true, then the following holds:
127 * START_DIR and PATTERN are pointers to char * and upon return they
128 * contain the information provided by the user.
130 * CONTENT holds a strdup of the contents specified by the user if he
131 * asked for them or 0 if not (note, this is different from the
132 * behavior for the other two parameters.
136 static int case_sensitive = 1;
138 static int
139 find_parameters (char **start_dir, char **pattern, char **content)
141 int return_value;
142 char *temp_dir;
143 WCheck *case_sense;
144 static char* case_label = N_("case &Sensitive");
146 static char *in_contents = NULL;
147 static char *in_start_dir = NULL;
148 static char *in_start_name = NULL;
150 static char* labs[] = {N_("Start at:"), N_("Filename:"), N_("Content: ")};
151 static char* buts[] = {N_("&Ok"), N_("&Tree"), N_("&Cancel")};
152 static int ilen = 30, istart = 14;
153 static int b0 = 3, b1 = 16, b2 = 36;
155 #ifdef ENABLE_NLS
156 static int i18n_flag = 0;
158 if (!i18n_flag)
160 register int i = sizeof(labs)/sizeof(labs[0]);
161 int l1, maxlen = 0;
163 while (i--)
165 l1 = strlen (labs [i] = _(labs [i]));
166 if (l1 > maxlen)
167 maxlen = l1;
169 i = maxlen + ilen + 7;
170 if (i > FIND_X)
171 FIND_X = i;
173 for (i = sizeof(buts)/sizeof(buts[0]), l1 = 0; i--; )
175 l1 += strlen (buts [i] = _(buts [i]));
177 l1 += 21;
178 if (l1 > FIND_X)
179 FIND_X = l1;
181 ilen = FIND_X - 7 - maxlen; /* for the case of very long buttons :) */
182 istart = FIND_X - 3 - ilen;
184 b1 = b0 + strlen(buts[0]) + 7;
185 b2 = FIND_X - (strlen(buts[2]) + 6);
187 i18n_flag = 1;
188 case_label = _(case_label);
191 #endif /* ENABLE_NLS */
193 find_par_start:
194 if (!in_start_dir)
195 in_start_dir = g_strdup (".");
196 if (!in_start_name)
197 in_start_name = g_strdup (easy_patterns ? "*" : ".");
198 if (!in_contents)
199 in_contents = g_strdup ("");
201 find_dlg = create_dlg (0, 0, FIND_Y, FIND_X, dialog_colors,
202 common_dialog_callback, "[Find File]", "findfile",
203 DLG_CENTER | DLG_GRID);
205 x_set_dialog_title (find_dlg, _("Find File"));
207 add_widget (find_dlg, button_new (11, b2, B_CANCEL, NORMAL_BUTTON,
208 buts[2], 0 ,0, "cancel"));
209 add_widget (find_dlg, button_new (11, b1, B_TREE, NORMAL_BUTTON,
210 buts[1], 0, 0, "tree"));
211 add_widget (find_dlg, button_new (11, b0, B_ENTER, DEFPUSH_BUTTON,
212 buts[0], 0, 0, "ok"));
214 case_sense = check_new (9, 3, case_sensitive, case_label, "find-case-check");
215 add_widget (find_dlg, case_sense);
217 in_with = input_new (7, istart, INPUT_COLOR, ilen, in_contents, "content");
218 add_widget (find_dlg, in_with);
220 in_name = input_new (5, istart, INPUT_COLOR, ilen, in_start_name, "name");
221 add_widget (find_dlg, in_name);
223 in_start = input_new (3, istart, INPUT_COLOR, ilen, in_start_dir, "start");
224 add_widget (find_dlg, in_start);
226 add_widget (find_dlg, label_new (7, 3, labs[2], "label-cont"));
227 add_widget (find_dlg, label_new (5, 3, labs[1], "label-file"));
228 add_widget (find_dlg, label_new (3, 3, labs[0], "label-start"));
230 run_dlg (find_dlg);
232 switch (find_dlg->ret_value){
233 case B_CANCEL:
234 return_value = 0;
235 break;
237 case B_TREE:
238 temp_dir = g_strdup (in_start->buffer);
239 case_sensitive = case_sense->state & C_BOOL;
240 destroy_dlg (find_dlg);
241 g_free (in_start_dir);
242 if (strcmp (temp_dir, ".") == 0){
243 g_free (temp_dir);
244 temp_dir = g_strdup (cpanel->cwd);
246 in_start_dir = tree_box (temp_dir);
247 if (in_start_dir)
248 g_free (temp_dir);
249 else
250 in_start_dir = temp_dir;
251 /* Warning: Dreadful goto */
252 goto find_par_start;
253 break;
255 default:
256 case_sensitive = case_sense->state & C_BOOL;
257 return_value = 1;
258 *start_dir = g_strdup (in_start->buffer);
259 *pattern = g_strdup (in_name->buffer);
261 g_free (in_contents);
262 if (in_with->buffer [0]){
263 *content = g_strdup (in_with->buffer);
264 in_contents = g_strdup (*content);
265 } else
266 *content = in_contents = NULL;
268 g_free (in_start_dir);
269 in_start_dir = g_strdup (*start_dir);
270 g_free (in_start_name);
271 in_start_name = g_strdup (*pattern);
274 destroy_dlg (find_dlg);
276 return return_value;
279 static void
280 push_directory (char *dir)
282 dir_stack *new;
284 new = g_new (dir_stack, 1);
285 new->name = g_strdup (dir);
286 new->prev = dir_stack_base;
287 dir_stack_base = new;
290 static char*
291 pop_directory (void)
293 char *name;
294 dir_stack *next;
296 if (dir_stack_base){
297 name = dir_stack_base->name;
298 next = dir_stack_base->prev;
299 g_free (dir_stack_base);
300 dir_stack_base = next;
301 return name;
302 } else
303 return 0;
306 static void
307 insert_file (char *dir, char *file)
309 char *tmp_name;
310 static char *dirname;
311 int i;
313 if (dir [0] == PATH_SEP && dir [1] == PATH_SEP)
314 dir++;
315 i = strlen (dir);
316 if (i){
317 if (dir [i - 1] != PATH_SEP){
318 dir [i] = PATH_SEP;
319 dir [i + 1] = 0;
323 if (old_dir){
324 if (strcmp (old_dir, dir)){
325 g_free (old_dir);
326 old_dir = g_strdup (dir);
327 dirname = add_to_list (dir, NULL);
329 } else {
330 old_dir = g_strdup (dir);
331 dirname = add_to_list (dir, NULL);
334 tmp_name = g_strconcat (" ", file, NULL);
335 add_to_list (tmp_name, dirname);
336 g_free (tmp_name);
339 static void
340 find_add_match (Dlg_head *h, char *dir, char *file)
342 int p = ++matches & 7;
344 insert_file (dir, file);
346 /* Scroll nicely */
347 if (!p)
348 listbox_select_last (find_list, 1);
349 else
350 listbox_select_last (find_list, 0);
351 /* Updates the current listing */
352 send_message (h, &find_list->widget, WIDGET_DRAW, 0);
353 if (p == 7)
354 mc_refresh ();
358 * get_line_at:
360 * Returns malloced null-terminated line from file file_fd.
361 * Input is buffered in buf_size long buffer.
362 * Current pos in buf is stored in pos.
363 * n_read - number of read chars.
364 * has_newline - is there newline ?
366 static char *
367 get_line_at (int file_fd, char *buf, int *pos, int *n_read, int buf_size, int *has_newline)
369 char *buffer = 0;
370 int buffer_size = 0;
371 char ch = 0;
372 int i = 0;
374 do {
375 if (*pos >= *n_read){
376 *pos = 0;
377 if ((*n_read = mc_read (file_fd, buf, buf_size)) <= 0)
378 break;
381 ch = buf [(*pos)++];
382 if (ch == 0) {
383 /* skip possible leading zero(s) */
384 if (i == 0)
385 continue;
386 else
387 break;
390 if (i >= buffer_size - 1){
391 buffer = g_realloc (buffer, buffer_size += 80);
394 buffer [i++] = ch;
396 } while (ch != '\n');
398 *has_newline = ch ? 1 : 0;
400 if (buffer){
401 buffer [i] = 0;
404 return buffer;
408 * search_content:
410 * Search the global (FIXME) content_pattern string in the
411 * DIRECTORY/FILE. It will add the found entries to the find listbox.
413 static void
414 search_content (Dlg_head *h, char *directory, char *filename)
416 struct stat s;
417 char buffer [BUF_SMALL];
418 char *fname;
419 int file_fd;
420 regex_t r; /* FIXME: move from search_content and make static */
421 int flags = REG_EXTENDED|REG_NOSUB;
423 fname = concat_dir_and_file (directory, filename);
425 if (mc_stat (fname, &s) != 0 || !S_ISREG (s.st_mode)){
426 g_free (fname);
427 return;
430 file_fd = mc_open (fname, O_RDONLY);
431 g_free (fname);
433 if (file_fd == -1)
434 return;
436 g_snprintf (buffer, sizeof (buffer), _("Grepping in %s"), name_trunc (filename, FIND2_X_USE));
438 status_update (buffer);
439 mc_refresh ();
441 enable_interrupt_key ();
442 got_interrupt ();
444 if (!case_sensitive)
445 flags |= REG_ICASE;
447 /* FIXME: Move regcomp/regfree from search_content;
448 * Inform user about malformed regular expression.
450 if (regcomp (&r, content_pattern, flags) == 0){
451 int line = 1;
452 int pos = 0;
453 int n_read = 0;
454 int has_newline;
455 char *p;
456 int found = 0;
458 while ((p = get_line_at (file_fd, buffer, &pos, &n_read, sizeof (buffer), &has_newline))){
459 if (found == 0){ /* Search in binary line once */
460 if (regexec (&r, p, 1, 0, 0) == 0){
461 g_free (p);
462 p = g_strdup_printf ("%d:%s", line, filename);
463 find_add_match (h, directory, p);
464 found = 1;
467 if (has_newline){
468 line++;
469 found = 0;
471 g_free (p);
473 regfree (&r);
475 disable_interrupt_key ();
476 mc_close (file_fd);
479 static int
480 do_search (struct Dlg_head *h)
482 static struct dirent *dp = 0;
483 static DIR *dirp = 0;
484 static char directory [MC_MAXPATHLEN+2];
485 struct stat tmp_stat;
486 static int pos;
487 static int subdirs_left = 0;
488 char *tmp_name; /* For building file names */
490 if (!h) { /* someone forces me to close dirp */
491 if (dirp) {
492 mc_closedir (dirp);
493 dirp = 0;
495 dp = 0;
496 return 1;
498 do_search_begin:
499 while (!dp){
501 if (dirp){
502 mc_closedir (dirp);
503 dirp = 0;
506 while (!dirp){
507 char *tmp;
509 attrset (REVERSE_COLOR);
510 while (1) {
511 tmp = pop_directory ();
512 if (!tmp){
513 running = 0;
514 status_update (_("Finished"));
515 stop_idle (h);
516 return 0;
518 if (find_ignore_dirs){
519 int found;
520 char *temp_dir = g_strconcat (":", tmp, ":", NULL);
522 found = strstr (find_ignore_dirs, temp_dir) != 0;
523 g_free (temp_dir);
524 if (found)
525 g_free (tmp);
526 else
527 break;
528 } else
529 break;
532 strcpy (directory, tmp);
533 g_free (tmp);
535 if (verbose){
536 char buffer [BUF_SMALL];
538 g_snprintf (buffer, sizeof (buffer), _("Searching %s"), name_trunc (directory, FIND2_X_USE));
539 status_update (buffer);
541 /* mc_stat should not be called after mc_opendir
542 because vfs_s_opendir modifies the st_nlink
544 mc_stat (directory, &tmp_stat);
545 subdirs_left = tmp_stat.st_nlink - 2;
546 /* Commented out as unnecessary
547 if (subdirs_left < 0)
548 subdirs_left = MAXINT;
550 dirp = mc_opendir (directory);
552 dp = mc_readdir (dirp);
555 if (strcmp (dp->d_name, ".") == 0 ||
556 strcmp (dp->d_name, "..") == 0){
557 dp = mc_readdir (dirp);
558 return 1;
561 tmp_name = concat_dir_and_file (directory, dp->d_name);
563 if (subdirs_left){
564 mc_lstat (tmp_name, &tmp_stat);
565 if (S_ISDIR (tmp_stat.st_mode)){
566 push_directory (tmp_name);
567 subdirs_left--;
571 if (regexp_match (find_pattern, dp->d_name, match_file)){
572 if (content_pattern)
573 search_content (h, directory, dp->d_name);
574 else
575 find_add_match (h, directory, dp->d_name);
578 g_free (tmp_name);
579 dp = mc_readdir (dirp);
581 /* Displays the nice dot */
582 count++;
583 if (!(count & 31)){
584 /* For nice updating */
585 char *rotating_dash = "|/-\\";
587 if (verbose){
588 pos = (pos + 1) % 4;
589 attrset (NORMALC);
590 dlg_move (h, FIND2_Y-6, FIND2_X - 4);
591 addch (rotating_dash [pos]);
592 mc_refresh ();
594 } else
595 goto do_search_begin;
596 return 1;
599 static void
600 init_find_vars (void)
602 char *dir;
604 if (old_dir){
605 g_free (old_dir);
606 old_dir = 0;
608 count = 0;
609 matches = 0;
611 /* Remove all the items in the stack */
612 while ((dir = pop_directory ()) != NULL)
613 g_free (dir);
616 static void
617 find_do_view_edit (int unparsed_view, int edit, char *dir, char *file)
619 char *fullname, *filename;
620 int line;
622 if (content_pattern){
623 filename = strchr (file + 4, ':') + 1;
624 line = atoi (file + 4);
625 } else {
626 filename = file + 4;
627 line = 0;
629 if (dir [0] == '.' && dir [1] == 0)
630 fullname = g_strdup (filename);
631 else if (dir [0] == '.' && dir [1] == PATH_SEP)
632 fullname = concat_dir_and_file (dir+2, filename);
633 else
634 fullname = concat_dir_and_file (dir, filename);
636 if (edit)
637 do_edit_at_line (fullname, line);
638 else
639 view_file_at_line (fullname, unparsed_view, use_internal_view, line);
640 g_free (fullname);
643 static void
644 get_list_info (char **file, char **dir)
646 listbox_get_current (find_list, file, dir);
649 static char *
650 add_to_list (char *text, void *data)
652 return listbox_add_item (find_list, 0, 0, text, data);
655 static void
656 stop_idle (void *data)
658 set_idle_proc (data, 0);
661 static int
662 view_edit_currently_selected_file (int unparsed_view, int edit)
664 WLEntry *entry = find_list->current;
665 char *dir;
667 if (!entry)
668 return MSG_NOT_HANDLED;
670 dir = entry->data;
672 if (!entry->text || !dir)
673 return MSG_NOT_HANDLED;
675 find_do_view_edit (unparsed_view, edit, dir, entry->text);
676 return MSG_HANDLED;
679 static int
680 find_callback (struct Dlg_head *h, int id, int Msg)
682 switch (Msg){
683 case DLG_DRAW:
684 common_dialog_repaint (h);
685 break;
687 case DLG_KEY:
688 if (id == KEY_F(3) || id == KEY_F(13)){
689 int unparsed_view = (id == KEY_F(13));
690 return view_edit_currently_selected_file (unparsed_view, 0);
692 if (id == KEY_F(4)){
693 return view_edit_currently_selected_file (0, 1);
695 return MSG_NOT_HANDLED;
697 case DLG_IDLE:
698 do_search (h);
699 break;
701 return 0;
704 /* Handles the Stop/Start button in the find window */
705 static int
706 start_stop (int button, void *extra)
708 running = is_start;
709 set_idle_proc (find_dlg, running);
710 is_start = !is_start;
712 status_update (is_start ? _("Stopped") : _("Searching"));
713 button_set_text (stop_button, fbuts [is_start].text);
715 return 0;
718 /* Handle view command, when invoked as a button */
719 static int
720 find_do_view_file (int button, void *extra)
722 view_edit_currently_selected_file (0, 0);
723 return 0;
726 /* Handle edit command, when invoked as a button */
727 static int
728 find_do_edit_file (int button, void *extra)
730 view_edit_currently_selected_file (0, 1);
731 return 0;
734 static void
735 setup_gui (void)
737 #ifdef ENABLE_NLS
738 static int i18n_flag = 0;
739 if (!i18n_flag)
741 register int i = sizeof (fbuts) / sizeof (fbuts[0]);
742 while (i--)
743 fbuts [i].len = strlen (fbuts [i].text = _(fbuts [i].text)) + 3;
744 fbuts [2].len += 2; /* DEFPUSH_BUTTON */
745 i18n_flag = 1;
747 #endif /* ENABLE_NLS */
750 * Dynamically place buttons centered within current window size
753 int l0 = max (fbuts[0].len, fbuts[1].len);
754 int l1 = fbuts[2].len + fbuts[3].len + l0 + fbuts[4].len;
755 int l2 = fbuts[5].len + fbuts[6].len + fbuts[7].len;
756 int r1, r2;
758 FIND2_X = COLS - 16;
760 /* Check, if both button rows fit within FIND2_X */
761 if (l1 + 9 > FIND2_X) FIND2_X = l1 + 9;
762 if (l2 + 8 > FIND2_X) FIND2_X = l2 + 8;
764 /* compute amount of space between buttons for each row */
765 r1 = (FIND2_X - 4 - l1) % 5;
766 l1 = (FIND2_X - 4 - l1) / 5;
767 r2 = (FIND2_X - 4 - l2) % 4;
768 l2 = (FIND2_X - 4 - l2) / 4;
770 /* ...and finally, place buttons */
771 fbuts [2].x = 2 + r1/2 + l1;
772 fbuts [3].x = fbuts [2].x + fbuts [2].len + l1;
773 fbuts [0].x = fbuts [3].x + fbuts [3].len + l1;
774 fbuts [4].x = fbuts [0].x + l0 + l1;
775 fbuts [5].x = 2 + r2/2 + l2;
776 fbuts [6].x = fbuts [5].x + fbuts [5].len + l2;
777 fbuts [7].x = fbuts [6].x + fbuts [6].len + l2;
780 find_dlg = create_dlg (0, 0, FIND2_Y, FIND2_X, dialog_colors,
781 find_callback, "[Find File]", "mfind", DLG_CENTER | DLG_GRID);
783 x_set_dialog_title (find_dlg, _("Find file"));
785 add_widget (find_dlg,
786 button_new (FIND2_Y-3, fbuts[7].x, B_VIEW, NORMAL_BUTTON,
787 fbuts[7].text, find_do_edit_file, find_dlg, "button-edit"));
788 add_widget (find_dlg,
789 button_new (FIND2_Y-3, fbuts[6].x, B_VIEW, NORMAL_BUTTON,
790 fbuts[6].text, find_do_view_file, find_dlg, "button-view"));
791 add_widget (find_dlg,
792 button_new (FIND2_Y-3, fbuts[5].x, B_PANELIZE, NORMAL_BUTTON,
793 fbuts[5].text, 0, 0, "button-panelize"));
795 add_widget (find_dlg,
796 button_new (FIND2_Y-4, fbuts[4].x, B_CANCEL, NORMAL_BUTTON,
797 fbuts[4].text, 0, 0, "button-quit"));
798 stop_button = button_new (FIND2_Y-4, fbuts[0].x, B_STOP, NORMAL_BUTTON,
799 fbuts[0].text, start_stop, find_dlg, "start-stop");
800 add_widget (find_dlg, stop_button);
801 add_widget (find_dlg,
802 button_new (FIND2_Y-4, fbuts[3].x, B_AGAIN, NORMAL_BUTTON,
803 fbuts[3].text, 0, 0, "button-again"));
804 add_widget (find_dlg,
805 button_new (FIND2_Y-4, fbuts[2].x, B_ENTER, DEFPUSH_BUTTON,
806 fbuts[2].text, 0, 0, "button-chdir"));
808 status_label = label_new (FIND2_Y-6, 4, _("Searching"), "label-search");
809 add_widget (find_dlg, status_label);
811 find_list = listbox_new (2, 2, FIND2_X-4, FIND2_Y-9, listbox_finish, 0, "listbox");
812 add_widget (find_dlg, find_list);
815 static int
816 run_process (void)
818 set_idle_proc (find_dlg, 1);
819 run_dlg (find_dlg);
820 return find_dlg->ret_value;
823 static void
824 status_update (char *text)
826 label_set_text (status_label, text);
829 static void
830 kill_gui (void)
832 set_idle_proc (find_dlg, 0);
833 destroy_dlg (find_dlg);
836 static int
837 find_file (char *start_dir, char *pattern, char *content, char **dirname, char **filename)
839 int return_value = 0;
840 char *dir;
841 char *dir_tmp, *file_tmp;
843 setup_gui ();
845 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
846 find_pattern = pattern;
847 content_pattern = content;
849 init_find_vars ();
850 push_directory (start_dir);
852 return_value = run_process ();
854 /* Remove all the items in the stack */
855 while ((dir = pop_directory ()) != NULL)
856 g_free (dir);
858 get_list_info (&file_tmp, &dir_tmp);
860 if (dir_tmp)
861 *dirname = g_strdup (dir_tmp);
862 if (file_tmp)
863 *filename = g_strdup (file_tmp);
865 if (return_value == B_PANELIZE && *filename){
866 int status, link_to_dir, stalled_link;
867 int next_free = 0;
868 int i;
869 struct stat buf;
870 WLEntry *entry = find_list->list;
871 dir_list *list = &cpanel->dir;
872 char *dir, *name;
874 for (i = 0; entry && i < find_list->count; entry = entry->next, i++){
875 char *filename;
877 if (content_pattern)
878 filename = strchr (entry->text+4, ':')+1;
879 else
880 filename = entry->text+4;
882 if (!entry->text || !entry->data)
883 continue;
884 dir = entry->data;
885 if (dir [0] == '.' && dir [1] == 0)
886 name = g_strdup (filename);
887 else if (dir [0] == '.' && dir [1] == PATH_SEP)
888 name = concat_dir_and_file (dir + 2, filename);
889 else
890 name = concat_dir_and_file (dir, filename);
891 status = handle_path (list, name, &buf, next_free, &link_to_dir,
892 &stalled_link);
893 if (status == 0) {
894 g_free (name);
895 continue;
897 if (status == -1) {
898 g_free (name);
899 break;
902 /* don't add files more than once to the panel */
903 if (content_pattern && next_free > 0){
904 if (strcmp (list->list [next_free-1].fname, name) == 0) {
905 g_free (name);
906 continue;
910 if (!next_free) /* first turn i.e clean old list */
911 panel_clean_dir (cpanel);
912 list->list [next_free].fnamelen = strlen (name);
913 list->list [next_free].fname = name;
914 file_mark (cpanel, next_free, 0);
915 list->list [next_free].f.link_to_dir = link_to_dir;
916 list->list [next_free].f.stalled_link = stalled_link;
917 list->list [next_free].f.dir_size_computed = 0;
918 list->list [next_free].buf = buf;
919 next_free++;
920 if (!(next_free & 15))
921 rotate_dash ();
923 if (next_free){
924 cpanel->count = next_free;
925 cpanel->is_panelized = 1;
926 /* Done by panel_clean_dir a few lines above
927 cpanel->dirs_marked = 0;
928 cpanel->marked = 0;
929 cpanel->total = 0;
930 cpanel->top_file = 0;
931 cpanel->selected = 0;*/
933 if (start_dir [0] == PATH_SEP){
934 strcpy (cpanel->cwd, PATH_SEP_STR);
935 chdir (PATH_SEP_STR);
940 kill_gui ();
941 do_search (0); /* force do_search to release resources */
942 if (old_dir){
943 g_free (old_dir);
944 old_dir = 0;
946 return return_value;
949 void
950 do_find (void)
952 char *start_dir, *pattern, *content;
953 char *filename, *dirname;
954 int v, dir_and_file_set;
955 int done = 0;
957 while (!done){
958 if (!find_parameters (&start_dir, &pattern, &content))
959 break;
961 dirname = filename = NULL;
962 is_start = 0;
963 v = find_file (start_dir, pattern, content, &dirname, &filename);
964 g_free (start_dir);
965 g_free (pattern);
967 if (v == B_ENTER){
968 if (dirname || filename){
969 if (dirname){
970 do_cd (dirname, cd_exact);
971 if (filename)
972 try_to_select (cpanel, filename + (content ?
973 (strchr (filename + 4, ':') - filename + 1) : 4) );
974 } else if (filename)
975 do_cd (filename, cd_exact);
976 paint_panel (cpanel);
977 select_item (cpanel);
979 if (dirname)
980 g_free (dirname);
981 if (filename)
982 g_free (filename);
983 break;
985 if (content)
986 g_free (content);
987 dir_and_file_set = dirname && filename;
988 if (dirname) g_free (dirname);
989 if (filename) g_free (filename);
990 if (v == B_CANCEL)
991 break;
993 if (v == B_PANELIZE){
994 if (dir_and_file_set){
995 try_to_select (cpanel, NULL);
996 panel_re_sort (cpanel);
997 paint_panel (cpanel);
999 break;