コード例 #1
0
/* Composes two views containing only files that are unique to each of them.
 * Assumes that both lists are sorted by id. */
static void
make_unique_lists(entries_t curr, entries_t other)
{
	int i, j = 0;

	flist_custom_start(curr_view, "unique");
	flist_custom_start(other_view, "unique");

	for(i = 0; i < other.nentries; ++i)
	{
		const int id = other.entries[i].id;

		while(j < curr.nentries && curr.entries[j].id < id)
		{
			flist_custom_put(curr_view, &curr.entries[j]);
			++j;
		}

		if(j >= curr.nentries || curr.entries[j].id != id)
		{
			flist_custom_put(other_view, &other.entries[i]);
			continue;
		}

		while(j < curr.nentries && curr.entries[j].id == id)
		{
			free_dir_entry(curr_view, &curr.entries[j++]);
		}
		while(i < other.nentries && other.entries[i].id == id)
		{
			free_dir_entry(other_view, &other.entries[i++]);
		}
		--i;
	}

	/* Entries' data has been moved out of them or freed, so need to free only the
	 * lists. */
	dynarray_free(curr.entries);
	dynarray_free(other.entries);

	(void)flist_custom_finish(curr_view, CV_REGULAR, 1);
	(void)flist_custom_finish(other_view, CV_REGULAR, 1);

	curr_view->list_pos = 0;
	other_view->list_pos = 0;

	ui_view_schedule_redraw(curr_view);
	ui_view_schedule_redraw(other_view);
}
コード例 #2
0
ファイル: tabs.c プロジェクト: acklinr/vifm
/* Switches to pane tab specified by its index if the index is valid. */
static void
tabs_goto_pane(int idx)
{
	pane_tabs_t *const ptabs = get_pane_tabs(curr_view);

	if(ptabs->current == idx)
	{
		return;
	}

	if(idx < 0 || idx >= (int)DA_SIZE(ptabs->tabs))
	{
		return;
	}

	ptabs->tabs[ptabs->current].view = *curr_view;
	assign_preview(&ptabs->tabs[ptabs->current].preview, &curr_stats.preview);
	*curr_view = ptabs->tabs[idx].view;
	assign_preview(&curr_stats.preview, &ptabs->tabs[idx].preview);
	ptabs->current = idx;

	stats_set_quickview(curr_stats.preview.on);
	ui_view_schedule_redraw(curr_view);

	load_view_options(curr_view);

	(void)vifm_chdir(flist_get_dir(curr_view));
}
コード例 #3
0
ファイル: tabs.c プロジェクト: phantasea/vifm
/* Switches to global tab specified by its index if the index is valid. */
static void
tabs_goto_global(int idx)
{
	if(current_tab == idx)
	{
		return;
	}

	//add by sim1 +++++++++++++++++++++++++++++
	if(idx < 0)
	{
		idx = last_tab;
	}
	//add by sim1 -----------------------------

	if(idx < 0 || idx >= (int)DA_SIZE(gtabs))
	{
		return;
	}

	gtabs[current_tab].left.tabs[gtabs[current_tab].left.current].view = lwin;
	gtabs[current_tab].right.tabs[gtabs[current_tab].right.current].view = rwin;
	capture_global_state(&gtabs[current_tab]);
	assign_preview(&gtabs[current_tab].preview, &curr_stats.preview);

	lwin = gtabs[idx].left.tabs[gtabs[idx].left.current].view;
	rwin = gtabs[idx].right.tabs[gtabs[idx].right.current].view;
	if(gtabs[idx].active_pane != (curr_view == &rwin))
	{
		swap_view_roles();
	}
	curr_stats.number_of_windows = (gtabs[idx].only_mode ? 1 : 2);
	curr_stats.split = gtabs[idx].split;
	curr_stats.splitter_pos = gtabs[idx].splitter_pos;
	assign_preview(&curr_stats.preview, &gtabs[idx].preview);

	last_tab = current_tab;  //add by sim1
	current_tab = idx;

	stats_set_quickview(curr_stats.preview.on);
	ui_view_schedule_redraw(&lwin);
	ui_view_schedule_redraw(&rwin);

	load_view_options(curr_view);

	(void)vifm_chdir(flist_get_dir(curr_view));
}
コード例 #4
0
ファイル: tabs.c プロジェクト: phantasea/vifm
/* Switches to pane tab specified by its index if the index is valid. */
static void
tabs_goto_pane(int idx)
{
	pane_tabs_t *const ptabs = get_pane_tabs(curr_view);

	if(ptabs->current == idx)
	{
		return;
	}

	//add by sim1 +++++++++++++++++++++++++++++++++++
	if(idx < 0)
	{
		idx = ptabs->last;
		if (idx == ptabs->current)
		{
			return;
		}
	}
	//add by sim1 -----------------------------------

	if(idx < 0 || idx >= (int)DA_SIZE(ptabs->tabs))
	{
		return;
	}

	ptabs->tabs[ptabs->current].view = *curr_view;
	assign_preview(&ptabs->tabs[ptabs->current].preview, &curr_stats.preview);
	*curr_view = ptabs->tabs[idx].view;
	assign_preview(&curr_stats.preview, &ptabs->tabs[idx].preview);

	ptabs->last = ptabs->current;  //add by sim1
	ptabs->current = idx;

	stats_set_quickview(curr_stats.preview.on);
	ui_view_schedule_redraw(curr_view);

	load_view_options(curr_view);

	(void)vifm_chdir(flist_get_dir(curr_view));

	//add by sim1 for test
	//ui_sb_msgf("tabs_goto_pane: curr=%d, last=%d, tabs=%d", ptabs->current, ptabs->last, (int)DA_SIZE(ptabs->tabs));
}
コード例 #5
0
int
goto_search_match(FileView *view, int backward)
{
	const int wrap_start = backward ? view->list_rows : -1;
	if(!find_and_goto_match(view, view->list_pos, backward))
	{
		if(!cfg.wrap_scan || !find_and_goto_match(view, wrap_start, backward))
		{
			return 0;
		}
	}

	/* Redraw the cursor which also might synchronize cursors of two views. */
	fview_cursor_redraw(view);
	/* Schedule redraw of the view to highlight search matches. */
	ui_view_schedule_redraw(view);

	return 1;
}
コード例 #6
0
int
compare_two_panes(CompareType ct, ListType lt, int group_paths, int skip_empty)
{
	int next_id = 1;
	entries_t curr, other;

	trie_t *const trie = trie_create();
	ui_cancellation_reset();
	ui_cancellation_enable();

	curr = make_diff_list(trie, curr_view, &next_id, ct, skip_empty, 0);
	other = make_diff_list(trie, other_view, &next_id, ct, skip_empty,
			lt == LT_DUPS);

	ui_cancellation_disable();
	trie_free_with_data(trie, &free_compare_records);

	/* Clear progress message displayed by make_diff_list(). */
	ui_sb_quick_msg_clear();

	if(ui_cancellation_requested())
	{
		free_dir_entries(curr_view, &curr.entries, &curr.nentries);
		free_dir_entries(other_view, &other.entries, &other.nentries);
		status_bar_message("Comparison has been cancelled");
		return 1;
	}

	if(!group_paths || lt != LT_ALL)
	{
		/* Sort both lists according to unique file numbers to group identical files
		 * (sorting is stable, tags are set in make_diff_list()). */
		qsort(curr.entries, curr.nentries, sizeof(*curr.entries), &id_sorter);
		qsort(other.entries, other.nentries, sizeof(*other.entries), &id_sorter);
	}

	if(lt == LT_UNIQUE)
	{
		make_unique_lists(curr, other);
		return 0;
	}

	if(lt == LT_DUPS)
	{
		leave_only_dups(&curr, &other);
	}

	flist_custom_start(curr_view, lt == LT_ALL ? "diff" : "dups diff");
	flist_custom_start(other_view, lt == LT_ALL ? "diff" : "dups diff");

	fill_side_by_side(curr, other, group_paths);

	if(flist_custom_finish(curr_view, CV_DIFF, 0) != 0)
	{
		show_error_msg("Comparison", "No results to display");
		return 0;
	}
	if(flist_custom_finish(other_view, CV_DIFF, 0) != 0)
	{
		assert(0 && "The error shouldn't be happening here.");
	}

	curr_view->list_pos = 0;
	other_view->list_pos = 0;
	curr_view->custom.diff_cmp_type = ct;
	other_view->custom.diff_cmp_type = ct;
	curr_view->custom.diff_path_group = group_paths;
	other_view->custom.diff_path_group = group_paths;

	assert(curr_view->list_rows == other_view->list_rows &&
			"Diff views must be in sync!");

	ui_view_schedule_redraw(curr_view);
	ui_view_schedule_redraw(other_view);
	return 0;
}
コード例 #7
0
int
compare_one_pane(FileView *view, CompareType ct, ListType lt, int skip_empty)
{
	int i, dup_id;
	FileView *other = (view == curr_view) ? other_view : curr_view;
	const char *const title = (lt == LT_ALL)  ? "compare"
	                        : (lt == LT_DUPS) ? "dups" : "nondups";

	int next_id = 1;
	entries_t curr;

	trie_t *trie = trie_create();
	ui_cancellation_reset();
	ui_cancellation_enable();

	curr = make_diff_list(trie, view, &next_id, ct, skip_empty, 0);

	ui_cancellation_disable();
	trie_free_with_data(trie, &free_compare_records);

	/* Clear progress message displayed by make_diff_list(). */
	ui_sb_quick_msg_clear();

	if(ui_cancellation_requested())
	{
		free_dir_entries(view, &curr.entries, &curr.nentries);
		status_bar_message("Comparison has been cancelled");
		return 1;
	}

	qsort(curr.entries, curr.nentries, sizeof(*curr.entries), &id_sorter);

	flist_custom_start(view, title);

	dup_id = -1;
	next_id = 0;
	for(i = 0; i < curr.nentries; ++i)
	{
		dir_entry_t *entry = &curr.entries[i];

		if(lt == LT_ALL)
		{
			flist_custom_put(view, entry);
			continue;
		}

		if(entry->id == dup_id)
		{
			put_or_free(view, entry, next_id, lt == LT_DUPS);
			continue;
		}

		dup_id = (i < curr.nentries - 1 && entry[0].id == entry[1].id)
		       ? entry->id
		       : -1;

		if(entry->id == dup_id)
		{
			put_or_free(view, entry, ++next_id, lt == LT_DUPS);
			continue;
		}

		put_or_free(view, entry, next_id, lt == LT_UNIQUE);
	}

	/* Entries' data has been moved out of them or freed, so need to free only the
	 * list. */
	dynarray_free(curr.entries);

	if(flist_custom_finish(view, lt == LT_UNIQUE ? CV_REGULAR : CV_COMPARE,
				0) != 0)
	{
		show_error_msg("Comparison", "No results to display");
		return 0;
	}

	/* Leave the other pane, if it's in the CV_DIFF mode, two panes are needed for
	 * this. */
	if(other->custom.type == CV_DIFF)
	{
		cd_updir(other, 1);
	}

	view->list_pos = 0;
	ui_view_schedule_redraw(view);
	return 0;
}
コード例 #8
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;
	}
}
コード例 #9
0
ファイル: filtering.c プロジェクト: vifm/vifm
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);
}