From 08dab099a7bdd15a484be8e2965c1ea4145d28f3 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Wed, 21 Dec 2016 19:43:54 -0500 Subject: [PATCH] add BufferPane::walk_line() to commonize logic for laying out a line to the screen --- src/gui/BufferPane.cc | 190 +++++++++++++++--------------------------- src/gui/BufferPane.h | 1 + 2 files changed, 67 insertions(+), 124 deletions(-) diff --git a/src/gui/BufferPane.cc b/src/gui/BufferPane.cc index e2f6efd..77ddfcc 100644 --- a/src/gui/BufferPane.cc +++ b/src/gui/BufferPane.cc @@ -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()); } -int BufferPane::rows_in_line(const Buffer::Iterator & start_of_line) +void BufferPane::walk_line(const Buffer::Iterator & start_of_line, std::function callback) { - int rows = 1; + int row_offset = 0; int screen_column = 0; + int virtual_column = 0; Buffer::Iterator i = start_of_line; for (;;) { uint32_t code_point = *i; if ((code_point == '\n') || (!i.valid())) { + callback(row_offset, screen_column, virtual_column, 0, i); break; } - else if (code_point == '\t') + int c_width; + if (code_point == '\t') { uint8_t tabstop = m_buffer->tabstop(); - screen_column += tabstop - screen_column % tabstop; - if (screen_column > m_columns) + c_width = tabstop - screen_column % tabstop; + } + 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; - rows++; + row_offset++; } } else { - int c_width = character_width(code_point); - if (((screen_column + c_width) > m_columns) && - (c_width <= m_columns)) + if ((screen_column + c_width) >= m_columns) { - rows++; - screen_column = c_width; + row_offset++; + screen_column = 0; } else { @@ -53,63 +70,36 @@ int BufferPane::rows_in_line(const Buffer::Iterator & start_of_line) } 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 rows = 1; - int screen_column = 0; - Buffer::Iterator i = start_of_line; - for (;;) - { + int saved_row_offset; + 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) { 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) { - *iterator_row_offset = rows; + *iterator_row_offset = row_offset; } - i.go_forward(); - } - return rows; + if ((code_point != '\n') && (code_point != 0xFFFFFFFFu)) + { + saved_row_offset = row_offset; + } + }); + return saved_row_offset + 1; } 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 row_offset = 0; - int screen_column = 0; - int virtual_column = 0; - Buffer::Iterator i = start_of_line; - for (;;) - { + int saved_row_offset = 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) { 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 (screen_column == m_columns) - { - 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); - } + /* TODO: highlight multi-column characters */ + draw_cursor(x, y, false); } - break; - } - 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) + if ((code_point == '\n') || (code_point == 0xFFFFFFFFu)) { - 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 { - 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) - { - 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; + }); + return saved_row_offset + 1; } int BufferPane::character_width(uint32_t character) diff --git a/src/gui/BufferPane.h b/src/gui/BufferPane.h index 4a709ad..7eb892a 100644 --- a/src/gui/BufferPane.h +++ b/src/gui/BufferPane.h @@ -40,6 +40,7 @@ protected: int screen_rows_below_line(const Buffer::Iterator & line); int screen_rows_above_line(const Buffer::Iterator & line, std::list> backward_lines); int update_cursor_row(std::list> backward_lines); + void walk_line(const Buffer::Iterator & start_of_line, std::function callback); int col_x(int col) { return col * m_window->font()->get_advance();