remove PieceTable

This commit is contained in:
Josh Holtrop 2016-11-01 21:44:01 -04:00
parent 65468bd2e5
commit fbca1f995a
7 changed files with 13 additions and 985 deletions

View File

@ -7,13 +7,11 @@
Buffer::Buffer() Buffer::Buffer()
{ {
piece_table = std::make_shared<PieceTable>();
m_file_buffer = nullptr; m_file_buffer = nullptr;
m_file_buffer_size = 0u; m_file_buffer_size = 0u;
m_eol_at_eof = true; m_eol_at_eof = true;
m_line_endings = LineEndings::LF; m_line_endings = LineEndings::LF;
m_encoding = Encoding::UTF_8; m_encoding = Encoding::UTF_8;
piece_table->encoding = m_encoding;
} }
Buffer::~Buffer() Buffer::~Buffer()
@ -38,7 +36,7 @@ bool Buffer::load_from_file(const char * filename)
return false; return false;
} }
m_file_buffer_size = ((unsigned long)file_size + System::page_size) & System::page_base_mask; m_file_buffer_size = ((unsigned long)file_size + 2u * System::page_size) & System::page_base_mask;
m_file_buffer = (uint8_t *)System::alloc_pages(m_file_buffer_size >> System::page_size_log); m_file_buffer = (uint8_t *)System::alloc_pages(m_file_buffer_size >> System::page_size_log);
if (m_file_buffer == NULL) if (m_file_buffer == NULL)
{ {
@ -52,22 +50,12 @@ bool Buffer::load_from_file(const char * filename)
} }
TextLoader text_loader; TextLoader text_loader;
text_loader.load_buffer(m_file_buffer, file_size); size_t loaded_size;
text_loader.load_buffer(m_file_buffer, file_size, &loaded_size);
piece_table = std::make_shared<PieceTable>();
for (auto it = text_loader.begin(); it != text_loader.end(); it++)
{
auto next = it;
next++;
bool eol = next != text_loader.end();
it->start[it->length] = PieceTable::INTERNAL_EOL;
piece_table->append_initial_line_piece(it->start, it->length + 1u, eol);
}
m_eol_at_eof = text_loader.get_eol_at_eof(); m_eol_at_eof = text_loader.get_eol_at_eof();
m_line_endings = text_loader.get_line_endings(); m_line_endings = text_loader.get_line_endings();
m_encoding = text_loader.get_encoding(); m_encoding = text_loader.get_encoding();
piece_table->encoding = m_encoding;
return true; return true;
} }
@ -80,31 +68,7 @@ bool Buffer::write_to_file(const char * filename)
return false; return false;
} }
uint32_t bytes_written = 0u; /* TODO */
for (auto piece = piece_table->start_piece->next;
piece != piece_table->end_piece;
piece = piece->next)
{
uint32_t length = piece->length;
if (piece->eol())
{
length--;
}
if (!file.write(piece->start, length))
{
return false;
}
bytes_written += length;
if (((piece->next != piece_table->end_piece) && piece->eol()) ||
(m_eol_at_eof && bytes_written > 0u))
{
if (!file.write(LineEndings::spans[m_line_endings]))
{
return false;
}
bytes_written += LineEndings::spans[m_line_endings].length;
}
}
return true; return true;
} }

View File

