static int search_menu_backwards(menu_info *m, int start_pos) { int match_up = -1; int match_down = -1; int x; for(x = m->len - 1; x > -1; x--) { if(!m->matches[x]) continue; if(match_up < 0) { if(x <= start_pos) match_up = x; } if(match_down < 0) { if(x > start_pos) match_down = x; } } if(match_up > -1 || match_down > -1) { int pos; if(!cfg.wrap_scan && match_up <= -1) { status_bar_errorf("Search hit TOP without match for: %s", m->regexp); return 1; } pos = (match_up > -1) ? match_up : match_down; clean_menu_position(m); move_to_menu_pos(pos, m); status_bar_messagef("%d %s", m->matching_entries, (m->matching_entries == 1) ? "match" : "matches"); } else { move_to_menu_pos(m->pos, m); if(!cfg.wrap_scan) status_bar_errorf("Search hit TOP without match for: %s", m->regexp); else status_bar_errorf("No matches for: %s", m->regexp); return 1; } return 0; }
/* Restores current item from the trash. */ static KHandlerResponse restore_current(menu_data_t *m) { char *trash_path; int err; cmd_group_begin("restore: "); cmd_group_end(); /* The string is freed in restore_from_trash(), thus must be cloned. */ trash_path = strdup(trash_list[m->pos].trash_name); err = restore_from_trash(trash_path); free(trash_path); if(err != 0) { const char *const orig_path = m->items[m->pos]; status_bar_errorf("Failed to restore %s", orig_path); curr_stats.save_msg = 1; return KHR_UNHANDLED; } remove_current_item(m->state); return KHR_REFRESH_WINDOW; }
int find_vwpattern(const char *pattern, int backward) { int err; if(pattern == NULL) return 0; if(vi->last_search_backward != -1) regfree(&vi->re); vi->last_search_backward = -1; if((err = regcomp(&vi->re, pattern, get_regexp_cflags(pattern))) != 0) { status_bar_errorf("Invalid pattern: %s", get_regexp_error(err, &vi->re)); regfree(&vi->re); draw(); return 1; } vi->last_search_backward = backward; search(vi->search_repeat, backward); return curr_stats.save_msg; }
/* Looks for next matching element in backward direction from current position. * Returns new value for save_msg flag. */ static int search_menu_backwards(menu_state_t *m, int start_pos) { int match_up = -1; int match_down = -1; int i; for(i = m->d->len - 1; i > -1; --i) { if(m->matches[i][0] < 0) { continue; } if(match_up < 0 && i <= start_pos) { match_up = i; } if(match_down < 0 && i > start_pos) { match_down = i; } } if(!cfg.wrap_scan && match_up <= -1) { status_bar_errorf("Search hit TOP without match for: %s", m->regexp); return 1; } return navigate_to_match(m, (match_up > -1) ? match_up : match_down); }
/* Looks for next matching element in forward direction from current position. * Returns new value for save_msg flag. */ static int search_menu_forwards(menu_state_t *m, int start_pos) { int match_up = -1; int match_down = -1; int i; for(i = 0; i < m->d->len; ++i) { if(m->matches[i][0] < 0) { continue; } if(match_up < 0 && i < start_pos) { match_up = i; } if(match_down < 0 && i >= start_pos) { match_down = i; } } if(!cfg.wrap_scan && match_down <= -1) { status_bar_errorf("Search hit BOTTOM without match for: %s", m->regexp); return 1; } return navigate_to_match(m, (match_down > -1) ? match_down : match_up); }
static int resolve_mark(char mark) { int result; result = check_mark_directory(curr_view, mark); if(result < 0) status_bar_errorf("Trying to use an invalid mark: '%c", mark); return result; }
void print_search_fail_msg(const FileView *view, int backward) { const char *const regexp = cfg_get_last_search_pattern(); int cflags; regex_t re; int err; if(regexp[0] == '\0') { status_bar_message(""); return; } cflags = get_regexp_cflags(regexp); err = regcomp(&re, regexp, cflags); if(err != 0) { status_bar_errorf("Regexp (%s) error: %s", regexp, get_regexp_error(err, &re)); regfree(&re); return; } regfree(&re); if(cfg.wrap_scan) { status_bar_errorf("No matching files for: %s", regexp); } else if(backward) { status_bar_errorf("Search hit TOP without match for: %s", regexp); } else { status_bar_errorf("Search hit BOTTOM without match for: %s", regexp); } }
void setup_user_bookmark(const char mark, const char directory[], const char file[], time_t timestamp) { if(is_user_bookmark(mark)) { set_mark(mark, directory, file, timestamp, 1); } else { status_bar_errorf("Only user's bookmarks can be loaded, but got: %c", mark); } }
void menu_print_search_msg(const menu_state_t *m) { int cflags; regex_t re; int err; /* Can be NULL after regex compilation failure. */ if(m->regexp == NULL) { return; } cflags = get_regexp_cflags(m->regexp); err = regcomp(&re, m->regexp, cflags); if(err != 0) { status_bar_errorf("Regexp (%s) error: %s", m->regexp, get_regexp_error(err, &re)); regfree(&re); return; } regfree(&re); if(m->matching_entries > 0) { status_bar_messagef("%d of %d %s", get_match_index(m), m->matching_entries, (m->matching_entries == 1) ? "match" : "matches"); } else { status_bar_errorf("No matches for: %s", m->regexp); } }
/* Goes through all menu items and marks those that match search pattern. * Returns non-zero on error. */ static int search_menu(menu_state_t *ms, int start_pos, int print_errors) { menu_data_t *const m = ms->d; int cflags; regex_t re; int err; int i; if(ms->matches == NULL) { ms->matches = reallocarray(NULL, m->len, sizeof(*ms->matches)); } memset(ms->matches, -1, 2*sizeof(**ms->matches)*m->len); ms->matching_entries = 0; if(ms->regexp[0] == '\0') { return 0; } cflags = get_regexp_cflags(ms->regexp); err = regcomp(&re, ms->regexp, cflags); if(err != 0) { if(print_errors) { status_bar_errorf("Regexp error: %s", get_regexp_error(err, &re)); } regfree(&re); return -1; } for(i = 0; i < m->len; ++i) { regmatch_t matches[1]; if(regexec(&re, m->items[i], 1, matches, 0) == 0) { ms->matches[i][0] = matches[0].rm_so; ms->matches[i][1] = matches[0].rm_eo; ++ms->matching_entries; } } regfree(&re); return 0; }
/* Returns non-zero on error */ static int search_menu(menu_info *m, int start_pos) { int cflags; regex_t re; int err; if(m->matches == NULL) m->matches = malloc(sizeof(int)*m->len); memset(m->matches, 0, sizeof(int)*m->len); if(m->regexp[0] == '\0') return 0; cflags = get_regexp_cflags(m->regexp); if((err = regcomp(&re, m->regexp, cflags)) == 0) { int x; m->matching_entries = 0; for(x = 0; x < m->len; x++) { if(regexec(&re, m->items[x], 0, NULL, 0) != 0) continue; m->matches[x] = 1; m->matching_entries++; } regfree(&re); return 0; } else { status_bar_errorf("Regexp error: %s", get_regexp_error(err, &re)); regfree(&re); return -1; } }
int run_ext_command(const char cmd[], MacroFlags flags, int bg, int *save_msg) { if(bg && flags != MF_NONE && flags != MF_NO_TERM_MUX && flags != MF_IGNORE) { status_bar_errorf("\"%s\" macro can't be combined with \" &\"", macros_to_str(flags)); *save_msg = 1; return -1; } if(flags == MF_STATUSBAR_OUTPUT) { output_to_statusbar(cmd); *save_msg = 1; return -1; } else if(flags == MF_IGNORE) { *save_msg = 0; if(bg) { int error; setup_shellout_env(); error = (start_background_job(cmd, 1) != 0); cleanup_shellout_env(); if(error) { status_bar_errorf("Failed to start in bg: %s", cmd); *save_msg = 1; } } else { output_to_nowhere(cmd); } return -1; } else if(flags == MF_MENU_OUTPUT || flags == MF_MENU_NAV_OUTPUT) { const int navigate = flags == MF_MENU_NAV_OUTPUT; setup_shellout_env(); *save_msg = show_user_menu(curr_view, cmd, navigate) != 0; cleanup_shellout_env(); } else if(flags == MF_SPLIT && curr_stats.term_multiplexer != TM_NONE) { run_in_split(curr_view, cmd); } else if(flags == MF_CUSTOMVIEW_OUTPUT || flags == MF_VERYCUSTOMVIEW_OUTPUT) { const int very = flags == MF_VERYCUSTOMVIEW_OUTPUT; output_to_custom_flist(curr_view, cmd, very); } else { return 0; } return 1; }
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; } }
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; } }