void modes_pre(void) { if(vle_mode_is(CMDLINE_MODE)) { touchwin(status_bar); wrefresh(status_bar); return; } else if(ANY(vle_mode_is, SORT_MODE, CHANGE_MODE, ATTR_MODE)) { return; } else if(vle_mode_is(VIEW_MODE)) { view_pre(); return; } else if(is_in_menu_like_mode()) { menu_pre(); return; } if(!curr_stats.save_msg) { clean_status_bar(); wrefresh(status_bar); } }
static void parse_recieved_arguments(char *args[]) { char lwin_path[PATH_MAX] = ""; char rwin_path[PATH_MAX] = ""; int lwin_handle = 0, rwin_handle = 0; int argc = 0; while(args[argc] != NULL) { argc++; } parse_args(argc, args, args[0], lwin_path, rwin_path, &lwin_handle, &rwin_handle); exec_startup_commands(argc, args); if(get_mode() != NORMAL_MODE && get_mode() != VIEW_MODE) { return; } #ifdef _WIN32 SwitchToThisWindow(GetConsoleWindow(), TRUE); BringWindowToTop(GetConsoleWindow()); SetForegroundWindow(GetConsoleWindow()); #endif if(view_needs_cd(&lwin, lwin_path)) { remote_cd(&lwin, lwin_path, lwin_handle); } if(view_needs_cd(&rwin, rwin_path)) { remote_cd(&rwin, rwin_path, rwin_handle); } if(lwin_path[0] != '\0' && rwin_path[0] == '\0' && curr_view != &lwin) { change_window(); } clean_status_bar(); curr_stats.save_msg = 0; }
void modes_statusbar_update(void) { if(curr_stats.save_msg) { if(vle_mode_is(VISUAL_MODE)) { update_vmode_input(); } } else if(curr_view->selected_files || vle_mode_is(VISUAL_MODE)) { print_selected_msg(); } else { clean_status_bar(); } }
static void leave_cmdline_mode(void) { int attr; if(getmaxy(status_bar) > 1) { curr_stats.need_redraw = 2; wresize(status_bar, 1, getmaxx(stdscr) - 19); mvwin(status_bar, getmaxy(stdscr) - 1, 0); if(prev_mode == MENU_MODE) { wresize(menu_win, getmaxy(stdscr) - 1, getmaxx(stdscr)); update_menu(); } } else { wresize(status_bar, 1, getmaxx(stdscr) - 19); } curs_set(FALSE); curr_stats.save_msg = 0; free(input_stat.line); free(input_stat.line_buf); clean_status_bar(); if(*mode == CMDLINE_MODE) *mode = prev_mode; if(*mode != MENU_MODE) update_pos_window(curr_view); attr = cfg.cs.color[CMD_LINE_COLOR].attr; wattroff(status_bar, COLOR_PAIR(DCOLOR_BASE + CMD_LINE_COLOR) | attr); if(prev_mode != MENU_MODE && prev_mode != VIEW_MODE) { draw_dir_list(curr_view, curr_view->top_line); move_to_list_pos(curr_view, curr_view->list_pos); } }
static void leave_cmdline_mode(void) { int attr; if(getmaxy(status_bar) > 1) { curr_stats.need_update = UT_FULL; wresize(status_bar, 1, getmaxx(stdscr) - FIELDS_WIDTH); mvwin(status_bar, getmaxy(stdscr) - 1, 0); if(prev_mode == MENU_MODE) { wresize(menu_win, getmaxy(stdscr) - 1, getmaxx(stdscr)); update_menu(); } } else { wresize(status_bar, 1, getmaxx(stdscr) - FIELDS_WIDTH); } curs_set(FALSE); curr_stats.save_msg = 0; free(input_stat.line); free(input_stat.initial_line); free(input_stat.line_buf); clean_status_bar(); if(*mode == CMDLINE_MODE) *mode = prev_mode; if(*mode != MENU_MODE) update_pos_window(curr_view); attr = cfg.cs.color[CMD_LINE_COLOR].attr; wattroff(status_bar, COLOR_PAIR(DCOLOR_BASE + CMD_LINE_COLOR) | attr); if(prev_mode != MENU_MODE && prev_mode != VIEW_MODE) { redraw_current_view(); } }
int fuse_try_unmount(FileView *view) { char buf[14 + PATH_MAX + 1]; fuse_mount_t *runner, *trailer; int status; fuse_mount_t *sniffer; char *escaped_mount_point; runner = fuse_mounts; trailer = NULL; while(runner) { if(paths_are_equal(runner->mount_point, view->curr_dir)) { break; } trailer = runner; runner = runner->next; } if(runner == NULL) { return 0; } /* we are exiting a top level dir */ escaped_mount_point = escape_filename(runner->mount_point, 0); snprintf(buf, sizeof(buf), "%s %s 2> /dev/null", curr_stats.fuse_umount_cmd, escaped_mount_point); LOG_INFO_MSG("FUSE unmount command: `%s`", buf); free(escaped_mount_point); /* Have to chdir to parent temporarily, so that this DIR can be unmounted. */ if(vifm_chdir(cfg.fuse_home) != 0) { show_error_msg("FUSE UMOUNT ERROR", "Can't chdir to FUSE home"); return -1; } status_bar_message("FUSE unmounting selected file, please stand by.."); status = background_and_wait_for_status(buf, 0, NULL); clean_status_bar(); /* check child status */ if(!WIFEXITED(status) || WEXITSTATUS(status)) { werase(status_bar); show_error_msgf("FUSE UMOUNT ERROR", "Can't unmount %s. It may be busy.", runner->source_file_name); (void)vifm_chdir(flist_get_dir(view)); return -1; } /* remove the directory we created for the mount */ if(path_exists(runner->mount_point, DEREF)) rmdir(runner->mount_point); /* remove mount point from fuse_mount_t */ sniffer = runner->next; if(trailer) trailer->next = sniffer ? sniffer : NULL; else fuse_mounts = sniffer; updir_from_mount(view, runner); free(runner); return 1; }
/* mount_point should be an array of at least PATH_MAX characters * Returns non-zero on error. */ static int fuse_mount(FileView *view, char file_full_path[], const char param[], const char program[], char mount_point[]) { /* TODO: refactor this function fuse_mount(). */ int mount_point_id; char buf[2*PATH_MAX]; char *escaped_filename; int foreground; char errors_file[PATH_MAX]; int status; int cancelled; escaped_filename = escape_filename(get_current_file_name(view), 0); mount_point_id = get_last_mount_point_id(fuse_mounts); do { snprintf(mount_point, PATH_MAX, "%s/%03d_%s", cfg.fuse_home, ++mount_point_id, get_current_file_name(view)); } while(path_exists(mount_point, DEREF)); if(os_mkdir(mount_point, S_IRWXU) != 0) { free(escaped_filename); show_error_msg("Unable to create FUSE mount directory", mount_point); return -1; } free(escaped_filename); /* Just before running the mount, I need to chdir out temporarily from any FUSE mounted paths, Otherwise the fuse-zip command fails with "fusermount: failed to open current directory: permission denied" (this happens when mounting JARs from mounted JARs) */ if(vifm_chdir(cfg.fuse_home) != 0) { show_error_msg("FUSE MOUNT ERROR", "Can't chdir() to FUSE home"); return -1; } format_mount_command(mount_point, file_full_path, param, program, sizeof(buf), buf, &foreground); status_bar_message("FUSE mounting selected file, please stand by.."); if(foreground) { def_prog_mode(); endwin(); } generate_tmp_file_name("vifm.errors", errors_file, sizeof(errors_file)); strcat(buf, " 2> "); strcat(buf, errors_file); LOG_INFO_MSG("FUSE mount command: `%s`", buf); status = background_and_wait_for_status(buf, !foreground, &cancelled); clean_status_bar(); /* Check child process exit status. */ if(!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) { FILE *ef; if(!WIFEXITED(status)) { LOG_ERROR_MSG("FUSE mounter didn't exit!"); } else { LOG_ERROR_MSG("FUSE mount command exit status: %d", WEXITSTATUS(status)); } ef = os_fopen(errors_file, "r"); if(ef == NULL) { LOG_SERROR_MSG(errno, "Failed to open temporary stderr file: %s", errors_file); } show_errors_from_file(ef, "FUSE mounter error"); werase(status_bar); if(cancelled) { status_bar_message("FUSE mount cancelled"); curr_stats.save_msg = 1; } else { show_error_msg("FUSE MOUNT ERROR", file_full_path); } if(unlink(errors_file) != 0) { LOG_SERROR_MSG(errno, "Error file deletion failure: %d", errors_file); } /* Remove the directory we created for the mount. */ (void)rmdir(mount_point); (void)vifm_chdir(flist_get_dir(view)); return -1; } unlink(errors_file); status_bar_message("FUSE mount success"); register_mount(&fuse_mounts, file_full_path, mount_point, mount_point_id); return 0; }
/* * mount_point should be an array of at least PATH_MAX characters * Returns non-zero on error. */ static int fuse_mount(FileView *view, char *file_full_path, const char *param, const char *program, char *mount_point) { /* TODO: refactor this function fuse_mount() */ fuse_mount_t *runner = NULL; int mount_point_id = 0; fuse_mount_t *fuse_item = NULL; char buf[2*PATH_MAX]; char *escaped_filename; int clear_before_mount = 0; char errors_file[PATH_MAX]; int status; escaped_filename = escape_filename(get_current_file_name(view), 0); /* get mount_point_id + mount_point and set runner pointing to the list's * tail */ if(fuse_mounts != NULL) { runner = fuse_mounts; while(runner->next != NULL) runner = runner->next; mount_point_id = runner->mount_point_id; } do { snprintf(mount_point, PATH_MAX, "%s/%03d_%s", cfg.fuse_home, ++mount_point_id, get_current_file_name(view)); } while(path_exists(mount_point)); if(make_dir(mount_point, S_IRWXU) != 0) { free(escaped_filename); show_error_msg("Unable to create FUSE mount directory", mount_point); return -1; } free(escaped_filename); /* Just before running the mount, I need to chdir out temporarily from any FUSE mounted paths, Otherwise the fuse-zip command fails with "fusermount: failed to open current directory: permission denied" (this happens when mounting JARs from mounted JARs) */ if(vifm_chdir(cfg.fuse_home) != 0) { show_error_msg("FUSE MOUNT ERROR", "Can't chdir() to FUSE home"); return -1; } clear_before_mount = format_mount_command(mount_point, file_full_path, param, program, sizeof(buf), buf); status_bar_message("FUSE mounting selected file, please stand by.."); if(clear_before_mount) { def_prog_mode(); endwin(); } generate_tmp_file_name("vifm.errors", errors_file, sizeof(errors_file)); strcat(buf, " 2> "); strcat(buf, errors_file); LOG_INFO_MSG("FUSE mount command: `%s`", buf); status = background_and_wait_for_status(buf); clean_status_bar(); /* check child status */ if(!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { FILE *ef = fopen(errors_file, "r"); print_errors(ef); unlink(errors_file); werase(status_bar); /* remove the directory we created for the mount */ if(path_exists(mount_point)) rmdir(mount_point); show_error_msg("FUSE MOUNT ERROR", file_full_path); (void)vifm_chdir(view->curr_dir); return -1; } unlink(errors_file); status_bar_message("FUSE mount success"); fuse_item = malloc(sizeof(*fuse_item)); copy_str(fuse_item->source_file_name, sizeof(fuse_item->source_file_name), file_full_path); strcpy(fuse_item->source_file_dir, view->curr_dir); canonicalize_path(mount_point, fuse_item->mount_point, sizeof(fuse_item->mount_point)); fuse_item->mount_point_id = mount_point_id; fuse_item->next = NULL; if(fuse_mounts == NULL) fuse_mounts = fuse_item; else runner->next = fuse_item; return 0; }
void event_loop(const int *quit) { /* TODO: refactor this function event_loop(). */ LOG_FUNC_ENTER; const wchar_t *const prev_input_buf = curr_input_buf; const size_t *const prev_input_buf_pos = curr_input_buf_pos; wchar_t input_buf[128]; size_t input_buf_pos; int last_result = 0; int wait_for_enter = 0; int timeout = cfg.timeout_len; input_buf[0] = L'\0'; input_buf_pos = 0; curr_input_buf = &input_buf[0]; curr_input_buf_pos = &input_buf_pos; while(!*quit) { wint_t c; size_t counter; int got_input; if(!ensure_term_is_ready()) { wait_for_enter = 0; continue; } lwin.user_selection = 1; rwin.user_selection = 1; modes_pre(); /* Waits for timeout then skips if no keypress. Short-circuit if we're not * waiting for the next key after timeout. */ do { modes_periodic(); check_background_jobs(); got_input = get_char_async_loop(status_bar, &c, timeout) != ERR; if(!got_input && input_buf_pos == 0) { timeout = cfg.timeout_len; continue; } break; } while(1); /* Ensure that current working directory is set correctly (some pieces of * code rely on this). */ (void)vifm_chdir(flist_get_dir(curr_view)); if(got_input) { if(wait_for_enter) { wait_for_enter = 0; curr_stats.save_msg = 0; clean_status_bar(); if(c == L'\x0d') { continue; } } if(c == L'\x1a') /* Ctrl-Z */ { def_prog_mode(); endwin(); stop_process(); continue; } if(input_buf_pos < ARRAY_LEN(input_buf) - 2) { input_buf[input_buf_pos++] = c; input_buf[input_buf_pos] = L'\0'; } else { /* Recover from input buffer overflow by resetting its contents. */ reset_input_buf(input_buf, &input_buf_pos); clear_input_bar(); continue; } } counter = get_key_counter(); if(!got_input && last_result == KEYS_WAIT_SHORT) { last_result = execute_keys_timed_out(input_buf); counter = get_key_counter() - counter; assert(counter <= input_buf_pos); if(counter > 0) { memmove(input_buf, input_buf + counter, (wcslen(input_buf) - counter + 1)*sizeof(wchar_t)); } } else { if(got_input) { curr_stats.save_msg = 0; } last_result = execute_keys(input_buf); counter = get_key_counter() - counter; assert(counter <= input_buf_pos); if(counter > 0) { input_buf_pos -= counter; memmove(input_buf, input_buf + counter, (wcslen(input_buf) - counter + 1)*sizeof(wchar_t)); } if(last_result == KEYS_WAIT || last_result == KEYS_WAIT_SHORT) { if(got_input) { modupd_input_bar(input_buf); } if(last_result == KEYS_WAIT_SHORT && wcscmp(input_buf, L"\033") == 0) { timeout = 1; } if(counter > 0) { clear_input_bar(); } if(!curr_stats.save_msg && curr_view->selected_files && !vle_mode_is(CMDLINE_MODE)) { print_selected_msg(); } continue; } } timeout = cfg.timeout_len; process_scheduled_updates(); reset_input_buf(input_buf, &input_buf_pos); clear_input_bar(); if(is_status_bar_multiline()) { wait_for_enter = 1; update_all_windows(); continue; } /* Ensure that current working directory is set correctly (some pieces of * code rely on this). PWD could be changed during command execution, but * it should be correct for modes_post() in case of preview modes. */ (void)vifm_chdir(flist_get_dir(curr_view)); modes_post(); } curr_input_buf = prev_input_buf; curr_input_buf_pos = prev_input_buf_pos; }
/* * Main Loop * Everything is driven from this function with the exception of * signals which are handled in signals.c */ void main_loop(void) { LOG_FUNC_ENTER; int last_result = 0; int wait_enter = 0; int timeout = cfg.timeout_len; buf[0] = L'\0'; while(1) { wchar_t c; size_t counter; int ret; is_term_working(); #ifdef _WIN32 update_win_console(); #endif lwin.user_selection = 1; rwin.user_selection = 1; if(curr_stats.too_small_term > 0) { touchwin(stdscr); wrefresh(stdscr); mvwin(status_bar, 0, 0); wresize(status_bar, getmaxy(stdscr), getmaxx(stdscr)); werase(status_bar); waddstr(status_bar, "Terminal is too small for vifm"); touchwin(status_bar); wrefresh(status_bar); #ifndef _WIN32 pause(); #endif continue; } else if(curr_stats.too_small_term < 0) { wtimeout(status_bar, 0); while(wget_wch(status_bar, (wint_t*)&c) != ERR); curr_stats.too_small_term = 0; modes_redraw(); wtimeout(status_bar, cfg.timeout_len); wait_enter = 0; curr_stats.save_msg = 0; status_bar_message(""); } modes_pre(); /* This waits for timeout then skips if no keypress. */ ret = read_char(status_bar, (wint_t*)&c, timeout); /* Ensure that current working directory is set correctly (some pieces of * code rely on this). */ (void)vifm_chdir(curr_view->curr_dir); if(ret != ERR && pos != ARRAY_LEN(buf) - 2) { if(c == L'\x1a') /* Ctrl-Z */ { def_prog_mode(); endwin(); #ifndef _WIN32 { void (*saved_stp_sig_handler)(int) = signal(SIGTSTP, SIG_DFL); kill(0, SIGTSTP); signal(SIGTSTP, saved_stp_sig_handler); } #endif continue; } if(wait_enter) { wait_enter = 0; curr_stats.save_msg = 0; clean_status_bar(); if(c == L'\x0d') continue; } buf[pos++] = c; buf[pos] = L'\0'; } if(wait_enter && ret == ERR) continue; counter = get_key_counter(); if(ret == ERR && last_result == KEYS_WAIT_SHORT) { last_result = execute_keys_timed_out(buf); counter = get_key_counter() - counter; assert(counter <= pos); if(counter > 0) { memmove(buf, buf + counter, (wcslen(buf) - counter + 1)*sizeof(wchar_t)); } } else { if(ret != ERR) curr_stats.save_msg = 0; last_result = execute_keys(buf); counter = get_key_counter() - counter; assert(counter <= pos); if(counter > 0) { pos -= counter; memmove(buf, buf + counter, (wcslen(buf) - counter + 1)*sizeof(wchar_t)); } if(last_result == KEYS_WAIT || last_result == KEYS_WAIT_SHORT) { if(ret != ERR) modupd_input_bar(buf); if(last_result == KEYS_WAIT_SHORT && wcscmp(buf, L"\033") == 0) timeout = 1; if(counter > 0) clear_input_bar(); if(!curr_stats.save_msg && curr_view->selected_files && get_mode() != CMDLINE_MODE) print_selected_msg(); continue; } } timeout = cfg.timeout_len; process_scheduled_updates(); pos = 0; buf[0] = L'\0'; clear_input_bar(); if(is_status_bar_multiline()) { wait_enter = 1; update_all_windows(); continue; } /* Ensure that current working directory is set correctly (some pieces of * code rely on this). PWD could be changed during command execution, but * it should be correct for modes_post() in case of preview modes. */ (void)vifm_chdir(curr_view->curr_dir); modes_post(); } }