jes/src-c/core/BufferLineWalker.cc
2018-07-25 20:47:02 -04:00

102 lines
2.4 KiB
C++

#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> buffer,
std::shared_ptr<Buffer::Iterator> 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<Buffer::Iterator>(*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();
}