/* 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; }
/* Handles current content of the menu to Vim as quickfix list. */ static void cmd_v(key_info_t key_info, keys_info_t *keys_info) { int bg; const char *vi_cmd; FILE *vim_stdin; char *cmd; int i; int qf = 1; /* If both first and last lines do not contain colons, treat lines as list of * file names. */ if(strchr(menu->items[0], ':') == NULL && strchr(menu->items[menu->len - 1], ':') == NULL) { qf = 0; } ui_shutdown(); curr_stats.need_update = UT_FULL; vi_cmd = cfg_get_vicmd(&bg); if(!qf) { char *const arg = shell_like_escape("+exe 'bd!|args' " "join(map(getline('1','$'),'fnameescape(v:val)'))", 0); cmd = format_str("%s %s +argument%d -", vi_cmd, arg, menu->pos + 1); free(arg); } else if(menu->pos == 0) { /* For some reason +cc1 causes noisy messages on status line, so handle this * case separately. */ cmd = format_str("%s +cgetbuffer +bd! +cfirst -", vi_cmd); } else { cmd = format_str("%s +cgetbuffer +bd! +cfirst +cc%d -", vi_cmd, menu->pos + 1); } vim_stdin = popen(cmd, "w"); free(cmd); if(vim_stdin == NULL) { recover_after_shellout(); show_error_msg("Vim QuickFix", "Failed to send list of files to editor."); return; } for(i = 0; i < menu->len; ++i) { fputs(menu->items[i], vim_stdin); putc('\n', vim_stdin); } pclose(vim_stdin); recover_after_shellout(); }
/* Composes command to be run using terminal multiplexer. Returns newly * allocated string that should be freed by the caller. */ static char * gen_term_multiplexer_cmd(const char cmd[], int pause) { char *title_arg; char *raw_shell_cmd; char *escaped_shell_cmd; char *shell_cmd = NULL; if(curr_stats.term_multiplexer != TM_TMUX && curr_stats.term_multiplexer != TM_SCREEN) { assert(0 && "Unexpected active terminal multiplexer value."); return NULL; } title_arg = gen_term_multiplexer_title_arg(cmd); raw_shell_cmd = format_str("%s%s", cmd, pause ? PAUSE_STR : ""); escaped_shell_cmd = shell_like_escape(raw_shell_cmd, 0); if(curr_stats.term_multiplexer == TM_TMUX) { char *const arg = format_str("%s -c %s", cfg.shell, escaped_shell_cmd); char *const escaped_arg = shell_like_escape(arg, 0); shell_cmd = format_str("tmux new-window %s %s", title_arg, escaped_arg); free(escaped_arg); free(arg); } else if(curr_stats.term_multiplexer == TM_SCREEN) { set_pwd_in_screen(flist_get_dir(curr_view)); shell_cmd = format_str("screen %s %s -c %s", title_arg, cfg.shell, escaped_shell_cmd); } else { assert(0 && "Unsupported terminal multiplexer type."); } free(escaped_shell_cmd); free(raw_shell_cmd); free(title_arg); return shell_cmd; }
/* Draws box and title of the menu. */ static void draw_menu_frame(const menu_state_t *m) { const size_t title_len = getmaxx(menu_win) - 2*4; const char *const suffix = menu_and_view_are_in_sync(m->d, m->view) ? "" : replace_home_part(m->d->cwd); const char *const at = (suffix[0] == '\0' ? "" : " @ "); char *const title = format_str("%s%s%s", m->d->title, at, suffix); if(utf8_strsw(title) > title_len) { const size_t len = utf8_nstrsnlen(title, title_len - 3); strcpy(title + len, "..."); } box(menu_win, 0, 0); wattron(menu_win, A_BOLD); checked_wmove(menu_win, 0, 3); wprint(menu_win, " "); wprint(menu_win, title); wprint(menu_win, " "); wattroff(menu_win, A_BOLD); free(title); }
/* Writes path configuration file and directories for further usage. */ static void store_config_paths(void) { LOG_FUNC_ENTER; const char *const trash_dir_fmt = #ifndef _WIN32 "%%r/.vifm-Trash-%%u,%s/" TRASH ",%%r/.vifm-Trash"; #else "%%r/.vifm-Trash,%s/" TRASH; #endif char *fuse_home; const char *trash_base = path_exists_at(env_get(VIFM_EV), TRASH, DEREF) ? cfg.config_dir : cfg.data_dir; const char *base = path_exists(cfg.data_dir, DEREF) ? cfg.data_dir : cfg.config_dir; snprintf(cfg.home_dir, sizeof(cfg.home_dir), "%s/", env_get(HOME_EV)); copy_str(cfg.config_dir, sizeof(cfg.config_dir), env_get(VIFM_EV)); snprintf(cfg.colors_dir, sizeof(cfg.colors_dir), "%s/colors/", cfg.config_dir); snprintf(cfg.trash_dir, sizeof(cfg.trash_dir), trash_dir_fmt, trash_base); snprintf(cfg.log_file, sizeof(cfg.log_file), "%s/" LOG, base); fuse_home = format_str("%s/fuse/", base); (void)cfg_set_fuse_home(fuse_home); free(fuse_home); }
void disp_tm_edit(void * edit_data) { struct edit_ctrl * edit_ptr; struct tm * tm_buf; char str[32]; int x, y; int fwidth, fheight; static int prev_pos = 0; time_t t; edit_ptr = (struct edit_ctrl *)edit_data; tm_buf = (struct tm *)edit_ptr->buf; format_str(str, 32, "%02u/%02u/%02u %02u:%02u", tm_buf->tm_mday, tm_buf->tm_mon + 1, getyear2(tm_buf->tm_year), tm_buf->tm_hour, tm_buf->tm_min); x = edit_ptr->x; y = edit_ptr->y; fwidth = fh[edit_ptr->font]->width; fheight = fh[edit_ptr->font]->height; OLED_puts(x , y, 0xff, edit_ptr->font, str); x += tm_get_pointer_pos(prev_pos) * fwidth; y += fheight; OLED_clr(x, y, fwidth, fheight); prev_pos = edit_ptr->buf_pos; x = edit_ptr->x + tm_get_pointer_pos(prev_pos) * fwidth; OLED_puts(x , y, 0xff, edit_ptr->font, "^"); /* t = mktime2(&tm4edit); format_str(str, 32, "%ld, %llx", t, (unsigned long long)t * 1000); OLED_puts(0, 5 * 9, 0xff, edit_ptr->font, str); */ }
void menu_morph_into_cmdline(CmdLineSubmode submode, const char input[], int external) { /* input might point to part of menu data. */ char *input_copy; if(input[0] == '\0') { show_error_msg("Command insertion", "Ignoring empty command"); return; } input_copy = external ? format_str("!%s", input) : strdup(input); if(input_copy == NULL) { show_error_msg("Error", "Not enough memory"); return; } leave_menu_mode(0); enter_cmdline_mode(submode, input_copy, NULL); free(input_copy); }
void ui_stat_draw_popup_line(WINDOW *win, const char item[], const char descr[], size_t max_width) { char *left, *right, *line; const size_t text_width = utf8_strsw(item); const size_t win_width = getmaxx(win); const int align_columns = (max_width <= win_width/4); const char *const fmt = align_columns ? "%-*s %-*s" : "%-*s %*s"; size_t width_left; size_t item_width; if(text_width >= win_width) { char *const whole = right_ellipsis(item, win_width, curr_stats.ellipsis); wprint(win, whole); free(whole); return; } left = right_ellipsis(item, win_width - 3, curr_stats.ellipsis); item_width = align_columns ? max_width : utf8_strsw(left); width_left = win_width - 2 - MAX(item_width, utf8_strsw(left)); right = right_ellipsis(descr, width_left, curr_stats.ellipsis); line = format_str(fmt, (int)item_width, left, (int)width_left, right); free(left); free(right); wprint(win, line); free(line); }
gmux_t * gmux_create(const char name[]) { gmux_t *const gmux = malloc(sizeof(*gmux)); if(gmux == NULL) { return NULL; } gmux->name = format_str("Local\\%s-gmux", name); if(gmux->name == NULL) { free(gmux); return NULL; } gmux->handle = CreateMutex(NULL, FALSE, gmux->name); if(gmux->handle == NULL) { free(gmux->name); free(gmux); return NULL; } return gmux; }
int show_trashes_menu(view_t *view, int calc_size) { char **trashes; int ntrashes; int i; static menu_data_t m; menus_init_data(&m, view, format_str("%sNon-empty trash directories", calc_size ? "[ size] " : ""), strdup("No non-empty trash directories found")); m.execute_handler = &execute_trashes_cb; m.key_handler = &trashes_khandler; m.extra_data = calc_size; trashes = list_trashes(&ntrashes); show_progress(NULL, 0); for(i = 0; i < ntrashes; i++) { char *const item = format_item(trashes[i], calc_size); m.len = put_into_string_array(&m.items, m.len, item); } free_string_array(trashes, ntrashes); return menus_enter(m.state, view); }
/* Configures environment variables before shellout. Should be used in pair * with cleanup_shellout_env(). */ static void setup_shellout_env(void) { const char *mount_file; const char *term_multiplexer_fmt; char *escaped_path; char *cmd; /* Need to use internal value instead of getcwd() for a symlink directory. */ env_set("PWD", curr_view->curr_dir); mount_file = fuse_get_mount_file(curr_view->curr_dir); if(mount_file == NULL) { env_remove(FUSE_FILE_ENVVAR); return; } env_set(FUSE_FILE_ENVVAR, mount_file); switch(curr_stats.term_multiplexer) { case TM_TMUX: term_multiplexer_fmt = "tmux set-environment %s %s"; break; case TM_SCREEN: term_multiplexer_fmt = "screen -X setenv %s %s"; break; default: return; } escaped_path = shell_like_escape(mount_file, 0); cmd = format_str(term_multiplexer_fmt, FUSE_FILE_ENVVAR, escaped_path); (void)vifm_system(cmd); free(cmd); free(escaped_path); }
int show_fileviewers_menu(FileView *view, const char fname[]) { static menu_info m; assoc_records_t file_viewers; init_menu_info(&m, format_str("Viewers that match %s", fname), format_str("No viewers match %s", fname)); file_viewers = ft_get_all_viewers(fname); fill_menu_from_records(&m, &file_viewers); ft_assoc_records_free(&file_viewers); return display_menu(&m, view); }
/* Tries to expands tilde in the front of the path. Returns the path or newly * allocated string without tilde. */ static char * try_replace_tilde(const char path[]) { #ifndef _WIN32 char name[NAME_MAX]; const char *p; char *result; struct passwd *pw; #endif if(path[0] != '~') { return (char *)path; } if(path[1] == '\0' || path[1] == '/') { char *const result = format_str("%s%s", cfg.home_dir, (path[1] == '/') ? (path + 2) : ""); return result; } #ifndef _WIN32 if((p = strchr(path, '/')) == NULL) { p = path + strlen(path); copy_str(name, sizeof(name), path + 1); } else { snprintf(name, p - (path + 1) + 1, "%s", path + 1); p++; } if((pw = getpwnam(name)) == NULL) { return (char *)path; } chosp(pw->pw_dir); result = format_str("%s/%s", pw->pw_dir, p); return result; #else return (char *)path; #endif }
/* Removes all files inside given trash directory (even those that this instance * of vifm is not aware of). */ static void empty_trash_dir(const char trash_dir[]) { char *const task_desc = format_str("Empty trash: %s", trash_dir); char *const op_desc = format_str("Emptying %s", replace_home_part(trash_dir)); char *const trash_dir_copy = strdup(trash_dir); if(bg_execute(task_desc, op_desc, BG_UNDEFINED_TOTAL, 1, &empty_trash_in_bg, trash_dir_copy) != 0) { free(trash_dir_copy); } free(op_desc); free(task_desc); }
TEST_F(OutputFormatterTest, OtherCharacterAfterBackslashInFormatString) { std::wstring format_str(L"%p\\d %p"); OutputFormatter formater(&input, format_str); auto res = formater.Format(); EXPECT_TRUE((*res)[0] == std::wstring(L"my_file1\\d my_file1")); EXPECT_TRUE((*res)[1] == std::wstring(L"my_file2\\d my_file2")); }
TEST_F(OutputFormatterTest, HorizontalTabInFormatString) { std::wstring format_str(L"%p\\t%p"); OutputFormatter formater(&input, format_str); auto res = formater.Format(); EXPECT_TRUE((*res)[0] == std::wstring(L"my_file1 my_file1")); EXPECT_TRUE((*res)[1] == std::wstring(L"my_file2 my_file2")); }
TEST_F(OutputFormatterTest, EscapedBackslashInFormatString) { std::wstring format_str(L"%p\\\\%p\\\\"); OutputFormatter formater(&input, format_str); auto res = formater.Format(); EXPECT_TRUE((*res)[0] == std::wstring(L"my_file1\\my_file1\\")); EXPECT_TRUE((*res)[1] == std::wstring(L"my_file2\\my_file2\\")); }
/* Formats a command to edit selected files of the current view in an editor. * Returns a newly allocated string, which should be freed by the caller. */ TSTATIC char * format_edit_selection_cmd(int *bg) { char *const files = expand_macros("%f", NULL, NULL, 1); char *const cmd = format_str("%s %s", cfg_get_vicmd(bg), files); free(files); return cmd; }
int show_fileprograms_menu(FileView *view, const char fname[]) { static menu_info m; assoc_records_t file_programs; init_menu_info(&m, FILEPROGRAMS_MENU, format_str("No programs match %s", fname)); m.title = format_str(" Programs that match %s ", fname); file_programs = ft_get_all_programs(fname); fill_menu_from_records(&m, &file_programs); ft_assoc_records_free(&file_programs); return display_menu(&m, view); }
string write_roster_players(string roster_filename, const RosterPlayerArray& players_arr) { ofstream rosterfile(roster_filename.c_str()); if (!rosterfile) return format_str("Failed to open roster %s", roster_filename.c_str()); rosterfile << "Name Age Nat Prs St Tk Ps Sh Sm Ag KAb TAb PAb SAb Gam Sav Ktk Kps Sht Gls Ass DP Inj Sus Fit\n"; rosterfile << "------------------------------------------------------------------------------------------------------\n"; for (RosterPlayerConstIterator player = players_arr.begin(); player != players_arr.end(); ++player) { rosterfile << format_str("%-13s%3d%4s%4s%3d%3d%3d%3d%3d%3d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d\n", player->name.c_str(), player->age, player->nationality.c_str(), player->pref_side.c_str(), player->st, player->tk, player->ps, player->sh, player->stamina, player->ag, player->st_ab, player->tk_ab, player->ps_ab, player->sh_ab, player->games, player->saves, player->tackles, player->keypasses, player->shots, player->goals, player->assists, player->dp, player->injury, player->suspension, player->fitness); } rosterfile << endl; return ""; }
/* Changes $PWD in running GNU/screen session to the specified path. Needed for * symlink directories and sshfs mounts. */ static void set_pwd_in_screen(const char path[]) { char *const escaped_dir = shell_like_escape(path, 0); char *const set_pwd = format_str("screen -X setenv PWD %s", escaped_dir); (void)vifm_system(set_pwd); free(set_pwd); free(escaped_dir); }
/* Replaces *str with a copy of the with string extended by the suffix. *str * can be NULL in which case it's treated as empty string, equal to the with * (then function does nothing). Returns non-zero if memory allocation * failed. */ static void append_to_string(char **str, const char suffix[]) { const char *const non_null_str = (*str == NULL) ? "" : *str; char *const appended_str = format_str("%s%s", non_null_str, suffix); if(appended_str != NULL) { free(*str); *str = appended_str; } }
/* Collects files under specified file system tree. */ static void list_files_recursively(const char path[], int skip_dot_files, strlist_t *list) { int i; /* Obtain sorted list of files. */ int len; char **lst = list_sorted_files(path, &len); if(len < 0) { return; } /* Visit all subdirectories ignoring symbolic links to directories. */ for(i = 0; i < len && !ui_cancellation_requested(); ++i) { char *full_path; if(skip_dot_files && lst[i][0] == '.') { update_string(&lst[i], NULL); continue; } full_path = format_str("%s/%s", path, lst[i]); if(is_dir(full_path)) { if(!is_symlink(full_path)) { list_files_recursively(full_path, skip_dot_files, list); } free(full_path); update_string(&lst[i], NULL); } else { free(lst[i]); lst[i] = full_path; } show_progress("Listing...", 1000); } /* Append files. */ for(i = 0; i < len; ++i) { if(lst[i] != NULL) { list->nitems = put_into_string_array(&list->items, list->nitems, lst[i]); } } free(lst); }
static void test_max_count_is_handled_correctly(void) { char *const keys = format_str("%udd", INT_MAX); wchar_t *const keysw = to_wide(keys); assert_false(IS_KEYS_RET_CODE(execute_keys(keysw))); assert_int_equal(INT_MAX, last_command_count); free(keysw); free(keys); }
char * fast_run_complete(const char cmd[]) { char *result = NULL; const char *args; char command[NAME_MAX]; char *completed; args = extract_cmd_name(cmd, 0, sizeof(command), command); if(is_path_absolute(command)) { return strdup(cmd); } vle_compl_reset(); complete_command_name(command); vle_compl_unite_groups(); completed = vle_compl_next(); if(vle_compl_get_count() > 2) { int c = vle_compl_get_count() - 1; while(c-- > 0) { if(stroscmp(command, completed) == 0) { result = strdup(cmd); break; } else { free(completed); completed = vle_compl_next(); } } if(result == NULL) { status_bar_error("Command beginning is ambiguous"); } } else { free(completed); completed = vle_compl_next(); result = format_str("%s %s", completed, args); } free(completed); return result; }
/* Performs conversions on files in trash required for partial backward * compatibility. Returns newly allocated string that should be freed by the * caller. */ static char * convert_old_trash_path(const char trash_path[]) { if(!is_path_absolute(trash_path) && is_dir_writable(cfg.trash_dir)) { char *const full_path = format_str("%s/%s", cfg.trash_dir, trash_path); if(path_exists(full_path, DEREF)) { return full_path; } free(full_path); } return strdup(trash_path); }
char * describe_abbrev(const wchar_t lhs[], const wchar_t rhs[], int no_remap, int offset) { enum { LHS_MIN_WIDTH = 13 }; const char map_mark = no_remap ? '*' : ' '; char *const keys = wstr_to_spec(rhs); char *const descr = format_str("%-*ls %3c %s", offset + LHS_MIN_WIDTH, lhs, map_mark, keys); free(keys); return descr; }
/* does real job on setting terminal title */ static void set_terminal_title(const char *path) { #ifdef _WIN32 wchar_t buf[2048]; vifm_swprintf(buf, ARRAY_LEN(buf), L"%" WPRINTF_MBSTR L" - VIFM", path); SetConsoleTitleW(buf); #else char *const title = format_str("\033]2;%s - VIFM\007", path); putp(title); fflush(stdout); free(title); #endif }
/* Does all the real work on setting terminal title. */ static void set_terminal_title(const char path[]) { #ifdef _WIN32 wchar_t *utf16; char title[2048]; snprintf(title, sizeof(title), "%s - VIFM", path); utf16 = utf8_to_utf16(title); SetConsoleTitleW(utf16); free(utf16); #else char *const title = format_str("\033]2;%s - VIFM\007", path); putp(title); fflush(stdout); free(title); #endif }
/* Makes fingerprint of file contents (all or part of it of fixed size). * Returns the fingerprint as a string, which is empty or NULL on error. */ static char * get_contents_fingerprint(const char path[], const dir_entry_t *entry) { #if INTPTR_MAX == INT64_MAX #define XX_BITS 64 #else #define XX_BITS 32 #endif #define XX__(name, bits) XXH ## bits ## _ ## name #define XX_(name, bits) XX__(name, bits) #define XX(name) XX_(name, XX_BITS) XX(state_t) st; char block[BLOCK_SIZE]; size_t to_read = PREFIX_SIZE; FILE *in = os_fopen(path, "rb"); if(in == NULL) { return strdup(""); } XX(reset)(&st, 0U); while(to_read != 0U) { const size_t portion = MIN(sizeof(block), to_read); const size_t nread = fread(&block, 1, portion, in); if(nread == 0U) { break; } XX(update)(&st, block, nread); to_read -= nread; } fclose(in); return format_str("%" PRINTF_ULL "|%" PRINTF_ULL, (unsigned long long)entry->size, (unsigned long long)XX(digest)(&st)); #undef XX_BITS #undef XX__ #undef XX_ #undef XX }