102 lines
2.4 KiB
C++
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();
|
|
}
|