Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
/* Ensures that terminal is in proper state for a loop iteration.  Returns
 * non-zero if so, otherwise zero is returned. */
static int
ensure_term_is_ready(void)
{
	ui_update_term_state();

	update_terminal_settings();

	if(curr_stats.term_state == TS_TOO_SMALL)
	{
		ui_display_too_small_term_msg();
		wait_for_signal();
		return 0;
	}

	if(curr_stats.term_state == TS_BACK_TO_NORMAL)
	{
		wint_t c;

		wtimeout(status_bar, 0);
		while(compat_wget_wch(status_bar, &c) != ERR);
		curr_stats.term_state = TS_NORMAL;
		modes_redraw();
		wtimeout(status_bar, cfg.timeout_len);

		curr_stats.save_msg = 0;
		status_bar_message("");
	}

	return 1;
}
Ejemplo n.º 3
0
/* Ensures that terminal is in proper state for a loop iteration.  Returns
 * non-zero if so, otherwise zero is returned. */
static int
ensure_term_is_ready(void)
{
	ui_update_term_state();

	update_terminal_settings();

	if(curr_stats.term_state == TS_TOO_SMALL)
	{
		ui_display_too_small_term_msg();
		wait_for_signal();
		return 0;
	}

	if(curr_stats.term_state == TS_BACK_TO_NORMAL)
	{
		ui_drain_input();
		curr_stats.term_state = TS_NORMAL;
		modes_redraw();

		curr_stats.save_msg = 0;
		ui_sb_msg("");
	}

	return 1;
}
Ejemplo n.º 4
0
/* Internal function for displaying error messages to a user.  Automatically
 * skips whitespace in front of the message and does nothing for empty messages
 * (due to skipping whitespace-only are counted as empty). When the prompt_skip
 * isn't zero, asks user about successive messages.  Returns non-zero if all
 * successive messages should be skipped, otherwise zero is returned. */
static int
prompt_error_msg_internal(const char title[], const char message[],
		int prompt_skip)
{
	static int skip_until_started;

	if(curr_stats.load_stage == 0)
		return 1;
	if(curr_stats.load_stage < 2 && skip_until_started)
		return 1;

	message = skip_whitespace(message);
	if(*message == '\0')
	{
		return 0;
	}

	msg_kind = D_ERROR;

	redraw_error_msg(title, message, prompt_skip, 0);

	enter(MASK(R_OK) | (prompt_skip ? MASK(R_CANCEL) : 0));

	if(curr_stats.load_stage < 2)
		skip_until_started = (result == R_CANCEL);

	modes_update();
	if(curr_stats.need_update != UT_NONE)
		modes_redraw();

	return result == R_CANCEL;
}
Ejemplo n.º 5
0
/* 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);
}
Ejemplo n.º 6
0
/* Common implementation of prompt message.  The variants can be NULL. */
static void
prompt_msg_internal(const char title[], const char message[],
		const response_variant variants[])
{
	responses = variants;
	msg_kind = D_QUERY;

	redraw_error_msg(title, message, 0, 0);

	enter(variants == NULL ? MASK(R_YES, R_NO) : 0);

	modes_redraw();
}
Ejemplo n.º 7
0
void
stats_silence_ui(int more)
{
	if(more)
	{
		++curr_stats.silent_ui;
	}
	else if(--curr_stats.silent_ui == 0)
	{
		modes_redraw();
	}

	assert(curr_stats.silent_ui >= 0 && "Unbalanced calls to stats_silence_ui()");
}
Ejemplo n.º 8
0
/* Updates TUI or its elements if something is scheduled. */
static void
process_scheduled_updates(void)
{
	int need_redraw = 0;

	ui_stat_job_bar_check_for_updates();

	if(vle_mode_get_primary() != MENU_MODE)
	{
		need_redraw += (process_scheduled_updates_of_view(curr_view) != 0);
		need_redraw += (process_scheduled_updates_of_view(other_view) != 0);
	}

	need_redraw += (fetch_redraw_scheduled() != 0);

	if(need_redraw)
	{
		modes_redraw();
	}
}
Ejemplo n.º 9
0
Archivo: menus.c Proyecto: lyuts/vifm
/* Internal function for displaying error messages to a user.  Automatically
 * skips whitespace in front of the message and does nothing for empty messages
 * (due to skipping whitespace-only are counted as empty). When the prompt_skip
 * isn't zero, asks user about successive messages.  Returns non-zero if all
 * successive messages should be skipped, otherwise zero is returned. */
