#include "BufferLineWalker.h" /** * Construct a BufferLineWalker. * * @param buffer The Buffer we're iterating. * @param start_of_line Buffer iterator pointing to the beginning of the buffer line. * @param view_width View width, beyond which characters will wrap to the next line. * @param character_width_determiner Functor to return the width (in columns) of a character. */ BufferLineWalker::BufferLineWalker( std::shared_ptr buffer, std::shared_ptr start_of_line, int view_width, CharacterWidthDeterminer & character_width_determiner) : m_buffer(buffer), m_character_width_determiner(character_width_determiner) { m_view_width = view_width; m_row_offset = 0; m_screen_column = 0; m_virtual_column = 0; m_iterator = std::make_shared(*start_of_line); process_new_character(); } void BufferLineWalker::process_new_character() { if ((!m_iterator) || (!m_iterator->valid())) { m_code_point = '\n'; m_character_width = 0; return; } m_code_point = **m_iterator; if (m_code_point == '\n') { m_character_width = 0; return; } if (m_code_point == '\t') { uint8_t tabstop = m_buffer->tabstop(); m_character_width = tabstop - m_virtual_column % tabstop; return; } m_character_width = m_character_width_determiner(m_code_point); if (((m_screen_column + m_character_width) > m_view_width) && (m_screen_column > 0)) { m_row_offset++; m_screen_column = 0; } } void BufferLineWalker::operator++(int unused) { if (!m_iterator) return; if ((m_code_point == '\n') || (!m_iterator->valid())) { m_code_point = '\n'; m_iterator.reset(); return; } /* Adjust virtual column. */ m_virtual_column += m_character_width; /* Adjust screen position. */ if (m_code_point == '\t') { m_screen_column += m_character_width; while (m_screen_column >= m_view_width) { m_screen_column -= m_view_width; m_row_offset++; } } else { if ((m_screen_column + m_character_width) >= m_view_width) { m_row_offset++; m_screen_column = 0; } else { m_screen_column += m_character_width; } } m_iterator->go_forward(); process_new_character(); }