Beispiel #1
0
/* Adds decorations like ellipsis to the output.  Returns actual align type used
 * for the column (might not match col->info.align). */
static AlignType
decorate_output(const column_t *col, char buf[], size_t max_line_width)
{
	const size_t len = get_width_on_screen(buf);
	const size_t max_col_width = calculate_max_width(col, len, max_line_width);
	const int too_long = len > max_col_width;
	AlignType result;

	if(!too_long)
	{
		return (col->info.align == AT_RIGHT ? AT_RIGHT : AT_LEFT);
	}

	if(col->info.align == AT_LEFT ||
			(col->info.align == AT_DYN && len <= max_col_width))
	{
		const size_t truncate_pos = utf8_strsnlen(buf, max_col_width);
		buf[truncate_pos] = '\0';
		result = AT_LEFT;
	}
	else
	{
		int extra_spaces;

		const size_t truncate_pos = utf8_strsnlen(buf, len - max_col_width);
		const char *new_beginning = buf + truncate_pos;

		extra_spaces = 0;
		while(get_width_on_screen(new_beginning) > max_col_width)
		{
			++extra_spaces;
			new_beginning += utf8_chrw(new_beginning);
		}

		memmove(buf + extra_spaces, new_beginning, strlen(new_beginning) + 1);
		if(extra_spaces != 0)
		{
			memset(buf, ' ', extra_spaces);
		}

		assert(get_width_on_screen(buf) == max_col_width && "Column isn't filled.");
		result = AT_RIGHT;
	}

	if(col->info.cropping == CT_ELLIPSIS)
	{
		add_ellipsis(result, buf);
	}

	return result;
}
Beispiel #2
0
/* Adds ellipsis to the string in buf not changing enlarging its length (at most
 * three first or last characters are replaced). */
static void
add_ellipsis(AlignType align, char buf[])
{
	const size_t len = get_width_on_screen(buf);
	const size_t dot_count = MIN(len, MAX_ELLIPSIS_DOT_COUNT);
	if(align == AT_LEFT)
	{
		const size_t width_limit = len - dot_count;
		const size_t pos = utf8_strsnlen(buf, width_limit);
		memset(buf + pos, '.', dot_count);
		buf[pos + dot_count] = '\0';
	}
	else
	{
		const char *new_beginning = buf;
		size_t skipped = 0;
		while(skipped < dot_count)
		{
			skipped += utf8_chrsw(new_beginning);
			new_beginning += utf8_chrw(new_beginning);
		}

		memmove(buf + dot_count, new_beginning, strlen(new_beginning) + 1);
		memset(buf, '.', dot_count);
	}
}
Beispiel #3
0
void
columns_format_line(columns_t *cols, const void *data, size_t max_line_width)
{
	char prev_col_buf[1024 + 1];
	size_t prev_col_start = 0UL;
	prev_col_buf[0] = '\0';

	size_t i;
	size_t prev_col_end = 0;

	recalculate_if_needed(cols, max_line_width);

	for(i = 0U; i < cols->count; ++i)
	{
		/* Use big buffer to hold whole item so there will be no issues with right
		 * aligned fields. */
		char col_buffer[sizeof(prev_col_buf)];
		char full_column[sizeof(prev_col_buf)];
		size_t cur_col_start;
		AlignType align;
		const column_t *const col = &cols->list[i];

		col->func(col->info.column_id, data, sizeof(col_buffer), col_buffer);
		strcpy(full_column, col_buffer);
		align = decorate_output(col, col_buffer, max_line_width);
		cur_col_start = calculate_start_pos(col, col_buffer, align);

		/* Ensure that we are not trying to draw current column in the middle of a
		 * character inside previous column. */
		if(prev_col_end > cur_col_start)
		{
			const size_t prev_col_max_width = (cur_col_start > prev_col_start)
			                                ? (cur_col_start - prev_col_start)
			                                : 0UL;
			const size_t break_point = utf8_strsnlen(prev_col_buf,
					prev_col_max_width);
			prev_col_buf[break_point] = '\0';
			fill_gap_pos(data, prev_col_start + get_width_on_screen(prev_col_buf),
					cur_col_start);
		}
		else
		{
			fill_gap_pos(data, prev_col_end, cur_col_start);
		}

		print_func(data, col->info.column_id, col_buffer, cur_col_start, align,
				full_column);

		prev_col_end = cur_col_start + get_width_on_screen(col_buffer);

		/* Store information about the current column for usage on the next
		 * iteration. */
		strcpy(prev_col_buf, col_buffer);
		prev_col_start = cur_col_start;
	}

	fill_gap_pos(data, prev_col_end, max_line_width);
}
Beispiel #4
0
TEST(get_real_string_width_in_the_middle_b, IF(utf8_locale))
{
#define ENDING "丝刀"
	const char utf8_str[] = "师从螺" ENDING;
	const char utf8_end[] = ENDING;
#undef ENDING
	const size_t expected_len = strlen(utf8_str) - strlen(utf8_end);
	const size_t calculated_len = utf8_strsnlen(utf8_str, 7);
	assert_int_equal(expected_len, calculated_len);
}
Beispiel #5
0
/* Retrieves beginning of the text that should be displayed.  Returns the
 * beginning. */
static const char *
get_text_beginning(void)
{
    int skipped = 0;
    const char *text_piece = text + data[curr_line][2];
    /* Skip invisible virtual lines (those that are above current one). */
    while(skipped < curr_vline - data[curr_line][0])
    {
        text_piece += utf8_strsnlen(text_piece, viewport_width);
        ++skipped;
    }
    return text_piece;
}
Beispiel #6
0
/* Formats status line in the "old way" (before introduction of 'statusline'
 * option). */
