int init_status(config_t *config) { inside_screen = !is_null_or_empty(env_get(SCREEN_ENVVAR)); inside_tmux = !is_null_or_empty(env_get(TMUX_ENVVAR)); load_def_values(&curr_stats, config); determine_fuse_umount_cmd(&curr_stats); set_gtk_available(&curr_stats); curr_stats.exec_env_type = get_exec_env_type(); stats_update_shell_type(config->shell); return reset_status(config); }
int vim_write_file_list(const FileView *view, int nfiles, char *files[]) { FILE *fp; const char *const files_out = curr_stats.chosen_files_out; if(is_null_or_empty(files_out)) { return 0; } if(strcmp(files_out, "-") == 0) { dump_filenames(view, curr_stats.original_stdout, nfiles, files); return 0; } fp = os_fopen(files_out, "w"); if(fp == NULL) { LOG_SERROR_MSG(errno, "Can't open file for writing: \"%s\"", files_out); return 1; } dump_filenames(view, fp, nfiles, files); fclose(fp); return 0; }
void vim_write_dir(const char path[]) { /* TODO: move this and other non-Vim related code to extern.c unit. */ FILE *fp; const char *const dir_out = curr_stats.chosen_dir_out; if(is_null_or_empty(dir_out)) { return; } if(strcmp(dir_out, "-") == 0) { fputs(path, curr_stats.original_stdout); return; } fp = os_fopen(dir_out, "w"); if(fp == NULL) { LOG_SERROR_MSG(errno, "Can't open file for writing: \"%s\"", dir_out); return; } fputs(path, fp); fclose(fp); }
/* Tries to use $XDG_CONFIG_HOME/vifm as configuration directory. Returns * non-zero on success, otherwise zero is returned. */ static int try_xdg_for_conf(void) { LOG_FUNC_ENTER; char *config_dir; const char *const config_home = env_get("XDG_CONFIG_HOME"); if(!is_null_or_empty(config_home) && is_path_absolute(config_home)) { config_dir = format_str("%s/vifm", config_home); } else if(path_exists_at(env_get(HOME_EV), ".config", DEREF)) { config_dir = format_str("%s/.config/vifm", env_get(HOME_EV)); } else { return 0; } env_set(VIFM_EV, config_dir); free(config_dir); return 1; }
void cfg_load(void) { const char *rc; const int prev_global_local_settings = curr_stats.global_local_settings; /* Make changes of usually local settings during configuration affect all * views. */ curr_stats.global_local_settings = 1; /* Try to load global configuration. */ (void)cfg_source_file(PACKAGE_SYSCONF_DIR "/" VIFMRC); /* Try to load local configuration. */ rc = env_get(MYVIFMRC_EV); if(!is_null_or_empty(rc)) { (void)cfg_source_file(rc); } //add by sim1: disabling millerview for VSPLIT if (curr_stats.number_of_windows == 2 && curr_stats.split == VSPLIT) { set_millerview(FALSE); } curr_stats.global_local_settings = prev_global_local_settings; }
int show_bmarks_menu(FileView *view, const char tags[], int go_on_single_match) { static menu_info m; init_menu_info(&m, strdup("Bookmarks"), strdup("No bookmarks found")); m.execute_handler = &execute_bmarks_cb; m.key_handler = &bmarks_khandler; if(is_null_or_empty(tags)) { bmarks_list(&bmarks_cb, &m); } else { bmarks_find(tags, &bmarks_cb, &m); } if(go_on_single_match && m.len == 1) { goto_selected_file(view, m.items[m.pos], 0); reset_popup_menu(&m); return curr_stats.save_msg; } return display_menu(&m, view); }
Status ws_new_pattern(SyntaxPattern **syn_pattern_ptr, const Regex *regex, SyntaxToken token) { assert(syn_pattern_ptr != NULL); assert(regex != NULL); assert(!is_null_or_empty(regex->regex_pattern)); SyntaxPattern *syn_pattern = malloc(sizeof(SyntaxPattern)); if (syn_pattern == NULL) { return OUT_OF_MEMORY("Unable to allocate SyntaxPattern"); } memset(syn_pattern, 0, sizeof(SyntaxPattern)); Status status = ru_compile_custom_error_msg(&syn_pattern->regex, regex, "pattern "); if (!STATUS_IS_SUCCESS(status)) { free(syn_pattern); return status; } syn_pattern->token = token; *syn_pattern_ptr = syn_pattern; return STATUS_SUCCESS; }
char * eval_arglist(const char args[], const char **stop_ptr) { size_t len = 0; char *eval_result = NULL; assert(args[0] != '\0'); while(args[0] != '\0') { char *free_this = NULL; const char *tmp_result = NULL; var_t result = var_false(); const ParsingErrors parsing_error = parse(args, &result); if(parsing_error == PE_INVALID_EXPRESSION && is_prev_token_whitespace()) { result = get_parsing_result(); tmp_result = free_this = var_to_string(result); args = get_last_parsed_char(); } else if(parsing_error == PE_NO_ERROR) { tmp_result = free_this = var_to_string(result); args = get_last_position(); } if(tmp_result == NULL) { var_free(result); break; } if(!is_null_or_empty(eval_result)) { eval_result = extend_string(eval_result, " ", &len); } eval_result = extend_string(eval_result, tmp_result, &len); var_free(result); free(free_this); args = skip_whitespace(args); } if(args[0] == '\0') { return eval_result; } else { free(eval_result); *stop_ptr = args; return NULL; } }
int stats_init(config_t *config) { inside_screen = !is_null_or_empty(env_get(SCREEN_ENVVAR)); inside_tmux = !is_null_or_empty(env_get(TMUX_ENVVAR)); load_def_values(&curr_stats, config); determine_fuse_umount_cmd(&curr_stats); set_gtk_available(&curr_stats); curr_stats.exec_env_type = get_exec_env_type(); stats_update_shell_type(config->shell); (void)hist_init(&curr_stats.cmd_hist, config->history_len); (void)hist_init(&curr_stats.search_hist, config->history_len); (void)hist_init(&curr_stats.prompt_hist, config->history_len); (void)hist_init(&curr_stats.filter_hist, config->history_len); hists_resize(config->history_len); return stats_reset(config); }
const char * ma_get_clean_cmd(const char cmd[]) { const char *clean_cmd; const char *const break_point = strstr(cmd, "%pc"); if(break_point == NULL) { return NULL; } clean_cmd = break_point + 3; return is_null_or_empty(clean_cmd) ? NULL : clean_cmd; }
/*! * \brief * Loads the server list from the user settings. * * \param xml_element * Pointer to an xml element that parents the version checkers settings. * * Loads the server list and the date the available version was last checked on, from the users settings. */ void c_version_check_manager_base::LoadSettings(TiXmlElement* xml_element) { m_states.last_checked_day = 0; m_states.last_checked_month = 0; m_states.last_checked_year = 0; for(int i = 0; i < NUMBEROF(m_version_xml.urls); i++) m_version_xml.urls[i][0] = 0; // if there is no settings element, we still want to set the default // xml location if(xml_element == NULL) { m_version_xml.list_version = 0; strcpy_s(m_version_xml.urls[0], sizeof(HTTP::t_http_url), c_version_check_manager_base::g_fallback_xml_location); return; } //do-while-false for easy fall-through do { //get the last date the version was checked if(!xml_element->Attribute("day", &m_states.last_checked_day)) { m_states.last_checked_day = 0; break; } if(!xml_element->Attribute("month", &m_states.last_checked_month)) { m_states.last_checked_month = 0; break; } if(!xml_element->Attribute("year", &m_states.last_checked_year)) { m_states.last_checked_year = 0; break; } }while(false); UpdateDateState(); //get the xml locations from the user settings TiXmlElement* server_list = xml_element->FirstChildElement("server_list"); if(!server_list) return; if(!server_list->Attribute("version", &m_version_xml.list_version)) return; TiXmlElement* server = server_list->FirstChildElement("server"); if(!server) return; for(int i = 0; server && (i < NUMBEROF(m_version_xml.urls)); i++) { const char* url = server->GetText(); if(!is_null_or_empty(url)) strcpy_s(m_version_xml.urls[i], sizeof(HTTP::t_http_url), url); server = server->NextSiblingElement("server"); } }
/* Reads data to be displayed handling error cases. Returns zero on success, 1 * if file is a directory, 2 on file reading error, 3 on issues with viewer or * 4 on empty input. */ static int get_view_data(view_info_t *vi, const char file_to_view[]) { FILE *fp; const char *const viewer = get_viewer_for_file(get_last_path_component(file_to_view)); if(is_null_or_empty(viewer)) { if(is_dir(file_to_view)) { return 1; } else if((fp = fopen(file_to_view, "rb")) == NULL) { return 2; } } else if((fp = use_info_prog(viewer)) == NULL) { return 3; } vi->lines = is_null_or_empty(viewer) ? read_file_lines(fp, &vi->nlines) : read_stream_lines(fp, &vi->nlines); fclose(fp); if(vi->lines == NULL || vi->nlines == 0) { return 4; } return 0; }
/** * Generate a "HN" child in the root to hold the DNS hostname, if defined. * This is a documented GTKG extension. */ static void g2_build_add_hostname(g2_tree_t *t) { if ( !GNET_PROPERTY(is_firewalled) && GNET_PROPERTY(give_server_hostname) && !is_null_or_empty(GNET_PROPERTY(server_hostname)) ) { g2_tree_t *c; const char *hostname = GNET_PROPERTY(server_hostname); c = g2_tree_alloc_copy("HN", hostname, strlen(hostname)); g2_tree_add_child(t, c); } }
/*! * \brief * Starts the update checking process. * * Sends the requests for the xml files from the xml urls. */ void c_version_check_manager_base::CheckForUpdates() { m_states.is_request_in_progress = false; // start the xml downloaders for(int i = 0; i < NUMBEROF(m_xml_sources); i++) { // if the xml source is empty, don't start the download if(is_null_or_empty(m_version_xml.urls[i])) continue; m_xml_sources[i].SetURL(m_version_xml.urls[i]); m_xml_sources[i].Start(); m_states.is_request_in_progress |= (m_xml_sources[i].Status() == Enums::_http_file_download_status_in_progress); } }
/* Tries to find directory for data files. */ static void find_data_dir(void) { LOG_FUNC_ENTER; const char *const data_home = env_get("XDG_DATA_HOME"); if(is_null_or_empty(data_home) || !is_path_absolute(data_home)) { snprintf(cfg.data_dir, sizeof(cfg.data_dir) - 4, "%s/.local/share/", env_get(HOME_EV)); } else { snprintf(cfg.data_dir, sizeof(cfg.data_dir) - 4, "%s/", data_home); } strcat(cfg.data_dir, "vifm"); }
PromptSuggestion *pc_new_suggestion(const char *text, SuggestionRank rank, const void *data) { assert(!is_null_or_empty(text)); PromptSuggestion *suggestion = malloc(sizeof(PromptSuggestion)); RETURN_IF_NULL(suggestion); if ((suggestion->text = strdup(text)) == NULL) { free(suggestion); return NULL; } suggestion->text_len = strlen(text); suggestion->rank = rank; suggestion->data = data; return suggestion; }
/* Composes title for window of a terminal multiplexer from a command. Returns * newly allocated string that should be freed by the caller. */ static char * gen_term_multiplexer_title_arg(const char cmd[]) { int bg; const char *const vicmd = cfg_get_vicmd(&bg); const char *const visubcmd = strstr(cmd, vicmd); char *command_name = NULL; const char *title; char *title_arg; if(visubcmd != NULL) { title = skip_whitespace(visubcmd + strlen(vicmd) + 1); } else { char *const separator = strchr(cmd, ' '); if(separator != NULL) { *separator = '\0'; command_name = strdup(cmd); *separator = ' '; } title = command_name; } if(is_null_or_empty(title)) { title_arg = strdup(""); } else { const char opt_c = (curr_stats.term_multiplexer == TM_SCREEN) ? 't' : 'n'; char *const escaped_title = shell_like_escape(title, 0); title_arg = format_str("-%c %s", opt_c, escaped_title); free(escaped_title); } free(command_name); return title_arg; }
void vim_write_empty_file_list(void) { FILE *fp; const char *const files_out = curr_stats.chosen_files_out; if(is_null_or_empty(files_out) || strcmp(files_out, "-") == 0) { return; } fp = os_fopen(files_out, "w"); if(fp != NULL) { fclose(fp); } else { LOG_SERROR_MSG(errno, "Can't truncate file: \"%s\"", files_out); } }
/*! * \brief * Prints the current and available versions to the console. * * Prints the current and available versions to the console. */ void c_version_check_manager_dedi::DisplayVersions(bool is_new_version) { blam::console_printf(false, ""); // if a new version is available display the versions if(is_new_version) { // print the current and available versions to the console // need to see how the console looks though to make sure we dont // mess up anything, could make it colourful too blam::console_printf(false, "New version of OpenSauce available!"); blam::console_printf(false, "Current version:\t\t%i.%i.%i (%s)", m_current_version.m_major, m_current_version.m_minor, m_current_version.m_build, m_current_version.m_build_date); if(is_null_or_empty(m_available_version.m_build_date)) { blam::console_printf(false, "Available version:\t\t%i.%i.%i", m_available_version.m_major, m_available_version.m_minor, m_available_version.m_build); } else { blam::console_printf(false, "Available version:\t\t%i.%i.%i (%s)", m_available_version.m_major, m_available_version.m_minor, m_available_version.m_build, m_available_version.m_build_date); } } else { blam::console_printf(false, "No updates available"); } blam::console_printf(false, ""); }
void cfg_load(void) { const char *rc; const int prev_global_local_settings = curr_stats.global_local_settings; /* Make changes of usually local settings during configuration affect all * views. */ curr_stats.global_local_settings = 1; /* Try to load global configuration. */ (void)cfg_source_file(PACKAGE_SYSCONF_DIR "/" VIFMRC); /* Try to load local configuration. */ rc = env_get(MYVIFMRC_EV); if(!is_null_or_empty(rc)) { (void)cfg_source_file(rc); } curr_stats.global_local_settings = prev_global_local_settings; }
void c_screen_controller_mainmenubottombar::BindDynamicProperties() { AddDynamicProperty(K_LBL_OPENSAUCE_NEW_VERSION_ID, K_PROPERTY_TEXT_ID, [this](Control::i_control& control, Control::i_property_interface& property) { if(m_available_version_set) { return; } auto& version_checker = Networking::VersionCheck::c_version_check_manager_base::VersionChecker(); if(version_checker.IsNewVersionAvailable()) { auto& version = version_checker.AvailableVersion(); char version_string[36]; if(is_null_or_empty(version.m_build_date)) { sprintf_s(version_string, "v%i.%i.%i available!", version.m_major, version.m_minor, version.m_build); } else { sprintf_s(version_string, "v%i.%i.%i (%s) available!", version.m_major, version.m_minor, version.m_build, version.m_build_date); } property.Set(control, version_string); m_available_version_set = true; } }); }
/* Displays sourcing error message to a user. */ static void show_sourcing_error(const char filename[], int line_num) { const char *const last_msg = ui_sb_last(); curr_stats.save_msg = 1; /* User choice is saved by prompt_error_msgf internally. */ if(is_null_or_empty(last_msg)) { (void)prompt_error_msgf("File Sourcing Error", "Error in %s at line %d", filename, line_num); } else { /* The space is needed because empty lines are automatically removed. */ (void)prompt_error_msgf("File Sourcing Error", "Error in %s at line %d:\n" " \n%s", filename, line_num, last_msg); } curr_stats.save_msg = 0; }
int vim_run_choose_cmd(const FileView *view) { char *expanded_cmd; if(is_null_or_empty(curr_stats.on_choose)) { return 0; } if(!view->dir_entry[view->list_pos].selected) { erase_selection(curr_view); } expanded_cmd = expand_macros(curr_stats.on_choose, NULL, NULL, 1); if(vifm_system(expanded_cmd) != EXIT_SUCCESS) { free(expanded_cmd); return 1; } return 0; }
/*! * \brief * Saves the current server list to the users settings. * * \param xml_element * Pointer to an xml element that parents the version checkers settings. * * Saves the current server list and current date to the users settings. */ void c_version_check_manager_base::SaveSettings(TiXmlElement* xml_element) { //set the attributes for the last date the version was checked xml_element->SetAttribute("day", m_states.last_checked_day); xml_element->SetAttribute("month", m_states.last_checked_month); xml_element->SetAttribute("year", m_states.last_checked_year); //save the current file urls to the user settings TiXmlElement* server_list = new TiXmlElement("server_list"); server_list->SetAttribute("version", m_version_xml.list_version); for(int32 i = 0; i < NUMBEROF(m_version_xml.urls); i++) { if(is_null_or_empty(m_version_xml.urls[i])) continue; TiXmlElement* server = new TiXmlElement("server"); TiXmlText* server_address = new TiXmlText(m_version_xml.urls[i]); server->LinkEndChild(server_address); server_list->LinkEndChild(server); } xml_element->LinkEndChild(server_list); }
int stats_file_choose_action_set(void) { return !is_null_or_empty(curr_stats.chosen_files_out) || !is_null_or_empty(curr_stats.on_choose); }
// Places the specified image in the specified slot; nID = -1 means don't matter static void MessSpecifyImage(int drvindex, const device_image_interface *device, LPCSTR pszFilename) { const char *s, *file_extension; windows_options o; load_options(o, OPTIONS_GAME, drvindex); if (LOG_SOFTWARE) dprintf("MessSpecifyImage(): device=%p pszFilename='%s'\n", device, pszFilename); // see if the software is already loaded (why?) if (device == NULL) { for (device_image_interface &dev : image_interface_iterator(s_config->mconfig->root_device())) { const char *opt_name = dev.instance_name(); s = o.value(opt_name); if ((s != NULL) && (core_stricmp(s, pszFilename)==0)) { device = &dev; break; } } } // still not found? find an empty slot for which the device uses the // same file extension if (device == NULL) { // identify the file extension file_extension = strrchr(pszFilename, '.'); file_extension = file_extension ? file_extension + 1 : NULL; if (file_extension) { for (device_image_interface &dev : image_interface_iterator(s_config->mconfig->root_device())) { const char *opt_name = dev.instance_name(); s = o.value(opt_name); if (is_null_or_empty(s) && dev.uses_file_extension(file_extension)) { device = &dev; break; } } } } // no choice but to replace the existing cart if (device == NULL) { if (file_extension) { for (device_image_interface &dev : image_interface_iterator(s_config->mconfig->root_device())) { const char *opt_name = dev.instance_name(); s = o.value(opt_name); if (!is_null_or_empty(s) && dev.uses_file_extension(file_extension)) { device = &dev; break; } } } } if (device) { // place the image InternalSetSelectedSoftware(drvindex, s_config->mconfig, device, pszFilename); } else { // could not place the image if (LOG_SOFTWARE) dprintf("MessSpecifyImage(): Failed to place image '%s'\n", pszFilename); } }
void quick_view_file(FileView *view) { char path[PATH_MAX]; const dir_entry_t *entry; if(curr_stats.load_stage < 2) { return; } if(vle_mode_is(VIEW_MODE)) { return; } if(curr_stats.number_of_windows == 1) { return; } if(draw_abandoned_view_mode()) { return; } ui_view_erase(other_view); entry = &view->dir_entry[view->list_pos]; get_full_path_of(entry, sizeof(path), path); switch(view->dir_entry[view->list_pos].type) { case FT_CHAR_DEV: mvwaddstr(other_view->win, LINE, COL, "File is a Character Device"); break; case FT_BLOCK_DEV: mvwaddstr(other_view->win, LINE, COL, "File is a Block Device"); break; #ifndef _WIN32 case FT_SOCK: mvwaddstr(other_view->win, LINE, COL, "File is a Socket"); break; #endif case FT_FIFO: mvwaddstr(other_view->win, LINE, COL, "File is a Named Pipe"); break; case FT_LINK: if(get_link_target_abs(path, entry->origin, path, sizeof(path)) != 0) { mvwaddstr(other_view->win, LINE, COL, "Cannot resolve Link"); break; } if(!ends_with_slash(path) && is_dir(path)) { strncat(path, "/", sizeof(path) - strlen(path) - 1); } /* break intensionally omitted */ case FT_UNK: default: { const char *viewer; FILE *fp; char *const typed_fname = get_typed_fname(path); viewer = ft_get_viewer(typed_fname); free(typed_fname); if(viewer == NULL && is_dir(path)) { mvwaddstr(other_view->win, LINE, COL, "File is a Directory"); break; } if(is_null_or_empty(viewer)) { fp = os_fopen(path, "rb"); } else { fp = use_info_prog(viewer); } if(fp == NULL) { mvwaddstr(other_view->win, LINE, COL, "Cannot open file"); break; } ui_view_clear(other_view); wattrset(other_view->win, 0); view_file(fp, cfg.wrap_quick_view); fclose(fp); break; } } refresh_view_win(other_view); ui_view_title_update(other_view); }
/* Reads data to be displayed handling error cases. Returns zero on success, 1 * if file is a directory, 2 on file reading error, 3 on issues with viewer or * 4 on empty input. */ static int get_view_data(view_info_t *vi, const char file_to_view[]) { FILE *fp; const char *const viewer = gv_get_viewer(file_to_view); if(is_null_or_empty(viewer)) { if(is_dir(file_to_view)) { return 1; } fp = os_fopen(file_to_view, "rb"); if(fp == NULL) { return 2; } vi->lines = read_file_lines(fp, &vi->nlines); } else { const int graphics = is_graphics_viewer(viewer); FileView *const curr = curr_view; curr_view = curr_stats.view ? curr_view : (vi->view != NULL) ? vi->view : curr_view; curr_stats.preview_hint = vi->view; if(graphics) { /* Wait a bit to let terminal emulator do actual refresh (at least some * of them need this). */ usleep(50000); } fp = use_info_prog(viewer); curr_view = curr; curr_stats.preview_hint = NULL; if(fp == NULL) { return 3; } if(graphics) { vi->graphics = 1; } vi->lines = read_stream_lines(fp, &vi->nlines); } fclose(fp); if(vi->lines == NULL || vi->nlines == 0) { return 4; } return 0; }
int compare_move(FileView *from, FileView *to) { char from_path[PATH_MAX], to_path[PATH_MAX]; char *from_fingerprint, *to_fingerprint; const CompareType ct = from->custom.diff_cmp_type; dir_entry_t *const curr = &from->dir_entry[from->list_pos]; dir_entry_t *const other = &to->dir_entry[from->list_pos]; if(from->custom.type != CV_DIFF || !from->custom.diff_path_group) { status_bar_error("Not in diff mode with path grouping"); return 1; } if(curr->id == other->id && !fentry_is_fake(curr) && !fentry_is_fake(other)) { /* Nothing to do if files are already equal. */ return 0; } /* We're going at least to try to update one of views (which might refer to * the same directory), so schedule a reload. */ ui_view_schedule_reload(from); ui_view_schedule_reload(to); if(fentry_is_fake(curr)) { /* Just remove the other file (it can't be fake entry too). */ return fops_delete_current(to, 1, 0); } get_full_path_of(curr, sizeof(from_path), from_path); get_full_path_of(other, sizeof(to_path), to_path); if(fentry_is_fake(other)) { char to_path[PATH_MAX]; char canonical[PATH_MAX]; snprintf(to_path, sizeof(to_path), "%s/%s/%s", flist_get_dir(to), curr->origin + strlen(flist_get_dir(from)), curr->name); canonicalize_path(to_path, canonical, sizeof(canonical)); /* Copy current file to position of the other one using relative path with * different base. */ fops_replace(from, canonical, 0); /* Update the other entry to not be fake. */ remove_last_path_component(canonical); replace_string(&other->name, curr->name); replace_string(&other->origin, canonical); } else { /* Overwrite file in the other pane with corresponding file from current * pane. */ fops_replace(from, to_path, 1); } /* Obtaining file fingerprint relies on size field of entries, so try to load * it and ignore if it fails. */ other->size = get_file_size(to_path); /* Try to update id of the other entry by computing fingerprint of both files * and checking if they match. */ from_fingerprint = get_file_fingerprint(from_path, curr, ct); to_fingerprint = get_file_fingerprint(to_path, other, ct); if(!is_null_or_empty(from_fingerprint) && !is_null_or_empty(to_fingerprint)) { int match = (strcmp(from_fingerprint, to_fingerprint) == 0); if(match && ct == CT_CONTENTS) { match = files_are_identical(from_path, to_path); } if(match) { other->id = curr->id; } } free(from_fingerprint); free(to_fingerprint); return 0; }
/* Makes sorted by path list of entries that. The trie is used to keep track of * identical files. With non-zero dups_only, new files aren't added to the * trie. */ static entries_t make_diff_list(trie_t *trie, FileView *view, int *next_id, CompareType ct, int skip_empty, int dups_only) { int i; strlist_t files = {}; entries_t r = {}; int last_progress = 0; show_progress("Listing...", 0); if(flist_custom_active(view) && ONE_OF(view->custom.type, CV_REGULAR, CV_VERY)) { list_view_entries(view, &files); } else { list_files_recursively(flist_get_dir(view), view->hide_dot, &files); } show_progress("Querying...", 0); for(i = 0; i < files.nitems && !ui_cancellation_requested(); ++i) { char progress_msg[128]; int progress; int existing_id; char *fingerprint; const char *const path = files.items[i]; dir_entry_t *const entry = entry_list_add(view, &r.entries, &r.nentries, path); if(skip_empty && entry->size == 0) { free_dir_entry(view, entry); --r.nentries; continue; } fingerprint = get_file_fingerprint(path, entry, ct); /* In case we couldn't obtain fingerprint (e.g., comparing by contents and * files isn't readable), ignore the file and keep going. */ if(is_null_or_empty(fingerprint)) { free(fingerprint); free_dir_entry(view, entry); --r.nentries; continue; } entry->tag = i; if(get_file_id(trie, path, fingerprint, &existing_id, ct)) { entry->id = existing_id; } else if(dups_only) { entry->id = -1; } else { entry->id = *next_id; ++*next_id; put_file_id(trie, path, fingerprint, entry->id, ct); } free(fingerprint); progress = (i*100)/files.nitems; if(progress != last_progress) { last_progress = progress; snprintf(progress_msg, sizeof(progress_msg), "Querying... %d (% 2d%%)", i, progress); show_progress(progress_msg, -1); } } free_string_array(files.items, files.nitems); return r; }