#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; } }