static int read_char(WINDOW *win, wint_t *c, int timeout) { static const int T = 150; static const int IPC_F = 10; int i; int result = ERR; for(i = 0; i <= timeout/T; i++) { int j; if(is_redraw_scheduled()) { modes_redraw(); } if(!is_status_bar_multiline() && !is_in_menu_like_mode() && get_mode() != CMDLINE_MODE) { check_if_filelists_have_changed(curr_view); if(curr_stats.number_of_windows != 1 && !curr_stats.view) check_if_filelists_have_changed(other_view); } check_background_jobs(); for(j = 0; j < IPC_F; j++) { ipc_check(); wtimeout(win, MIN(T, timeout)/IPC_F); if((result = wget_wch(win, c)) != ERR) break; if(is_redraw_scheduled()) { modes_redraw(); } } if(result != ERR) break; timeout -= T; } return result; }
/* Updates TUI or it's elements if something is scheduled. */ static void process_scheduled_updates(void) { if(is_redraw_scheduled()) { modes_redraw(); } process_scheduled_updates_of_view(curr_view); process_scheduled_updates_of_view(other_view); }
/* * 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)my_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; if(is_redraw_scheduled()) { modes_redraw(); } 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)my_chdir(curr_view->curr_dir); modes_post(); } }