diff --git a/src/basic/basic.h b/src/basic/basic.h index 8d5eee8..6b54338 100644 --- a/src/basic/basic.h +++ b/src/basic/basic.h @@ -183,16 +183,47 @@ for (int i = 0; i < array.len; i += 1) { } } +// Simple delete + IterRemove(arr) { IterRemovePrepare(arr); remove_item = true; } +// +// Deleting backwards +// + For(arr.reverse_iter()) { defer{ arr.unordered_remove(it); }; } +// +// When double looping and deleting +// + +Array deleted_cursors = {scratch}; +ForItem(cursor, window->cursors) { + For(deleted_cursors) if (it == &cursor) goto end_of_cursor_loop; + + For(window->cursors) { + if (&it == &cursor) break; + bool a = cursor.range.max >= it.range.min && cursor.range.max <= it.range.max; + bool b = cursor.range.min >= it.range.min && cursor.range.min <= it.range.max; + if (a || b) { + deleted_cursors.add(&it); + cursor.range.max = Max(cursor.range.max, it.range.max); + cursor.range.min = Min(cursor.range.min, it.range.min); + break; + } + } +end_of_cursor_loop:; +} + +For(deleted_cursors) window->cursors.ordered_remove(*it); + + */ #define IterRemove(a) for (int i = 0; i < (a).len; i += 1) #define IterRemovePrepare(a) \ diff --git a/src/text_editor/layout.cpp b/src/text_editor/layout.cpp index 2d71d63..94d94ce 100644 --- a/src/text_editor/layout.cpp +++ b/src/text_editor/layout.cpp @@ -247,21 +247,29 @@ Array CalculateVisibleColumns(Arena *arena, Window &window) { } void BeforeEdit(Window *window) { + Scratch scratch; // 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 < window->cursors.len; cursor_i += 1) { - Cursor &cursor = window->cursors[cursor_i]; - IterRemove(window->cursors) { - IterRemovePrepare(window->cursors); - if (&cursor == &it) continue; + // @optimize: could probably reverse the inner loop and simply unordered remove + Array deleted_cursors = {scratch}; + ForItem(cursor, window->cursors) { + For(deleted_cursors) if (it == &cursor) goto end_of_cursor_loop; - if (cursor.range.max >= it.range.min && cursor.range.max <= it.range.max) { - remove_item = true; - cursor.range.max = it.range.max; + For(window->cursors) { + if (&it == &cursor) break; + bool a = cursor.range.max >= it.range.min && cursor.range.max <= it.range.max; + bool b = cursor.range.min >= it.range.min && cursor.range.min <= it.range.max; + if (a || b) { + deleted_cursors.add(&it); + cursor.range.max = Max(cursor.range.max, it.range.max); + cursor.range.min = Min(cursor.range.min, it.range.min); break; } } + end_of_cursor_loop:; } + + For(deleted_cursors) window->cursors.ordered_remove(*it); } void AfterEdit(Window *window, Array edits) { diff --git a/src/text_editor/main.cpp b/src/text_editor/main.cpp index 9d05c96..ac2a6ab 100644 --- a/src/text_editor/main.cpp +++ b/src/text_editor/main.cpp @@ -312,22 +312,51 @@ int main() { } if (IsKeyPressed(KEY_DELETE) || IsKeyPressedRepeat(KEY_DELETE)) { - if (IsKeyDown(KEY_LEFT_SHIFT)) { - } - } - if (IsKeyPressed(KEY_BACKSPACE) || IsKeyPressedRepeat(KEY_BACKSPACE)) { - if (IsKeyDown(KEY_LEFT_SHIFT)) { - } else { - BeforeEdit(focused_window); - Array edits = {FrameArena}; - String string = {}; - For(focused_window->cursors) { - int64_t pos = MoveLeft(focused_window->buffer, it.range.min); - AddEdit(&edits, {pos, it.range.min}, string); + // Select things to delete + For(focused_window->cursors) { + if (GetRangeSize(it.range)) continue; + if (IsKeyDown(KEY_LEFT_CONTROL)) { + int64_t pos = Seek(focused_window->buffer, it.range.min, ITERATE_FORWARD); + it = MakeCursor(it.range.min, pos); + } else { + int64_t pos = MoveRight(focused_window->buffer, it.range.min); + it = MakeCursor(it.range.min, pos); } - ApplyEdits(&focused_window->buffer, edits); - AfterEdit(focused_window, edits); } + + // Merge + BeforeEdit(focused_window); + + // Modify + Array edits = {FrameArena}; + String string = {}; + For(focused_window->cursors) AddEdit(&edits, it.range, string); + ApplyEdits(&focused_window->buffer, edits); + AfterEdit(focused_window, edits); + } + + if (IsKeyPressed(KEY_BACKSPACE) || IsKeyPressedRepeat(KEY_BACKSPACE)) { + // Select things to delete + For(focused_window->cursors) { + if (GetRangeSize(it.range)) continue; + if (IsKeyDown(KEY_LEFT_CONTROL)) { + int64_t pos = Seek(focused_window->buffer, it.range.min, ITERATE_BACKWARD); + it = MakeCursor(pos, it.range.min); + } else { + int64_t pos = MoveLeft(focused_window->buffer, it.range.min); + it = MakeCursor(pos, it.range.min); + } + } + + // Merge + BeforeEdit(focused_window); + + // Modify + Array edits = {FrameArena}; + String string = {}; + For(focused_window->cursors) AddEdit(&edits, it.range, string); + ApplyEdits(&focused_window->buffer, edits); + AfterEdit(focused_window, edits); } if (IsKeyPressed(KEY_ENTER) || IsKeyPressedRepeat(KEY_ENTER)) {