コード例 #1
0
ファイル: menus.c プロジェクト: ychaim/vifm
/* Draws error message on the screen or redraws the last message when both
 * title_arg and message_arg are NULL. */
static void
redraw_error_msg(const char title_arg[], const char message_arg[],
		int prompt_skip)
{
	/* TODO: refactor this function redraw_error_msg() */

	static const char *title;
	static const char *message;
	static int ctrl_c;

	int sx, sy;
	int x, y;
	int z;
	const char *text;

	if(title_arg != NULL && message_arg != NULL)
	{
		title = title_arg;
		message = message_arg;
		ctrl_c = prompt_skip;
	}

	assert(message != NULL);

	curs_set(FALSE);
	werase(error_win);

	getmaxyx(stdscr, sy, sx);

	y = sy - 3 + !cfg.last_status;
	x = sx - 2;
	wresize(error_win, y, x);

	z = strlen(message);
	if(z <= x - 2 && strchr(message, '\n') == NULL)
	{
		y = 6;
		wresize(error_win, y, x);
		mvwin(error_win, (sy - y)/2, (sx - x)/2);
		checked_wmove(error_win, 2, (x - z)/2);
		wprint(error_win, message);
	}
	else
	{
		int i;
		int cy = 2;
		i = 0;
		while(i < z)
		{
			int j;
			char buf[x - 2 + 1];

			snprintf(buf, sizeof(buf), "%s", message + i);

			for(j = 0; buf[j] != '\0'; j++)
				if(buf[j] == '\n')
					break;

			if(buf[j] != '\0')
				i++;
			buf[j] = '\0';
			i += j;

			if(buf[0] == '\0')
				continue;

			y = cy + 4;
			mvwin(error_win, (sy - y)/2, (sx - x)/2);
			wresize(error_win, y, x);

			checked_wmove(error_win, cy++, 1);
			wprint(error_win, buf);
		}
	}

	box(error_win, 0, 0);
	if(title[0] != '\0')
		mvwprintw(error_win, 0, (x - strlen(title) - 2)/2, " %s ", title);

	if(curr_stats.errmsg_shown == 1)
	{
		if(ctrl_c)
		{
			text = "Press Return to continue or Ctrl-C to skip other error messages";
		}
		else
		{
			text = "Press Return to continue";
		}
	}
	else
	{
		text = "Enter [y]es or [n]o";
	}
	mvwaddstr(error_win, y - 2, (x - strlen(text))/2, text);
}
コード例 #2
0
ファイル: menus.c プロジェクト: ychaim/vifm
void
draw_menu(menu_info *m)
{
	int i;
	int win_len;
	int x, y;

	getmaxyx(menu_win, y, x);
	win_len = x;
	werase(menu_win);

	normalize_top(m);

	x = m->top;

	box(menu_win, 0, 0);
	wattron(menu_win, A_BOLD);
	checked_wmove(menu_win, 0, 3);
	wprint(menu_win, m->title);
	wattroff(menu_win, A_BOLD);

	for(i = 1; x < m->len; i++, x++)
	{
		int z, off;
		char *buf;
		char *ptr = NULL;
		col_attr_t col;
		int type = WIN_COLOR;

		chomp(m->items[x]);
		if((ptr = strchr(m->items[x], '\n')) || (ptr = strchr(m->items[x], '\r')))
			*ptr = '\0';

		col = cfg.cs.color[WIN_COLOR];

		if(cfg.hl_search && m->matches != NULL && m->matches[x])
		{
			mix_colors(&col, &cfg.cs.color[SELECTED_COLOR]);
			type = SELECTED_COLOR;
		}

		init_pair(DCOLOR_BASE + type, col.fg, col.bg);
		wattron(menu_win, COLOR_PAIR(DCOLOR_BASE + type) | col.attr);

		z = m->hor_pos;
		off = 0;
		while(z-- > 0 && m->items[x][off] != '\0')
		{
			size_t l = get_char_width(m->items[x] + off);
			off += l;
		}

		buf = strdup(m->items[x] + off);
		for(z = 0; buf[z] != '\0'; z++)
			if(buf[z] == '\t')
				buf[z] = ' ';

		checked_wmove(menu_win, i, 2);
		if(get_screen_string_length(buf) > win_len - 4)
		{
			size_t len = get_normal_utf8_string_widthn(buf, win_len - 3 - 4);
			memset(buf + len, ' ', strlen(buf) - len);
			buf[len + 3] = '\0';
			wprint(menu_win, buf);
			mvwaddstr(menu_win, i, win_len - 5, "...");
		}
		else
		{
			const size_t len = get_normal_utf8_string_widthn(buf, win_len - 4);
			buf[len] = '\0';
			wprint(menu_win, buf);
		}
		waddstr(menu_win, " ");

		free(buf);

		wattroff(menu_win, COLOR_PAIR(DCOLOR_BASE + type) | col.attr);

		if(i + 3 > y)
			break;
	}
}
コード例 #3
0
ファイル: menus.c プロジェクト: ychaim/vifm
void
clean_menu_position(menu_info *m)
{
	int x, z;
	int off = 0;
	char * buf = (char *)NULL;
	col_attr_t col;
	int type = MENU_COLOR;

	x = getmaxx(menu_win) + get_utf8_overhead(m->items[m->pos]);

	buf = malloc(x + 2);

	/* TODO: check if this can ever be false. */
	if(m->items[m->pos] != NULL)
	{
		z = m->hor_pos;
		while(z-- > 0 && m->items[m->pos][off] != '\0')
		{
			size_t l = get_char_width(m->items[m->pos] + off);
			off += l;
			x -= l - 1;
		}
		snprintf(buf, x, " %s", m->items[m->pos] + off);
	}
	else
	{
		buf[0] = '\0';
	}

	for(z = 0; buf[z] != '\0'; z++)
		if(buf[z] == '\t')
			buf[z] = ' ';

	for(z = strlen(buf); z < x; z++)
		buf[z] = ' ';

	buf[x] = ' ';
	buf[x + 1] = '\0';

	col = cfg.cs.color[WIN_COLOR];

	if(cfg.hl_search && m->matches != NULL && m->matches[m->pos])
	{
		mix_colors(&col, &cfg.cs.color[SELECTED_COLOR]);
		type = SELECTED_COLOR;
	}

	init_pair(DCOLOR_BASE + type, col.fg, col.bg);
	wattrset(menu_win, COLOR_PAIR(type + DCOLOR_BASE) | col.attr);

	checked_wmove(menu_win, m->current, 1);
	if(get_screen_string_length(m->items[m->pos] + off) > getmaxx(menu_win) - 4)
	{
		size_t len = get_normal_utf8_string_widthn(buf,
				getmaxx(menu_win) - 3 - 4 + 1);
		memset(buf + len, ' ', strlen(buf) - len);
		buf[len + 3] = '\0';
		wprint(menu_win, buf);
		mvwaddstr(menu_win, m->current, getmaxx(menu_win) - 5, "...");
	}
	else
	{
		size_t len = get_normal_utf8_string_widthn(buf, getmaxx(menu_win) - 4 + 1);
		buf[len] = '\0';
		wprint(menu_win, buf);
	}
	waddstr(menu_win, " ");

	wattroff(menu_win, COLOR_PAIR(type + DCOLOR_BASE) | col.attr);

	free(buf);
}
コード例 #4
0
ファイル: menus.c プロジェクト: ychaim/vifm
void
move_to_menu_pos(int pos, menu_info *m)
{
	/* TODO: refactor this function move_to_menu_pos() */

	int redraw = 0;
	int x, z;
	char *buf = NULL;
	col_attr_t col;
	int off = 0;

	pos = MIN(m->len - 1, MAX(0, pos));
	if(pos < 0)
		return;

	normalize_top(m);

	if(pos > get_last_visible_line(m))
	{
		m->top = pos - (m->win_rows - 2 - 1);
		redraw = 1;
	}
	else if(pos < m->top)
	{
		m->top = pos;
		redraw = 1;
	}

	if(cfg.scroll_off > 0)
	{
		int s = MIN(DIV_ROUND_UP(m->win_rows - 2, 2), cfg.scroll_off);
		if(pos - m->top < s && m->top > 0)
		{
			m->top -= s - (pos - m->top);
			normalize_top(m);
			redraw = 1;
		}
		if(pos > get_last_visible_line(m) - s)
		{
			m->top += s - (get_last_visible_line(m) - pos);
			normalize_top(m);
			redraw = 1;
		}
	}

	m->current = 1 + (pos - m->top);

	if(redraw)
		draw_menu(m);

	x = getmaxx(menu_win) + get_utf8_overhead(m->items[pos]);
	buf = malloc(x + 2);
	if(buf == NULL)
		return;
	/* TODO: check if this can be false. */
	if(m->items[pos] != NULL)
	{
		z = m->hor_pos;
		while(z-- > 0 && m->items[pos][off] != '\0')
		{
			size_t l = get_char_width(m->items[pos] + off);
			off += l;
			x -= l - 1;
		}

		snprintf(buf, x, " %s", m->items[pos] + off);
	}
	else
	{
		buf[0] = '\0';
	}

	for(z = 0; buf[z] != '\0'; z++)
		if(buf[z] == '\t')
			buf[z] = ' ';

	for(z = strlen(buf); z < x; z++)
		buf[z] = ' ';

	buf[x] = ' ';
	buf[x + 1] = '\0';

	col = cfg.cs.color[WIN_COLOR];

	if(cfg.hl_search && m->matches != NULL && m->matches[pos])
		mix_colors(&col, &cfg.cs.color[SELECTED_COLOR]);

	mix_colors(&col, &cfg.cs.color[CURR_LINE_COLOR]);

	init_pair(DCOLOR_BASE + MENU_CURRENT_COLOR, col.fg, col.bg);
	wattrset(menu_win, COLOR_PAIR(DCOLOR_BASE + MENU_CURRENT_COLOR) | col.attr);

	checked_wmove(menu_win, m->current, 1);
	if(get_screen_string_length(m->items[pos] + off) > getmaxx(menu_win) - 4)
	{
		size_t len = get_normal_utf8_string_widthn(buf,
				getmaxx(menu_win) - 3 - 4 + 1);
		memset(buf + len, ' ', strlen(buf) - len);
		buf[len + 3] = '\0';
		wprint(menu_win, buf);
		mvwaddstr(menu_win, m->current, getmaxx(menu_win) - 5, "...");
	}
	else
	{
		size_t len = get_normal_utf8_string_widthn(buf, getmaxx(menu_win) - 4 + 1);
		buf[len] = '\0';
		wprint(menu_win, buf);
	}
	waddstr(menu_win, " ");

	wattroff(menu_win, COLOR_PAIR(DCOLOR_BASE + MENU_CURRENT_COLOR) | col.attr);

	m->pos = pos;
	free(buf);
	show_position_in_menu(m);
}
コード例 #5
0
ファイル: msg_dialog.c プロジェクト: acklinr/vifm
/* Draws possibly centered formatted message with specified title and control
 * message on error_win. */
