185 lines
3.5 KiB
C++
185 lines
3.5 KiB
C++
#include "Buffer.h"
|
|
|
|
bool Buffer::Cursor::is_start_of_line()
|
|
{
|
|
Iterator i2 = m_iterator;
|
|
if (!i2.check_go_back())
|
|
{
|
|
/* Iterator cannot go backwards so it is at beginning of buffer. */
|
|
return true;
|
|
}
|
|
return *i2 == '\n';
|
|
}
|
|
|
|
bool Buffer::Cursor::is_end_of_line(bool allow_eol)
|
|
{
|
|
if (*m_iterator == '\n')
|
|
{
|
|
return true;
|
|
}
|
|
if (!allow_eol)
|
|
{
|
|
Iterator i2 = m_iterator;
|
|
i2.go_forward();
|
|
if (*i2 == '\n')
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Buffer::Cursor::go_start_of_line()
|
|
{
|
|
bool moved = false;
|
|
Iterator i2 = m_iterator;
|
|
for (;;)
|
|
{
|
|
i2.go_back();
|
|
if (i2.valid() && (*i2 != '\n'))
|
|
{
|
|
moved = true;
|
|
m_iterator = i2;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (moved)
|
|
{
|
|
init_column();
|
|
}
|
|
return moved;
|
|
}
|
|
|
|
bool Buffer::Cursor::go_end_of_line(bool allow_eol)
|
|
{
|
|
bool moved = false;
|
|
if (go_right(allow_eol))
|
|
{
|
|
moved = true;
|
|
}
|
|
while (go_right(allow_eol))
|
|
{
|
|
;
|
|
}
|
|
return moved;
|
|
}
|
|
|
|
bool Buffer::Cursor::go_left()
|
|
{
|
|
if (!is_start_of_line())
|
|
{
|
|
uint32_t chr = *m_iterator;
|
|
if (m_iterator.check_go_back())
|
|
{
|
|
if (chr == '\t')
|
|
{
|
|
calculate_column();
|
|
}
|
|
else
|
|
{
|
|
/* TODO: handle multi-column characters */
|
|
m_column--;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Buffer::Cursor::go_right(bool allow_eol)
|
|
{
|
|
if (!is_end_of_line(allow_eol))
|
|
{
|
|
if (m_iterator.check_go_forward())
|
|
{
|
|
uint32_t chr = *m_iterator;
|
|
if (chr == '\t')
|
|
{
|
|
uint8_t tabstop = m_iterator.buffer()->tabstop();
|
|
m_column += tabstop - (m_column + 1u) % tabstop;
|
|
}
|
|
else
|
|
{
|
|
/* TODO: handle multi-column characters */
|
|
m_column++;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Buffer::Cursor::go_up(size_t target_column)
|
|
{
|
|
Buffer::Cursor c2 = *this;
|
|
c2.go_start_of_line();
|
|
if (!c2.m_iterator.check_go_back())
|
|
{
|
|
return false;
|
|
}
|
|
c2.go_start_of_line();
|
|
*this = c2;
|
|
m_line--;
|
|
m_column = 0u;
|
|
forward_to_column(target_column);
|
|
return true;
|
|
}
|
|
|
|
bool Buffer::Cursor::go_down(size_t target_column)
|
|
{
|
|
Buffer::Cursor c2 = *this;
|
|
c2.go_end_of_line(true);
|
|
if (!c2.m_iterator.check_go_forward())
|
|
{
|
|
return false;
|
|
}
|
|
*this = c2;
|
|
m_line++;
|
|
m_column = 0u;
|
|
forward_to_column(target_column);
|
|
return true;
|
|
}
|
|
|
|
void Buffer::Cursor::init_column()
|
|
{
|
|
if (*m_iterator == '\t')
|
|
{
|
|
m_column = m_iterator.buffer()->tabstop() - 1u;
|
|
}
|
|
else
|
|
{
|
|
m_column = 0u;
|
|
}
|
|
}
|
|
|
|
void Buffer::Cursor::calculate_column()
|
|
{
|
|
Buffer::Cursor tmp_cursor = *this;
|
|
tmp_cursor.go_start_of_line();
|
|
while (tmp_cursor < *this)
|
|
{
|
|
tmp_cursor.go_right(true);
|
|
}
|
|
m_column = tmp_cursor.m_column;
|
|
}
|
|
|
|
void Buffer::Cursor::forward_to_column(size_t target_column)
|
|
{
|
|
int32_t diff = abs((int32_t)(target_column - m_column));
|
|
if (diff == 0)
|
|
return;
|
|
while (go_right(false))
|
|
{
|
|
int32_t new_diff = abs((int32_t)(target_column - m_column));
|
|
if (new_diff > diff)
|
|
{
|
|
go_left();
|
|
return;
|
|
}
|
|
diff = new_diff;
|
|
}
|
|
}
|