@ -3,15 +3,12 @@
#include <list> #include <list>
#include <memory> #include <memory>
#include "PieceTable.h"
#include "LineEndings.h" #include "LineEndings.h"
#include "Encoding.h" #include "Encoding.h"
class Buffer class Buffer
{ {
public: public:
std::shared_ptr<PieceTable> piece_table;
Buffer(); Buffer();
~Buffer(); ~Buffer();
bool load_from_file(const char * filename); bool load_from_file(const char * filename);

View File

@ -1,610 +0,0 @@
#include "PieceTable.h"
PieceTable::PieceTable()
{
m_piece_index = 0u;
start_piece = add_piece();
end_piece = add_piece();
start_piece->length = 0u;
end_piece->length = 0u;
start_piece->next = end_piece;
end_piece->prev = start_piece;
tabstop = 4u;
m_append_buffer_index = 0u;
m_changes_index = 0u;
}
void PieceTable::append_initial_line_piece(uint8_t * start, uint32_t length, bool eol)
{
Piece * piece = add_piece();
piece->prev = end_piece->prev;
piece->next = end_piece;
piece->start = start;
piece->length = length;
end_piece->prev->next = piece;
end_piece->prev = piece;
m_num_lines++;
}
std::shared_ptr<PieceTable::Cursor> PieceTable::add_cursor()
{
auto cursor = std::make_shared<Cursor>(this);
m_cursors.push_back(cursor);
return cursor;
}
PieceTable::Iterator::Iterator(PieceTable * pt)
{
piece_table = pt;
piece = pt->start_piece->next;
while ((piece->length == 0u) && (piece != piece_table->end_piece))
{
piece = piece->next;
}
offset = 0u;
}
uint8_t PieceTable::Iterator::num_bytes_in_code_point() const
{
if (offset >= piece->length)
{
return 0u;
}
else
{
return Encoding::num_bytes_in_code_point(piece_table->encoding, &piece->start[offset]);
}
}
void PieceTable::Iterator::go_next_position()
{
if (valid())
{
uint8_t code_point_size = num_bytes_in_code_point();
if ((offset + code_point_size) >= piece->length)
{
do
{
piece = piece->next;
} while ((piece != piece_table->end_piece) &&
(piece->length == 0u));
offset = 0u;
return;
}
offset += code_point_size;
}
}
void PieceTable::Iterator::go_prev_position()
{
if (piece != piece_table->start_piece)
{
if (offset > 0)
{
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[offset - 1u]) - piece->start;
}
else
{
do
{
piece = piece->prev;
} while ((piece != piece_table->start_piece) &&
(piece->length == 0u));
if (piece->length > 0u)
{
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[piece->length - 1u]) - piece->start;
}
else
{
offset = 0u;
}
}
}
}
void PieceTable::Iterator::go_end_of_piece()
{
if (piece->length > 0u)
{
offset = Encoding::beginning_of_code_point(piece_table->encoding, &piece->start[piece->length - 1u]) - piece->start;
}
else
{
offset = 0u;
}
}
void PieceTable::Iterator::go_next_piece()
{
if (piece != piece_table->end_piece)
{
do
{
piece = piece->next;
} while ((piece != piece_table->end_piece) &&
(piece->length == 0u));
offset = 0u;
}
}
void PieceTable::Iterator::go_prev_piece()
{
if (piece != piece_table->start_piece)
{
do
{
piece = piece->prev;
} while ((piece != piece_table->start_piece) &&
(piece->length == 0u));
offset = 0u;
}
}
PieceTable::Cursor::Cursor(PieceTable * pt) : iterator(pt)
{
line = 0u;
init_column();
}
void PieceTable::Cursor::go_start_of_line()
{
Iterator last_iterator = iterator;
for (;;)
{
iterator.go_prev_piece();
if (iterator.piece_eol() || !iterator.valid())
{
break;
}
last_iterator = iterator;
}
iterator = last_iterator;
iterator.offset = 0u;
init_column();
}
bool PieceTable::Cursor::check_go_start_of_line()
{
uint32_t current_line = line;
uint32_t current_column = column;
go_start_of_line();
return (current_line != line) || (current_column != column);
}
void PieceTable::Cursor::go_end_of_line(bool allow_on_eol)
{
if (!iterator.valid())
{
return;
}
for (;;)
{
if (iterator.piece_eol())
{
break;
}
Iterator move_iterator = iterator;
move_iterator.go_next_piece();
if (move_iterator.valid())
{
iterator = move_iterator;
}
else
{
break;
}
}
iterator.go_end_of_piece();
calculate_column();
if (!allow_on_eol)
{
go_left(1);
}
}
bool PieceTable::Cursor::check_go_end_of_line(bool allow_on_eol)
{
uint32_t current_line = line;
uint32_t current_column = column;
go_end_of_line(allow_on_eol);
return (current_line != line) || (current_column != column);
}
void PieceTable::Cursor::go_up(int n, uint32_t desired_column)
{
if (!iterator.valid())
return;
Piece * p = prev_line();
if (p == nullptr)
{
return;
}
iterator.piece = p;
iterator.offset = 0u;
line--;
init_column();
forward_to_column(desired_column);
}
bool PieceTable::Cursor::check_go_up(int n, uint32_t desired_column)
{
uint32_t current_line = line;
uint32_t current_column = column;
go_up(n, desired_column);
return (current_line != line) || (current_column != column);
}
void PieceTable::Cursor::go_down(int n, uint32_t desired_column)
{
if (!iterator.valid())
return;
Piece * p = next_line();
if (p == nullptr)
{
return;
}
iterator.piece = p;
iterator.offset = 0u;
line++;
init_column();
forward_to_column(desired_column);
}
bool PieceTable::Cursor::check_go_down(int n, uint32_t desired_column)
{
uint32_t current_line = line;
uint32_t current_column = column;
go_down(n, desired_column);
return (current_line != line) || (current_column != column);
}
void PieceTable::Cursor::go_left(int n)
{
if (!iterator.valid())
return;
if (is_start_of_line())
{
return;
}
uint32_t chr = *iterator;
iterator.go_prev_position();
if (chr == '\t')
{
calculate_column();
}
else
{
/* TODO: handle multi-column characters */
column--;
}
}
bool PieceTable::Cursor::check_go_left(int n)
{
uint32_t current_line = line;
uint32_t current_column = column;
go_left(n);
return (current_line != line) || (current_column != column);
}
void PieceTable::Cursor::go_right(int n, bool allow_on_eol)
{
if (!iterator.valid())
return;
if (is_end_of_line())
{
return;
}
Iterator iterator_2 = iterator;
iterator.go_next_position();
if ((!allow_on_eol) && is_end_of_line())
{
iterator = iterator_2;
return;
}
uint32_t chr = *iterator;
if (chr == '\t')
{
uint8_t tabstop = iterator.piece_table->tabstop;
column += tabstop - (column + 1u) % tabstop;
}
else
{
/* TODO: handle multi-column characters */
column++;
}
}
bool PieceTable::Cursor::check_go_right(int n, bool allow_on_eol)
{
uint32_t current_line = line;
uint32_t current_column = column;
go_right(n, allow_on_eol);
return (current_line != line) || (current_column != column);
}
void PieceTable::Cursor::warp_to_inserted_piece(Piece * piece)
{
iterator.piece = piece;
iterator.offset = 0u;
iterator.go_end_of_piece();
calculate_column();
}
void PieceTable::Cursor::warp_to_beginning_of_piece(Piece * piece)
{
iterator.piece = piece;
iterator.offset = 0u;
calculate_column();
}
bool PieceTable::Cursor::is_start_of_line()
{
if (!iterator.valid() || (iterator.offset > 0u))
{
return false;
}
Iterator iterator2 = iterator;
iterator2.go_prev_piece();
return iterator2.piece_eol() || !iterator2.valid();
}
bool PieceTable::Cursor::is_end_of_line()
{
return *iterator == INTERNAL_EOL;
}
PieceTable::Piece * PieceTable::Cursor::prev_line() const
{
if (!iterator.valid())
{
return nullptr;
}
Cursor cursor2 = *this;
cursor2.go_start_of_line();
cursor2.iterator.go_prev_position();
if (!cursor2.iterator.valid())
{
return nullptr;
}
cursor2.go_start_of_line();
return cursor2.iterator.piece;
}
PieceTable::Piece * PieceTable::Cursor::next_line() const
{
if (!iterator.valid())
{
return nullptr;
}
Cursor cursor2 = *this;
cursor2.go_end_of_line(true);
cursor2.iterator.go_next_position();
if (!cursor2.iterator.valid())
{
return nullptr;
}
return cursor2.iterator.piece;
}
void PieceTable::Cursor::init_column()
{
uint32_t chr = *iterator;
/* TODO: handle multi-column characters */
column = (chr == '\t') ? iterator.piece_table->tabstop - 1u : 0u;
}
void PieceTable::Cursor::calculate_column()
{
Cursor tmp_cursor = *this;
tmp_cursor.go_start_of_line();
while ((tmp_cursor.iterator.piece != iterator.piece) ||
(tmp_cursor.iterator.offset < iterator.offset))
{
tmp_cursor.go_right(1, true);
}
column = tmp_cursor.column;
}
void PieceTable::Cursor::forward_to_column(uint32_t c)
{
int32_t diff = abs((int32_t)(c - column));
if (diff == 0)
return;
while (check_go_right(1, false))
{
int32_t new_diff = abs((int32_t)(c - column));
if (new_diff > diff)
{
go_left(1);
return;
}
diff = new_diff;
}
}
void PieceTable::begin_insert(Cursor & cursor, bool before)
{
Piece * piece = cursor.iterator.piece;
uint32_t offset = cursor.iterator.offset;
if (!before && cursor.iterator.has_char() && (*cursor != INTERNAL_EOL))
{
offset += cursor.iterator.num_bytes_in_code_point();
}
Change * change = add_change();
m_inserting_piece = add_piece();
m_inserting_piece->start = &m_append_buffer[m_append_buffer_index];
m_inserting_piece->length = 0u;
if (offset == 0u)
{
/* Insert happens at piece boundary between piece->prev and piece. */
change->before = piece->prev;
change->after = piece;
}
else if (offset >= piece->length)
{
/* Insert happens at piece boundary between piece and piece->next. */
change->before = piece;
change->after = piece->next;
}
else
{
/* Insert happens in the middle of a current piece. The piece must
* be split up. */
Piece * new_piece_1 = add_piece();
new_piece_1->start = piece->start;
new_piece_1->length = offset;
Piece * new_piece_2 = add_piece();
new_piece_2->start = piece->start + offset;
new_piece_2->length = piece->length - offset;
new_piece_1->prev = piece->prev;
new_piece_1->next = new_piece_2;
new_piece_2->prev = new_piece_1;
new_piece_2->next = piece->next;
Change * change2 = add_change();
change2->before = piece->prev;
change2->after = piece->next;
change2->chains[0][0] = piece;
change2->chains[0][1] = nullptr;
change2->chains[1][0] = new_piece_1;
change2->chains[1][1] = new_piece_2;
apply_change(change2, 1u);
change->before = new_piece_1;
change->after = new_piece_2;
}
change->chains[0][0] = nullptr;
change->chains[0][1] = nullptr;
change->chains[1][0] = m_inserting_piece;
change->chains[1][1] = nullptr;
apply_change(change, 1u);
cursor.warp_to_beginning_of_piece(change->after);
}
void PieceTable::insert_code_point(uint32_t code_point)
{
if (in_insert_mode())
{
/* TODO: worry about append buffer page boundaries */
uint8_t bytes = Encoding::encode(code_point, encoding, &m_append_buffer[m_append_buffer_index]);
m_inserting_piece->length += bytes;
m_append_buffer_index += bytes;
for (auto cursor : m_cursors)
{
cursor->calculate_column();
}
}
}
void PieceTable::end_insert()
{
m_inserting_piece = nullptr;
}
void PieceTable::insertion_test(Cursor & c)
{
Piece * piece = add_piece();
piece->start = &m_append_buffer[m_append_buffer_index];
piece->length = 3u;
m_append_buffer[m_append_buffer_index++] = 'x';
m_append_buffer[m_append_buffer_index++] = 'y';
m_append_buffer[m_append_buffer_index++] = 'z';
Change * change = add_change();
Change * change2 = nullptr;
if (c.iterator.valid())
{
change->before = c.iterator.piece->prev;
change->after = c.iterator.piece->next;
change->chains[0][0] = c.iterator.piece;
change->chains[0][1] = nullptr;
if (c.iterator.offset > 0u)
{
Piece * piece2 = add_piece();
piece2->start = c.iterator.piece->start;
piece2->length = c.iterator.offset;
Piece * piece3 = add_piece();
piece3->start = c.iterator.piece->start + c.iterator.offset;
piece3->length = c.iterator.piece->length - c.iterator.offset;
piece2->next = piece;
piece->prev = piece2;
piece->next = piece3;
piece3->prev = piece;
change->chains[1][0] = piece2;
change->chains[1][1] = piece;
change2 = add_change();
change2->before = piece;
change2->after = c.iterator.piece->next;
change2->chains[0][0] = nullptr;
change2->chains[0][1] = nullptr;
change2->chains[1][0] = piece3;
change2->chains[1][1] = nullptr;
}
else
{
change->chains[1][0] = piece;
change->chains[1][1] = nullptr;
if (c.iterator.piece->length != 0u)
{
change->after = c.iterator.piece;
}
}
}
else
{
change->before = start_piece;
change->after = end_piece;
change->chains[0][0] = nullptr;
change->chains[0][1] = nullptr;
change->chains[1][0] = piece;
change->chains[1][1] = nullptr;
}
apply_change(change, 1u);
if (change2 != nullptr)
{
apply_change(change2, 1u);
}
c.warp_to_inserted_piece(piece);
}
void PieceTable::undo()
{
if (m_changes_index > 0u)
{
m_changes_index--;
apply_change(&m_changes[m_changes_index], 0u);
}
}
void PieceTable::apply_change(Change * change, uint8_t forward)
{
Piece * p = change->before;
for (uint8_t i = 0; i < sizeof(change->chains[0]) / sizeof(change->chains[0][0]); i++)
{
if (change->chains[forward][i] == nullptr)
{
break;
}
p->next = change->chains[forward][i];
change->chains[forward][i]->prev = p;
p = change->chains[forward][i];
}
p->next = change->after;
change->after->prev = p;
}

