Exemplo n.º 1
0
Arquivo: sort.c Projeto: acklinr/vifm
void
sort_view(view_t *v)
{
	dir_entry_t *unsorted_list;

	if(v->sort[0] > SK_LAST)
	{
		/* Completely skip sorting if primary key isn't set. */
		return;
	}

	view = v;
	view_sort = v->sort;
	view_sort_groups = v->sort_groups;
	custom_view = flist_custom_active(v);

	if(!custom_view || !cv_tree(v->custom.type))
	{
		/* Tree sorting works fine for flat list, but requires a bit more
		 * resources, so skip it. */
		sort_sequence(&v->dir_entry[0], v->list_rows);
		return;
	}

	/* When local filter isn't empty, parent directories disappear and sorting
	 * stops being aware of tree structure to some degree.  Perform one more round
	 * of stable sorting of origins to group child nodes. */
	if(!filter_is_empty(&v->local_filter.filter))
	{
		flist_custom_uncompress_tree(v);
	}

	unsorted_list = v->dir_entry;
	v->dir_entry = dynarray_extend(NULL, v->list_rows*sizeof(*v->dir_entry));
	if(v->dir_entry != NULL)
	{
		sort_tree_slice(&v->dir_entry[0], unsorted_list, v->list_rows, 1);
	}
	else
	{
		/* Just do nothing on memory error. */
		v->dir_entry = unsorted_list;
		unsorted_list = NULL;
	}

	if(filter_is_empty(&v->local_filter.filter))
	{
		dynarray_free(unsorted_list);
	}
	else
	{
		filters_drop_temporaries(v, unsorted_list);
	}
}
Exemplo n.º 2
0
/* 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;
}
Exemplo n.º 3
0
Arquivo: set.c Projeto: KryDos/vifm
static void
test_set_to_empty_is_like_clear(void)
{
	filter_t filter;
	assert_int_equal(0, filter_init(&filter, 1));

	assert_int_equal(0, filter_set(&filter, ""));
	assert_true(filter_is_empty(&filter));

	filter_dispose(&filter);
}
Exemplo n.º 4
0
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;
	}
}
Exemplo n.º 5
0
/* 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;
}
Exemplo n.º 6
0
int
name_filters_empty(view_t *view)
{
	return matcher_is_empty(view->manual_filter)
	    && filter_is_empty(&view->auto_filter);
}
Exemplo n.º 7
0
void
name_filters_add_selection(view_t *view)
{
	dir_entry_t *entry;
	filter_t filter;
	int filtered;

	(void)filter_init(&filter, FILTER_DEF_CASE_SENSITIVITY);

	/* Traverse items and update/create filter values. */
	entry = NULL;
	while(iter_selection_or_current(view, &entry))
	{
		const char *name = entry->name;
		char name_with_slash[NAME_MAX + 1 + 1];

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

		(void)filter_append(&view->auto_filter, name);
		(void)filter_append(&filter, name);
	}

	/* Even current file might be unavailable for filtering.  In this case, just
	 * do nothing. */
	if(filter_is_empty(&filter))
	{
		filter_dispose(&filter);
		return;
	}

	if(view->custom.type == CV_DIFF)
	{
		(void)filter_in_compare(view, &filter, &is_newly_filtered);
		ui_view_schedule_redraw(view);
		filter_dispose(&filter);
		return;
	}

	/* Update entry lists to remove entries that must be filtered out now.  No
	 * view reload is needed. */
	filtered = zap_entries(view, view->dir_entry, &view->list_rows,
			&is_newly_filtered, &filter, 0, 1);
	if(flist_custom_active(view))
	{
		(void)zap_entries(view, view->local_filter.entries,
				&view->local_filter.entry_count, &is_newly_filtered, &filter, 1, 1);
	}
	else
	{
		view->filtered += filtered;
	}

	filter_dispose(&filter);

	fpos_ensure_valid_pos(view);
	ui_view_schedule_redraw(view);
}