Just a little correction at the it.po file.
[midnight-commander.git] / src / find.c
blob8de65435772d354de4365b8d2d84b63783079a1a
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 <ctype.h>
27 #include "global.h"
28 #include "tty.h"
29 #include "win.h"
30 #include "color.h"
31 #include "setup.h"
32 #include "find.h"
34 /* Dialog manager and widgets */
35 #include "dlg.h"
36 #include "widget.h"
38 #include "dialog.h" /* For do_refresh() */
39 #define DIR_H_INCLUDE_HANDLE_DIRENT
40 #include "dir.h"
41 #include "panel.h" /* current_panel */
42 #include "main.h" /* do_cd, try_to_select */
43 #include "wtools.h"
44 #include "cmd.h" /* view_file_at_line */
45 #include "boxes.h"
46 #include "../vfs/vfs.h"
48 /* Size of the find parameters window */
49 #define FIND_Y 14
50 static int FIND_X = 50;
52 /* Size of the find window */
53 #define FIND2_Y LINES-4
55 static int FIND2_X = 64;
56 #define FIND2_X_USE FIND2_X-20
58 /* A couple of extra messages we need */
59 enum {
60 B_STOP = B_USER + 1,
61 B_AGAIN,
62 B_PANELIZE,
63 B_TREE,
64 B_VIEW
67 /* List of directories to be ignored, separated by ':' */
68 char *find_ignore_dirs = 0;
70 static WInput *in_start; /* Start path */
71 static WInput *in_name; /* Pattern to search */
72 static WInput *in_with; /* Text inside filename */
73 static WCheck *case_sense; /* "case sensitive" checkbox */
75 static int running = 0; /* nice flag */
76 static char *find_pattern; /* Pattern to search */
77 static char *content_pattern; /* pattern to search inside files */
78 static int count; /* Number of files displayed */
79 static int matches; /* Number of matches */
80 static int is_start; /* Status of the start/stop toggle button */
81 static char *old_dir;
83 static Dlg_head *find_dlg; /* The dialog */
85 static WButton *stop_button; /* pointer to the stop button */
86 static WLabel *status_label; /* Finished, Searching etc. */
87 static WListbox *find_list; /* Listbox with the file list */
89 /* This keeps track of the directory stack */
90 typedef struct dir_stack {
91 char *name;
92 struct dir_stack *prev;
93 } dir_stack ;
95 static dir_stack *dir_stack_base = 0;
97 static struct {
98 char* text;
99 int len; /* length including space and brackets */
100 int x;
101 } fbuts [] = {
102 { N_("&Suspend"), 11, 29 },
103 { N_("Con&tinue"), 12, 29 },
104 { N_("&Chdir"), 11, 3 },
105 { N_("&Again"), 9, 17 },
106 { N_("&Quit"), 8, 43 },
107 { N_("Pane&lize"), 12, 3 },
108 { N_("&View - F3"), 13, 20 },
109 { N_("&Edit - F4"), 13, 38 }
112 static char *add_to_list (char *text, void *closure);
113 static void stop_idle (void *data);
114 static void status_update (char *text);
115 static void get_list_info (char **file, char **dir);
117 /* FIXME: r should be local variables */
118 static regex_t *r; /* Pointer to compiled content_pattern */
120 static int case_sensitive = 1;
123 * Callback for the parameter dialog.
124 * Validate regex, prevent closing the dialog if it's invalid.
126 static int
127 find_parm_callback (struct Dlg_head *h, int id, int Msg)
129 int flags;
131 switch (Msg) {
132 case DLG_VALIDATE:
133 if ((h->ret_value != B_ENTER) || !in_with->buffer[0])
134 return MSG_HANDLED;
136 flags = REG_EXTENDED | REG_NOSUB;
138 if (!(case_sense->state & C_BOOL))
139 flags |= REG_ICASE;
141 if (regcomp (r, in_with->buffer, flags)) {
142 message (1, MSG_ERROR, _(" Malformed regular expression "));
143 dlg_select_widget (h, in_with);
144 h->running = 1; /* Don't stop the dialog */
146 return MSG_HANDLED;
148 return default_dlg_callback (h, id, Msg);
152 * find_parameters: gets information from the user
154 * If the return value is true, then the following holds:
156 * START_DIR and PATTERN are pointers to char * and upon return they
157 * contain the information provided by the user.
159 * CONTENT holds a strdup of the contents specified by the user if he
160 * asked for them or 0 if not (note, this is different from the
161 * behavior for the other two parameters.
164 static int
165 find_parameters (char **start_dir, char **pattern, char **content)
167 int return_value;
168 char *temp_dir;
169 static char *case_label = N_("case &Sensitive");
171 static char *in_contents = NULL;
172 static char *in_start_dir = NULL;
173 static char *in_start_name = NULL;
175 static char *labs[] =
176 { N_("Start at:"), N_("Filename:"), N_("Content: ") };
177 static char *buts[] = { N_("&OK"), N_("&Tree"), N_("&Cancel") };
178 static int ilen = 30, istart = 14;
179 static int b0 = 3, b1 = 16, b2 = 36;
181 #ifdef ENABLE_NLS
182 static int i18n_flag = 0;
184 if (!i18n_flag) {
185 register int i = sizeof (labs) / sizeof (labs[0]);
186 int l1, maxlen = 0;
188 while (i--) {
189 l1 = strlen (labs[i] = _(labs[i]));
190 if (l1 > maxlen)
191 maxlen = l1;
193 i = maxlen + ilen + 7;
194 if (i > FIND_X)
195 FIND_X = i;
197 for (i = sizeof (buts) / sizeof (buts[0]), l1 = 0; i--;) {
198 l1 += strlen (buts[i] = _(buts[i]));
200 l1 += 21;
201 if (l1 > FIND_X)
202 FIND_X = l1;
204 ilen = FIND_X - 7 - maxlen; /* for the case of very long buttons :) */
205 istart = FIND_X - 3 - ilen;
207 b1 = b0 + strlen (buts[0]) + 7;
208 b2 = FIND_X - (strlen (buts[2]) + 6);
210 i18n_flag = 1;
211 case_label = _(case_label);
213 #endif /* ENABLE_NLS */
215 find_par_start:
216 if (!in_start_dir)
217 in_start_dir = g_strdup (".");
218 if (!in_start_name)
219 in_start_name = g_strdup (easy_patterns ? "*" : ".");
220 if (!in_contents)
221 in_contents = g_strdup ("");
223 find_dlg =
224 create_dlg (0, 0, FIND_Y, FIND_X, dialog_colors,
225 find_parm_callback, "[Find File]", _("Find File"),
226 DLG_CENTER);
228 add_widget (find_dlg,
229 button_new (11, b2, B_CANCEL, NORMAL_BUTTON, buts[2], 0, 0,
230 "cancel"));
231 add_widget (find_dlg,
232 button_new (11, b1, B_TREE, NORMAL_BUTTON, buts[1], 0, 0,
233 "tree"));
234 add_widget (find_dlg,
235 button_new (11, b0, B_ENTER, DEFPUSH_BUTTON, buts[0], 0, 0,
236 "ok"));
238 case_sense =
239 check_new (9, 3, case_sensitive, case_label, "find-case-check");
240 add_widget (find_dlg, case_sense);
242 in_with =
243 input_new (7, istart, INPUT_COLOR, ilen, in_contents, "content");
244 add_widget (find_dlg, in_with);
246 in_name =
247 input_new (5, istart, INPUT_COLOR, ilen, in_start_name, "name");
248 add_widget (find_dlg, in_name);
250 in_start =
251 input_new (3, istart, INPUT_COLOR, ilen, in_start_dir, "start");
252 add_widget (find_dlg, in_start);
254 add_widget (find_dlg, label_new (7, 3, labs[2], "label-cont"));
255 add_widget (find_dlg, label_new (5, 3, labs[1], "label-file"));
256 add_widget (find_dlg, label_new (3, 3, labs[0], "label-start"));
258 run_dlg (find_dlg);
260 switch (find_dlg->ret_value) {
261 case B_CANCEL:
262 return_value = 0;
263 break;
265 case B_TREE:
266 temp_dir = g_strdup (in_start->buffer);
267 case_sensitive = case_sense->state & C_BOOL;
268 destroy_dlg (find_dlg);
269 g_free (in_start_dir);
270 if (strcmp (temp_dir, ".") == 0) {
271 g_free (temp_dir);
272 temp_dir = g_strdup (cpanel->cwd);
274 in_start_dir = tree_box (temp_dir);
275 if (in_start_dir)
276 g_free (temp_dir);
277 else
278 in_start_dir = temp_dir;
279 /* Warning: Dreadful goto */
280 goto find_par_start;
281 break;
283 default:
284 g_free (in_contents);
285 if (in_with->buffer[0]) {
286 *content = g_strdup (in_with->buffer);
287 in_contents = g_strdup (*content);
288 } else {
289 *content = in_contents = NULL;
290 r = 0;
293 case_sensitive = case_sense->state & C_BOOL;
294 return_value = 1;
295 *start_dir = g_strdup (in_start->buffer);
296 *pattern = g_strdup (in_name->buffer);
298 g_free (in_start_dir);
299 in_start_dir = g_strdup (*start_dir);
300 g_free (in_start_name);
301 in_start_name = g_strdup (*pattern);
304 destroy_dlg (find_dlg);
306 return return_value;
309 static void
310 push_directory (char *dir)
312 dir_stack *new;
314 new = g_new (dir_stack, 1);
315 new->name = g_strdup (dir);
316 new->prev = dir_stack_base;
317 dir_stack_base = new;
320 static char*
321 pop_directory (void)
323 char *name;
324 dir_stack *next;
326 if (dir_stack_base){
327 name = dir_stack_base->name;
328 next = dir_stack_base->prev;
329 g_free (dir_stack_base);
330 dir_stack_base = next;
331 return name;
332 } else
333 return 0;
336 static void
337 insert_file (char *dir, char *file)
339 char *tmp_name;
340 static char *dirname;
341 int i;
343 if (dir [0] == PATH_SEP && dir [1] == PATH_SEP)
344 dir++;
345 i = strlen (dir);
346 if (i){
347 if (dir [i - 1] != PATH_SEP){
348 dir [i] = PATH_SEP;
349 dir [i + 1] = 0;
353 if (old_dir){
354 if (strcmp (old_dir, dir)){
355 g_free (old_dir);
356 old_dir = g_strdup (dir);
357 dirname = add_to_list (dir, NULL);
359 } else {
360 old_dir = g_strdup (dir);
361 dirname = add_to_list (dir, NULL);
364 tmp_name = g_strconcat (" ", file, NULL);
365 add_to_list (tmp_name, dirname);
366 g_free (tmp_name);
369 static void
370 find_add_match (Dlg_head *h, char *dir, char *file)
372 int p = ++matches & 7;
374 insert_file (dir, file);
376 /* Scroll nicely */
377 if (!p)
378 listbox_select_last (find_list, 1);
379 else
380 listbox_select_last (find_list, 0);
381 /* Updates the current listing */
382 send_message (&find_list->widget, WIDGET_DRAW, 0);
383 if (p == 7)
384 mc_refresh ();
388 * get_line_at:
390 * Returns malloced null-terminated line from file file_fd.
391 * Input is buffered in buf_size long buffer.
392 * Current pos in buf is stored in pos.
393 * n_read - number of read chars.
394 * has_newline - is there newline ?
396 static char *
397 get_line_at (int file_fd, char *buf, int *pos, int *n_read, int buf_size, int *has_newline)
399 char *buffer = 0;
400 int buffer_size = 0;
401 char ch = 0;
402 int i = 0;
404 do {
405 if (*pos >= *n_read){
406 *pos = 0;
407 if ((*n_read = mc_read (file_fd, buf, buf_size)) <= 0)
408 break;
411 ch = buf [(*pos)++];
412 if (ch == 0) {
413 /* skip possible leading zero(s) */
414 if (i == 0)
415 continue;
416 else
417 break;
420 if (i >= buffer_size - 1){
421 buffer = g_realloc (buffer, buffer_size += 80);
424 buffer [i++] = ch;
426 } while (ch != '\n');
428 *has_newline = ch ? 1 : 0;
430 if (buffer){
431 buffer [i] = 0;
434 return buffer;
438 * search_content:
440 * Search the global (FIXME) regexp compiled content_pattern string in the
441 * DIRECTORY/FILE. It will add the found entries to the find listbox.
443 static void
444 search_content (Dlg_head *h, char *directory, char *filename)
446 struct stat s;
447 char buffer [BUF_SMALL];
448 char *fname;
449 int file_fd;
451 fname = concat_dir_and_file (directory, filename);
453 if (mc_stat (fname, &s) != 0 || !S_ISREG (s.st_mode)){
454 g_free (fname);
455 return;
458 file_fd = mc_open (fname, O_RDONLY);
459 g_free (fname);
461 if (file_fd == -1)
462 return;
464 g_snprintf (buffer, sizeof (buffer), _("Grepping in %s"), name_trunc (filename, FIND2_X_USE));
466 status_update (buffer);
467 mc_refresh ();
469 enable_interrupt_key ();
470 got_interrupt ();
473 int line = 1;
474 int pos = 0;
475 int n_read = 0;
476 int has_newline;
477 char *p;
478 int found = 0;
480 while ((p = get_line_at (file_fd, buffer, &pos, &n_read, sizeof (buffer), &has_newline))){
481 if (found == 0){ /* Search in binary line once */
482 if (regexec (r, p, 1, 0, 0) == 0){
483 g_free (p);
484 p = g_strdup_printf ("%d:%s", line, filename);
485 find_add_match (h, directory, p);
486 found = 1;
489 if (has_newline){
490 line++;
491 found = 0;
493 g_free (p);
496 disable_interrupt_key ();
497 mc_close (file_fd);
500 static int
501 do_search (struct Dlg_head *h)
503 static struct dirent *dp = 0;
504 static DIR *dirp = 0;
505 static char directory [MC_MAXPATHLEN+2];
506 struct stat tmp_stat;
507 static int pos;
508 static int subdirs_left = 0;
509 char *tmp_name; /* For building file names */
511 if (!h) { /* someone forces me to close dirp */
512 if (dirp) {
513 mc_closedir (dirp);
514 dirp = 0;
516 dp = 0;
517 return 1;
519 do_search_begin:
520 while (!dp){
522 if (dirp){
523 mc_closedir (dirp);
524 dirp = 0;
527 while (!dirp){
528 char *tmp;
530 attrset (REVERSE_COLOR);
531 while (1) {
532 tmp = pop_directory ();
533 if (!tmp){
534 running = 0;
535 status_update (_("Finished"));
536 stop_idle (h);
537 return 0;
539 if (find_ignore_dirs){
540 int found;
541 char *temp_dir = g_strconcat (":", tmp, ":", NULL);
543 found = strstr (find_ignore_dirs, temp_dir) != 0;
544 g_free (temp_dir);
545 if (found)
546 g_free (tmp);
547 else
548 break;
549 } else
550 break;
553 strcpy (directory, tmp);
554 g_free (tmp);
556 if (verbose){
557 char buffer [BUF_SMALL];
559 g_snprintf (buffer, sizeof (buffer), _("Searching %s"), name_trunc (directory, FIND2_X_USE));
560 status_update (buffer);
562 /* mc_stat should not be called after mc_opendir
563 because vfs_s_opendir modifies the st_nlink
565 mc_stat (directory, &tmp_stat);
566 subdirs_left = tmp_stat.st_nlink - 2;
567 /* Commented out as unnecessary
568 if (subdirs_left < 0)
569 subdirs_left = MAXINT;
571 dirp = mc_opendir (directory);
573 dp = mc_readdir (dirp);
576 if (strcmp (dp->d_name, ".") == 0 ||
577 strcmp (dp->d_name, "..") == 0){
578 dp = mc_readdir (dirp);
579 return 1;
582 tmp_name = concat_dir_and_file (directory, dp->d_name);
584 if (subdirs_left){
585 mc_lstat (tmp_name, &tmp_stat);
586 if (S_ISDIR (tmp_stat.st_mode)){
587 push_directory (tmp_name);
588 subdirs_left--;
592 if (regexp_match (find_pattern, dp->d_name, match_file)){
593 if (content_pattern)
594 search_content (h, directory, dp->d_name);
595 else
596 find_add_match (h, directory, dp->d_name);
599 g_free (tmp_name);
600 dp = mc_readdir (dirp);
602 /* Displays the nice dot */
603 count++;
604 if (!(count & 31)){
605 /* For nice updating */
606 char *rotating_dash = "|/-\\";
608 if (verbose){
609 pos = (pos + 1) % 4;
610 attrset (NORMALC);
611 dlg_move (h, FIND2_Y-6, FIND2_X - 4);
612 addch (rotating_dash [pos]);
613 mc_refresh ();
615 } else
616 goto do_search_begin;
617 return 1;
620 static void
621 init_find_vars (void)
623 char *dir;
625 if (old_dir){
626 g_free (old_dir);
627 old_dir = 0;
629 count = 0;
630 matches = 0;
632 /* Remove all the items in the stack */
633 while ((dir = pop_directory ()) != NULL)
634 g_free (dir);
637 static void
638 find_do_view_edit (int unparsed_view, int edit, char *dir, char *file)
640 char *fullname, *filename;
641 int line;
643 if (content_pattern){
644 filename = strchr (file + 4, ':') + 1;
645 line = atoi (file + 4);
646 } else {
647 filename = file + 4;
648 line = 0;
650 if (dir [0] == '.' && dir [1] == 0)
651 fullname = g_strdup (filename);
652 else if (dir [0] == '.' && dir [1] == PATH_SEP)
653 fullname = concat_dir_and_file (dir+2, filename);
654 else
655 fullname = concat_dir_and_file (dir, filename);
657 if (edit)
658 do_edit_at_line (fullname, line);
659 else
660 view_file_at_line (fullname, unparsed_view, use_internal_view, line);
661 g_free (fullname);
664 static void
665 get_list_info (char **file, char **dir)
667 listbox_get_current (find_list, file, dir);
670 static char *
671 add_to_list (char *text, void *data)
673 return listbox_add_item (find_list, 0, 0, text, data);
676 static void
677 stop_idle (void *data)
679 set_idle_proc (data, 0);
682 static int
683 view_edit_currently_selected_file (int unparsed_view, int edit)
685 WLEntry *entry = find_list->current;
686 char *dir;
688 if (!entry)
689 return MSG_NOT_HANDLED;
691 dir = entry->data;
693 if (!entry->text || !dir)
694 return MSG_NOT_HANDLED;
696 find_do_view_edit (unparsed_view, edit, dir, entry->text);
697 return MSG_HANDLED;
700 static int
701 find_callback (struct Dlg_head *h, int id, int Msg)
703 switch (Msg){
704 case DLG_DRAW:
705 common_dialog_repaint (h);
706 break;
708 case DLG_KEY:
709 if (id == KEY_F(3) || id == KEY_F(13)){
710 int unparsed_view = (id == KEY_F(13));
711 return view_edit_currently_selected_file (unparsed_view, 0);
713 if (id == KEY_F(4)){
714 return view_edit_currently_selected_file (0, 1);
716 return MSG_NOT_HANDLED;
718 case DLG_IDLE:
719 do_search (h);
720 break;
722 return 0;
725 /* Handles the Stop/Start button in the find window */
726 static int
727 start_stop (int button, void *extra)
729 running = is_start;
730 set_idle_proc (find_dlg, running);
731 is_start = !is_start;
733 status_update (is_start ? _("Stopped") : _("Searching"));
734 button_set_text (stop_button, fbuts [is_start].text);
736 return 0;
739 /* Handle view command, when invoked as a button */
740 static int
741 find_do_view_file (int button, void *extra)
743 view_edit_currently_selected_file (0, 0);
744 return 0;
747 /* Handle edit command, when invoked as a button */
748 static int
749 find_do_edit_file (int button, void *extra)
751 view_edit_currently_selected_file (0, 1);
752 return 0;
755 static void
756 setup_gui (void)
758 #ifdef ENABLE_NLS
759 static int i18n_flag = 0;
760 if (!i18n_flag) {
761 register int i = sizeof (fbuts) / sizeof (fbuts[0]);
762 while (i--)
763 fbuts[i].len = strlen (fbuts[i].text = _(fbuts[i].text)) + 3;
764 fbuts[2].len += 2; /* DEFPUSH_BUTTON */
765 i18n_flag = 1;
767 #endif /* ENABLE_NLS */
770 * Dynamically place buttons centered within current window size
773 int l0 = max (fbuts[0].len, fbuts[1].len);
774 int l1 = fbuts[2].len + fbuts[3].len + l0 + fbuts[4].len;
775 int l2 = fbuts[5].len + fbuts[6].len + fbuts[7].len;
776 int r1, r2;
778 FIND2_X = COLS - 16;
780 /* Check, if both button rows fit within FIND2_X */
781 if (l1 + 9 > FIND2_X)
782 FIND2_X = l1 + 9;
783 if (l2 + 8 > FIND2_X)
784 FIND2_X = l2 + 8;
786 /* compute amount of space between buttons for each row */
787 r1 = (FIND2_X - 4 - l1) % 5;
788 l1 = (FIND2_X - 4 - l1) / 5;
789 r2 = (FIND2_X - 4 - l2) % 4;
790 l2 = (FIND2_X - 4 - l2) / 4;
792 /* ...and finally, place buttons */
793 fbuts[2].x = 2 + r1 / 2 + l1;
794 fbuts[3].x = fbuts[2].x + fbuts[2].len + l1;
795 fbuts[0].x = fbuts[3].x + fbuts[3].len + l1;
796 fbuts[4].x = fbuts[0].x + l0 + l1;
797 fbuts[5].x = 2 + r2 / 2 + l2;
798 fbuts[6].x = fbuts[5].x + fbuts[5].len + l2;
799 fbuts[7].x = fbuts[6].x + fbuts[6].len + l2;
802 find_dlg = create_dlg (0, 0, FIND2_Y, FIND2_X, dialog_colors,
803 find_callback, "[Find File]", _("Find File"),
804 DLG_CENTER);
806 add_widget (find_dlg,
807 button_new (FIND2_Y - 3, fbuts[7].x, B_VIEW, NORMAL_BUTTON,
808 fbuts[7].text, find_do_edit_file, find_dlg,
809 "button-edit"));
810 add_widget (find_dlg,
811 button_new (FIND2_Y - 3, fbuts[6].x, B_VIEW, NORMAL_BUTTON,
812 fbuts[6].text, find_do_view_file, find_dlg,
813 "button-view"));
814 add_widget (find_dlg,
815 button_new (FIND2_Y - 3, fbuts[5].x, B_PANELIZE,
816 NORMAL_BUTTON, fbuts[5].text, 0, 0,
817 "button-panelize"));
819 add_widget (find_dlg,
820 button_new (FIND2_Y - 4, fbuts[4].x, B_CANCEL,
821 NORMAL_BUTTON, fbuts[4].text, 0, 0,
822 "button-quit"));
823 stop_button =
824 button_new (FIND2_Y - 4, fbuts[0].x, B_STOP, NORMAL_BUTTON,
825 fbuts[0].text, start_stop, find_dlg, "start-stop");
826 add_widget (find_dlg, stop_button);
827 add_widget (find_dlg,
828 button_new (FIND2_Y - 4, fbuts[3].x, B_AGAIN,
829 NORMAL_BUTTON, fbuts[3].text, 0, 0,
830 "button-again"));
831 add_widget (find_dlg,
832 button_new (FIND2_Y - 4, fbuts[2].x, B_ENTER,
833 DEFPUSH_BUTTON, fbuts[2].text, 0, 0,
834 "button-chdir"));
836 status_label =
837 label_new (FIND2_Y - 6, 4, _("Searching"), "label-search");
838 add_widget (find_dlg, status_label);
840 find_list =
841 listbox_new (2, 2, FIND2_X - 4, FIND2_Y - 9, listbox_finish, 0,
842 "listbox");
843 add_widget (find_dlg, find_list);
846 static int
847 run_process (void)
849 set_idle_proc (find_dlg, 1);
850 run_dlg (find_dlg);
851 return find_dlg->ret_value;
854 static void
855 status_update (char *text)
857 label_set_text (status_label, text);
860 static void
861 kill_gui (void)
863 set_idle_proc (find_dlg, 0);
864 destroy_dlg (find_dlg);
867 static int
868 find_file (char *start_dir, char *pattern, char *content, char **dirname, char **filename)
870 int return_value = 0;
871 char *dir;
872 char *dir_tmp, *file_tmp;
874 setup_gui ();
876 /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
877 find_pattern = pattern;
878 content_pattern = content;
880 init_find_vars ();
881 push_directory (start_dir);
883 return_value = run_process ();
885 /* Remove all the items in the stack */
886 while ((dir = pop_directory ()) != NULL)
887 g_free (dir);
889 get_list_info (&file_tmp, &dir_tmp);
891 if (dir_tmp)
892 *dirname = g_strdup (dir_tmp);
893 if (file_tmp)
894 *filename = g_strdup (file_tmp);
896 if (return_value == B_PANELIZE && *filename){
897 int status, link_to_dir, stale_link;
898 int next_free = 0;
899 int i;
900 struct stat buf;
901 WLEntry *entry = find_list->list;
902 dir_list *list = &cpanel->dir;
903 char *dir, *name;
905 for (i = 0; entry && i < find_list->count; entry = entry->next, i++){
906 char *filename;
908 if (!entry->text || !entry->data)
909 continue;
911 if (content_pattern)
912 filename = strchr (entry->text+4, ':')+1;
913 else
914 filename = entry->text+4;
916 dir = entry->data;
917 if (dir [0] == '.' && dir [1] == 0)
918 name = g_strdup (filename);
919 else if (dir [0] == '.' && dir [1] == PATH_SEP)
920 name = concat_dir_and_file (dir + 2, filename);
921 else
922 name = concat_dir_and_file (dir, filename);
923 status = handle_path (list, name, &buf, next_free, &link_to_dir,
924 &stale_link);
925 if (status == 0) {
926 g_free (name);
927 continue;
929 if (status == -1) {
930 g_free (name);
931 break;
934 /* don't add files more than once to the panel */
935 if (content_pattern && next_free > 0){
936 if (strcmp (list->list [next_free-1].fname, name) == 0) {
937 g_free (name);
938 continue;
942 if (!next_free) /* first turn i.e clean old list */
943 panel_clean_dir (cpanel);
944 list->list [next_free].fnamelen = strlen (name);
945 list->list [next_free].fname = name;
946 file_mark (cpanel, next_free, 0);
947 list->list [next_free].f.link_to_dir = link_to_dir;
948 list->list [next_free].f.stale_link = stale_link;
949 list->list [next_free].f.dir_size_computed = 0;
950 list->list [next_free].buf = buf;
951 next_free++;
952 if (!(next_free & 15))
953 rotate_dash ();
955 if (next_free){
956 cpanel->count = next_free;
957 cpanel->is_panelized = 1;
958 /* Done by panel_clean_dir a few lines above
959 cpanel->dirs_marked = 0;
960 cpanel->marked = 0;
961 cpanel->total = 0;
962 cpanel->top_file = 0;
963 cpanel->selected = 0;*/
965 if (start_dir [0] == PATH_SEP){
966 strcpy (cpanel->cwd, PATH_SEP_STR);
967 chdir (PATH_SEP_STR);
972 kill_gui ();
973 do_search (0); /* force do_search to release resources */
974 if (old_dir){
975 g_free (old_dir);
976 old_dir = 0;
978 return return_value;
981 void
982 do_find (void)
984 char *start_dir, *pattern, *content;
985 char *filename, *dirname;
986 int v, dir_and_file_set;
987 regex_t rx; /* Compiled content_pattern to search inside files */
989 for (r = &rx; find_parameters (&start_dir, &pattern, &content); r = &rx){
991 dirname = filename = NULL;
992 is_start = 0;
993 v = find_file (start_dir, pattern, content, &dirname, &filename);
994 g_free (start_dir);
995 g_free (pattern);
996 if (r)
997 regfree (r);
999 if (v == B_ENTER){
1000 if (dirname || filename){
1001 if (dirname){
1002 do_cd (dirname, cd_exact);
1003 if (filename)
1004 try_to_select (cpanel, filename + (content ?
1005 (strchr (filename + 4, ':') - filename + 1) : 4) );
1006 } else if (filename)
1007 do_cd (filename, cd_exact);
1008 paint_panel (cpanel);
1009 select_item (cpanel);
1011 if (dirname)
1012 g_free (dirname);
1013 if (filename)
1014 g_free (filename);
1015 break;
1017 if (content)
1018 g_free (content);
1019 dir_and_file_set = dirname && filename;
1020 if (dirname) g_free (dirname);
1021 if (filename) g_free (filename);
1022 if (v == B_CANCEL)
1023 break;
1025 if (v == B_PANELIZE){
1026 if (dir_and_file_set){
1027 try_to_select (cpanel, NULL);
1028 panel_re_sort (cpanel);
1029 paint_panel (cpanel);
1031 break;