View File

@ -1,210 +0,0 @@
#ifndef PIECETABLE_H
#define PIECETABLE_H
#include <stdint.h>
#include "PagedBuffer.h"
#include <utility>
#include <memory>
#include <list>
#include "Encoding.h"
class PieceTable
{
public:
enum
{
INTERNAL_EOL = '\n',
};
struct Piece
{
/** The previous piece in the chain. */
Piece * prev;
/** The next piece in the chain. */
Piece * next;
/** Text that the piece describes. */
uint8_t * start;
/** Length of the text (in bytes). */
uint32_t length;
/** Get whether this piece is the end of a line. */
bool eol() { return (length > 0u) && (start[length - 1u] == INTERNAL_EOL); }
};
struct Iterator
{
/** The piece table the cursor belongs to. */
PieceTable * piece_table;
/** The piece. */
Piece * piece;
/** Byte offset within the piece. */
uint32_t offset;
Iterator(PieceTable * pt);
/** Get the character pointed to by the cursor. */
uint32_t operator*() const
{
if (has_char())
{
return Encoding::decode(piece_table->encoding, &piece->start[offset]);
}
else
{
return 0xFFFFFFFFu;
}
}
uint8_t num_bytes_in_code_point() const;
void go_next_position();
void go_prev_position();
void go_end_of_piece();
void go_next_piece();
void go_prev_piece();
bool valid() const
{
return (piece != piece_table->start_piece) &&
(piece != piece_table->end_piece);
}
bool has_char() const
{
return valid() && (offset < piece->length);
}
bool operator==(const Iterator & other) const
{
return (other.piece == piece) && (other.offset == offset);
}
bool operator!=(const Iterator & other) const
{
return !(*this == other);
}
bool piece_eol()
{
return piece->eol();
}
};
struct Cursor
{
Iterator iterator;
uint32_t line;
uint32_t column;
/** Get the character pointed to by the cursor. */
uint32_t operator*() const
{
return *iterator;
}
Cursor(PieceTable * pt);
void go_start_of_line();
void go_end_of_line(bool allow_on_eol);
void go_up(int n, uint32_t desired_column);
void go_down(int n, uint32_t desired_column);
void go_left(int n);
void go_right(int n, bool allow_on_eol);
bool check_go_start_of_line();
bool check_go_end_of_line(bool allow_on_eol);
bool check_go_up(int n, uint32_t desired_column);
bool check_go_down(int n, uint32_t desired_column);
bool check_go_left(int n);
bool check_go_right(int n, bool allow_on_eol);
bool operator==(const Cursor & c) const
{
return (c.line == line) && (c.column == column);
}
bool operator!=(const Cursor & c) const
{
return !(*this == c);
}
void warp_to_inserted_piece(Piece * piece);
void warp_to_beginning_of_piece(Piece * piece);
void calculate_column();
protected:
bool is_start_of_line();
bool is_end_of_line();
Piece * prev_line() const;
Piece * next_line() const;
void init_column();
void forward_to_column(uint32_t c);
};
struct Change
{
Piece * before;
Piece * after;
Piece * chains[2][2];
};
Piece * start_piece;
Piece * end_piece;
uint8_t tabstop;
Encoding::Type encoding;
PieceTable();
uint32_t get_num_lines() { return m_num_lines; }
void append_initial_line_piece(uint8_t * start, uint32_t length, bool eol);
std::shared_ptr<Cursor> add_cursor();
void begin_insert(Cursor & cursor, bool before);
void insert_code_point(uint32_t code_point);
void end_insert();
void insertion_test(Cursor & c);
void undo();
bool in_insert_mode() { return m_inserting_piece != nullptr; }
protected:
Piece * add_piece()
{
return &m_pieces[m_piece_index++];
}
Piece & operator[](uint32_t index)
{
return m_pieces[index];
}
Change * add_change()
{
return &m_changes[m_changes_index++];
}
void apply_change(Change * change, uint8_t forward);
uint32_t m_num_lines;
PagedBuffer<uint8_t> m_append_buffer;
uint32_t m_append_buffer_index;
PagedBuffer<Piece> m_pieces;
/** Next available piece index. */
uint32_t m_piece_index;
PagedBuffer<Change> m_changes;
uint32_t m_changes_index;
Piece * m_inserting_piece;
std::list<std::shared_ptr<Cursor>> m_cursors;
};
#endif

