diff --git a/src/basic/basic.h b/src/basic/basic.h index 3dcc6e2..9117a44 100644 --- a/src/basic/basic.h +++ b/src/basic/basic.h @@ -493,6 +493,14 @@ struct Array { // @copy_paste array slice + T get_or_default(int64_t i, T default_value = {}) { + T result = default_value; + if (i >= 0 && i < len) { + result = data[i]; + } + return result; + } + T pop() { Assert(len > 0); return data[--len]; diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index 25fb421..d3887d2 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -349,6 +349,7 @@ LineAndColumn FindLineAndColumn(Buffer &buffer, int64_t pos) { result.column = 1; result.line = FindLine(buffer, pos); for (BufferIter iter = Iterate(buffer, result.line.range); IsValid(iter); Advance(&iter)) { + // @todo: make sure we handle when there is invalid unicode in the stream if (iter.pos == pos) { result.column = iter.codepoint_index; break; @@ -395,7 +396,7 @@ int64_t Seek(Buffer &buffer, int64_t pos, int64_t direction = ITERATE_FORWARD) { bool seek_whitespace = standing_on_whitespace == false; bool seek_word = standing_on_whitespace; - int64_t result = max; + int64_t result = direction == ITERATE_BACKWARD ? 0 : buffer.len; BufferIter iter = Iterate(buffer, {min, max}, direction); int64_t prev_pos = iter.pos; for (; IsValid(iter); Advance(&iter)) { diff --git a/src/text_editor/main.cpp b/src/text_editor/main.cpp index 1e4484e..fe8a8a5 100644 --- a/src/text_editor/main.cpp +++ b/src/text_editor/main.cpp @@ -178,7 +178,15 @@ int main() { if (IsKeyPressed(KEY_LEFT) || IsKeyPressedRepeat(KEY_LEFT)) { For(focused_window->cursors) { - it.max = it.min = MoveLeft(focused_window->buffer, it.min); + if (IsKeyDown(KEY_LEFT_CONTROL)) { + it.max = it.min = Seek(focused_window->buffer, it.min, ITERATE_BACKWARD); + } else { + if (IsKeyDown(KEY_LEFT_SHIFT)) { + it.min = MoveLeft(focused_window->buffer, it.min); + } else { + it.max = it.min = MoveLeft(focused_window->buffer, it.min); + } + } } } if (IsKeyPressed(KEY_RIGHT) || IsKeyPressedRepeat(KEY_RIGHT)) { @@ -186,7 +194,11 @@ int main() { if (IsKeyDown(KEY_LEFT_CONTROL)) { it.max = it.min = Seek(focused_window->buffer, it.min, ITERATE_FORWARD); } else { - it.max = it.min = MoveRight(focused_window->buffer, it.min); + if (IsKeyDown(KEY_LEFT_SHIFT)) { + it.max = MoveRight(focused_window->buffer, it.max); + } else { + it.max = it.min = MoveRight(focused_window->buffer, it.min); + } } } } @@ -201,15 +213,17 @@ int main() { } } - // Merge cursors that overlap - IterRemove(focused_window->cursors) { - IterRemovePrepare(focused_window->cursors); - - ForItem(cursor, focused_window->cursors) { + // Merge cursors that overlap, this needs to be handled before any edits to + // make sure overlapping edits won't happen. + for (int64_t cursor_i = 0; cursor_i < focused_window->cursors.len; cursor_i += 1) { + Range &cursor = focused_window->cursors[cursor_i]; + IterRemove(focused_window->cursors) { + IterRemovePrepare(focused_window->cursors); if (&cursor == &it) continue; - if (cursor.min == it.min) { + if (cursor.max > it.min && cursor.max <= it.max) { remove_item = true; + cursor.max = it.max; break; } } @@ -285,6 +299,7 @@ int main() { struct Cell { Rect2 rect; int codepoint; + int64_t column; int64_t pos; }; @@ -352,7 +367,7 @@ int main() { // Clip everything that is outside the window and screen if (CheckCollisionRecs(cell_rectangle, ToRectangle(window_text_rect_in_render_units_clamped_to_screen))) { - row.cells.add({cell_rect, codepoint, iter.pos}); + row.cells.add({cell_rect, codepoint, iter.codepoint_index, iter.pos}); row.rect.max = cell_rect.max; } @@ -388,19 +403,41 @@ int main() { } } - // Draw the cursor + // Draw cursor stuff ForItem(cursor, window.cursors) { + Line min_line = FindLine(window.buffer, cursor.min); + Line max_line = FindLine(window.buffer, cursor.max); + bool selecting = cursor.min != cursor.max; ForItem(row, rows) { - Range line_range = window.buffer.lines[row.line]; - if (cursor.min >= line_range.min && cursor.min <= line_range.max) { + // Draw line highlights + if (row.line == min_line.number) { + DrawRectangleRec(ToRectangle(row.rect), {255, 0, 0, 30}); + } + // if (row.line == max_line.number) { + // DrawRectangleRec(ToRectangle(row.rect), {0, 255, 0, 30}); + // } - ForItem(cell, row.cells) { - if (cursor.min == cell.pos) { - Rect2 rect = cell.rect; - rect = CutLeft(&rect, 4); - DrawRectangleRec(ToRectangle(rect), RED); + ForItem(cell, row.cells) { + // Draw selection + if (selecting) { + if (row.line >= min_line.number && row.line <= max_line.number) { + if (cell.pos >= cursor.min && cell.pos < cursor.max) { + DrawRectangleRec(ToRectangle(cell.rect), BLUE); + } } } + + // Draw cursors + if (cell.pos == cursor.min) { + Rect2 rect = cell.rect; + rect = CutLeft(&rect, 4); + DrawRectangleRec(ToRectangle(rect), RED); + } + if (cell.pos == cursor.max) { + Rect2 rect = cell.rect; + rect = CutLeft(&rect, 2); + DrawRectangleRec(ToRectangle(rect), GREEN); + } } } }