示例#1
0
文件: filtering.c 项目: vifm/vifm
/* Checks whether list of files is incomplete.  Returns non-zero if so,
 * otherwise zero is returned. */
static int
list_is_incomplete(view_t *view)
{
	if(view->filtered > 0 && !filter_is_empty(&view->local_filter.filter))
	{
		return 1;
	}

	if(flist_custom_active(view) && view->custom.type != CV_TREE)
	{
		return 0;
	}

	/* Check if there are any directories without leaf nodes.  They aren't counted
	 * as filtered out, so need to check separately (or start counting them in
	 * some way). */
	int i;
	for(i = 0; i < view->list_rows; ++i)
	{
		dir_entry_t *const entry = &view->dir_entry[i];
		if(entry->type == FT_DIR && entry->child_count == 0 &&
				!is_parent_dir(entry->name))
		{
			return 1;
		}
	}

	return 0;
}
示例#2
0
/* Checks if file specified can be displayed. Used to filter some files, that
 * are hidden intentionally.  Returns non-zero if file can be made visible. */
static int
file_can_be_displayed(const char directory[], const char filename[])
{
	if(is_parent_dir(filename))
	{
		return cfg_parent_dir_is_visible(is_root_dir(directory));
	}
	return path_exists_at(directory, filename, DEREF);
}
示例#3
0
文件: running.c 项目: cfillion/vifm
void
open_dir(FileView *view)
{
	char full_path[PATH_MAX];
	const char *filename;

	filename = get_current_file_name(view);

	if(is_parent_dir(filename))
	{
		cd_updir(view, 1);
		return;
	}

	get_current_full_path(view, sizeof(full_path), full_path);

	if(cd_is_possible(full_path))
	{
		navigate_to(view, full_path);
	}
}
示例#4
0
文件: filtering.c 项目: vifm/vifm
void
local_filter_update_view(view_t *view, int rel_pos)
{
	int pos = extract_previously_selected_pos(view);

	if(pos < 0)
	{
		pos = find_nearest_neighour(view);
	}

	if(pos >= 0)
	{
		if(pos == 0 && is_parent_dir(view->dir_entry[0].name) &&
				view->list_rows > 1 && !filter_is_empty(&view->local_filter.filter))
		{
			++pos;
		}

		view->list_pos = pos;
		view->top_line = pos - rel_pos;
	}
}
示例#5
0
文件: search.c 项目: lowtalker/vifm
int
find_pattern(FileView *view, const char pattern[], int backward, int move,
             int *const found, int interactive)
{
    int cflags;
    int nmatches = 0;
    regex_t re;
    int err;
    FileView *other;

    if(move && cfg.hl_search)
    {
        clean_selected_files(view);
    }

    reset_search_results(view);

    if(pattern[0] == '\0')
    {
        *found = 1;
        return 0;
    }

    *found = 0;

    cflags = get_regexp_cflags(pattern);
    if((err = regcomp(&re, pattern, cflags)) == 0)
    {
        int i;
        for(i = 0; i < view->list_rows; ++i)
        {
            regmatch_t matches[1];
            dir_entry_t *const entry = &view->dir_entry[i];

            if(is_parent_dir(entry->name))
            {
                continue;
            }

            if(regexec(&re, entry->name, 1, matches, 0) != 0)
            {
                continue;
            }

            entry->search_match = nmatches + 1;
            entry->match_left = matches[0].rm_so;
            entry->match_right = matches[0].rm_eo;
            if(cfg.hl_search)
            {
                entry->selected = 1;
                ++view->selected_files;
            }
            ++nmatches;
        }
        regfree(&re);
    }
    else
    {
        if(interactive)
        {
            status_bar_errorf("Regexp error: %s", get_regexp_error(err, &re));
        }
        regfree(&re);
        return 1;
    }

    other = (view == &lwin) ? &rwin : &lwin;
    if(other->matches != 0 && strcmp(other->last_search, pattern) != 0)
    {
        other->last_search[0] = '\0';
        ui_view_reset_search_highlight(other);
    }
    view->matches = nmatches;
    copy_str(view->last_search, sizeof(view->last_search), pattern);

    /* Need to redraw the list so that the matching files are highlighted */
    draw_dir_list(view);

    view->matches = nmatches;
    if(nmatches > 0)
    {
        const int was_found = move ? goto_search_match(view, backward) : 1;
        *found = was_found;

        if(cfg.hl_search && !was_found)
        {
            /* Update the view.  It look might have changed, because of selection. */
            fview_cursor_redraw(view);
        }

        if(!cfg.hl_search)
        {
            if(interactive)
            {
                print_result(view, was_found, backward);
            }
            return 1;
        }
        return 0;
    }
    else
    {
        fview_cursor_redraw(view);
        if(interactive)
        {
            print_search_fail_msg(view, backward);
        }
        return 1;
    }
}
示例#6
0
int
find_pattern(FileView *view, const char pattern[], int backward, int move,
		int *const found, int print_errors)
{
	int cflags;
	int nmatches = 0;
	regex_t re;
	int err;
	FileView *other;

	if(move && cfg.hl_search)
	{
		flist_sel_stash(view);
	}

	reset_search_results(view);

	/* We at least could wipe out previous search results, so schedule a
	 * redraw. */
	ui_view_schedule_redraw(view);

	if(pattern[0] == '\0')
	{
		*found = 1;
		return 0;
	}

	*found = 0;

	cflags = get_regexp_cflags(pattern);
	if((err = regcomp(&re, pattern, cflags)) == 0)
	{
		int i;
		for(i = 0; i < view->list_rows; ++i)
		{
			regmatch_t matches[1];
			dir_entry_t *const entry = &view->dir_entry[i];
			const char *name = entry->name;
			char *free_this = NULL;

			if(is_parent_dir(name))
			{
				continue;
			}

			if(fentry_is_dir(entry))
			{
				free_this = format_str("%s/", name);
				name = free_this;
			}

			if(regexec(&re, name, 1, matches, 0) != 0)
			{
				free(free_this);
				continue;
			}
			free(free_this);

			entry->search_match = nmatches + 1;
			entry->match_left = matches[0].rm_so;
			entry->match_right = matches[0].rm_eo;
			if(cfg.hl_search)
			{
				entry->selected = 1;
				++view->selected_files;
			}
			++nmatches;
		}
		regfree(&re);
	}
	else
	{
		if(print_errors)
		{
			status_bar_errorf("Regexp error: %s", get_regexp_error(err, &re));
		}
		regfree(&re);
		return -1;
	}

	other = (view == &lwin) ? &rwin : &lwin;
	if(other->matches != 0 && strcmp(other->last_search, pattern) != 0)
	{
		other->last_search[0] = '\0';
		ui_view_reset_search_highlight(other);
	}
	view->matches = nmatches;
	copy_str(view->last_search, sizeof(view->last_search), pattern);

	view->matches = nmatches;
	if(nmatches > 0)
	{
		const int was_found = move ? goto_search_match(view, backward) : 1;
		*found = was_found;

		if(!cfg.hl_search)
		{
			if(print_errors)
			{
				print_result(view, was_found, backward);
			}
			return 1;
		}
		return 0;
	}
	else
	{
		if(print_errors)
		{
			print_search_fail_msg(view, backward);
		}
		return 1;
	}
}
示例#7
0
文件: sort.c 项目: lyuts/vifm
static int
sort_dir_list(const void *one, const void *two)
{
	int retval;
	char *pfirst, *psecond;
	dir_entry_t *const first = (dir_entry_t *)one;
	dir_entry_t *const second = (dir_entry_t *)two;
	int first_is_dir;
	int second_is_dir;
	int dirs;

	if(is_parent_dir(first->name))
	{
		return -1;
	}
	else if(is_parent_dir(second->name))
	{
		return 1;
	}

	first_is_dir = is_directory_entry(first);
	second_is_dir = is_directory_entry(second);

	dirs = first_is_dir || second_is_dir;

	retval = 0;
	switch(sort_type)
	{
		case SORT_BY_NAME:
		case SORT_BY_INAME:
			if(first->name[0] == '.' && second->name[0] != '.')
				retval = -1;
			else if(first->name[0] != '.' && second->name[0] == '.')
				retval = 1;
			else
				retval = compare_file_names(dirs, first->name, second->name,
						sort_type == SORT_BY_INAME);
			break;

		case SORT_BY_TYPE:
			if(first_is_dir != second_is_dir)
			{
				retval = first_is_dir ? -1 : 1;
			}
			break;

		case SORT_BY_EXTENSION:
			pfirst  = strrchr(first->name,  '.');
			psecond = strrchr(second->name, '.');

			if(pfirst && psecond)
				retval = compare_file_names(dirs, ++pfirst, ++psecond, 0);
			else if(pfirst || psecond)
				retval = pfirst ? -1 : 1;
			else
				retval = compare_file_names(dirs, first->name, second->name, 0);
			break;

		case SORT_BY_SIZE:
			{
				if(first_is_dir)
					tree_get_data(curr_stats.dirsize_cache, first->name, &first->size);

				if(second_is_dir)
					tree_get_data(curr_stats.dirsize_cache, second->name, &second->size);

				retval = (first->size < second->size) ?
						-1 : (first->size > second->size);
			}
			break;

		case SORT_BY_TIME_MODIFIED:
			retval = first->mtime - second->mtime;
			break;

		case SORT_BY_TIME_ACCESSED:
			retval = first->atime - second->atime;
			break;

		case SORT_BY_TIME_CHANGED:
			retval = first->ctime - second->ctime;
			break;
#ifndef _WIN32
		case SORT_BY_MODE:
			retval = first->mode - second->mode;
			break;

		case SORT_BY_OWNER_NAME: /* FIXME */
		case SORT_BY_OWNER_ID:
			retval = first->uid - second->uid;
			break;

		case SORT_BY_GROUP_NAME: /* FIXME */
		case SORT_BY_GROUP_ID:
			retval = first->gid - second->gid;
			break;

		case SORT_BY_PERMISSIONS:
			{
				char first_perm[11], second_perm[11];
				get_perm_string(first_perm, sizeof(first_perm), first->mode);
				get_perm_string(second_perm, sizeof(second_perm), second->mode);
				retval = strcmp(first_perm, second_perm);
			}
			break;
#endif

		default:
			assert(0 && "All possible sort options should be handled");
			break;
	}

	if(retval == 0)
	{
		retval = first->list_num - second->list_num;
	}
	else if(sort_descending)
	{
		retval = -retval;
	}

	return retval;
}
示例#8
0
文件: filtering.c 项目: vifm/vifm
/* Copies/moves elements of the unfiltered list into dir_entry list.  add
 * parameter controls whether entries matching filter are copied into dir_entry
 * list.  clear parameter controls whether entries not matching filter are
 * cleared in unfiltered list.  Returns zero unless addition is performed in
 * which case can return non-zero when all files got filtered out. */