View File

@ -144,10 +144,9 @@ bool Window::create(std::shared_ptr<Buffer> buffer)
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, 0); glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, 0);
m_buffer = buffer; m_buffer = buffer;
m_cursor = m_buffer->piece_table->add_cursor();
m_cursor_row = 0; m_cursor_row = 0;
m_scroll_offset = 5; m_scroll_offset = 5;
m_target_column = m_cursor->column; m_target_column = 0u; /* TODO: fix */
glClearColor (0.0, 0.0, 0.0, 0.0); glClearColor (0.0, 0.0, 0.0, 0.0);
@ -250,6 +249,7 @@ void Window::handle_keysym(uint32_t keysym)
void Window::handle_keyval(uint32_t keyval) void Window::handle_keyval(uint32_t keyval)
{ {
#if 0
if (m_buffer->piece_table->in_insert_mode()) if (m_buffer->piece_table->in_insert_mode())
{ {
if (keyval == '\033') if (keyval == '\033')
@ -263,6 +263,7 @@ void Window::handle_keyval(uint32_t keyval)
redraw(); redraw();
} }
else else
#endif
{ {
switch (keyval) switch (keyval)
{ {
@ -287,27 +288,13 @@ void Window::handle_keyval(uint32_t keyval)
case 'l': case 'l':
cursor_move(CURSOR_RIGHT); cursor_move(CURSOR_RIGHT);
break; break;
case 'p':
insertion_test();
break;
case 'u':
m_buffer->piece_table->undo();
redraw();
break;
case 'i':
m_buffer->piece_table->begin_insert(*m_cursor, true);
redraw();
break;
case 'a':
m_buffer->piece_table->begin_insert(*m_cursor, false);
redraw();
break;
} }
} }
} }
void Window::cursor_move(int which) void Window::cursor_move(int which)
{ {
#if 0
bool moved = false; bool moved = false;
int current_row_offset = m_cursor->column / m_columns; int current_row_offset = m_cursor->column / m_columns;
int row_offset = 0; int row_offset = 0;
@ -374,6 +361,7 @@ void Window::cursor_move(int which)
update_cursor_row(m_cursor_row + row_offset); update_cursor_row(m_cursor_row + row_offset);
redraw(); redraw();
} }
#endif
} }
void Window::update_cursor_row(int cursor_row) void Window::update_cursor_row(int cursor_row)
@ -381,103 +369,8 @@ void Window::update_cursor_row(int cursor_row)
m_cursor_row = std::max(m_scroll_offset, std::min(m_rows - m_scroll_offset - 1, cursor_row)); m_cursor_row = std::max(m_scroll_offset, std::min(m_rows - m_scroll_offset - 1, cursor_row));
} }
std::pair<int, PieceTable::Cursor> Window::calculate_start_position()
{
m_cursor_row = std::min(m_cursor_row, m_rows - 1);
int row = m_cursor_row - m_cursor->column / m_columns;
PieceTable::Cursor cursor = *m_cursor;
cursor.go_start_of_line();
while (row > 0)
{
if (cursor.check_go_up(1, 0u))
{
PieceTable::Cursor c = cursor;
c.go_end_of_line(false);
row -= c.column / m_columns + 1;
}
else
{
m_cursor_row -= row;
row = 0;
}
}
return std::pair<int, PieceTable::Cursor>(row, cursor);
}
void Window::draw_buffer() void Window::draw_buffer()
{ {
auto start_position = calculate_start_position();
int row = start_position.first;
PieceTable::Cursor cursor = start_position.second;
int last_vertical_crosshair_row = -1;
int crosshair_row_offset = m_cursor->column / m_columns;
int crosshair_screen_column = m_cursor->column % m_columns;
for (;;)
{
if ((last_vertical_crosshair_row < row) &&
(cursor.column >= m_cursor->column))
{
int crosshair_screen_row = row + crosshair_row_offset;
if ((crosshair_screen_row >= 0) &&
(crosshair_screen_row < m_rows))
{
draw_crosshair(crosshair_screen_column, crosshair_screen_row);
}
last_vertical_crosshair_row = row;
}
int row_offset = cursor.column / m_columns;
int screen_row = row + row_offset;
if (screen_row >= m_rows)
break;
int screen_column = cursor.column % m_columns;
if (screen_row >= 0)
{
if (cursor.line == m_cursor->line)
draw_crosshair(screen_column, screen_row);
if (cursor == *m_cursor)
draw_cursor(screen_column, screen_row, m_buffer->piece_table->in_insert_mode());
uint32_t character = *cursor;
if ((character != 0xFFFFFFFFu) &&
(character != ' ') &&
(character != '\t') &&
(character != '\n'))
draw_buffer_character(screen_column, screen_row, character);
}
bool eol = !cursor.check_go_right(1, true);
bool draw_insert_mode_cursor = false;
if (!eol && *cursor == PieceTable::INTERNAL_EOL)
{
if ((cursor == *m_cursor) && m_buffer->piece_table->in_insert_mode())
{
row_offset = cursor.column / m_columns;
screen_row = row + row_offset;
screen_column = cursor.column % m_columns;
draw_insert_mode_cursor = true;
}
eol = true;
}
if (eol)
{
bool last_row = !cursor.check_go_down(1, 0);
if (last_vertical_crosshair_row < row)
{
int crosshair_screen_row = row + crosshair_row_offset;
if (crosshair_screen_row == screen_row)
{
draw_crosshair(crosshair_screen_column, crosshair_screen_row);
}
last_vertical_crosshair_row = row;
}
if (draw_insert_mode_cursor)
{
draw_cursor(screen_column, screen_row, true);
}
if (last_row)
break;
row = screen_row + 1;
}
}
} }
void Window::draw_buffer_character(int screen_column, int screen_row, uint32_t character) void Window::draw_buffer_character(int screen_column, int screen_row, uint32_t character)
@ -562,6 +455,7 @@ void Window::draw_status_bar()
{ {
draw_rect(0, m_font.get_line_height(), m_width, 1, 0.5, 0.5, 0.5, 1.0); draw_rect(0, m_font.get_line_height(), m_width, 1, 0.5, 0.5, 0.5, 1.0);
draw_rect(0, 0, m_width, m_font.get_line_height(), 0.0, 0.0, 0.0, 1.0); draw_rect(0, 0, m_width, m_font.get_line_height(), 0.0, 0.0, 0.0, 1.0);
#if 0
char cursor_position[20]; char cursor_position[20];
sprintf(cursor_position, "%d, %d", m_cursor->line + 1, m_cursor->column + 1u); sprintf(cursor_position, "%d, %d", m_cursor->line + 1, m_cursor->column + 1u);
int cursor_position_length = strlen(cursor_position); int cursor_position_length = strlen(cursor_position);
@ -571,12 +465,7 @@ void Window::draw_status_bar()
draw_character(x, 0, cursor_position[i]); draw_character(x, 0, cursor_position[i]);
x += m_font.get_advance(); x += m_font.get_advance();
} }
} #endif
void Window::insertion_test()
{
m_buffer->piece_table->insertion_test(*m_cursor);
redraw();
} }
uint32_t Window::get_keyval(SDL_Keycode keysym) uint32_t Window::get_keyval(SDL_Keycode keysym)

