/* 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); }
/* 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)); }
/* 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(>abs[current_tab]); assign_preview(>abs[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, >abs[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)); }
/* 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)); }
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; }
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; }
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; }
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; } }
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); }