static int
prompt_error_msg_internal(const char title[], const char message[],
		int prompt_skip)
{
	static int skip_until_started;
	int key;

	if(curr_stats.load_stage == 0)
		return 1;
	if(curr_stats.load_stage < 2 && skip_until_started)
		return 1;

	message = skip_whitespace(message);
	if(*message == '\0')
	{
		return 0;
	}

	curr_stats.errmsg_shown = 1;

	redraw_error_msg(title, message, prompt_skip);

	do
		key = wgetch(error_win);
	while(key != 13 && (!prompt_skip || key != 3)); /* ascii Return, Ctrl-c */

	if(curr_stats.load_stage < 2)
		skip_until_started = key == 3;

	werase(error_win);
	wrefresh(error_win);

	curr_stats.errmsg_shown = 0;

	modes_update();
	if(curr_stats.need_update != UT_NONE)
		modes_redraw();

	return key == 3;
}
Ejemplo n.º 10
0
void
modes_redraw(void)
{
	LOG_FUNC_ENTER;

	static int in_here;

	if(curr_stats.load_stage < 2)
	{
		return;
	}

	if(in_here++ > 0)
	{
		/* TODO: is this still needed?  Update scheduling might have solved issues
		 * caused by asynchronous execution of this function in the past. */
		return;
	}

	if(curr_stats.term_state != TS_NORMAL)
	{
		update_screen(UT_REDRAW);
		goto finish;
	}

	if(vle_mode_is(CMDLINE_MODE))
	{
		redraw_cmdline();
		goto finish;
	}
	else if(vle_primary_mode_is(MENU_MODE))
	{
		menu_redraw();
		if(vle_mode_is(MSG_MODE))
		{
			redraw_msg_dialog(0);
		}
		goto finish;
	}
	else if(vle_mode_is(FILE_INFO_MODE))
	{
		redraw_file_info_dialog();
		goto finish;
	}

	update_screen(UT_REDRAW);

	if(curr_stats.save_msg)
	{
		status_bar_message(NULL);
	}

	if(vle_mode_is(SORT_MODE))
	{
		redraw_sort_dialog();
	}
	else if(vle_mode_is(CHANGE_MODE))
	{
		redraw_change_dialog();
	}
	else if(vle_mode_is(ATTR_MODE))
	{
		redraw_attr_dialog();
	}
	else if(vle_mode_is(VIEW_MODE))
	{
		view_redraw();
	}
	else if(vle_mode_is(MSG_MODE))
	{
		redraw_msg_dialog(0);
	}

finish:
	if(--in_here > 0)
	{
		modes_redraw();
	}
}
Ejemplo n.º 11
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 wait_for_suggestion = 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;

	/* Make sure to set the working directory once in order to have the
	 * desired state even before any events are processed. */
	(void)vifm_chdir(flist_get_dir(curr_view));

	while(!*quit)
	{
		wint_t c;
		size_t counter;
		int got_input;

		lwin.user_selection = 1;
		rwin.user_selection = 1;

		modes_pre();

		/* Waits for timeout then skips if no key press.  Short-circuit if we're not
		 * waiting for the next key after timeout. */
		do
		{
			const int actual_timeout = wait_for_suggestion
			                         ? MIN(timeout, cfg.sug.delay)
			                         : timeout;

			if(!ensure_term_is_ready())
			{
				wait_for_enter = 0;
				continue;
			}

			modes_periodic();

			bg_check();

			got_input = (get_char_async_loop(status_bar, &c, actual_timeout) != ERR);

			/* If suggestion delay timed out, reset it and wait the rest of the
			 * timeout. */
			if(!got_input && wait_for_suggestion)
			{
				wait_for_suggestion = 0;
				timeout -= actual_timeout;
				display_suggestion_box(input_buf);
				continue;
			}
			wait_for_suggestion = 0;

			if(!got_input && (input_buf_pos == 0 || last_result == KEYS_WAIT))
			{
				timeout = cfg.timeout_len;
				continue;
			}

			if(got_input && c == K(KEY_RESIZE))
			{
				modes_redraw();
				continue;
			}

			break;
		}
		while(1);

		suggestions_are_visible = 0;

		/* Ensure that current working directory is set correctly (some pieces of
		 * code rely on this, e.g. %c macro in current directory). */
		(void)vifm_chdir(flist_get_dir(curr_view));

		if(got_input)
		{
			if(wait_for_enter)
			{
				wait_for_enter = 0;
				curr_stats.save_msg = 0;
				ui_sb_clear();
				if(c == WC_CR)
				{
					continue;
				}
			}

			if(c == WC_C_z)
			{
				ui_shutdown();
				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 = vle_keys_counter();
		if(!got_input && last_result == KEYS_WAIT_SHORT)
		{
			hide_suggestion_box();

			last_result = vle_keys_exec_timed_out(input_buf);
			counter = vle_keys_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;
			}

			if(last_result == KEYS_WAIT || last_result == KEYS_WAIT_SHORT)
			{
				hide_suggestion_box();
			}

			last_result = vle_keys_exec(input_buf);

			counter = vle_keys_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(should_display_suggestion_box())
				{
					wait_for_suggestion = 1;
				}

				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(ui_sb_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;
}
Ejemplo n.º 12
0
/*
 * 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();
	}
}