static int
update_filtering_lists(view_t *view, int add, int clear)
{
	/* filters_drop_temporaries() is a similar function. */

	size_t i;
	size_t list_size = 0U;
	dir_entry_t *parent_entry = NULL;
	int parent_added = 0;

	for(i = 0; i < view->local_filter.unfiltered_count; ++i)
	{
		/* FIXME: some very long file names won't be matched against some
		 * regexps. */
		char name_with_slash[NAME_MAX + 1 + 1];

		dir_entry_t *const entry = &view->local_filter.unfiltered[i];
		const char *name = entry->name;

		if(is_parent_dir(name))
		{
			if(entry->child_pos == 0)
			{
				parent_entry = entry;
				if(add && cfg_parent_dir_is_visible(is_root_dir(view->curr_dir)))
				{
					(void)add_dir_entry(&view->dir_entry, &list_size, entry);

					parent_added = 1;
				}
				continue;
			}
			else if(!filter_is_empty(&view->local_filter.filter))
			{
				if(clear)
				{
					fentry_free(view, entry);
				}
				continue;
			}
		}

		if(fentry_is_dir(entry))
		{
			append_slash(name, name_with_slash, sizeof(name_with_slash));
			name = name_with_slash;
		}

		/* tag links to position of nodes passed through filter in list of visible
		 * files.  Nodes that didn't pass have -1. */
		entry->tag = -1;
		if(filter_matches(&view->local_filter.filter, name) != 0)
		{
			if(add)
			{
				dir_entry_t *e = add_dir_entry(&view->dir_entry, &list_size, entry);
				if(e != NULL)
				{
					entry->tag = list_size - 1U;
					/* We basically grow the tree node by node while performing
					 * reparenting. */
					reparent_tree_node(entry, e);
				}
			}
		}
		else
		{
			if(clear)
			{
				fentry_free(view, entry);
			}
		}
	}

	if(clear)
	{
		/* XXX: the check of name pointer is horrible, but is needed to prevent
		 *      freeing of entry in use. */
		if(!parent_added && parent_entry != NULL && list_size != 0U &&
				view->dir_entry[0].name != parent_entry->name)
		{
			fentry_free(view, parent_entry);
		}
	}
	if(add)
	{
		view->list_rows = list_size;
		view->filtered = view->local_filter.prefiltered_count
		               + view->local_filter.unfiltered_count - list_size;
		ensure_filtered_list_not_empty(view, parent_entry);
		return list_size == 0U
		    || (list_size == 1U && parent_added &&
						(filter_matches(&view->local_filter.filter, "../") == 0));
	}
	return 0;
}
示例#9
0
static int
sort_dir_list(const void *one, const void *two)
{
	int retval;
	char *pfirst, *psecond;
	dir_entry_t *const first = (dir_entry_t *)one;
	dir_entry_t *const second = (dir_entry_t *)two;
	int first_is_dir;
	int second_is_dir;

	if(is_parent_dir(first->name))
	{
		return -1;
	}
	else if(is_parent_dir(second->name))
	{
		return 1;
	}

	first_is_dir = is_directory_entry(first);
	second_is_dir = is_directory_entry(second);

	retval = 0;
	switch(sort_type)
	{
		case SK_BY_NAME:
		case SK_BY_INAME:
			if(custom_view)
			{
				retval = compare_entry_names(first, second, sort_type == SK_BY_INAME);
			}
			else
			{
				retval = compare_full_file_names(first->name, second->name,
						sort_type == SK_BY_INAME);
			}
			break;

		case SK_BY_DIR:
			if(first_is_dir != second_is_dir)
			{
				retval = first_is_dir ? -1 : 1;
			}
			break;

		case SK_BY_TYPE:
			retval = strcmp(get_type_str(first->type), get_type_str(second->type));
			break;

		case SK_BY_FILEEXT:
		case SK_BY_EXTENSION:
			pfirst = strrchr(first->name,  '.');
			psecond = strrchr(second->name, '.');

			if(first_is_dir && second_is_dir && sort_type == SK_BY_FILEEXT)
			{
				retval = compare_file_names(first->name, second->name, 0);
			}
			else if(first_is_dir != second_is_dir && sort_type == SK_BY_FILEEXT)
			{
				retval = first_is_dir ? -1 : 1;
			}
			else if(pfirst && psecond)
			{
				if(pfirst == first->name && psecond != second->name)
				{
					retval = -1;
				}
				else if(pfirst != first->name && psecond == second->name)
				{
					retval = 1;
				}
				else
				{
					retval = compare_file_names(++pfirst, ++psecond, 0);
				}
			}
			else if(pfirst || psecond)
				retval = pfirst ? -1 : 1;
			else
				retval = compare_file_names(first->name, second->name, 0);
			break;

		case SK_BY_SIZE:
			{
				if(first_is_dir)
				{
					char full_path[PATH_MAX];
					get_full_path_of(first, sizeof(full_path), full_path);
					tree_get_data(curr_stats.dirsize_cache, full_path, &first->size);
				}

				if(second_is_dir)
				{
					char full_path[PATH_MAX];
					get_full_path_of(second, sizeof(full_path), full_path);
					tree_get_data(curr_stats.dirsize_cache, full_path, &second->size);
				}

				retval = (first->size < second->size)
				       ? -1
				       : (first->size > second->size);
			}
			break;

		case SK_BY_TIME_MODIFIED:
			retval = first->mtime - second->mtime;
			break;

		case SK_BY_TIME_ACCESSED:
			retval = first->atime - second->atime;
			break;

		case SK_BY_TIME_CHANGED:
			retval = first->ctime - second->ctime;
			break;
#ifndef _WIN32
		case SK_BY_MODE:
			retval = first->mode - second->mode;
			break;

		case SK_BY_OWNER_NAME: /* FIXME */
		case SK_BY_OWNER_ID:
			retval = first->uid - second->uid;
			break;

		case SK_BY_GROUP_NAME: /* FIXME */
		case SK_BY_GROUP_ID:
			retval = first->gid - second->gid;
			break;

		case SK_BY_PERMISSIONS:
			{
				char first_perm[11], second_perm[11];
				get_perm_string(first_perm, sizeof(first_perm), first->mode);
				get_perm_string(second_perm, sizeof(second_perm), second->mode);
				retval = strcmp(first_perm, second_perm);
			}
			break;
#endif
	}

	if(retval == 0)
	{
		retval = first->list_num - second->list_num;
	}
	else if(sort_descending)
	{
		retval = -retval;
	}

	return retval;
}
示例#10
0
文件: sort.c 项目: acklinr/vifm
static int
sort_dir_list(const void *one, const void *two)
{
	/* TODO: refactor this function sort_dir_list(). */

	int retval;
	const dir_entry_t *const first = one;
	const dir_entry_t *const second = two;

	const int first_is_dir = fentry_is_dir(first);
	const int second_is_dir = fentry_is_dir(second);

	if(first_is_dir && is_parent_dir(first->name))
	{
		return -1;
	}
	if(second_is_dir && is_parent_dir(second->name))
	{
		return 1;
	}

	retval = 0;
	switch(sort_type)
	{
		char *pfirst, *psecond;

		case SK_BY_NAME:
		case SK_BY_INAME:
			if(custom_view)
			{
				retval = compare_entry_names(first, second, sort_type == SK_BY_INAME);
			}
			else
			{
				retval = compare_full_file_names(first->name, second->name,
						sort_type == SK_BY_INAME);
			}
			break;

		case SK_BY_DIR:
			if(first_is_dir != second_is_dir)
			{
				retval = first_is_dir ? -1 : 1;
			}
			break;

		case SK_BY_TYPE:
			retval = strcmp(get_type_str(first->type), get_type_str(second->type));
			break;

		case SK_BY_FILEEXT:
		case SK_BY_EXTENSION:
			pfirst = strrchr(first->name,  '.');
			psecond = strrchr(second->name, '.');

			if(first_is_dir && second_is_dir && sort_type == SK_BY_FILEEXT)
			{
				retval = compare_file_names(first->name, second->name, 0);
			}
			else if(first_is_dir != second_is_dir && sort_type == SK_BY_FILEEXT)
			{
				retval = first_is_dir ? -1 : 1;
			}
			else if(pfirst && psecond)
			{
				if(pfirst == first->name && psecond != second->name)
				{
					retval = -1;
				}
				else if(pfirst != first->name && psecond == second->name)
				{
					retval = 1;
				}
				else
				{
					retval = compare_file_names(++pfirst, ++psecond, 0);
				}
			}
			else if(pfirst || psecond)
				retval = pfirst ? -1 : 1;
			else
				retval = compare_file_names(first->name, second->name, 0);
			break;

		case SK_BY_SIZE:
			retval = compare_file_sizes(first, second);
			break;

		case SK_BY_NITEMS:
			retval = compare_item_count(first, first_is_dir, second, second_is_dir);
			break;

		case SK_BY_GROUPS:
			retval = compare_group(first->name, second->name, sort_data);
			break;

		case SK_BY_TARGET:
			retval = compare_targets(first, second);
			break;

		case SK_BY_TIME_MODIFIED:
			retval = first->mtime - second->mtime;
			break;

		case SK_BY_TIME_ACCESSED:
			retval = first->atime - second->atime;
			break;

		case SK_BY_TIME_CHANGED:
			retval = first->ctime - second->ctime;
			break;

#ifndef _WIN32
		case SK_BY_MODE:
			retval = first->mode - second->mode;
			break;

		case SK_BY_INODE:
			retval = first->inode - second->inode;
			break;

		case SK_BY_OWNER_NAME: /* FIXME */
		case SK_BY_OWNER_ID:
			retval = first->uid - second->uid;
			break;

		case SK_BY_GROUP_NAME: /* FIXME */
		case SK_BY_GROUP_ID:
			retval = first->gid - second->gid;
			break;

		case SK_BY_PERMISSIONS:
			{
				char first_perm[11], second_perm[11];
				get_perm_string(first_perm, sizeof(first_perm), first->mode);
				get_perm_string(second_perm, sizeof(second_perm), second->mode);
				retval = strcmp(first_perm, second_perm);
			}
			break;

		case SK_BY_NLINKS:
			retval = first->nlinks - second->nlinks;
			break;
#endif
	}

	if(retval == 0)
	{
		retval = first->tag - second->tag;
	}
	else if(sort_descending)
	{
		retval = -retval;
	}

	return retval;
}