static void
draw_msg(const char title[], const char msg[], const char ctrl_msg[],
		int centered, int recommended_width)
{
	enum { margin = 1 };

	int sw, sh;
	int w, h;
	int max_h;
	int len;
	size_t ctrl_msg_n;
	size_t wctrl_msg;
	size_t i;
	int first_line_x = 1;
	const int first_line_y = 2;

	curs_set(0);

	getmaxyx(stdscr, sh, sw);

	ctrl_msg_n = MAX(measure_sub_lines(ctrl_msg, &wctrl_msg), 1U);

	max_h = sh - 2 - ctrl_msg_n + !cfg.display_statusline;
	h = max_h;
	/* The outermost condition is for VLA below (to calm static analyzers). */
	w = MAX(2 + 2*margin, MIN(sw - 2,
	        MAX(MAX(recommended_width, sw/3),
	            (int)MAX(wctrl_msg, determine_width(msg)) + 4)));
	wresize(error_win, h, w);

	werase(error_win);

	len = strlen(msg);
	if(len <= w - 2 && strchr(msg, '\n') == NULL)
	{
		first_line_x = (w - len)/2;
		h = 5 + ctrl_msg_n;
		wresize(error_win, h, w);
		mvwin(error_win, (sh - h)/2, (sw - w)/2);
		checked_wmove(error_win, first_line_y, first_line_x);
		wprint(error_win, msg);
	}
	else
	{
		int i = 0;
		int cy = first_line_y;
		while(i < len)
		{
			int j;
			char buf[w - 2 - 2*margin + 1];
			int cx;

			copy_str(buf, sizeof(buf), msg + i);

			for(j = 0; buf[j] != '\0'; j++)
				if(buf[j] == '\n')
					break;

			if(buf[j] != '\0')
				i++;
			buf[j] = '\0';
			i += j;

			if(buf[0] == '\0')
				continue;

			if(cy >= max_h - (int)ctrl_msg_n - 3)
			{
				/* Skip trailing part of the message if it's too long, just print how
				 * many lines we're omitting. */
				size_t max_len;
				const int more_lines = 1U + measure_sub_lines(msg + i, &max_len);
				snprintf(buf, sizeof(buf), "<<%d more line%s not shown>>", more_lines,
						(more_lines == 1) ? "" : "s");
				/* Make sure this is the last iteration of the loop. */
				i = len;
			}

			h = 1 + cy + 1 + ctrl_msg_n + 1;
			wresize(error_win, h, w);
			mvwin(error_win, (sh - h)/2, (sw - w)/2);

			cx = centered ? (w - utf8_strsw(buf))/2 : (1 + margin);
			if(cy == first_line_y)
			{
				first_line_x = cx;
			}
			checked_wmove(error_win, cy++, cx);
			wprint(error_win, buf);
		}
	}

	box(error_win, 0, 0);
	if(title[0] != '\0')
	{
		mvwprintw(error_win, 0, (w - strlen(title) - 2)/2, " %s ", title);
	}

	/* Print control message line by line. */
	for(i = ctrl_msg_n; i > 0U; --i)
	{
		const size_t len = strcspn(ctrl_msg, "\n");
		mvwaddnstr(error_win, h - i - 1, MAX(0, (w - (int)len)/2), ctrl_msg, len);
		ctrl_msg = skip_char(ctrl_msg + len + 1U, '/');
	}

	checked_wmove(error_win, first_line_y, first_line_x);
}