void tabs_only(view_t *view) { if(cfg.pane_tabs) { pane_tabs_t *const ptabs = get_pane_tabs(curr_view); while(DA_SIZE(ptabs->tabs) != 1U) { pane_tab_t *const ptab = &ptabs->tabs[ptabs->current == 0 ? 1 : 0]; ptabs->current -= (ptabs->current == 0 ? 0 : 1); free_pane_tab(ptab); DA_REMOVE(ptabs->tabs, ptab); } } else { while(DA_SIZE(gtabs) != 1U) { global_tab_t *const gtab = >abs[current_tab == 0 ? 1 : 0]; current_tab -= (current_tab == 0 ? 0 : 1); free_global_tab(gtab); DA_REMOVE(gtabs, gtab); } } }
/* Creates new tab with the specified name, which might be NULL. Returns newly * created tab on success or NULL on error. */ static pane_tab_t * tabs_new_pane(pane_tabs_t *ptabs, view_t *view, const char name[]) { pane_tab_t new_tab = {}; if(DA_EXTEND(ptabs->tabs) == NULL) { return NULL; } DA_COMMIT(ptabs->tabs); /* We're called from tabs_init() and just need to create internal structures * without cloning data (or it will leak). */ if(DA_SIZE(gtabs) == 0U) { ptabs->tabs[0] = new_tab; return &ptabs->tabs[0]; } clone_view(&new_tab.view, view); update_string(&new_tab.name, name); if(DA_SIZE(ptabs->tabs) == 1U) { ptabs->tabs[0] = new_tab; return &ptabs->tabs[0]; } memmove(ptabs->tabs + ptabs->current + 2, ptabs->tabs + ptabs->current + 1, sizeof(*ptabs->tabs)*(DA_SIZE(ptabs->tabs) - (ptabs->current + 2))); ptabs->tabs[ptabs->current + 1] = new_tab; return &ptabs->tabs[ptabs->current + 1]; }
/* Creates new global tab with the specified name, which might be NULL. Returns * zero on success, otherwise non-zero is returned. */ static int tabs_new_global(const char name[]) { global_tab_t new_tab = {}; if(DA_EXTEND(gtabs) == NULL) { return 1; } if(tabs_new_pane(&new_tab.left, &lwin, NULL) == NULL || tabs_new_pane(&new_tab.right, &rwin, NULL) == NULL) { free_global_tab(&new_tab); return 1; } update_string(&new_tab.name, name); capture_global_state(&new_tab); new_tab.preview.on = curr_stats.preview.on; DA_COMMIT(gtabs); /* We're called from tabs_init(). */ if(DA_SIZE(gtabs) == 1U) { gtabs[0U] = new_tab; return 0; } memmove(gtabs + current_tab + 2, gtabs + current_tab + 1, sizeof(*gtabs)*(DA_SIZE(gtabs) - (current_tab + 2))); gtabs[current_tab + 1] = new_tab; tabs_goto(current_tab + 1); return 0; }
int tabs_count(const view_t *view) { if(cfg.pane_tabs) { pane_tabs_t *const ptabs = get_pane_tabs(view); return (int)DA_SIZE(ptabs->tabs); } return (int)DA_SIZE(gtabs); }
void tabs_next(int n) { if(cfg.pane_tabs) { pane_tabs_t *const ptabs = get_pane_tabs(curr_view); const int count = (int)DA_SIZE(ptabs->tabs); tabs_goto((ptabs->current + n)%count); } else { tabs_goto((current_tab + 1)%(int)DA_SIZE(gtabs)); } }
void tabs_previous(int n) { if(cfg.pane_tabs) { pane_tabs_t *const ptabs = get_pane_tabs(curr_view); const int count = (int)DA_SIZE(ptabs->tabs); tabs_goto((ptabs->current + count - n)%count); } else { const int count = DA_SIZE(gtabs); tabs_goto((current_tab + count - n)%count); } }
void vle_aucmd_list(const char event[], const char patterns[], vle_aucmd_list_cb cb, void *arg) { size_t i; int len; char **pats = get_patterns(patterns, &len); for(i = 0U; i < DA_SIZE(autocmds); ++i) { char pat[1U + strlen(autocmds[i].pattern) + 1U]; copy_str(&pat[1], sizeof(pat) - 1U, autocmds[i].pattern); pat[0] = autocmds[i].negated ? '!' : '='; if(event != NULL && strcasecmp(event, autocmds[i].event) != 0) { continue; } if(patterns != NULL && !is_in_string_array(pats, len, pat)) { continue; } cb(autocmds[i].event, autocmds[i].pattern, autocmds[i].negated, autocmds[i].action, arg); } free_string_array(pats, len); }
void vle_aucmd_remove(const char event[], const char patterns[]) { int i; int len; char **pats = get_patterns(patterns, &len); for(i = (int)DA_SIZE(autocmds) - 1; i >= 0; --i) { char pat[1U + strlen(autocmds[i].pattern) + 1U]; copy_str(&pat[1], sizeof(pat) - 1U, autocmds[i].pattern); pat[0] = autocmds[i].negated ? '!' : '='; if(event != NULL && strcasecmp(event, autocmds[i].event) != 0) { continue; } if(patterns != NULL && !is_in_string_array(pats, len, pat)) { continue; } free_autocmd_data(&autocmds[i]); DA_REMOVE(autocmds, &autocmds[i]); } free_string_array(pats, len); }
/* 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)); }
/* Frees resources owned by a collection of pane tabs. */ static void free_pane_tabs(pane_tabs_t *ptabs) { size_t i; for(i = 0U; i < DA_SIZE(ptabs->tabs); ++i) { free_pane_tab(&ptabs->tabs[i]); } DA_REMOVE_ALL(ptabs->tabs); }
void tabs_close(void) { // XXX: FUSE filesystems aren't exited this way, but this might be OK because // usually we exit from them on explicit ".." by a user. if(cfg.pane_tabs) { pane_tabs_t *const ptabs = get_pane_tabs(curr_view); pane_tab_t *const ptab = &ptabs->tabs[ptabs->current]; const int n = (int)DA_SIZE(ptabs->tabs); if(n != 1) { tabs_goto(ptabs->current + (ptabs->current == n - 1 ? -1 : +1)); if(ptabs->current > ptab - ptabs->tabs) { --ptabs->current; } free_pane_tab(ptab); DA_REMOVE(ptabs->tabs, ptab); } //add by sim1 for test //ui_sb_msgf("tabs_close: curr=%d, last=%d, tabs=%d", ptabs->current, ptabs->last, (int)DA_SIZE(ptabs->tabs)); } else { global_tab_t *const gtab = >abs[current_tab]; const int n = (int)DA_SIZE(gtabs); if(n != 1) { tabs_goto(current_tab == n - 1 ? current_tab - 1 : current_tab + 1); if(current_tab > gtab - gtabs) { --current_tab; } free_global_tab(gtab); DA_REMOVE(gtabs, gtab); } } }
int tabs_get(view_t *view, int idx, tab_info_t *tab_info) { if(cfg.pane_tabs) { pane_tabs_t *const ptabs = get_pane_tabs(view); const int n = (int)DA_SIZE(ptabs->tabs); if(idx < 0 || idx >= n) { return 0; } tab_info->view = (idx == ptabs->current ? view : &ptabs->tabs[idx].view); tab_info->name = ptabs->tabs[idx].name; tab_info->last = (idx == n - 1); return 1; } else { global_tab_t *gtab; const int n = (int)DA_SIZE(gtabs); if(idx < 0 || idx >= n) { return 0; } gtab = >abs[idx]; tab_info->name = gtab->name; tab_info->last = (idx == n - 1); if(idx == current_tab) { tab_info->view = view; return 1; } tab_info->view = gtab->active_pane ? >ab->right.tabs[gtab->right.current].view : >ab->left.tabs[gtab->left.current].view; return 1; } }
int tabs_visitor_count(const char path[]) { int count = 0; int i; for(i = 0; i < (int)DA_SIZE(gtabs); ++i) { global_tab_t *const gtab = >abs[i]; view_t *const lview = (i == current_tab ? &lwin : NULL); view_t *const rview = (i == current_tab ? &rwin : NULL); count += count_pane_visitors(>ab->left, path, lview); count += count_pane_visitors(>ab->right, path, rview); } return count; }
/* 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)); }
/* Fixes data fields of views after they got moved from one pane to another. The * view parameter indicates destination pane. */ static void normalize_pane_tabs(const pane_tabs_t *ptabs, view_t *view) { view_t tmp = *view; view_t *const other = (view == &rwin ? &lwin : &rwin); int i; for(i = 0; i < (int)DA_SIZE(ptabs->tabs); ++i) { if(i != ptabs->current) { view_t *const v = &ptabs->tabs[i].view; ui_swap_view_data(v, &tmp); *v = tmp; flist_update_origins(v, &other->curr_dir[0], &view->curr_dir[0]); } } }
/* 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)); }
/* Counts number of pane tabs from the collection that are inside specified * path. When view parameter isn't NULL, it's a possible replacement view to * use instead of the stored one. Returns the count. */ static int count_pane_visitors(const pane_tabs_t *ptabs, const char path[], const view_t *view) { int count = 0; int i; for(i = 0; i < (int)DA_SIZE(ptabs->tabs); ++i) { const pane_tab_t *const ptab = &ptabs->tabs[i]; const view_t *const v = (view != NULL && i == ptabs->current) ? view : &ptab->view; if(path_starts_with(v->curr_dir, path)) { ++count; } } return count; }
int tabs_get(view_t *view, int idx, tab_info_t *tab_info) { if(cfg.pane_tabs) { pane_tabs_t *const ptabs = get_pane_tabs(view); const int n = (int)DA_SIZE(ptabs->tabs); if(idx < 0 || idx >= n) { return 0; } tab_info->view = (idx == ptabs->current ? view : &ptabs->tabs[idx].view); tab_info->name = ptabs->tabs[idx].name; tab_info->last = (idx == n - 1); return 1; } return get_global_tab(view, idx, tab_info, 1); }
void vle_aucmd_execute(const char event[], const char path[], void *arg) { size_t i; char canonic_path[PATH_MAX]; canonicalize_path(path, canonic_path, sizeof(canonic_path)); if(!is_root_dir(canonic_path)) { chosp(canonic_path); } for(i = 0U; i < DA_SIZE(autocmds); ++i) { if(strcasecmp(event, autocmds[i].event) == 0 && is_pattern_match(&autocmds[i], canonic_path)) { autocmds[i].handler(autocmds[i].action, arg); } } }
/* Fills *tab_info for the global tab specified by its index and side (view * parameter) when return_active is zero, otherwise active one is used. Returns * non-zero on success, otherwise zero is returned. */ static int get_global_tab(view_t *view, int idx, tab_info_t *tab_info, int return_active) { const int n = (int)DA_SIZE(gtabs); if(idx < 0 || idx >= n) { return 0; } global_tab_t *gtab = >abs[idx]; tab_info->name = gtab->name; tab_info->last = (idx == n - 1); if(idx == current_tab) { tab_info->view = view; return 1; } tab_info->view = (return_active && !gtab->active_pane) || (!return_active && view == &lwin) ? >ab->left.tabs[gtab->left.current].view : >ab->right.tabs[gtab->right.current].view; return 1; }