/* 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; }
/* Checks if file specified can be displayed. Used to filter some files, that * are hidden intentionally. Returns non-zero if file can be made visible. */ static int file_can_be_displayed(const char directory[], const char filename[]) { if(is_parent_dir(filename)) { return cfg_parent_dir_is_visible(is_root_dir(directory)); } return path_exists_at(directory, filename, DEREF); }
void open_dir(FileView *view) { char full_path[PATH_MAX]; const char *filename; filename = get_current_file_name(view); if(is_parent_dir(filename)) { cd_updir(view, 1); return; } get_current_full_path(view, sizeof(full_path), full_path); if(cd_is_possible(full_path)) { navigate_to(view, full_path); } }
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; } }
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; } }
static int sort_dir_list(const void *one, const void *two) { int retval; char *pfirst, *psecond; dir_entry_t *const first = (dir_entry_t *)one; dir_entry_t *const second = (dir_entry_t *)two; int first_is_dir; int second_is_dir; int dirs; if(is_parent_dir(first->name)) { return -1; } else if(is_parent_dir(second->name)) { return 1; } first_is_dir = is_directory_entry(first); second_is_dir = is_directory_entry(second); dirs = first_is_dir || second_is_dir; retval = 0; switch(sort_type) { case SORT_BY_NAME: case SORT_BY_INAME: if(first->name[0] == '.' && second->name[0] != '.') retval = -1; else if(first->name[0] != '.' && second->name[0] == '.') retval = 1; else retval = compare_file_names(dirs, first->name, second->name, sort_type == SORT_BY_INAME); break; case SORT_BY_TYPE: if(first_is_dir != second_is_dir) { retval = first_is_dir ? -1 : 1; } break; case SORT_BY_EXTENSION: pfirst = strrchr(first->name, '.'); psecond = strrchr(second->name, '.'); if(pfirst && psecond) retval = compare_file_names(dirs, ++pfirst, ++psecond, 0); else if(pfirst || psecond) retval = pfirst ? -1 : 1; else retval = compare_file_names(dirs, first->name, second->name, 0); break; case SORT_BY_SIZE: { if(first_is_dir) tree_get_data(curr_stats.dirsize_cache, first->name, &first->size); if(second_is_dir) tree_get_data(curr_stats.dirsize_cache, second->name, &second->size); retval = (first->size < second->size) ? -1 : (first->size > second->size); } break; case SORT_BY_TIME_MODIFIED: retval = first->mtime - second->mtime; break; case SORT_BY_TIME_ACCESSED: retval = first->atime - second->atime; break; case SORT_BY_TIME_CHANGED: retval = first->ctime - second->ctime; break; #ifndef _WIN32 case SORT_BY_MODE: retval = first->mode - second->mode; break; case SORT_BY_OWNER_NAME: /* FIXME */ case SORT_BY_OWNER_ID: retval = first->uid - second->uid; break; case SORT_BY_GROUP_NAME: /* FIXME */ case SORT_BY_GROUP_ID: retval = first->gid - second->gid; break; case SORT_BY_PERMISSIONS: { char first_perm[11], second_perm[11]; get_perm_string(first_perm, sizeof(first_perm), first->mode); get_perm_string(second_perm, sizeof(second_perm), second->mode); retval = strcmp(first_perm, second_perm); } break; #endif default: assert(0 && "All possible sort options should be handled"); break; } if(retval == 0) { retval = first->list_num - second->list_num; } else if(sort_descending) { retval = -retval; } return retval; }
/* 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; }
static int sort_dir_list(const void *one, const void *two) { int retval; char *pfirst, *psecond; dir_entry_t *const first = (dir_entry_t *)one; dir_entry_t *const second = (dir_entry_t *)two; int first_is_dir; int second_is_dir; if(is_parent_dir(first->name)) { return -1; } else if(is_parent_dir(second->name)) { return 1; } first_is_dir = is_directory_entry(first); second_is_dir = is_directory_entry(second); retval = 0; switch(sort_type) { case SK_BY_NAME: case SK_BY_INAME: if(custom_view) { retval = compare_entry_names(first, second, sort_type == SK_BY_INAME); } else { retval = compare_full_file_names(first->name, second->name, sort_type == SK_BY_INAME); } break; case SK_BY_DIR: if(first_is_dir != second_is_dir) { retval = first_is_dir ? -1 : 1; } break; case SK_BY_TYPE: retval = strcmp(get_type_str(first->type), get_type_str(second->type)); break; case SK_BY_FILEEXT: case SK_BY_EXTENSION: pfirst = strrchr(first->name, '.'); psecond = strrchr(second->name, '.'); if(first_is_dir && second_is_dir && sort_type == SK_BY_FILEEXT) { retval = compare_file_names(first->name, second->name, 0); } else if(first_is_dir != second_is_dir && sort_type == SK_BY_FILEEXT) { retval = first_is_dir ? -1 : 1; } else if(pfirst && psecond) { if(pfirst == first->name && psecond != second->name) { retval = -1; } else if(pfirst != first->name && psecond == second->name) { retval = 1; } else { retval = compare_file_names(++pfirst, ++psecond, 0); } } else if(pfirst || psecond) retval = pfirst ? -1 : 1; else retval = compare_file_names(first->name, second->name, 0); break; case SK_BY_SIZE: { if(first_is_dir) { char full_path[PATH_MAX]; get_full_path_of(first, sizeof(full_path), full_path); tree_get_data(curr_stats.dirsize_cache, full_path, &first->size); } if(second_is_dir) { char full_path[PATH_MAX]; get_full_path_of(second, sizeof(full_path), full_path); tree_get_data(curr_stats.dirsize_cache, full_path, &second->size); } retval = (first->size < second->size) ? -1 : (first->size > second->size); } break; case SK_BY_TIME_MODIFIED: retval = first->mtime - second->mtime; break; case SK_BY_TIME_ACCESSED: retval = first->atime - second->atime; break; case SK_BY_TIME_CHANGED: retval = first->ctime - second->ctime; break; #ifndef _WIN32 case SK_BY_MODE: retval = first->mode - second->mode; break; case SK_BY_OWNER_NAME: /* FIXME */ case SK_BY_OWNER_ID: retval = first->uid - second->uid; break; case SK_BY_GROUP_NAME: /* FIXME */ case SK_BY_GROUP_ID: retval = first->gid - second->gid; break; case SK_BY_PERMISSIONS: { char first_perm[11], second_perm[11]; get_perm_string(first_perm, sizeof(first_perm), first->mode); get_perm_string(second_perm, sizeof(second_perm), second->mode); retval = strcmp(first_perm, second_perm); } break; #endif } if(retval == 0) { retval = first->list_num - second->list_num; } else if(sort_descending) { retval = -retval; } return retval; }
static int sort_dir_list(const void *one, const void *two) { /* TODO: refactor this function sort_dir_list(). */ int retval; const dir_entry_t *const first = one; const dir_entry_t *const second = two; const int first_is_dir = fentry_is_dir(first); const int second_is_dir = fentry_is_dir(second); if(first_is_dir && is_parent_dir(first->name)) { return -1; } if(second_is_dir && is_parent_dir(second->name)) { return 1; } retval = 0; switch(sort_type) { char *pfirst, *psecond; case SK_BY_NAME: case SK_BY_INAME: if(custom_view) { retval = compare_entry_names(first, second, sort_type == SK_BY_INAME); } else { retval = compare_full_file_names(first->name, second->name, sort_type == SK_BY_INAME); } break; case SK_BY_DIR: if(first_is_dir != second_is_dir) { retval = first_is_dir ? -1 : 1; } break; case SK_BY_TYPE: retval = strcmp(get_type_str(first->type), get_type_str(second->type)); break; case SK_BY_FILEEXT: case SK_BY_EXTENSION: pfirst = strrchr(first->name, '.'); psecond = strrchr(second->name, '.'); if(first_is_dir && second_is_dir && sort_type == SK_BY_FILEEXT) { retval = compare_file_names(first->name, second->name, 0); } else if(first_is_dir != second_is_dir && sort_type == SK_BY_FILEEXT) { retval = first_is_dir ? -1 : 1; } else if(pfirst && psecond) { if(pfirst == first->name && psecond != second->name) { retval = -1; } else if(pfirst != first->name && psecond == second->name) { retval = 1; } else { retval = compare_file_names(++pfirst, ++psecond, 0); } } else if(pfirst || psecond) retval = pfirst ? -1 : 1; else retval = compare_file_names(first->name, second->name, 0); break; case SK_BY_SIZE: retval = compare_file_sizes(first, second); break; case SK_BY_NITEMS: retval = compare_item_count(first, first_is_dir, second, second_is_dir); break; case SK_BY_GROUPS: retval = compare_group(first->name, second->name, sort_data); break; case SK_BY_TARGET: retval = compare_targets(first, second); break; case SK_BY_TIME_MODIFIED: retval = first->mtime - second->mtime; break; case SK_BY_TIME_ACCESSED: retval = first->atime - second->atime; break; case SK_BY_TIME_CHANGED: retval = first->ctime - second->ctime; break; #ifndef _WIN32 case SK_BY_MODE: retval = first->mode - second->mode; break; case SK_BY_INODE: retval = first->inode - second->inode; break; case SK_BY_OWNER_NAME: /* FIXME */ case SK_BY_OWNER_ID: retval = first->uid - second->uid; break; case SK_BY_GROUP_NAME: /* FIXME */ case SK_BY_GROUP_ID: retval = first->gid - second->gid; break; case SK_BY_PERMISSIONS: { char first_perm[11], second_perm[11]; get_perm_string(first_perm, sizeof(first_perm), first->mode); get_perm_string(second_perm, sizeof(second_perm), second->mode); retval = strcmp(first_perm, second_perm); } break; case SK_BY_NLINKS: retval = first->nlinks - second->nlinks; break; #endif } if(retval == 0) { retval = first->tag - second->tag; } else if(sort_descending) { retval = -retval; } return retval; }