diff --git a/src/text_editor/buffer_ops.cpp b/src/text_editor/buffer_ops.cpp deleted file mode 100644 index c199213..0000000 --- a/src/text_editor/buffer_ops.cpp +++ /dev/null @@ -1,128 +0,0 @@ -const int DIR_RIGHT = 0; -const int DIR_LEFT = 1; -const int DIR_DOWN = 2; -const int DIR_UP = 3; -const int DIR_COUNT = 4; - -const bool CTRL_PRESSED = true; - -Int MoveOnWhitespaceBoundary(Buffer &buffer, Int pos, int direction) { - Assert(direction == DIR_RIGHT || direction == DIR_LEFT); - bool right = direction == DIR_RIGHT; - - pos = Clamp(pos, (Int)0, buffer.len); - bool standing_on_whitespace = IsWhitespace(buffer.str[pos]); - bool standing_on_symbol = IsSymbol(buffer.str[pos]); - bool standing_on_word = !standing_on_whitespace && !standing_on_symbol; - bool seek_whitespace = standing_on_whitespace == false; - bool seek_word = standing_on_whitespace || standing_on_symbol; - bool seek_symbol = standing_on_whitespace || standing_on_word; - - Int result = right ? buffer.len : 0; - Int delta = right ? 1 : -1; - Int prev_pos = pos; - for (Int i = pos; right ? i < buffer.len : i >= 0; i += delta) { - bool is_whitespace = IsWhitespace(buffer.str[i]); - bool is_symbol = IsSymbol(buffer.str[i]); - bool is_word = !is_whitespace && !is_symbol; - Int res = right ? i : prev_pos; - if (seek_word && is_word) { - result = res; - break; - } - if (seek_whitespace && is_whitespace) { - result = res; - break; - } - if (seek_symbol && is_symbol) { - result = res; - break; - } - prev_pos = i; - } - return result; -} - -Int MoveOnWhitespaceBoundaryVertical(Buffer &buffer, Int pos, int direction) { - Assert(direction == DIR_UP || direction == DIR_DOWN); - - bool up = direction == DIR_UP; - Int delta = up ? -1 : 1; - - Int result = pos; - Int next_line = PosToLine(buffer, pos) + delta; - for (Int line = next_line; up ? line >= 0 : line < buffer.line_starts.len; line += delta) { - Range line_range = GetLineRange(buffer, line); - result = line_range.min; - - bool whitespace_line = true; - for (Int i = line_range.min; i < line_range.max; i += 1) { - if (!IsWhitespace(buffer.str[i])) { - whitespace_line = false; - break; - } - } - if (whitespace_line) break; - } - return result; -} - -Int MovePos(Buffer &buffer, Int pos, int direction, bool ctrl_pressed = false) { - Assert(direction >= 0 && direction <= 3); - if (ctrl_pressed) { - switch (direction) { - case DIR_RIGHT: return MoveOnWhitespaceBoundary(buffer, pos, direction); - case DIR_LEFT: return MoveOnWhitespaceBoundary(buffer, pos - 1, direction); - case DIR_DOWN: return MoveOnWhitespaceBoundaryVertical(buffer, pos, direction); - case DIR_UP: return MoveOnWhitespaceBoundaryVertical(buffer, pos, direction); - default: return pos; - } - } else { - switch (direction) { - case DIR_RIGHT: return Clamp(pos + 1, (Int)0, buffer.len); - case DIR_LEFT: return Clamp(pos - 1, (Int)0, buffer.len); - case DIR_DOWN: return OffsetByLine(&buffer, pos, 1); - case DIR_UP: return OffsetByLine(&buffer, pos, -1); - default: return pos; - } - } -} - -Caret FindInBuffer(Buffer *buffer, String16 needle, Caret caret, bool find_next = false) { - Int pos = caret.range.min; - String16 medium = GetString(*buffer, {pos, INT64_MAX}); - - Caret result = {}; - Int index = 0; - if (Seek(medium, needle, &index)) { - result = MakeCaret(pos + index + needle.len, pos + index); - } else { - medium = GetString(*buffer); - if (Seek(medium, needle, &index)) { - result = MakeCaret(index + needle.len, index); - } - } - - if (find_next && AreEqual(result, caret)) { - caret.range.min = Clamp(*buffer, caret.range.min + 1); - caret.range.max = Clamp(*buffer, caret.range.max + 1); - result = FindInBuffer(buffer, needle, caret, false); - } - - return result; -} - -Array FindAllInBuffer(Allocator allocator, Buffer *buffer, String16 needle) { - Array result = {allocator}; - String16 string_buffer = GetString(*buffer); - for (Int pos = 0;;) { - Int index = 0; - String16 medium = Skip(string_buffer, pos); - if (!Seek(medium, needle, &index)) { - break; - } - Add(&result, Rng(pos + index, pos + index + needle.len)); - pos += needle.len; - } - return result; -} diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index 3accb94..aeb16d7 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -39,6 +39,14 @@ struct Event { const char *text; }; +const int DIR_RIGHT = 0; +const int DIR_LEFT = 1; +const int DIR_DOWN = 2; +const int DIR_UP = 3; +const int DIR_COUNT = 4; +const bool CTRL_PRESSED = true; +bool SHIFT_PRESSED = true; + #define Press(KEY) (event.key == KEY) #define Ctrl(KEY) (event.key == KEY && event.ctrl) #define Shift(KEY) (event.key == KEY && event.shift) diff --git a/src/text_editor/commands_window.cpp b/src/text_editor/commands_window.cpp index 7ef8032..73d2dd6 100644 --- a/src/text_editor/commands_window.cpp +++ b/src/text_editor/commands_window.cpp @@ -1,3 +1,152 @@ + +void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) { + Assert(direction == DIR_UP || direction == DIR_DOWN); + View &view = *GetActiveView(window); + Buffer *buffer = GetBuffer(view.active_buffer); + + Rect2I visible_cells_rect = GetVisibleCells(window); + Int y = GetSize(visible_cells_rect).y - 2; + if (direction == DIR_UP) y = -y; + + For(view.carets) { + XY xy = PosToXY(*buffer, GetFront(it)); + if (direction == DIR_DOWN && xy.line == buffer->line_starts.len - 1) { + Range line_range = GetLineRange(*buffer, xy.line); + xy.col = line_range.max - line_range.min; + } else if (direction == DIR_UP && xy.line == 0) { + xy.col = 0; + } + xy.line += y; + + Int pos = XYToPos(*buffer, xy); + if (shift) { + it = ChangeFront(it, pos); + } else { + it = MakeCaret(pos); + } + } +} + +void Command_MoveCursorsToSide(View *view, int direction, bool shift = false) { + Assert(direction == DIR_LEFT || direction == DIR_RIGHT); + Buffer *buffer = GetBuffer(view->active_buffer); + + For(view->carets) { + Int pos = GetFront(it); + if (direction == DIR_RIGHT) { + pos = GetLineEnd(buffer, pos); + } else { + pos = GetLineStart(buffer, pos); + } + + if (shift) { + it = ChangeFront(it, pos); + } else { + it.range.max = it.range.min = pos; + } + } +} + +Caret MoveCaret(Buffer *buffer, Caret it, int direction, bool ctrl = false, bool shift = false) { + Int front = GetFront(it); + Int range_size = GetSize(it.range); + switch (direction) { + case DIR_UP: { + if (ctrl && shift) { + Int pos = GetPrevEmptyLineStart(buffer, front); + it = ChangeFront(it, pos); + } else if (ctrl) { + Int pos = GetPrevEmptyLineStart(buffer, it.range.min); + it = MakeCaret(pos); + } else if (shift) { + Int pos = OffsetByLine(buffer, front, -1); + it = ChangeFront(it, pos); + } else { + if (range_size == 0) { + Int pos = OffsetByLine(buffer, it.range.min, -1); + it = MakeCaret(pos); + } else { + it = MakeCaret(it.range.min); + } + } + } break; + case DIR_DOWN: { + if (ctrl && shift) { + Int pos = GetNextEmptyLineStart(buffer, front); + it = ChangeFront(it, pos); + } else if (ctrl) { + Int pos = GetNextEmptyLineStart(buffer, it.range.max); + it = MakeCaret(pos); + } else if (shift) { + Int pos = OffsetByLine(buffer, front, 1); + it = ChangeFront(it, pos); + } else { + if (range_size == 0) { + Int pos = OffsetByLine(buffer, it.range.max, 1); + it = MakeCaret(pos); + } else { + it = MakeCaret(it.range.max); + } + } + } break; + case DIR_LEFT: { + if (ctrl && shift) { + Int pos = GetPrevWordStart(buffer, front); + it = ChangeFront(it, pos); + } else if (ctrl) { + if (range_size != 0 && front != it.range.min) { + it = MakeCaret(it.range.min); + } else { + Int pos = GetPrevWordStart(buffer, it.range.min); + it = MakeCaret(pos); + } + } else if (shift) { + Int pos = GetPrevChar(buffer, front); + it = ChangeFront(it, pos); + } else { + if (range_size == 0) { + Int pos = GetPrevChar(buffer, it.range.min); + it = MakeCaret(pos); + } else { + it = MakeCaret(it.range.min); + } + } + } break; + case DIR_RIGHT: { + if (ctrl && shift) { + Int pos = GetNextWordEnd(buffer, front); + it = ChangeFront(it, pos); + } else if (ctrl) { + if (range_size != 0 && front != it.range.max) { + it = MakeCaret(it.range.max); + } else { + Int pos = GetNextWordEnd(buffer, it.range.max); + it = MakeCaret(pos); + } + } else if (shift) { + Int pos = GetNextChar(buffer, front); + it = ChangeFront(it, pos); + } else { + if (range_size == 0) { + Int pos = GetNextChar(buffer, it.range.max); + it = MakeCaret(pos); + } else { + it = MakeCaret(it.range.max); + } + } + } break; + } + return it; +} + +void Command_Move(View *view, int direction, bool ctrl = false, bool shift = false) { + Assert(direction < DIR_COUNT); + Buffer *buffer = GetBuffer(view->active_buffer); + For(view->carets) { + it = MoveCaret(buffer, it, direction, ctrl, shift); + } +} + void Command_Replace(View *view, String16 string) { Buffer *buffer = GetBuffer(view->active_buffer); Scratch scratch; @@ -28,7 +177,7 @@ void Command_DuplicateLine(View *view, int direction) { ApplyEdits(buffer, edits); AfterEdit(buffer, &edits, &view->carets); - For(view->carets) it = MakeCaret(MovePos(*buffer, it.range.min, direction, false)); + Command_Move(view, direction); } Int FindRangeByPos(Array &ranges, Int pos) { @@ -177,90 +326,6 @@ void Command_KillSelectedLines(View *view) { AfterEdit(buffer, &edits, &view->carets, KILL_SELECTION); } -bool SHIFT_PRESSED = true; -void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) { - Assert(direction == DIR_UP || direction == DIR_DOWN); - View &view = *GetActiveView(window); - Buffer *buffer = GetBuffer(view.active_buffer); - - Rect2I visible_cells_rect = GetVisibleCells(window); - Int y = GetSize(visible_cells_rect).y - 2; - if (direction == DIR_UP) y = -y; - - For(view.carets) { - XY xy = PosToXY(*buffer, GetFront(it)); - if (direction == DIR_DOWN && xy.line == buffer->line_starts.len - 1) { - Range line_range = GetLineRange(*buffer, xy.line); - xy.col = line_range.max - line_range.min; - } else if (direction == DIR_UP && xy.line == 0) { - xy.col = 0; - } - xy.line += y; - - Int pos = XYToPos(*buffer, xy); - if (shift) { - it = ChangeFront(it, pos); - } else { - it = MakeCaret(pos); - } - } -} - -void Command_MoveCursorsToSide(View *view, int direction, bool shift = false) { - Assert(direction == DIR_LEFT || direction == DIR_RIGHT); - Buffer *buffer = GetBuffer(view->active_buffer); - - For(view->carets) { - Int pos = GetFront(it); - if (direction == DIR_RIGHT) { - pos = GetLineEnd(buffer, pos); - } else { - pos = GetLineStart(buffer, pos); - } - - if (shift) { - it = ChangeFront(it, pos); - } else { - it.range.max = it.range.min = pos; - } - } -} - -void Command_Move(View *view, int direction, bool ctrl = false, bool shift = false) { - Assert(direction < DIR_COUNT); - Buffer *buffer = GetBuffer(view->active_buffer); - For(view->carets) { - Int front = GetFront(it); - switch (direction) { - case DIR_UP: { - } break; - case DIR_DOWN: { - if (ctrl && shift) { - Int pos = GetNextEmptyLineStart(buffer, front); - it = ChangeFront(it, pos); - } else if (ctrl) { - Int pos = GetNextEmptyLineStart(buffer, it.range.max); - it = MakeCaret(pos); - } else if (shift) { - Int pos = OffsetByLine(buffer, front, 1); - it = ChangeFront(it, pos); - } else { - if (GetSize(it.range) == 0) { - Int pos = OffsetByLine(buffer, it.range.max, 1); - it = MakeCaret(pos); - } else { - it = MakeCaret(it.range.max); - } - } - } break; - case DIR_LEFT: { - } break; - case DIR_RIGHT: { - } break; - } - } -} - void Command_Delete(View *view, int direction, bool ctrl = false) { Assert(direction == DIR_LEFT || direction == DIR_RIGHT); Scratch scratch; @@ -271,8 +336,7 @@ void Command_Delete(View *view, int direction, bool ctrl = false) { // Select things to delete For(view->carets) { if (GetSize(it.range)) continue; - Int pos = MovePos(*buffer, it.range.min, direction, ctrl); - it = MakeCaret(pos, it.range.min); + it = MoveCaret(buffer, it, direction, ctrl, SHIFT_PRESSED); } MergeCarets(view); @@ -306,17 +370,20 @@ void Command_CreateCursorVertical(View *_view, int direction) { View &view = *_view; Buffer *buffer = GetBuffer(view.active_buffer); + Int line_offset = direction == DIR_UP ? -1 : 1; + Scratch scratch; Array arr = {scratch}; For(view.carets) { if (PosToLine(*buffer, it.range.min) == PosToLine(*buffer, it.range.max)) { - Int f = MovePos(*buffer, GetFront(it), direction); - Int b = MovePos(*buffer, GetBack(it), direction); + Int f = OffsetByLine(buffer, GetFront(it), line_offset); + Int b = OffsetByLine(buffer, GetBack(it), line_offset); Add(&arr, MakeCaret(f, b)); } else { - Int pos = direction == DIR_UP ? it.range.min : it.range.max; - Int min = MovePos(*buffer, pos, direction); - Add(&arr, MakeCaret(min)); + Int pos = direction == DIR_UP ? it.range.min : it.range.max; + Caret caret = MakeCaret(pos); + caret = MoveCaret(buffer, caret, direction); + Add(&arr, caret); } } For(arr) Add(&view.carets, it); @@ -391,6 +458,45 @@ void MergeCarets(View *view, Range *mouse_selection_anchor) { Swap(&view->carets[first_caret_index], &view->carets[0]); } +Caret FindInBuffer(Buffer *buffer, String16 needle, Caret caret, bool find_next = false) { + Int pos = caret.range.min; + String16 medium = GetString(*buffer, {pos, INT64_MAX}); + + Caret result = {}; + Int index = 0; + if (Seek(medium, needle, &index)) { + result = MakeCaret(pos + index + needle.len, pos + index); + } else { + medium = GetString(*buffer); + if (Seek(medium, needle, &index)) { + result = MakeCaret(index + needle.len, index); + } + } + + if (find_next && AreEqual(result, caret)) { + caret.range.min = Clamp(*buffer, caret.range.min + 1); + caret.range.max = Clamp(*buffer, caret.range.max + 1); + result = FindInBuffer(buffer, needle, caret, false); + } + + return result; +} + +Array FindAllInBuffer(Allocator allocator, Buffer *buffer, String16 needle) { + Array result = {allocator}; + String16 string_buffer = GetString(*buffer); + for (Int pos = 0;;) { + Int index = 0; + String16 medium = Skip(string_buffer, pos); + if (!Seek(medium, needle, &index)) { + break; + } + Add(&result, Rng(pos + index, pos + index + needle.len)); + pos += needle.len; + } + return result; +} + void WindowCommand(Event event, Window *window, View *view) { ProfileFunction(); Buffer *buffer = GetBuffer(view->active_buffer); @@ -409,33 +515,6 @@ void WindowCommand(Event event, Window *window, View *view) { } } - // Underline - if (event.ctrl) { - Caret caret = view->carets[0]; - if (GetSize(caret.range) == 0) { - view->underline_pos[view->underline_count++] = caret.range.min; - Assert(view->underline_count <= 2); - } - - { - Vec2I mouse = MouseVec2I(); - Vec2I mworld = mouse - window->document_rect.min + view->scroll; - Vec2I pos = mworld / Vec2I{FontCharSpacing, FontLineSpacing}; - XY xy = {(Int)(pos.x), (Int)(pos.y)}; - Int p = XYToPosErrorOutOfBounds(*buffer, xy); - if (p != -1) { - view->underline_pos[view->underline_count++] = p; - Assert(view->underline_count <= 2); - - if (Mouse(LEFT)) { - Range enclose = EncloseLoadWord(buffer, p); - String16 string = GetString(*buffer, enclose); - Open(string); - } - } - } - } - if (CtrlAlt(SDLK_DOWN)) { Command_DuplicateLine(view, DIR_DOWN); } else if (AltShift(SDLK_DOWN)) { @@ -455,63 +534,33 @@ void WindowCommand(Event event, Window *window, View *view) { } else if (AltShift(SDLK_UP)) { Command_CreateCursorVertical(view, DIR_UP); } else if (CtrlShift(SDLK_UP)) { - For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_UP, CTRL_PRESSED)); + Command_Move(view, DIR_UP, CTRL_PRESSED, SHIFT_PRESSED); } else if (Ctrl(SDLK_UP)) { - For(view->carets) it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP, CTRL_PRESSED)); + Command_Move(view, DIR_UP, CTRL_PRESSED); } else if (Shift(SDLK_UP)) { - For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_UP)); + Command_Move(view, DIR_UP, false, SHIFT_PRESSED); } else if (Press(SDLK_UP)) { - For(view->carets) { - if (GetSize(it.range) == 0) { - it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP)); - } else { - it = MakeCaret(it.range.min); - } - } + Command_Move(view, DIR_UP); } if (CtrlShift(SDLK_LEFT)) { - For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_LEFT, true)); + Command_Move(view, DIR_LEFT, CTRL_PRESSED, SHIFT_PRESSED); } else if (Ctrl(SDLK_LEFT)) { - For(view->carets) { - if (GetSize(it.range) != 0 && GetFront(it) != it.range.min) { - it = MakeCaret(it.range.min); - } else { - it = MakeCaret(MovePos(*buffer, it.range.min, DIR_LEFT, true)); - } - } + Command_Move(view, DIR_LEFT, CTRL_PRESSED); } else if (Shift(SDLK_LEFT)) { - For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_LEFT, false)); + Command_Move(view, DIR_LEFT, false, SHIFT_PRESSED); } else if (Press(SDLK_LEFT)) { - For(view->carets) { - if (GetSize(it.range) == 0) { - it = MakeCaret(MovePos(*buffer, it.range.min, DIR_LEFT, false)); - } else { - it = MakeCaret(it.range.min); - } - } + Command_Move(view, DIR_LEFT); } if (CtrlShift(SDLK_RIGHT)) { - For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_RIGHT, true)); + Command_Move(view, DIR_RIGHT, CTRL_PRESSED, SHIFT_PRESSED); } else if (Ctrl(SDLK_RIGHT)) { - For(view->carets) { - if (GetSize(it.range) != 0 && GetFront(it) != it.range.max) { - it = MakeCaret(it.range.max); - } else { - it = MakeCaret(MovePos(*buffer, it.range.max, DIR_RIGHT, true)); - } - } + Command_Move(view, DIR_RIGHT, CTRL_PRESSED); } else if (Shift(SDLK_RIGHT)) { - For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_RIGHT, false)); + Command_Move(view, DIR_RIGHT, false, SHIFT_PRESSED); } else if (Press(SDLK_RIGHT)) { - For(view->carets) { - if (GetSize(it.range) == 0) { - it = MakeCaret(MovePos(*buffer, it.range.max, DIR_RIGHT, false)); - } else { - it = MakeCaret(it.range.max); - } - } + Command_Move(view, DIR_RIGHT); } if (CtrlShift(SDLK_Z)) { @@ -718,6 +767,33 @@ void WindowCommand(Event event, Window *window, View *view) { } } + // Underline + if (event.ctrl) { + Caret caret = view->carets[0]; + if (GetSize(caret.range) == 0) { + view->underline_pos[view->underline_count++] = caret.range.min; + Assert(view->underline_count <= 2); + } + + { + Vec2I mouse = MouseVec2I(); + Vec2I mworld = mouse - window->document_rect.min + view->scroll; + Vec2I pos = mworld / Vec2I{FontCharSpacing, FontLineSpacing}; + XY xy = {(Int)(pos.x), (Int)(pos.y)}; + Int p = XYToPosErrorOutOfBounds(*buffer, xy); + if (p != -1) { + view->underline_pos[view->underline_count++] = p; + Assert(view->underline_count <= 2); + + if (Mouse(LEFT)) { + Range enclose = EncloseLoadWord(buffer, p); + String16 string = GetString(*buffer, enclose); + Open(string); + } + } + } + } + { Vec2I mouse = MouseVec2I(); diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 98c4fcd..0cd6d93 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -26,7 +26,6 @@ int FullScreenPositionX, FullScreenPositionY; #include "buffer_helpers.cpp" #include "buffer.cpp" #include "buffer_multi_cursor.cpp" -#include "buffer_ops.cpp" #include "buffer_history.cpp" #include "buffer_fuzzy_search.cpp" #include "buffer_test_load.cpp"