📄 find.c
字号:
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;
}
do_search_begin:
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;
label_set_text (status_label, _("Finished"));
set_idle_proc (h, 0);
return;
}
if (find_ignore_dirs){
char *temp_dir = copy_strings (":", tmp, ":", 0);
if (strstr (find_ignore_dirs, temp_dir))
free (tmp);
else
break;
} else
break;
}
strcpy (directory, tmp);
free (tmp);
if (verbose){
char buffer [50];
sprintf (buffer, _("Searching %s"), name_trunc (directory, FIND2_X_USE));
label_set_text (status_label, buffer);
}
dirp = mc_opendir (directory);
mc_stat (directory, &tmp_stat);
subdirs_left = tmp_stat.st_nlink - 2;
/* Commented out as unnecessary
if (subdirs_left < 0)
subdirs_left = MAXINT;
*/
}
dp = mc_readdir (dirp);
}
if (strcmp (dp->d_name, ".") == 0 ||
strcmp (dp->d_name, "..") == 0){
dp = mc_readdir (dirp);
#ifdef HAVE_XVIEW
xv_post_proc (h, (void (*)(void *))do_search, (void *)h);
#endif
return;
}
tmp_name = get_full_name (directory, dp->d_name);
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);
}
free (tmp_name);
dp = mc_readdir (dirp);
/* Displays the nice dot */
count++;
if (!(count & 31)){
if (verbose){
#ifndef HAVE_X
pos = (pos + 1) % 4;
attrset (NORMALC);
dlg_move (h, FIND2_Y-6, FIND2_X - 4);
addch (rotating_dash [pos]);
mc_refresh ();
}
} else
goto do_search_begin;
#else
}
}
#ifdef HAVE_XVIEW
xv_post_proc (h, (void (*)(void *))do_search, (void *)h);
#endif
#endif
x_flush_events ();
}
static int
view_edit_currently_selected_file (int unparsed_view, int edit)
{
WLEntry *entry = find_list->current;
char *dir, *fullname, *filename;
int line;
if (!entry)
return MSG_NOT_HANDLED;
dir = entry->data;
if (!entry->text || !dir)
return MSG_NOT_HANDLED;
if (content_pattern){
filename = strchr (entry->text + 4, ':') + 1;
line = atoi (entry->text + 4);
} else {
filename = entry->text + 4;
line = 0;
}
if (dir [0] == '.' && dir [1] == 0)
fullname = strdup (filename);
else if (dir [0] == '.' && dir [1] == PATH_SEP)
fullname = get_full_name (dir+2, filename);
else
fullname = get_full_name (dir, filename);
if (edit)
do_edit_at_line (fullname, line);
else
view_file_at_line (fullname, unparsed_view, use_internal_view, line);
free (fullname);
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;
label_set_text (status_label, is_start ? _("Stopped") : _("Searching"));
button_set_text (stop_button, fbuts [is_start].text);
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
init_find_vars (void)
{
char *dir;
if (old_dir){
free (old_dir);
old_dir = 0;
}
count = 0;
matches = 0;
/* Remove all the items in the stack */
while ((dir = pop_directory ()) != NULL)
free (dir);
}
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;
#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;
}
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"));
add_widgetl (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"), 0);
add_widgetl (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"), 0);
add_widgetl (find_dlg,
button_new (FIND2_Y-3, fbuts[5].x, B_PANELIZE, NORMAL_BUTTON,
fbuts[5].text, 0, 0, "button-panelize"), XV_WLAY_CENTERROW);
add_widgetl (find_dlg,
button_new (FIND2_Y-4, fbuts[4].x, B_CANCEL, NORMAL_BUTTON,
fbuts[4].text, 0, 0, "button-quit"), XV_WLAY_RIGHTOF);
stop_button = button_new (FIND2_Y-4, fbuts[0].x, B_STOP, NORMAL_BUTTON,
fbuts[0].text, start_stop, find_dlg, "start-stop");
add_widgetl (find_dlg, stop_button, XV_WLAY_RIGHTOF);
add_widgetl (find_dlg,
button_new (FIND2_Y-4, fbuts[3].x, B_AGAIN, NORMAL_BUTTON,
fbuts[3].text, 0, 0, "button-again"), XV_WLAY_RIGHTOF);
add_widgetl (find_dlg,
button_new (FIND2_Y-4, fbuts[2].x, B_ENTER, DEFPUSH_BUTTON,
fbuts[2].text, 0, 0, "button-chdir"), XV_WLAY_CENTERROW);
status_label = label_new (FIND2_Y-6, 4, _("Searching"), "label-search");
add_widgetl (find_dlg, status_label, XV_WLAY_BELOWOF);
find_list = listbox_new (2, 2, FIND2_X-4, FIND2_Y-9, listbox_finish, 0, "listbox");
add_widgetl (find_dlg, find_list, XV_WLAY_EXTENDWIDTH);
/* FIXME: Need to cleanup this, this ought to be passed non-globaly */
find_pattern = pattern;
content_pattern = content;
set_idle_proc (find_dlg, 1);
init_find_vars ();
push_directory (start_dir);
#ifdef HAVE_XVIEW
xv_post_proc (find_dlg, (void (*)(void *))do_search, (void *)find_dlg);
#endif
run_dlg (find_dlg);
return_value = find_dlg->ret_value;
/* Remove all the items in the stack */
while ((dir = pop_directory ()) != NULL)
free (dir);
listbox_get_current (find_list, &file_tmp, &dir_tmp);
if (dir_tmp)
*dirname = strdup (dir_tmp);
if (file_tmp)
*filename = strdup (file_tmp);
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 = strdup (filename);
else if (dir [0] == '.' && dir [1] == PATH_SEP)
name = get_full_name (dir + 2, filename);
else
name = get_full_name (dir, filename);
status = handle_path (list, name, &buf, next_free, &link_to_dir,
&stalled_link);
if (status == 0) {
free (name);
continue;
}
if (status == -1) {
free (name);
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) {
free (name);
continue;
}
}
if (!next_free) /* first turn i.e clean old list */
clean_dir (list, cpanel->count);
list->list [next_free].fnamelen = strlen (name);
list->list [next_free].fname = name;
list->list [next_free].cache = NULL;
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].buf = buf;
next_free++;
if (!(next_free & 15))
rotate_dash ();
}
if (next_free){
cpanel->count = next_free;
cpanel->is_panelized = 1;
cpanel->dirs_marked = 0;
cpanel->has_dir_sizes = 0;
cpanel->marked = 0;
cpanel->total = 0;
cpanel->top_file = 0;
cpanel->selected = 0;
if (start_dir [0] == PATH_SEP){
strcpy (cpanel->cwd, PATH_SEP_STR);
chdir (PATH_SEP_STR);
}
}
}
set_idle_proc (find_dlg, 0);
destroy_dlg (find_dlg);
do_search (0); /* force do_search to release resources */
if (old_dir){
free (old_dir);
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);
free (start_dir);
free (pattern);
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)
free (dirname);
if (filename)
free (filename);
break;
}
if (content)
free (content);
dir_and_file_set = dirname && filename;
if (dirname) free (dirname);
if (filename) free (filename);
if (v == B_CANCEL)
break;
if (v == B_PANELIZE){
if (dir_and_file_set){
try_to_select (cpanel, NULL);
paint_panel (cpanel);
}
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -