From 3d4e8230fe8a367f511cff3d5af3beb6d408d2f4 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 24 Aug 2017 20:52:33 -0400 Subject: [PATCH] move character iteration logic from BufferView to BufferLineWalker --- src/core/BufferLineWalker.cc | 101 +++++++++++++++++++++++++++++++++++ src/core/BufferLineWalker.h | 29 ++++++++++ src/core/BufferView.cc | 57 -------------------- src/core/BufferView.h | 1 - 4 files changed, 130 insertions(+), 58 deletions(-) create mode 100644 src/core/BufferLineWalker.cc create mode 100644 src/core/BufferLineWalker.h diff --git a/src/core/BufferLineWalker.cc b/src/core/BufferLineWalker.cc new file mode 100644 index 0000000..77e6305 --- /dev/null +++ b/src/core/BufferLineWalker.cc @@ -0,0 +1,101 @@ +#include "BufferLineWalker.h" + +/** + * Construct a BufferLineWalker. + */ +BufferLineWalker::BufferLineWalker( + std::shared_ptr buffer, + CharacterWidthDeterminer & character_width_determiner) + : m_buffer(buffer), + m_character_width_determiner(character_width_determiner) +{ + m_width = 1; +} + +/** + * Set the view width. + * + * @param width View width. + */ +void BufferLineWalker::set_width(int width) +{ + m_width = std::max(1, width); +} + +/** + * Invoke the callback for each character in the buffer line, wrapping to the + * next screen line and taking into account multi-column characters. + * + * Callback parameters: + * - row_offset + * - screen column + * - virtual column + * - character width + * - buffer iterator + * If the callback function returns true, iteration continues. Otherwise + * iteration is terminated. + * + * @param start_of_line Buffer iterator pointing to the beginning of the buffer line. + * @param callback Function to call for each character in the line. + */ +void BufferLineWalker::walk_line( + const Buffer::Iterator & start_of_line, + std::function callback) +{ + 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; + } + int c_width; + if (code_point == '\t') + { + uint8_t tabstop = m_buffer->tabstop(); + c_width = tabstop - virtual_column % tabstop; + } + else + { + c_width = m_character_width_determiner(code_point); + if (((screen_column + c_width) > m_width) && + (screen_column > 0)) + { + row_offset++; + screen_column = 0; + } + } + if (!callback(row_offset, screen_column, virtual_column, c_width, i)) + { + break; + } + virtual_column += c_width; + if (code_point == '\t') + { + screen_column += c_width; + while (screen_column >= m_width) + { + screen_column -= m_width; + row_offset++; + } + } + else + { + if ((screen_column + c_width) >= m_width) + { + row_offset++; + screen_column = 0; + } + else + { + screen_column += c_width; + } + } + i.go_forward(); + } +} diff --git a/src/core/BufferLineWalker.h b/src/core/BufferLineWalker.h new file mode 100644 index 0000000..56f51b8 --- /dev/null +++ b/src/core/BufferLineWalker.h @@ -0,0 +1,29 @@ +#ifndef BUFFERLINEWALKER_H +#define BUFFERLINEWALKER_H + +#include "Buffer.h" +#include "CharacterWidthDeterminer.h" +#include + +/** + * Provides functionality to walk a line of a buffer taking into account the + * view width and multi-column characters. + */ +class BufferLineWalker +{ +public: + BufferLineWalker( + std::shared_ptr buffer, + CharacterWidthDeterminer & character_width_determiner); + void set_width(int width); + void walk_line( + const Buffer::Iterator & start_of_line, + std::function callback); + +protected: + std::shared_ptr m_buffer; + CharacterWidthDeterminer & m_character_width_determiner; + int m_width; +}; + +#endif diff --git a/src/core/BufferView.cc b/src/core/BufferView.cc index a075328..7d0168b 100644 --- a/src/core/BufferView.cc +++ b/src/core/BufferView.cc @@ -23,60 +23,3 @@ void BufferView::set_scroll_offset(int scroll_offset) { m_scroll_offset = std::max(0, scroll_offset); } - -void BufferView::iter_cols(const Buffer::Iterator & start_of_line, std::function callback) -{ - 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; - } - int c_width; - if (code_point == '\t') - { - uint8_t tabstop = m_buffer->tabstop(); - c_width = tabstop - virtual_column % tabstop; - } - else - { - c_width = m_character_width_determiner(code_point); - if (((screen_column + c_width) > m_width) && - (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_width) - { - screen_column -= m_width; - row_offset++; - } - } - else - { - if ((screen_column + c_width) >= m_width) - { - row_offset++; - screen_column = 0; - } - else - { - screen_column += c_width; - } - } - i.go_forward(); - } -} diff --git a/src/core/BufferView.h b/src/core/BufferView.h index 5856afe..5f95a4f 100644 --- a/src/core/BufferView.h +++ b/src/core/BufferView.h @@ -18,7 +18,6 @@ public: void resize(int width, int height); void set_scroll_offset(int scroll_offset); void iter_lines(std::function callback); - void iter_cols(const Buffer::Iterator & start_of_line, std::function callback); protected: std::shared_ptr m_buffer;