add BufferPane::walk_line() to commonize logic for laying out a line to the screen
This commit is contained in:
parent
24fced221f
commit
08dab099a7
@ -15,36 +15,53 @@ void BufferPane::resize(int width, int height)
|
|||||||
m_rows = std::max(1, (m_height + m_window->font()->get_line_height() - 1) / m_window->font()->get_line_height());
|
m_rows = std::max(1, (m_height + m_window->font()->get_line_height() - 1) / m_window->font()->get_line_height());
|
||||||
}
|
}
|
||||||
|
|
||||||
int BufferPane::rows_in_line(const Buffer::Iterator & start_of_line)
|
void BufferPane::walk_line(const Buffer::Iterator & start_of_line, std::function<void(int, int, int, int, const Buffer::Iterator &)> callback)
|
||||||
{
|
{
|
||||||
int rows = 1;
|
int row_offset = 0;
|
||||||
int screen_column = 0;
|
int screen_column = 0;
|
||||||
|
int virtual_column = 0;
|
||||||
Buffer::Iterator i = start_of_line;
|
Buffer::Iterator i = start_of_line;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
uint32_t code_point = *i;
|
uint32_t code_point = *i;
|
||||||
if ((code_point == '\n') || (!i.valid()))
|
if ((code_point == '\n') || (!i.valid()))
|
||||||
{
|
{
|
||||||
|
callback(row_offset, screen_column, virtual_column, 0, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (code_point == '\t')
|
int c_width;
|
||||||
|
if (code_point == '\t')
|
||||||
{
|
{
|
||||||
uint8_t tabstop = m_buffer->tabstop();
|
uint8_t tabstop = m_buffer->tabstop();
|
||||||
screen_column += tabstop - screen_column % tabstop;
|
c_width = tabstop - screen_column % tabstop;
|
||||||
if (screen_column > m_columns)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c_width = character_width(code_point);
|
||||||
|
}
|
||||||
|
if (((screen_column + c_width) > m_columns) &&
|
||||||
|
(screen_column > 0))
|
||||||
|
{
|
||||||
|
row_offset++;
|
||||||
|
screen_column = 0;
|
||||||
|
}
|
||||||
|
callback(row_offset, screen_column, virtual_column, c_width, i);
|
||||||
|
virtual_column += c_width;
|
||||||
|
if (code_point == '\t')
|
||||||
|
{
|
||||||
|
screen_column += c_width;
|
||||||
|
while (screen_column >= m_columns)
|
||||||
{
|
{
|
||||||
screen_column -= m_columns;
|
screen_column -= m_columns;
|
||||||
rows++;
|
row_offset++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int c_width = character_width(code_point);
|
if ((screen_column + c_width) >= m_columns)
|
||||||
if (((screen_column + c_width) > m_columns) &&
|
|
||||||
(c_width <= m_columns))
|
|
||||||
{
|
{
|
||||||
rows++;
|
row_offset++;
|
||||||
screen_column = c_width;
|
screen_column = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -53,63 +70,36 @@ int BufferPane::rows_in_line(const Buffer::Iterator & start_of_line)
|
|||||||
}
|
}
|
||||||
i.go_forward();
|
i.go_forward();
|
||||||
}
|
}
|
||||||
return rows;
|
}
|
||||||
|
|
||||||
|
int BufferPane::rows_in_line(const Buffer::Iterator & start_of_line)
|
||||||
|
{
|
||||||
|
int saved_row_offset;
|
||||||
|
walk_line(start_of_line, [&saved_row_offset](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & i) {
|
||||||
|
uint32_t code_point = *i;
|
||||||
|
if ((code_point != '\n') && (code_point != 0xFFFFFFFFu))
|
||||||
|
{
|
||||||
|
saved_row_offset = row_offset;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return saved_row_offset + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BufferPane::rows_in_line_with_iterator_offset(const Buffer::Iterator & start_of_line, const Buffer::Iterator & reference, int * iterator_row_offset)
|
int BufferPane::rows_in_line_with_iterator_offset(const Buffer::Iterator & start_of_line, const Buffer::Iterator & reference, int * iterator_row_offset)
|
||||||
{
|
{
|
||||||
int rows = 1;
|
int saved_row_offset;
|
||||||
int screen_column = 0;
|
walk_line(start_of_line, [&saved_row_offset, &reference, &iterator_row_offset](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & i) {
|
||||||
Buffer::Iterator i = start_of_line;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
uint32_t code_point = *i;
|
uint32_t code_point = *i;
|
||||||
if ((code_point == '\n') || (!i.valid()))
|
|
||||||
{
|
|
||||||
if (i == reference)
|
|
||||||
{
|
|
||||||
if (screen_column == m_columns)
|
|
||||||
{
|
|
||||||
*iterator_row_offset = rows;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*iterator_row_offset = rows - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (code_point == '\t')
|
|
||||||
{
|
|
||||||
uint8_t tabstop = m_buffer->tabstop();
|
|
||||||
screen_column += tabstop - screen_column % tabstop;
|
|
||||||
if (screen_column > m_columns)
|
|
||||||
{
|
|
||||||
screen_column -= m_columns;
|
|
||||||
rows++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int c_width = character_width(code_point);
|
|
||||||
if (((screen_column + c_width) > m_columns) &&
|
|
||||||
(c_width <= m_columns))
|
|
||||||
{
|
|
||||||
rows++;
|
|
||||||
screen_column = c_width;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
screen_column += c_width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == reference)
|
if (i == reference)
|
||||||
{
|
{
|
||||||
*iterator_row_offset = rows;
|
*iterator_row_offset = row_offset;
|
||||||
}
|
}
|
||||||
i.go_forward();
|
if ((code_point != '\n') && (code_point != 0xFFFFFFFFu))
|
||||||
}
|
{
|
||||||
return rows;
|
saved_row_offset = row_offset;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return saved_row_offset + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BufferPane::screen_rows_below_line(const Buffer::Iterator & line)
|
int BufferPane::screen_rows_below_line(const Buffer::Iterator & line)
|
||||||
@ -189,81 +179,33 @@ void BufferPane::draw()
|
|||||||
|
|
||||||
int BufferPane::draw_buffer_line(int screen_row, const Buffer::Iterator & start_of_line)
|
int BufferPane::draw_buffer_line(int screen_row, const Buffer::Iterator & start_of_line)
|
||||||
{
|
{
|
||||||
int row_offset = 0;
|
int saved_row_offset = 0;
|
||||||
int screen_column = 0;
|
walk_line(start_of_line, [this, &saved_row_offset, &screen_row](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & i) {
|
||||||
int virtual_column = 0;
|
|
||||||
Buffer::Iterator i = start_of_line;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
uint32_t code_point = *i;
|
uint32_t code_point = *i;
|
||||||
if ((code_point == '\n') || (!i.valid()))
|
int draw_row = screen_row + row_offset;
|
||||||
|
int x = col_x(screen_column);
|
||||||
|
int y = row_y(draw_row);
|
||||||
|
if ((draw_row >= 0) && (draw_row < m_rows))
|
||||||
{
|
{
|
||||||
if (i == *m_iterator)
|
if (i == *m_iterator)
|
||||||
{
|
{
|
||||||
if (screen_column == m_columns)
|
/* TODO: highlight multi-column characters */
|
||||||
{
|
draw_cursor(x, y, false);
|
||||||
int x = col_x(0);
|
|
||||||
int y = row_y(screen_row + row_offset + 1);
|
|
||||||
draw_cursor(x, y, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int x = col_x(screen_column);
|
|
||||||
int y = row_y(screen_row + row_offset);
|
|
||||||
draw_cursor(x, y, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
if ((code_point == '\n') || (code_point == 0xFFFFFFFFu))
|
||||||
}
|
|
||||||
else if (code_point == '\t')
|
|
||||||
{
|
|
||||||
uint8_t tabstop = m_buffer->tabstop();
|
|
||||||
int col_increment = tabstop - screen_column % tabstop;
|
|
||||||
virtual_column += col_increment;
|
|
||||||
screen_column += col_increment;
|
|
||||||
if (screen_column > m_columns)
|
|
||||||
{
|
{
|
||||||
screen_column -= m_columns;
|
|
||||||
row_offset++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int c_width = character_width(code_point);
|
|
||||||
virtual_column += c_width;
|
|
||||||
if (((screen_column + c_width) > m_columns) &&
|
|
||||||
(c_width <= m_columns))
|
|
||||||
{
|
|
||||||
row_offset++;
|
|
||||||
screen_column = c_width;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
screen_column += c_width;
|
saved_row_offset = row_offset;
|
||||||
|
if ((code_point != '\t') && (code_point != ' '))
|
||||||
|
{
|
||||||
|
m_window->gl()->draw_character(win_x(x), win_y(y), code_point, *m_window->font());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int draw_row = screen_row + row_offset;
|
});
|
||||||
if (draw_row >= m_rows)
|
return saved_row_offset + 1;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (draw_row >= 0)
|
|
||||||
{
|
|
||||||
int x = col_x(screen_column);
|
|
||||||
int y = row_y(screen_row + row_offset);
|
|
||||||
if (i == *m_iterator)
|
|
||||||
{
|
|
||||||
draw_cursor(x, y, false);
|
|
||||||
}
|
|
||||||
uint32_t c = *i;
|
|
||||||
if ((c != '\t') && (c != ' '))
|
|
||||||
{
|
|
||||||
m_window->gl()->draw_character(win_x(x), win_y(y), c, *m_window->font());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i.go_forward();
|
|
||||||
}
|
|
||||||
return row_offset + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int BufferPane::character_width(uint32_t character)
|
int BufferPane::character_width(uint32_t character)
|
||||||
|
@ -40,6 +40,7 @@ protected:
|
|||||||
int screen_rows_below_line(const Buffer::Iterator & line);
|
int screen_rows_below_line(const Buffer::Iterator & line);
|
||||||
int screen_rows_above_line(const Buffer::Iterator & line, std::list<std::pair<int, Buffer::Iterator>> backward_lines);
|
int screen_rows_above_line(const Buffer::Iterator & line, std::list<std::pair<int, Buffer::Iterator>> backward_lines);
|
||||||
int update_cursor_row(std::list<std::pair<int, Buffer::Iterator>> backward_lines);
|
int update_cursor_row(std::list<std::pair<int, Buffer::Iterator>> backward_lines);
|
||||||
|
void walk_line(const Buffer::Iterator & start_of_line, std::function<void(int, int, int, int, const Buffer::Iterator &)> callback);
|
||||||
int col_x(int col)
|
int col_x(int col)
|
||||||
{
|
{
|
||||||
return col * m_window->font()->get_advance();
|
return col * m_window->font()->get_advance();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user