View File

@ -44,14 +44,12 @@ protected:
void handle_keysym(uint32_t keysym); void handle_keysym(uint32_t keysym);
void handle_keyval(uint32_t keyval); void handle_keyval(uint32_t keyval);
void cursor_move(int which); void cursor_move(int which);
std::pair<int, PieceTable::Cursor> calculate_start_position();
void draw_buffer(); void draw_buffer();
void draw_buffer_character(int screen_column, int screen_row, uint32_t character); void draw_buffer_character(int screen_column, int screen_row, uint32_t character);
void draw_character(int x, int y, uint32_t character); void draw_character(int x, int y, uint32_t character);
void update_cursor_row(int cursor_row); void update_cursor_row(int cursor_row);
void draw_rect(int x, int y, int width, int height, float r, float g, float b, float a); void draw_rect(int x, int y, int width, int height, float r, float g, float b, float a);
void draw_status_bar(); void draw_status_bar();
void insertion_test();
uint32_t get_keyval(SDL_Keycode keysym); uint32_t get_keyval(SDL_Keycode keysym);
uint32_t get_shifted(uint32_t keysym); uint32_t get_shifted(uint32_t keysym);
@ -80,8 +78,6 @@ protected:
std::shared_ptr<glcxx::Array> m_rect_array; std::shared_ptr<glcxx::Array> m_rect_array;
std::shared_ptr<glcxx::Buffer> m_rect_buffer; std::shared_ptr<glcxx::Buffer> m_rect_buffer;
std::shared_ptr<PieceTable::Cursor> m_cursor;
Uint16 m_keymod; Uint16 m_keymod;
}; };

View File

@ -3,6 +3,7 @@
#include "TestSupport.h" #include "TestSupport.h"
#include "Path.h" #include "Path.h"
#if 0
TEST(BufferTest, writes_an_identical_file_to_what_is_loaded_if_no_changes_were_performed) TEST(BufferTest, writes_an_identical_file_to_what_is_loaded_if_no_changes_were_performed)
{ {
const char * files_to_test[] = { const char * files_to_test[] = {
@ -41,3 +42,4 @@ TEST(BufferTest, allows_navigating_using_cursors)
EXPECT_FALSE(cursor->check_go_down(1, cursor->column)); EXPECT_FALSE(cursor->check_go_down(1, cursor->column));
ASSERT_EQ((uint32_t)'T', **cursor); ASSERT_EQ((uint32_t)'T', **cursor);
} }
#endif