static void
update_stat_window_old(FileView *view, int lazy_redraw)
{
	const dir_entry_t *const entry = &view->dir_entry[view->list_pos];
	char name_buf[160*2 + 1];
	char perm_buf[26];
	char size_buf[56];
	char id_buf[52];
	int x;
	int cur_x;
	size_t print_width;
	char *filename;

	x = getmaxx(stdscr);
	wresize(stat_win, 1, x);
	wbkgdset(stat_win, COLOR_PAIR(cfg.cs.pair[STATUS_LINE_COLOR]) |
			cfg.cs.color[STATUS_LINE_COLOR].attr);

	filename = get_current_file_name(view);
	print_width = utf8_strsnlen(filename, 20 + MAX(0, x - 83));
	snprintf(name_buf, MIN(sizeof(name_buf), print_width + 1), "%s", filename);
	friendly_size_notation(entry->size, sizeof(size_buf), size_buf);

	get_uid_string(entry, 0, sizeof(id_buf), id_buf);
	if(id_buf[0] != '\0')
		strcat(id_buf, ":");
	get_gid_string(entry, 0, sizeof(id_buf) - strlen(id_buf),
			id_buf + strlen(id_buf));
#ifndef _WIN32
	get_perm_string(perm_buf, sizeof(perm_buf), entry->mode);
#else
	snprintf(perm_buf, sizeof(perm_buf), "%s", attr_str_long(entry->attrs));
#endif

	werase(stat_win);
	cur_x = 2;
	checked_wmove(stat_win, 0, cur_x);
	wprint(stat_win, name_buf);
	cur_x += 22;
	if(x > 83)
		cur_x += x - 83;
	mvwaddstr(stat_win, 0, cur_x, size_buf);
	cur_x += 12;
	mvwaddstr(stat_win, 0, cur_x, perm_buf);
	cur_x += 11;

	snprintf(name_buf, sizeof(name_buf), "%d %s filtered", view->filtered,
			(view->filtered == 1) ? "file" : "files");
	if(view->filtered > 0)
		mvwaddstr(stat_win, 0, x - (strlen(name_buf) + 2), name_buf);

	if(cur_x + strlen(id_buf) + 1 > x - (strlen(name_buf) + 2))
		break_at(id_buf, ':');
	if(cur_x + strlen(id_buf) + 1 > x - (strlen(name_buf) + 2))
		id_buf[0] = '\0';
	mvwaddstr(stat_win, 0, cur_x, id_buf);

	if(lazy_redraw)
	{
		wnoutrefresh(stat_win);
	}
	else
	{
		wrefresh(stat_win);
	}
}
Beispiel #7
0
/* Formats status line in the "old way" (before introduction of 'statusline'
 * option). */
static void
update_stat_window_old(view_t *view, int lazy_redraw)
{
	const dir_entry_t *const curr = get_current_entry(view);
	char name_buf[160*2 + 1];
	char perm_buf[26];
	char size_buf[64];
	char id_buf[52];
	int x;
	int cur_x;
	size_t print_width;
	char *filename;

	if(curr == NULL || fentry_is_fake(curr))
	{
		werase(stat_win);
		refresh_window(stat_win, lazy_redraw);
		return;
	}

	x = getmaxx(stdscr);
	wresize(stat_win, 1, x);

	ui_set_bg(stat_win, &cfg.cs.color[STATUS_LINE_COLOR],
			cfg.cs.pair[STATUS_LINE_COLOR]);

	filename = get_current_file_name(view);
	print_width = utf8_strsnlen(filename, 20 + MAX(0, x - 83));
	copy_str(name_buf, MIN(sizeof(name_buf), print_width + 1), filename);
	friendly_size_notation(fentry_get_size(view, curr), sizeof(size_buf),
			size_buf);

	get_uid_string(curr, 0, sizeof(id_buf), id_buf);
	if(id_buf[0] != '\0')
		strcat(id_buf, ":");
	get_gid_string(curr, 0, sizeof(id_buf) - strlen(id_buf),
			id_buf + strlen(id_buf));
#ifndef _WIN32
	get_perm_string(perm_buf, sizeof(perm_buf), curr->mode);
#else
	copy_str(perm_buf, sizeof(perm_buf), attr_str_long(curr->attrs));
#endif

	werase(stat_win);
	cur_x = 2;
	checked_wmove(stat_win, 0, cur_x);
	wprint(stat_win, name_buf);
	cur_x += 22;
	if(x > 83)
		cur_x += x - 83;
	mvwaddstr(stat_win, 0, cur_x, size_buf);
	cur_x += 12;
	mvwaddstr(stat_win, 0, cur_x, perm_buf);
	cur_x += 11;

	snprintf(name_buf, sizeof(name_buf), "%d %s filtered", view->filtered,
			(view->filtered == 1) ? "file" : "files");
	if(view->filtered > 0)
		mvwaddstr(stat_win, 0, x - (strlen(name_buf) + 2), name_buf);

	if(cur_x + strlen(id_buf) + 1 > x - (strlen(name_buf) + 2))
		break_at(id_buf, ':');
	if(cur_x + strlen(id_buf) + 1 > x - (strlen(name_buf) + 2))
		id_buf[0] = '\0';
	mvwaddstr(stat_win, 0, cur_x, id_buf);

	refresh_window(stat_win, lazy_redraw);
}