mc/src/find.c

1265 lines
29 KiB
C
Raw Normal View History

1998-02-27 07:54:42 +03:00
/* Find file command for the Midnight Commander
Copyright (C) The Free Software Foundation
Written 1995 by Miguel de Icaza
Complete rewrote.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
1998-02-27 07:54:42 +03:00
#include <config.h>
#include "tty.h"
#include <string.h>
#include <stdio.h>
#ifdef NEEDS_IO_H
1998-02-27 07:54:42 +03:00
# include <io.h>
#endif
#include <sys/stat.h>
#include <sys/param.h>
#include <fcntl.h>
#include <ctype.h>
#include "global.h"
#include "win.h"
#include "color.h"
#include "global.h"
#include "setup.h"
1998-12-03 00:27:27 +03:00
#include "find.h"
1998-02-27 07:54:42 +03:00
/* Dialog manager and widgets */
#include "dlg.h"
#include "widget.h"
#include "dialog.h" /* For do_refresh() */
#define DIR_H_INCLUDE_HANDLE_DIRENT
#include "dir.h"
#include "panel.h" /* current_panel */
#include "main.h" /* do_cd, try_to_select */
#include "wtools.h"
#include "tree.h"
#include "cmd.h" /* view_file_at_line */
#include "../vfs/vfs.h"
#ifndef PORT_HAS_FLUSH_EVENTS
# define x_flush_events()
#endif
1998-02-27 07:54:42 +03:00
/* Size of the find parameters window */
#define FIND_Y 14
static int FIND_X = 50;
1998-02-27 07:54:42 +03:00
/* Size of the find window */
#define FIND2_Y LINES-4
static int FIND2_X = 64;
1998-02-27 07:54:42 +03:00
#ifdef HAVE_X
# define FIND2_X_USE 35
#else
# define FIND2_X_USE FIND2_X-20
#endif
/* A couple of extra messages we need */
enum {
B_STOP = B_USER + 1,
B_AGAIN,
B_PANELIZE,
B_TREE,
B_VIEW
};
/* A list of directories to be ignores, separated with ':' */
char *find_ignore_dirs = 0;
static WInput *in_start; /* Start path */
static WInput *in_name; /* Pattern to search */
static WInput *in_with; /* text inside filename */
static int running = 0; /* nice flag */
static char *find_pattern; /* Pattern to search */
static char *content_pattern; /* pattern to search inside files */
static int count; /* Number of files displayed */
static int matches; /* Number of matches */
static int is_start; /* Status of the start/stop toggle button */
int max_loops_in_idle = 10;
static char *old_dir;
static Dlg_head *find_dlg; /* The dialog */
#ifdef HAVE_GNOME
static GtkWidget *g_find_dlg;
static GtkWidget *g_status_label;
static GtkWidget *g_clist;
static GtkWidget *g_start_stop;
static GtkWidget *g_start_stop_label;
static GtkWidget *g_view, *g_edit;
static GtkWidget *g_panelize;
static int current_row;
static int idle_tag;
static int stop;
#else
static WButton *stop_button; /* pointer to the stop button */
static WLabel *status_label; /* Finished, Searching etc. */
static WListbox *find_list; /* Listbox with the file list */
#endif
1998-02-27 07:54:42 +03:00
/* For nice updating */
static char *rotating_dash = "|/-\\";
/* This keeps track of the directory stack */
typedef struct dir_stack {
char *name;
struct dir_stack *prev;
} dir_stack ;
dir_stack *dir_stack_base = 0;
static struct {
char* text;
int len; /* length including space and brackets */
int x;
} fbuts [] = {
{ N_("&Suspend"), 11, 29 },
{ N_("Con&tinue"), 12, 29 },
{ N_("&Chdir"), 11, 3 },
{ N_("&Again"), 9, 17 },
{ N_("&Quit"), 8, 43 },
{ N_("Pane&lize"), 12, 3 },
{ N_("&View - F3"), 13, 20 },
{ N_("&Edit - F4"), 13, 38 }
};
static char *add_to_list (char *text, void *closure);
static void stop_idle (void *data);
static void status_update (char *text);
static void get_list_info (char **file, char **dir);
1998-02-27 07:54:42 +03:00
/*
* find_parameters: gets information from the user
*
* If the return value is true, then the following holds:
*
* START_DIR and PATTERN are pointers to char * and upon return they
* contain the information provided by the user.
*
* CONTENT holds a strdup of the contents specified by the user if he
* asked for them or 0 if not (note, this is different from the
* behavior for the other two parameters.
*
*/
static int case_sensitive = 1;
1998-02-27 07:54:42 +03:00
static int
find_parameters (char **start_dir, char **pattern, char **content)
{
int return_value;
#ifndef HAVE_GNOME
1998-02-27 07:54:42 +03:00
char *temp_dir;
#endif
WCheck *case_sense;
static char* case_label = N_("case sensi&tive");
1998-02-27 07:54:42 +03:00
static char *in_contents = NULL;
static char *in_start_dir = NULL;
static char *in_start_name = NULL;
static char* labs[] = {N_("Start at:"), N_("Filename:"), N_("Content: ")};
static char* buts[] = {N_("&Ok"), N_("&Tree"), N_("&Cancel")};
static int ilen = 30, istart = 14;
static int b0 = 3, b1 = 16, b2 = 36;
#ifdef ENABLE_NLS
static int i18n_flag = 0;
if (!i18n_flag)
{
register int i = sizeof(labs)/sizeof(labs[0]);
int l1, maxlen = 0;
while (i--)
{
l1 = strlen (labs [i] = _(labs [i]));
if (l1 > maxlen)
maxlen = l1;
}
i = maxlen + ilen + 7;
if (i > FIND_X)
FIND_X = i;
for (i = sizeof(buts)/sizeof(buts[0]), l1 = 0; i--; )
{
l1 += strlen (buts [i] = _(buts [i]));
}
l1 += 21;
if (l1 > FIND_X)
FIND_X = l1;
ilen = FIND_X - 7 - maxlen; /* for the case of very long buttons :) */
istart = FIND_X - 3 - ilen;
b1 = b0 + strlen(buts[0]) + 7;
b2 = FIND_X - (strlen(buts[2]) + 6);
i18n_flag = 1;
case_label = _(case_label);
}
#endif /* ENABLE_NLS */
1998-02-27 07:54:42 +03:00
find_par_start:
if (!in_start_dir)
in_start_dir = g_strdup (".");
1998-02-27 07:54:42 +03:00
if (!in_start_name)
in_start_name = g_strdup (easy_patterns ? "*" : ".");
1998-02-27 07:54:42 +03:00
if (!in_contents)
in_contents = g_strdup ("");
1998-02-27 07:54:42 +03:00
find_dlg = create_dlg (0, 0, FIND_Y, FIND_X, dialog_colors,
common_dialog_callback, "[Find File]", "findfile",
DLG_CENTER | DLG_GRID);
x_set_dialog_title (find_dlg, _("Find File"));
1998-02-27 07:54:42 +03:00
add_widget (find_dlg, button_new (11, b2, B_CANCEL, NORMAL_BUTTON,
buts[2], 0 ,0, "cancel"));
Ok, most of the "Elliot Lee confidential bug report" has been dealt with with this commit. This also addresses a bunch of the comments from the status.shtml from DrMike. Miguel. 1998-04-15 Miguel de Icaza <miguel@nuclecu.unam.mx> * screen.c (GT): Assign two spaces for the minimum size of the "type" field for the GNOME edition. This gives some extra space for the icon that gets displayed. * dlg.c (remove_widget): New function: used to remove a widget from an existing Dlg_head; (destroy_widget): Destroy a specific Widget. (add_widgetl): Extended to deal with the fact that a running Dlg_head can become empty. * panelize.c (l_call): Update the input line every time the user selects the entry with the mouse (pretty common in the gnome edition). * hotlist.c (add_new_group_input): Removed an extra field that was causing problems. * find.c (find_parameters): Tree button is gone for gnome until we get the tree function working on gnome. * cmd.c (save_setup_cmd): Per Elliot's suggestion, do not pop up a dialog box to inform the user about the saved setup. 1998-04-15 Miguel de Icaza <miguel@nuclecu.unam.mx> * gcmd.c (gnome_close_panel): Implement the close-the-panel functionality. * gscreen.c (x_panel_destroy): Implement the gnome mode way of destroying the panel. * gview.c (view_status): Add cacheing of the information status, to avoid excessive flicker. It would be better if GtkLabel did not flicker though. (scrollbar_moved): Scroll correctly. We now use view_move_backward and view_move_forward to adjust the scrollbar contents. This displays the scrollbar correctly. * gwidget.c (x_listbox_select_nth): This may be invoked before the widget has been created, work around this problem. * gscreen.c (show_dir): Set the title bar for the window to the current directoy. Reported by both Mike and Elliot. * layout: Updated to the new hotlist dialog box.
1998-04-16 06:45:53 +04:00
#ifndef HAVE_GNOME
add_widget (find_dlg, button_new (11, b1, B_TREE, NORMAL_BUTTON,
buts[1], 0, 0, "tree"));
Ok, most of the "Elliot Lee confidential bug report" has been dealt with with this commit. This also addresses a bunch of the comments from the status.shtml from DrMike. Miguel. 1998-04-15 Miguel de Icaza <miguel@nuclecu.unam.mx> * screen.c (GT): Assign two spaces for the minimum size of the "type" field for the GNOME edition. This gives some extra space for the icon that gets displayed. * dlg.c (remove_widget): New function: used to remove a widget from an existing Dlg_head; (destroy_widget): Destroy a specific Widget. (add_widgetl): Extended to deal with the fact that a running Dlg_head can become empty. * panelize.c (l_call): Update the input line every time the user selects the entry with the mouse (pretty common in the gnome edition). * hotlist.c (add_new_group_input): Removed an extra field that was causing problems. * find.c (find_parameters): Tree button is gone for gnome until we get the tree function working on gnome. * cmd.c (save_setup_cmd): Per Elliot's suggestion, do not pop up a dialog box to inform the user about the saved setup. 1998-04-15 Miguel de Icaza <miguel@nuclecu.unam.mx> * gcmd.c (gnome_close_panel): Implement the close-the-panel functionality. * gscreen.c (x_panel_destroy): Implement the gnome mode way of destroying the panel. * gview.c (view_status): Add cacheing of the information status, to avoid excessive flicker. It would be better if GtkLabel did not flicker though. (scrollbar_moved): Scroll correctly. We now use view_move_backward and view_move_forward to adjust the scrollbar contents. This displays the scrollbar correctly. * gwidget.c (x_listbox_select_nth): This may be invoked before the widget has been created, work around this problem. * gscreen.c (show_dir): Set the title bar for the window to the current directoy. Reported by both Mike and Elliot. * layout: Updated to the new hotlist dialog box.
1998-04-16 06:45:53 +04:00
#endif
add_widget (find_dlg, button_new (11, b0, B_ENTER, DEFPUSH_BUTTON,
buts[0], 0, 0, "ok"));
1998-02-27 07:54:42 +03:00
case_sense = check_new (9, 3, case_sensitive, case_label, "find-case-check");
add_widget (find_dlg, case_sense);
in_with = input_new (7, istart, INPUT_COLOR, ilen, in_contents, "content");
add_widget (find_dlg, in_with);
1998-02-27 07:54:42 +03:00
in_name = input_new (5, istart, INPUT_COLOR, ilen, in_start_name, "name");
add_widget (find_dlg, in_name);
1998-02-27 07:54:42 +03:00
in_start = input_new (3, istart, INPUT_COLOR, ilen, in_start_dir, "start");
add_widget (find_dlg, in_start);
1998-02-27 07:54:42 +03:00
add_widget (find_dlg, label_new (7, 3, labs[2], "label-cont"));
add_widget (find_dlg, label_new (5, 3, labs[1], "label-file"));
add_widget (find_dlg, label_new (3, 3, labs[0], "label-start"));
1998-02-27 07:54:42 +03:00
run_dlg (find_dlg);
switch (find_dlg->ret_value){
case B_CANCEL:
1998-02-27 07:54:42 +03:00
return_value = 0;
break;
#ifndef HAVE_GNOME
case B_TREE:
temp_dir = g_strdup (in_start->buffer);
case_sensitive = case_sense->state & C_BOOL;
1998-02-27 07:54:42 +03:00
destroy_dlg (find_dlg);
g_free (in_start_dir);
1998-02-27 07:54:42 +03:00
if (strcmp (temp_dir, ".") == 0){
g_free (temp_dir);
temp_dir = g_strdup (cpanel->cwd);
1998-02-27 07:54:42 +03:00
}
in_start_dir = tree (temp_dir);
if (in_start_dir)
g_free (temp_dir);
1998-02-27 07:54:42 +03:00
else
in_start_dir = temp_dir;
/* Warning: Dreadful goto */
goto find_par_start;
break;
#endif
default:
case_sensitive = case_sense->state & C_BOOL;
1998-02-27 07:54:42 +03:00
return_value = 1;
*start_dir = g_strdup (in_start->buffer);
*pattern = g_strdup (in_name->buffer);
1998-02-27 07:54:42 +03:00
g_free (in_contents);
1998-02-27 07:54:42 +03:00
if (in_with->buffer [0]){
*content = g_strdup (in_with->buffer);
in_contents = g_strdup (*content);
1998-02-27 07:54:42 +03:00
} else
*content = in_contents = NULL;
g_free (in_start_dir);
in_start_dir = g_strdup (*start_dir);
g_free (in_start_name);
in_start_name = g_strdup (*pattern);
1998-02-27 07:54:42 +03:00
}
destroy_dlg (find_dlg);
return return_value;
}
static void
push_directory (char *dir)
{
dir_stack *new;
new = g_new (dir_stack, 1);
new->name = g_strdup (dir);
1998-02-27 07:54:42 +03:00
new->prev = dir_stack_base;
dir_stack_base = new;
}
static char*
pop_directory (void)
{
char *name;
dir_stack *next;
if (dir_stack_base){
name = dir_stack_base->name;
next = dir_stack_base->prev;
g_free (dir_stack_base);
1998-02-27 07:54:42 +03:00
dir_stack_base = next;
return name;
} else
return 0;
}
static void
insert_file (char *dir, char *file)
{
char *tmp_name;
static char *dirname;
int i;
if (dir [0] == PATH_SEP && dir [1] == PATH_SEP)
dir++;
i = strlen (dir);
if (i){
if (dir [i - 1] != PATH_SEP){
dir [i] = PATH_SEP;
dir [i + 1] = 0;
}
}
if (old_dir){
if (strcmp (old_dir, dir)){
g_free (old_dir);
old_dir = g_strdup (dir);
dirname = add_to_list (dir, NULL);
1998-02-27 07:54:42 +03:00
}
} else {
old_dir = g_strdup (dir);
dirname = add_to_list (dir, NULL);
1998-02-27 07:54:42 +03:00
}
tmp_name = g_strconcat (" ", file, NULL);
add_to_list (tmp_name, dirname);
g_free (tmp_name);
1998-02-27 07:54:42 +03:00
}
static void
find_add_match (Dlg_head *h, char *dir, char *file)
{
int p = ++matches & 7;
insert_file (dir, file);
#ifndef HAVE_GNOME
1998-02-27 07:54:42 +03:00
/* Scroll nicely */
if (!p)
listbox_select_last (find_list, 1);
else
listbox_select_last (find_list, 0);
#endif
1998-02-27 07:54:42 +03:00
#ifndef HAVE_X
/* Updates the current listing */
send_message (h, &find_list->widget, WIDGET_DRAW, 0);
if (p == 7)
mc_refresh ();
#endif
}
static char *
1998-02-27 07:54:42 +03:00
locate_egrep (void)
{
/* commented out because mc runs egrep via execvp() which searches PATH
itself. It is likely that egrep in PATH is better than in /bin */
#if 0
1998-02-27 07:54:42 +03:00
char *paths [] = {
"/bin/egrep",
"/usr/bin/egrep",
"/sbin/egrep",
"/usr/sbin/egrep",
NULL
};
struct stat s;
char **p;
for (p = &paths [0]; *p; p++){
if (stat (*p, &s) == 0)
return *p;
}
#endif
return "egrep";
1998-02-27 07:54:42 +03:00
}
/*
* search_content:
*
* Search with egrep the global (FIXME) content_pattern string in the
* DIRECTORY/FILE. It will add the found entries to the find listbox.
*/
1998-12-03 00:27:27 +03:00
static void
1998-02-27 07:54:42 +03:00
search_content (Dlg_head *h, char *directory, char *filename)
{
struct stat s;
char buffer [BUF_SMALL];
1998-02-27 07:54:42 +03:00
char *fname, *p;
int file_fd, pipe, ignoring;
char c;
int i;
1998-02-27 07:54:42 +03:00
pid_t pid;
static char *egrep_path;
char *egrep_opts = case_sensitive ? "-n" : "-in";
1998-02-27 07:54:42 +03:00
fname = concat_dir_and_file (directory, filename);
1998-02-27 07:54:42 +03:00
if (mc_stat (fname, &s) != 0 || !S_ISREG (s.st_mode)){
g_free (fname);
1998-02-27 07:54:42 +03:00
return;
}
1998-02-27 07:54:42 +03:00
file_fd = mc_open (fname, O_RDONLY);
g_free (fname);
1998-02-27 07:54:42 +03:00
if (file_fd == -1)
return;
if (!egrep_path)
egrep_path = locate_egrep ();
#ifndef GREP_STDIN
pipe = mc_doublepopen (file_fd, -1, &pid, egrep_path, egrep_path, egrep_opts, content_pattern, NULL);
1998-02-27 07:54:42 +03:00
#else /* GREP_STDIN */
pipe = mc_doublepopen (file_fd, -1, &pid, egrep_path, egrep_path, egrep_opts, content_pattern, "-", NULL);
1998-02-27 07:54:42 +03:00
#endif /* GREP STDIN */
if (pipe == -1){
mc_close (file_fd);
return;
}
g_snprintf (buffer, sizeof (buffer), _("Grepping in %s"), name_trunc (filename, FIND2_X_USE));
1998-02-27 07:54:42 +03:00
status_update (buffer);
1998-02-27 07:54:42 +03:00
mc_refresh ();
p = buffer;
ignoring = 0;
enable_interrupt_key ();
got_interrupt ();
while (1){
i = read (pipe, &c, 1);
if (i == 0)
break;
1998-02-27 07:54:42 +03:00
if (c == '\n'){
p = buffer;
ignoring = 0;
}
1998-02-27 07:54:42 +03:00
if (ignoring)
continue;
if (c == ':'){
char *the_name;
*p = 0;
ignoring = 1;
the_name = g_strconcat (buffer, ":", filename, NULL);
1998-02-27 07:54:42 +03:00
find_add_match (h, directory, the_name);
g_free (the_name);
1998-02-27 07:54:42 +03:00
} else {
if (p - buffer < (sizeof (buffer)-1) && ISASCII (c) && isdigit (c))
*p++ = c;
else
*p = 0;
}
}
disable_interrupt_key ();
if (i == -1)
message (1, _(" Find/read "), _(" Problem reading from child "));
1998-02-27 07:54:42 +03:00
mc_doublepclose (pipe, pid);
mc_close (file_fd);
}
static int
1998-02-27 07:54:42 +03:00
do_search (struct Dlg_head *h)
{
static struct dirent *dp = 0;
static DIR *dirp = 0;
static char directory [MC_MAXPATHLEN+2];
struct stat tmp_stat;
#ifndef HAVE_X
1998-02-27 07:54:42 +03:00
static int pos;
#endif
1998-02-27 07:54:42 +03:00
static int subdirs_left = 0;
char *tmp_name; /* For bulding file names */
if (!h) { /* someone forces me to close dirp */
if (dirp) {
mc_closedir (dirp);
dirp = 0;
}
dp = 0;
return 1;
1998-02-27 07:54:42 +03:00
}
#ifndef HAVE_X
1998-02-27 07:54:42 +03:00
do_search_begin:
#endif
1998-02-27 07:54:42 +03:00
while (!dp){
if (dirp){
mc_closedir (dirp);
dirp = 0;
}
while (!dirp){
char *tmp;
#ifndef HAVE_X
attrset (REVERSE_COLOR);
#endif
while (1) {
tmp = pop_directory ();
if (!tmp){
running = 0;
status_update (_("Finished"));
stop_idle (h);
return 0;
1998-02-27 07:54:42 +03:00
}
if (find_ignore_dirs){
int found;
char *temp_dir = g_strconcat (":", tmp, ":", NULL);
found = strstr (find_ignore_dirs, temp_dir) != 0;
g_free (temp_dir);
if (found)
g_free (tmp);
1998-02-27 07:54:42 +03:00
else
break;
} else
break;
}
strcpy (directory, tmp);
g_free (tmp);
1998-02-27 07:54:42 +03:00
if (verbose){
char buffer [BUF_SMALL];
1998-02-27 07:54:42 +03:00
g_snprintf (buffer, sizeof (buffer), _("Searching %s"), name_trunc (directory, FIND2_X_USE));
status_update (buffer);
1998-02-27 07:54:42 +03:00
}
/* mc_stat should not be called after mc_opendir
because vfs_s_opendir modifies the st_nlink
*/
1998-02-27 07:54:42 +03:00
mc_stat (directory, &tmp_stat);
subdirs_left = tmp_stat.st_nlink - 2;
/* Commented out as unnecessary
if (subdirs_left < 0)
subdirs_left = MAXINT;
*/
dirp = mc_opendir (directory);
1998-02-27 07:54:42 +03:00
}
dp = mc_readdir (dirp);
}
if (strcmp (dp->d_name, ".") == 0 ||
strcmp (dp->d_name, "..") == 0){
dp = mc_readdir (dirp);
return 1;
1998-02-27 07:54:42 +03:00
}
tmp_name = concat_dir_and_file (directory, dp->d_name);
1998-02-27 07:54:42 +03:00
if (subdirs_left){
mc_lstat (tmp_name, &tmp_stat);
if (S_ISDIR (tmp_stat.st_mode)){
push_directory (tmp_name);
subdirs_left--;
}
}
if (regexp_match (find_pattern, dp->d_name, match_file)){
if (content_pattern)
search_content (h, directory, dp->d_name);
else
find_add_match (h, directory, dp->d_name);
}
g_free (tmp_name);
1998-02-27 07:54:42 +03:00
dp = mc_readdir (dirp);
/* Displays the nice dot */
count++;
if (!(count & 31)){
if (verbose){
#ifndef HAVE_X
pos = (pos + 1) % 4;
1998-02-27 07:54:42 +03:00
attrset (NORMALC);
dlg_move (h, FIND2_Y-6, FIND2_X - 4);
addch (rotating_dash [pos]);
mc_refresh ();
}
} else
goto do_search_begin;
#else
}
}
#endif
x_flush_events ();
return 1;
1998-02-27 07:54:42 +03:00
}
static void
init_find_vars (void)
1998-02-27 07:54:42 +03:00
{
char *dir;
if (old_dir){
g_free (old_dir);
old_dir = 0;
}
count = 0;
matches = 0;
1998-02-27 07:54:42 +03:00
/* Remove all the items in the stack */
while ((dir = pop_directory ()) != NULL)
g_free (dir);
}
1998-02-27 07:54:42 +03:00
static void
find_do_view_edit (int unparsed_view, int edit, char *dir, char *file)
{
char *fullname, *filename;
int line;
1998-02-27 07:54:42 +03:00
if (content_pattern){
filename = strchr (file + 4, ':') + 1;
line = atoi (file + 4);
1998-02-27 07:54:42 +03:00
} else {
filename = file + 4;
1998-02-27 07:54:42 +03:00
line = 0;
}
if (dir [0] == '.' && dir [1] == 0)
fullname = g_strdup (filename);
1998-02-27 07:54:42 +03:00
else if (dir [0] == '.' && dir [1] == PATH_SEP)
fullname = concat_dir_and_file (dir+2, filename);
1998-02-27 07:54:42 +03:00
else
fullname = concat_dir_and_file (dir, filename);
1998-02-27 07:54:42 +03:00
if (edit)
do_edit_at_line (fullname, line);
else
view_file_at_line (fullname, unparsed_view, use_internal_view, line);
g_free (fullname);
}
#ifdef HAVE_GNOME
static void
select_row (GtkCList *clist, gint row, gint column, GdkEvent *event)
{
gtk_widget_set_sensitive (g_edit, TRUE);
gtk_widget_set_sensitive (g_view, TRUE);
current_row = row;
}
static void
find_do_chdir (void)
{
gtk_idle_remove (idle_tag);
idle_tag = 0;
stop = B_ENTER;
gtk_main_quit ();
}
static void
find_do_again (void)
{
gtk_idle_remove (idle_tag);
idle_tag = 0;
stop = B_AGAIN;
gtk_main_quit ();
}
static void
find_do_panelize (void)
{
gtk_idle_remove (idle_tag);
idle_tag = 0;
stop = B_PANELIZE;
gtk_main_quit ();}
static void
find_start_stop (void)
{
if (is_start){
idle_tag = gtk_idle_add ((GtkFunction)do_search, g_find_dlg);
} else {
gtk_idle_remove (idle_tag);
idle_tag = 0;
}
gtk_label_set_text (GTK_LABEL (g_start_stop_label),
is_start ? _("Suspend") : _("Restart"));
is_start = !is_start;
status_update (is_start ? _("Stopped") : _("Searching"));
}
static void
find_do_view (void)
{
char *file, *dir;
get_list_info (&file, &dir);
find_do_view_edit (0, 0, dir, file);
}
static void
find_do_edit (void)
{
char *file, *dir;
get_list_info (&file, &dir);
find_do_view_edit (0, 1, dir, file);
}
static void
setup_gui (void)
{
GtkWidget *sw, *b1, *b2;
GtkWidget *box, *box2;
g_find_dlg = gnome_dialog_new (
_("Find file"),
GNOME_STOCK_BUTTON_OK,
NULL);
/* The buttons */
b1 = gtk_button_new_with_label (_("Change to this directory"));
b2 = gtk_button_new_with_label (_("Search again"));
g_start_stop_label = gtk_label_new (_("Suspend"));
g_start_stop = gtk_button_new ();
gtk_container_add (GTK_CONTAINER (g_start_stop), g_start_stop_label);
g_view = gtk_button_new_with_label (_("View this file"));
g_edit = gtk_button_new_with_label (_("Edit this file"));
g_panelize = gtk_button_new_with_label (_("Send the results to a Panel"));
box = gtk_hbox_new (TRUE, GNOME_PAD);
gtk_box_pack_start (GTK_BOX (box), b1, 0, 1, 0);
gtk_box_pack_start (GTK_BOX (box), b2, 0, 1, 0);
gtk_box_pack_start (GTK_BOX (box), g_start_stop, 0, 1, 0);
/* RECOONECT _("Panelize contents"), */
/* _("View"),
_("Edit"), */
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
g_clist = gtk_clist_new (1);
gtk_clist_set_selection_mode (GTK_CLIST (g_clist), GTK_SELECTION_SINGLE);
gtk_widget_set_usize (g_clist, -1, 200);
gtk_container_add (GTK_CONTAINER (sw), g_clist);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (g_find_dlg)->vbox),
sw, TRUE, TRUE, GNOME_PAD_SMALL);
current_row = -1;
stop = 0;
gtk_signal_connect (GTK_OBJECT (g_clist), "select_row",
GTK_SIGNAL_FUNC (select_row), NULL);
/*
* Connect the buttons
*/
gtk_signal_connect (
GTK_OBJECT (b1), "clicked", GTK_SIGNAL_FUNC (find_do_chdir), NULL);
gtk_signal_connect (
GTK_OBJECT (b2), "clicked", GTK_SIGNAL_FUNC (find_do_again), NULL);
gtk_signal_connect (
GTK_OBJECT (g_start_stop), "clicked", GTK_SIGNAL_FUNC (find_start_stop), NULL);
gtk_signal_connect (
GTK_OBJECT (g_panelize), "clicked", GTK_SIGNAL_FUNC (find_do_panelize), NULL);
/*
* View/edit buttons
*/
gtk_signal_connect (
GTK_OBJECT (g_view), "clicked", GTK_SIGNAL_FUNC (find_do_view), NULL);
gtk_signal_connect (
GTK_OBJECT (g_edit), "clicked", GTK_SIGNAL_FUNC (find_do_edit), NULL);
gtk_widget_set_sensitive (g_view, FALSE);
gtk_widget_set_sensitive (g_edit, FALSE);
box2 = gtk_hbox_new (1, GNOME_PAD + GNOME_PAD);
gtk_box_pack_start (GTK_BOX (box2), g_view, 0, 0, 0);
gtk_box_pack_start (GTK_BOX (box2), g_edit, 0, 0, 0);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (g_find_dlg)->vbox),
box, TRUE, TRUE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (g_find_dlg)->vbox),
box2, TRUE, TRUE, GNOME_PAD_SMALL);
g_status_label = gtk_label_new (_("Searching"));
gtk_misc_set_alignment (GTK_MISC (g_status_label), 0.0, 0.5);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (g_find_dlg)->vbox),
g_status_label, TRUE, TRUE, GNOME_PAD_SMALL);
gtk_widget_show_all (g_find_dlg);
gtk_widget_hide (GTK_WIDGET (g_view));
gtk_widget_hide (GTK_WIDGET (g_edit));
}
static int
run_process ()
{
idle_tag = gtk_idle_add ((GtkFunction)do_search, g_find_dlg);
gnome_dialog_run (GNOME_DIALOG (g_find_dlg));
g_start_stop = NULL;
return stop;
}
static void
kill_gui ()
{
gtk_object_destroy (GTK_OBJECT (g_find_dlg));
}
static void
stop_idle (void *data)
{
if (g_start_stop)
gtk_widget_set_sensitive (GTK_WIDGET (g_start_stop), FALSE);
}
static void
status_update (char *text)
{
gtk_label_set_text (GTK_LABEL (g_status_label), text);
x_flush_events ();
}
static char *
add_to_list (char *text, void *data)
{
int row;
char *texts [1];
texts [0] = text;
row = gtk_clist_append (GTK_CLIST (g_clist), texts);
gtk_clist_set_row_data (GTK_CLIST (g_clist), row, data);
#if 1
if (gtk_clist_row_is_visible (GTK_CLIST (g_clist), row) != GTK_VISIBILITY_FULL)
gtk_clist_moveto (GTK_CLIST (g_clist), row, 0, 0.5, 0.0);
#endif
return text;
}
static void
get_list_info (char **file, char **dir)
{
if (current_row == -1)
*file = *dir = NULL;
gtk_clist_get_text (GTK_CLIST (g_clist), current_row, 0, file);
*dir = gtk_clist_get_row_data (GTK_CLIST (g_clist), current_row);
}
#else
static void
get_list_info (char **file, char **dir)
{
listbox_get_current (find_list, file, dir);
}
static char *
add_to_list (char *text, void *data)
{
return listbox_add_item (find_list, 0, 0, text, data);
}
static void
stop_idle (void *data)
{
set_idle_proc (data, 0);
}
static int
view_edit_currently_selected_file (int unparsed_view, int edit)
{
WLEntry *entry = find_list->current;
char *dir;
if (!entry)
return MSG_NOT_HANDLED;
dir = entry->data;
if (!entry->text || !dir)
return MSG_NOT_HANDLED;
find_do_view_edit (unparsed_view, edit, dir, entry->text);
1998-02-27 07:54:42 +03:00
return MSG_HANDLED;
}
static int
find_callback (struct Dlg_head *h, int id, int Msg)
{
switch (Msg){
#ifndef HAVE_X
case DLG_DRAW:
common_dialog_repaint (h);
break;
#endif
case DLG_KEY:
if (id == KEY_F(3) || id == KEY_F(13)){
int unparsed_view = (id == KEY_F(13));
return view_edit_currently_selected_file (unparsed_view, 0);
}
if (id == KEY_F(4)){
return view_edit_currently_selected_file (0, 1);
}
return MSG_NOT_HANDLED;
case DLG_IDLE:
do_search (h);
break;
}
return 0;
}
/* Handles the Stop/Start button in the find window */
static int
start_stop (int button, void *extra)
{
running = is_start;
set_idle_proc (find_dlg, running);
is_start = !is_start;
status_update (is_start ? _("Stopped") : _("Searching"));
button_set_text (stop_button, fbuts [is_start].text);
1998-02-27 07:54:42 +03:00
return 0;
}
/* Handle view command, when invoked as a button */
static int
find_do_view_file (int button, void *extra)
{
view_edit_currently_selected_file (0, 0);
return 0;
}
/* Handle edit command, when invoked as a button */
static int
find_do_edit_file (int button, void *extra)
{
view_edit_currently_selected_file (0, 1);
return 0;
}
static void
setup_gui (void)
1998-02-27 07:54:42 +03:00
{
#ifdef ENABLE_NLS
static int i18n_flag = 0;
if (!i18n_flag)
{
register int i = sizeof (fbuts) / sizeof (fbuts[0]);
while (i--)
fbuts [i].len = strlen (fbuts [i].text = _(fbuts [i].text)) + 3;
fbuts [2].len += 2; /* DEFPUSH_BUTTON */
i18n_flag = 1;
}
#endif /* ENABLE_NLS */
/*
* Dynamically place buttons centered within current window size
*/
{
int l0 = max (fbuts[0].len, fbuts[1].len);
int l1 = fbuts[2].len + fbuts[3].len + l0 + fbuts[4].len;
int l2 = fbuts[5].len + fbuts[6].len + fbuts[7].len;
int r1, r2;
FIND2_X = COLS - 16;
/* Check, if both button rows fit within FIND2_X */
if (l1 + 9 > FIND2_X) FIND2_X = l1 + 9;
if (l2 + 8 > FIND2_X) FIND2_X = l2 + 8;
/* compute amount of space between buttons for each row */
r1 = (FIND2_X - 4 - l1) % 5;
l1 = (FIND2_X - 4 - l1) / 5;
r2 = (FIND2_X - 4 - l2) % 4;
l2 = (FIND2_X - 4 - l2) / 4;
/* ...and finally, place buttons */
fbuts [2].x = 2 + r1/2 + l1;
fbuts [3].x = fbuts [2].x + fbuts [2].len + l1;
fbuts [0].x = fbuts [3].x + fbuts [3].len + l1;
fbuts [4].x = fbuts [0].x + l0 + l1;
fbuts [5].x = 2 + r2/2 + l2;
fbuts [6].x = fbuts [5].x + fbuts [5].len + l2;
fbuts [7].x = fbuts [6].x + fbuts [6].len + l2;
}
1998-02-27 07:54:42 +03:00
find_dlg = create_dlg (0, 0, FIND2_Y, FIND2_X, dialog_colors,
find_callback, "[Find File]", "mfind", DLG_CENTER | DLG_GRID);
x_set_dialog_title (find_dlg, _("Find file"));
1998-02-27 07:54:42 +03:00
add_widget (find_dlg,
button_new (FIND2_Y-3, fbuts[7].x, B_VIEW, NORMAL_BUTTON,
fbuts[7].text, find_do_edit_file, find_dlg, "button-edit"));
add_widget (find_dlg,
button_new (FIND2_Y-3, fbuts[6].x, B_VIEW, NORMAL_BUTTON,
fbuts[6].text, find_do_view_file, find_dlg, "button-view"));
add_widget (find_dlg,
button_new (FIND2_Y-3, fbuts[5].x, B_PANELIZE, NORMAL_BUTTON,
fbuts[5].text, 0, 0, "button-panelize"));
add_widget (find_dlg,
button_new (FIND2_Y-4, fbuts[4].x, B_CANCEL, NORMAL_BUTTON,
fbuts[4].text, 0, 0, "button-quit"));
stop_button = button_new (FIND2_Y-4, fbuts[0].x, B_STOP, NORMAL_BUTTON,
fbuts[0].text, start_stop, find_dlg, "start-stop");
add_widget (find_dlg, stop_button);
add_widget (find_dlg,
button_new (FIND2_Y-4, fbuts[3].x, B_AGAIN, NORMAL_BUTTON,
fbuts[3].text, 0, 0, "button-again"));
add_widget (find_dlg,
button_new (FIND2_Y-4, fbuts[2].x, B_ENTER, DEFPUSH_BUTTON,
fbuts[2].text, 0, 0, "button-chdir"));
1998-02-27 07:54:42 +03:00
status_label = label_new (FIND2_Y-6, 4, _("Searching"), "label-search");
add_widget (find_dlg, status_label);
1998-02-27 07:54:42 +03:00
find_list = listbox_new (2, 2, FIND2_X-4, FIND2_Y-9, listbox_finish, 0, "listbox");
add_widget (find_dlg, find_list);
}
1998-02-27 07:54:42 +03:00
static int
run_process (void)
{
set_idle_proc (find_dlg, 1);
run_dlg (find_dlg);
return find_dlg->ret_value;
}
static void
status_update (char *text)
{
label_set_text (status_label, text);
}
static void
kill_gui (void)
{
set_idle_proc (find_dlg, 0);
destroy_dlg (find_dlg);
}
#endif
static int
find_file (char *start_dir, char *pattern, char *content, char **dirname, char **filename)
{
int return_value = 0;
char *dir;
char *dir_tmp, *file_tmp;
setup_gui ();
1998-02-27 07:54:42 +03:00
/* FIXME: Need to cleanup this, this ought to be passed non-globaly */
find_pattern = pattern;
content_pattern = content;
init_find_vars ();
push_directory (start_dir);
return_value = run_process ();
1998-02-27 07:54:42 +03:00
/* Remove all the items in the stack */
while ((dir = pop_directory ()) != NULL)
g_free (dir);
get_list_info (&file_tmp, &dir_tmp);
1998-02-27 07:54:42 +03:00
if (dir_tmp)
*dirname = g_strdup (dir_tmp);
1998-02-27 07:54:42 +03:00
if (file_tmp)
*filename = g_strdup (file_tmp);
#ifndef HAVE_GNOME
1998-02-27 07:54:42 +03:00
if (return_value == B_PANELIZE && *filename){
int status, link_to_dir, stalled_link;
int next_free = 0;
int i;
struct stat buf;
WLEntry *entry = find_list->list;
dir_list *list = &cpanel->dir;
char *dir, *name;
for (i = 0; entry && i < find_list->count; entry = entry->next, i++){
char *filename;
if (content_pattern)
filename = strchr (entry->text+4, ':')+1;
else
filename = entry->text+4;
if (!entry->text || !entry->data)
continue;
dir = entry->data;
if (dir [0] == '.' && dir [1] == 0)
name = g_strdup (filename);
1998-02-27 07:54:42 +03:00
else if (dir [0] == '.' && dir [1] == PATH_SEP)
name = concat_dir_and_file (dir + 2, filename);
1998-02-27 07:54:42 +03:00
else
name = concat_dir_and_file (dir, filename);
1998-02-27 07:54:42 +03:00
status = handle_path (list, name, &buf, next_free, &link_to_dir,
&stalled_link);
if (status == 0) {
g_free (name);
1998-02-27 07:54:42 +03:00
continue;
}
if (status == -1) {
g_free (name);
1998-02-27 07:54:42 +03:00
break;
}
/* don't add files more than once to the panel */
if (content_pattern && next_free > 0){
if (strcmp (list->list [next_free-1].fname, name) == 0) {
g_free (name);
1998-02-27 07:54:42 +03:00
continue;
}
}
if (!next_free) /* first turn i.e clean old list */
panel_clean_dir (cpanel);
1998-02-27 07:54:42 +03:00
list->list [next_free].fnamelen = strlen (name);
list->list [next_free].fname = name;
file_mark (cpanel, next_free, 0);
list->list [next_free].f.link_to_dir = link_to_dir;
list->list [next_free].f.stalled_link = stalled_link;
list->list [next_free].f.dir_size_computed = 0;
1998-02-27 07:54:42 +03:00
list->list [next_free].buf = buf;
next_free++;
if (!(next_free & 15))
rotate_dash ();
}
if (next_free){
cpanel->count = next_free;
cpanel->is_panelized = 1;
/* Done by panel_clean_dir a few lines above
1998-02-27 07:54:42 +03:00
cpanel->dirs_marked = 0;
cpanel->marked = 0;
cpanel->total = 0;
cpanel->top_file = 0;
cpanel->selected = 0;*/
1998-02-27 07:54:42 +03:00
if (start_dir [0] == PATH_SEP){
strcpy (cpanel->cwd, PATH_SEP_STR);
chdir (PATH_SEP_STR);
}
}
}
#endif
1998-02-27 07:54:42 +03:00
kill_gui ();
1998-02-27 07:54:42 +03:00
do_search (0); /* force do_search to release resources */
if (old_dir){
g_free (old_dir);
1998-02-27 07:54:42 +03:00
old_dir = 0;
}
return return_value;
}
void
do_find (void)
{
char *start_dir, *pattern, *content;
char *filename, *dirname;
int v, dir_and_file_set;
int done = 0;
while (!done){
if (!find_parameters (&start_dir, &pattern, &content))
break;
dirname = filename = NULL;
is_start = 0;
v = find_file (start_dir, pattern, content, &dirname, &filename);
g_free (start_dir);
g_free (pattern);
1998-02-27 07:54:42 +03:00
if (v == B_ENTER){
if (dirname || filename){
if (dirname){
do_cd (dirname, cd_exact);
if (filename)
try_to_select (cpanel, filename + (content ?
(strchr (filename + 4, ':') - filename + 1) : 4) );
} else if (filename)
do_cd (filename, cd_exact);
paint_panel (cpanel);
select_item (cpanel);
}
if (dirname)
g_free (dirname);
1998-02-27 07:54:42 +03:00
if (filename)
g_free (filename);
1998-02-27 07:54:42 +03:00
break;
}
if (content)
g_free (content);
1998-02-27 07:54:42 +03:00
dir_and_file_set = dirname && filename;
if (dirname) g_free (dirname);
if (filename) g_free (filename);
1998-02-27 07:54:42 +03:00
if (v == B_CANCEL)
break;
if (v == B_PANELIZE){
if (dir_and_file_set){
try_to_select (cpanel, NULL);
paint_panel (cpanel);
}
break;
}
}
}