diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index 3a55341..8d8e0c8 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -4,16 +4,18 @@ https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation #define BUFFER_DEBUG 0 void InitBuffer(Allocator allocator, Buffer *buffer) { + buffer->id = AllocBufferID(); buffer->cap = 4096; buffer->data = AllocArray(allocator, U16, buffer->cap); buffer->line_starts.allocator = allocator; Add(&buffer->line_starts, (Int)0); } -Buffer *CreateBuffer(Allocator allocator) { - Buffer *result = AllocType(allocator, Buffer); - InitBuffer(allocator, result); - return result; +BufferID CreateBuffer(Allocator allocator) { + Buffer result = {}; + InitBuffer(allocator, &result); + Add(&Buffers, result); + return result.id; } void Grow(Buffer *buffer, Int change_size) { diff --git a/src/text_editor/buffer.h b/src/text_editor/buffer.h deleted file mode 100644 index 5e4b022..0000000 --- a/src/text_editor/buffer.h +++ /dev/null @@ -1,46 +0,0 @@ -union Range { - struct { - Int min; - Int max; - }; - Int e[2]; -}; - -struct Caret { - union { - Range range; - Int pos[2]; - }; - Int ifront; -}; - -struct XY { - Int col; - Int line; -}; - -struct Edit { - Range range; - String16 string; -}; - -// @idea: maybe redo tree? -struct HistoryEntry { - Array edits; - Array carets; -}; - -// @todo: gap buffer to improve speed of inserting on big files with only one cursor? -struct Buffer { - union { - U16 *data; - wchar_t *str; - }; - Int len; - Int cap; - Array line_starts; - - Array undo_stack; - Array redo_stack; - int debug_edit_phase; -}; diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index f0ebe25..188a303 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -8,7 +8,7 @@ #include "../profiler/profiler.cpp" -#include "buffer.h" +#include "text_editor.h" #include "buffer_helpers.cpp" #include "buffer.cpp" #include "buffer_multi_cursor.cpp" @@ -30,13 +30,17 @@ Int FontCharSpacing; #include "commands.cpp" #include "colors.cpp" -#include "view.h" #include "windows.cpp" #include "view_commands_clipboard.cpp" #include "view_commands.cpp" #include "view_draw.cpp" /* +- Window IDS and View IDS and Buffer IDS +- Null Window, Null View, Null Buffer +- Open file (utf8->utf16), process determine line endings, tabs to spaces?, Save file (utf16->utf8) + + - move off raylib - line endings @@ -44,8 +48,6 @@ Int FontCharSpacing; - word completion - Colored strings - file dock on left side -- multiple Windows -- multiple views per window - Font cache */ @@ -79,26 +81,48 @@ int main(void) { Font = LoadFontEx("c:\\Windows\\Fonts\\consola.ttf", (int)FontSize, NULL, 500); FontCharSpacing = GetCharSpacing(Font, FontSize, FontSpacing); - View view = {}; - { - Window window = {}; + Window window = {AllocWindowID()}; { + View view = {}; + view.id = AllocViewID(); Add(&view.carets, {0, 0}); - view.buffer = CreateBuffer(Perm); - LoadTextA(view.buffer); - Add(&window.views, view); + view.buffer_id = CreateBuffer(Perm); + Buffer *buffer = GetBuffer(view.buffer_id); + LoadTextA(buffer); + Add(&Views, view); + Add(&window.views, view.id); + window.active_view = view.id; } Add(&Windows, window); } { - Window window = {}; + Window window = {AllocWindowID()}; { View view = {}; + view.id = AllocViewID(); Add(&view.carets, {0, 0}); - view.buffer = CreateBuffer(Perm); - LoadUnicode(view.buffer); - Add(&window.views, view); + view.buffer_id = CreateBuffer(Perm); + Buffer *buffer = GetBuffer(view.buffer_id); + LoadUnicode(buffer); + Add(&Views, view); + Add(&window.views, view.id); + window.active_view = view.id; + } + Add(&Windows, window); + } + { + Window window = {AllocWindowID()}; + { + View view = {}; + view.id = AllocViewID(); + Add(&view.carets, {0, 0}); + view.buffer_id = CreateBuffer(Perm); + Buffer *buffer = GetBuffer(view.buffer_id); + LoadLine(buffer); + Add(&Views, view); + Add(&window.views, view.id); + window.active_view = view.id; } Add(&Windows, window); } @@ -109,19 +133,26 @@ int main(void) { Rect2I screen_rect = GetScreenRect(); float line_numbers_size = MeasureTextEx(Font, "12345", (float)FontSize, (float)FontSpacing).x; { - Windows[0].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.5)); + Windows[0].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.33)); Windows[0].document_rect = Windows[0].total_rect; Windows[0].scrollbar_rect = CutRight(&Windows[0].document_rect, 10); Windows[0].infobar_rect = CutBottom(&Windows[0].document_rect, (Int)MenuFontSize); Windows[0].line_numbers_rect = CutLeft(&Windows[0].document_rect, (Int)line_numbers_size); } { - Windows[1].total_rect = screen_rect; + Windows[1].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.5)); Windows[1].document_rect = Windows[1].total_rect; Windows[1].scrollbar_rect = CutRight(&Windows[1].document_rect, 10); Windows[1].infobar_rect = CutBottom(&Windows[1].document_rect, (Int)MenuFontSize); Windows[1].line_numbers_rect = CutLeft(&Windows[1].document_rect, (Int)line_numbers_size); } + { + Windows[2].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 1.0)); + Windows[2].document_rect = Windows[2].total_rect; + Windows[2].scrollbar_rect = CutRight(&Windows[2].document_rect, 10); + Windows[2].infobar_rect = CutBottom(&Windows[2].document_rect, (Int)MenuFontSize); + Windows[2].line_numbers_rect = CutLeft(&Windows[2].document_rect, (Int)line_numbers_size); + } BeginDrawing(); ClearBackground(ColorBackground); diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h new file mode 100644 index 0000000..f52b8af --- /dev/null +++ b/src/text_editor/text_editor.h @@ -0,0 +1,110 @@ +// clang-format off +struct BufferID { Int id; }; +struct ViewID { Int id; }; +struct WindowID { Int id; }; + +union Range { struct { Int min; Int max; }; Int e[2]; }; +struct Caret { union { Range range; Int pos[2]; }; Int ifront;}; +struct XY { Int col; Int line; }; +// clang-format on + +struct Edit { + Range range; + String16 string; +}; + +// @idea: maybe redo tree? +struct HistoryEntry { + Array edits; + Array carets; +}; + +// @todo: gap buffer to improve speed of inserting on big files with only one cursor? +struct Buffer { + BufferID id; + union { + U16 *data; + wchar_t *str; + }; + Int len; + Int cap; + Array line_starts; + + Array undo_stack; + Array redo_stack; + int debug_edit_phase; +}; + +struct View { + ViewID id; + BufferID buffer_id; + Vec2I scroll; + Array carets; + Range selection_anchor; +}; + +struct Window { + WindowID id; + ViewID active_view; + Array views; + + Rect2I total_rect; + Rect2I scrollbar_rect; + Rect2I infobar_rect; + Rect2I line_numbers_rect; + Rect2I document_rect; + + int mouse_selecting_scrollbar; + bool mouse_selecting; + double mouse_scroller_offset; +}; + +struct Scroller { + Rect2 rect; + double begin; + double end; + Int line_count; +}; + +Rect2I GetVisibleCells(Window &window); +void AfterEdit(View *view, Array edits); +Scroller ComputeScrollerRect(Window &window); + +WindowID WindowIDs = {1}; +BufferID BufferIDs = {1}; +ViewID ViewIDs = {1}; + +Window NullWindow = {}; +View NullView = {}; +Buffer NullBuffer = {}; + +Array Buffers = {}; +Array Views = {}; +Array Windows = {}; +WindowID ActiveWindow = {}; + +inline Window *GetWindow(WindowID id) { + For(Windows) if (it.id.id == id.id) return ⁢ + return &NullWindow; +} + +inline Buffer *GetBuffer(BufferID id) { + For(Buffers) if (it.id.id == id.id) return ⁢ + return &NullBuffer; +} + +inline View *GetView(ViewID id) { + For(Views) if (it.id.id == id.id) return ⁢ + return &NullView; +} + +inline ViewID AllocViewID() { return {ViewIDs.id++}; } +inline WindowID AllocWindowID() { return {WindowIDs.id++}; } +inline BufferID AllocBufferID() { return {BufferIDs.id++}; } +inline bool IsActive(Window *window) { return window->id.id == ActiveWindow.id; } +inline bool IsActive(Window *window, View *view) { return window->active_view.id == view->id.id; } +inline Window *GetActiveWindow() { return GetWindow(ActiveWindow); } +inline View *GetActiveView(Window *window) { + if (window->active_view.id == 0) return GetView(window->views[0]); + else return GetView(window->active_view); +} diff --git a/src/text_editor/view.h b/src/text_editor/view.h deleted file mode 100644 index 80b078d..0000000 --- a/src/text_editor/view.h +++ /dev/null @@ -1,32 +0,0 @@ -struct View { - Vec2I scroll; - Buffer *buffer; - Array carets; - Range selection_anchor; -}; - -struct Window { - Int active_view; - Array views; - - Rect2I total_rect; - Rect2I scrollbar_rect; - Rect2I infobar_rect; - Rect2I line_numbers_rect; - Rect2I document_rect; - - int mouse_selecting_scrollbar; - bool mouse_selecting; - double mouse_scroller_offset; -}; - -struct Scroller { - Rect2 rect; - double begin; - double end; - Int line_count; -}; - -Rect2I GetVisibleCells(Window &window); -void AfterEdit(View *view, Array edits); -Scroller ComputeScrollerRect(Window &window); diff --git a/src/text_editor/view_commands.cpp b/src/text_editor/view_commands.cpp index e5b8ac5..eed3510 100644 --- a/src/text_editor/view_commands.cpp +++ b/src/text_editor/view_commands.cpp @@ -1,48 +1,50 @@ void Command_Replace(View *view, String16 string) { + Buffer *buffer = GetBuffer(view->buffer_id); Scratch scratch; - BeforeEdit(view->buffer, view->carets); + BeforeEdit(buffer, view->carets); MergeCarets(&view->carets); Array edits = {scratch}; For(view->carets) AddEdit(&edits, it.range, string); - ApplyEdits(view->buffer, edits); - AfterEdit(view->buffer, &edits, &view->carets); + ApplyEdits(buffer, edits); + AfterEdit(buffer, &edits, &view->carets); } void Command_DuplicateLine(View *view, int direction) { Assert(direction == DIR_UP || direction == DIR_DOWN); - BeforeEdit(view->buffer, view->carets); + Buffer *buffer = GetBuffer(view->buffer_id); + BeforeEdit(buffer, view->carets); For(view->carets) it = MakeCaret(GetFront(it)); MergeCarets(&view->carets); Scratch scratch; Array edits = {scratch}; For(view->carets) { - Int line = PosToLine(*view->buffer, it.range.min); - Range range = GetLineRange(*view->buffer, line); - String16 string = Copy(scratch, GetString(*view->buffer, range)); + Int line = PosToLine(*buffer, it.range.min); + Range range = GetLineRange(*buffer, line); + String16 string = Copy(scratch, GetString(*buffer, range)); Int pos = direction == DIR_UP ? range.min : range.max; AddEdit(&edits, Rng(pos), string); } - ApplyEdits(view->buffer, edits); - AfterEdit(view->buffer, &edits, &view->carets); + ApplyEdits(buffer, edits); + AfterEdit(buffer, &edits, &view->carets); - For(view->carets) it = MakeCaret(MovePos(*view->buffer, it.range.min, direction, false)); + For(view->carets) it = MakeCaret(MovePos(*buffer, it.range.min, direction, false)); } 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 &buf = *view.buffer; + View &view = *GetActiveView(window); + Buffer *buffer = GetBuffer(view.buffer_id); 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(buf, GetFront(it)); + XY xy = PosToXY(*buffer, GetFront(it)); xy.line += y; - Int pos = XYToPos(buf, xy); + Int pos = XYToPos(*buffer, xy); if (shift) { it = ChangeFront(it, pos); } else { @@ -53,12 +55,12 @@ void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = f void Command_MoveCursorsToSide(Window *window, int direction, bool shift = false) { Assert(direction == DIR_LEFT || direction == DIR_RIGHT); - View &view = *GetActiveView(*window); - Buffer &buf = *view.buffer; + View &view = *GetActiveView(window); + Buffer *buffer = GetBuffer(view.buffer_id); For(view.carets) { Int end_of_buffer = 0; - Range line_range = GetLineRange(buf, PosToLine(buf, GetFront(it)), &end_of_buffer); + Range line_range = GetLineRange(*buffer, PosToLine(*buffer, GetFront(it)), &end_of_buffer); Int pos = line_range.min; if (direction == DIR_RIGHT) { @@ -75,13 +77,13 @@ void Command_MoveCursorsToSide(Window *window, int direction, bool shift = false void Command_Delete(View *_view, int direction, bool ctrl = false) { Assert(direction == DIR_LEFT || direction == DIR_RIGHT); - View &view = *_view; - Buffer &buf = *view.buffer; + View &view = *_view; + Buffer *buffer = GetBuffer(view.buffer_id); // Select things to delete For(view.carets) { if (GetSize(it.range)) continue; - Int pos = MovePos(buf, it.range.min, direction, ctrl); + Int pos = MovePos(*buffer, it.range.min, direction, ctrl); it = MakeCaret(pos, it.range.min); } @@ -90,19 +92,19 @@ void Command_Delete(View *_view, int direction, bool ctrl = false) { void Command_CreateCursorVertical(View *_view, int direction) { Assert(direction == DIR_UP || direction == DIR_DOWN); - View &view = *_view; - Buffer &buf = *view.buffer; + View &view = *_view; + Buffer *buffer = GetBuffer(view.buffer_id); Scratch scratch; Array arr = {scratch}; For(view.carets) { - if (PosToLine(buf, it.range.min) == PosToLine(buf, it.range.max)) { - Int f = MovePos(buf, GetFront(it), direction); - Int b = MovePos(buf, GetBack(it), direction); + 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); Add(&arr, MakeCaret(f, b)); } else { Int pos = direction == DIR_UP ? it.range.min : it.range.max; - Int min = MovePos(buf, pos, direction); + Int min = MovePos(*buffer, pos, direction); Add(&arr, MakeCaret(min)); } } @@ -112,8 +114,8 @@ void Command_CreateCursorVertical(View *_view, int direction) { void HandleKeybindings(Window *window) { ProfileFunction(); - View &view = *GetActiveView(*window); - Buffer &buf = *view.buffer; + View &view = *GetActiveView(window); + Buffer *buffer = GetBuffer(view.buffer_id); Caret main_caret_on_begin_frame = view.carets[0]; { @@ -130,7 +132,7 @@ void HandleKeybindings(Window *window) { if (!IsActive(window)) { if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { - ActiveWindow = GetIndex(Windows, *window); + ActiveWindow = window->id; } } } @@ -141,9 +143,9 @@ void HandleKeybindings(Window *window) { } if (CtrlPress(KEY_F2)) { - LoadBigLine(view.buffer); + LoadBigLine(buffer); } else if (Press(KEY_F2)) { - LoadBigText(view.buffer); + LoadBigText(buffer); } if (Press(KEY_ESCAPE)) { @@ -155,15 +157,15 @@ void HandleKeybindings(Window *window) { } else if (AltShiftPress(KEY_DOWN)) { Command_CreateCursorVertical(&view, DIR_DOWN); } else if (CtrlShiftPress(KEY_DOWN)) { - For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_DOWN, true)); + For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_DOWN, true)); } else if (CtrlPress(KEY_DOWN)) { - For(view.carets) it = MakeCaret(MovePos(buf, it.range.max, DIR_DOWN, true)); + For(view.carets) it = MakeCaret(MovePos(*buffer, it.range.max, DIR_DOWN, true)); } else if (ShiftPress(KEY_DOWN)) { - For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_DOWN, false)); + For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_DOWN, false)); } else if (Press(KEY_DOWN)) { For(view.carets) { if (GetSize(it.range) == 0) { - it = MakeCaret(MovePos(buf, it.range.max, DIR_DOWN, false)); + it = MakeCaret(MovePos(*buffer, it.range.max, DIR_DOWN, false)); } else { it = MakeCaret(it.range.max); } @@ -175,15 +177,15 @@ void HandleKeybindings(Window *window) { } else if (AltShiftPress(KEY_UP)) { Command_CreateCursorVertical(&view, DIR_UP); } else if (CtrlShiftPress(KEY_UP)) { - For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_UP, CTRL_PRESSED)); + For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_UP, CTRL_PRESSED)); } else if (CtrlPress(KEY_UP)) { - For(view.carets) it = MakeCaret(MovePos(buf, it.range.min, DIR_UP, CTRL_PRESSED)); + For(view.carets) it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP, CTRL_PRESSED)); } else if (ShiftPress(KEY_UP)) { - For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_UP)); + For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_UP)); } else if (Press(KEY_UP)) { For(view.carets) { if (GetSize(it.range) == 0) { - it = MakeCaret(MovePos(buf, it.range.min, DIR_UP)); + it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP)); } else { it = MakeCaret(it.range.min); } @@ -191,21 +193,21 @@ void HandleKeybindings(Window *window) { } if (CtrlShiftPress(KEY_LEFT)) { - For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_LEFT, true)); + For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_LEFT, true)); } else if (CtrlPress(KEY_LEFT)) { For(view.carets) { if (GetSize(it.range) != 0 && GetFront(it) != it.range.min) { it = MakeCaret(it.range.min); } else { - it = MakeCaret(MovePos(buf, it.range.min, DIR_LEFT, true)); + it = MakeCaret(MovePos(*buffer, it.range.min, DIR_LEFT, true)); } } } else if (ShiftPress(KEY_LEFT)) { - For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_LEFT, false)); + For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_LEFT, false)); } else if (Press(KEY_LEFT)) { For(view.carets) { if (GetSize(it.range) == 0) { - it = MakeCaret(MovePos(buf, it.range.min, DIR_LEFT, false)); + it = MakeCaret(MovePos(*buffer, it.range.min, DIR_LEFT, false)); } else { it = MakeCaret(it.range.min); } @@ -213,21 +215,21 @@ void HandleKeybindings(Window *window) { } if (CtrlShiftPress(KEY_RIGHT)) { - For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_RIGHT, true)); + For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_RIGHT, true)); } else if (CtrlPress(KEY_RIGHT)) { For(view.carets) { if (GetSize(it.range) != 0 && GetFront(it) != it.range.max) { it = MakeCaret(it.range.max); } else { - it = MakeCaret(MovePos(buf, it.range.max, DIR_RIGHT, true)); + it = MakeCaret(MovePos(*buffer, it.range.max, DIR_RIGHT, true)); } } } else if (ShiftPress(KEY_RIGHT)) { - For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_RIGHT, false)); + For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_RIGHT, false)); } else if (Press(KEY_RIGHT)) { For(view.carets) { if (GetSize(it.range) == 0) { - it = MakeCaret(MovePos(buf, it.range.max, DIR_RIGHT, false)); + it = MakeCaret(MovePos(*buffer, it.range.max, DIR_RIGHT, false)); } else { it = MakeCaret(it.range.max); } @@ -235,24 +237,24 @@ void HandleKeybindings(Window *window) { } if (CtrlPress(KEY_D)) { - Range range = view.carets[0].range; - String16 string = GetString(buf, range); - String16 buffer = GetString(buf, {range.max, INT64_MAX}); - Int index = 0; - if (Seek(buffer, string, &index)) { + Range range = view.carets[0].range; + String16 string = GetString(*buffer, range); + String16 string_buffer = GetString(*buffer, {range.max, INT64_MAX}); + Int index = 0; + if (Seek(string_buffer, string, &index)) { Insert(&view.carets, MakeCaret(range.max + index, range.max + index + string.len), 0); } else { - String16 buffer = GetString(buf); - if (Seek(buffer, string, &index)) { + String16 string_buffer = GetString(*buffer); + if (Seek(string_buffer, string, &index)) { Insert(&view.carets, MakeCaret(index, index + string.len), 0); } } } if (CtrlShiftPress(KEY_Z)) { - RedoEdit(&buf, &view.carets); + RedoEdit(buffer, &view.carets); } else if (CtrlPress(KEY_Z)) { - UndoEdit(&buf, &view.carets); + UndoEdit(buffer, &view.carets); } if (CtrlPress(KEY_C)) { @@ -267,7 +269,7 @@ void HandleKeybindings(Window *window) { bool dont_update_scroll = false; if (CtrlPress(KEY_A)) { view.carets.len = 1; - view.carets[0] = MakeCaret(0, view.buffer->len); + view.carets[0] = MakeCaret(0, buffer->len); dont_update_scroll = true; } @@ -346,14 +348,14 @@ void HandleKeybindings(Window *window) { 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 = XYToPosWithoutNL(buf, xy); + Int p = XYToPosWithoutNL(*buffer, xy); if (mouse_in_view && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { if (IsDoubleClick()) { Caret *c = GetLast(view.carets); if (InBounds({c->range.min - 1, c->range.max + 1}, p)) { - c->range = EncloseWord(buf, p); + c->range = EncloseWord(*buffer, p); view.selection_anchor = c->range; } } else { @@ -414,7 +416,7 @@ void HandleKeybindings(Window *window) { if (!AreEqual(main_caret_on_begin_frame, view.carets[0]) && !dont_update_scroll) { Caret c = view.carets[0]; Int front = GetFront(c); - XY xy = PosToXY(buf, front); + XY xy = PosToXY(*buffer, front); Rect2I visible = GetVisibleCells(*window); Vec2I visible_cells = GetSize(visible); @@ -445,7 +447,7 @@ void HandleKeybindings(Window *window) { // Clip scroll { ProfileScope(clip_scroll); - Int last_line = LastLine(view.buffer[0]); + Int last_line = LastLine(*buffer); view.scroll.y = Clamp(view.scroll.y, (Int)0, Max((Int)0, (last_line - 1) * FontLineSpacing)); // @note: diff --git a/src/text_editor/view_commands_clipboard.cpp b/src/text_editor/view_commands_clipboard.cpp index f907e01..2537446 100644 --- a/src/text_editor/view_commands_clipboard.cpp +++ b/src/text_editor/view_commands_clipboard.cpp @@ -3,6 +3,7 @@ Array SavedClipboardCursors; void Command_Copy(View *view) { Allocator sys_allocator = GetSystemAllocator(); + Buffer *buffer = GetBuffer(view->buffer_id); SavedClipboardCursors.allocator = sys_allocator; if (SavedClipboardCursors.data) { @@ -18,14 +19,14 @@ void Command_Copy(View *view) { // First, if there is no selection - select the entire line For(view->carets) { if (GetSize(it.range) == 0) { - Int line = PosToLine(*view->buffer, it.range.min); - Range line_range = GetLineRange(*view->buffer, line); + Int line = PosToLine(*buffer, it.range.min); + Range line_range = GetLineRange(*buffer, line); it.range = line_range; } } For(view->carets) { - String16 string = GetString(*view->buffer, it.range); + String16 string = GetString(*buffer, it.range); String16 copy = Copy(sys_allocator, string); Add(&SavedClipboardCursors, copy); } @@ -38,23 +39,24 @@ void Command_Copy(View *view) { void Command_Paste(View *view) { Scratch scratch; + Buffer *buffer = GetBuffer(view->buffer_id); const char *text = GetClipboardText(); String string_ = text; String16 string = ToString16(scratch, string_); // Regular paste if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) { - BeforeEdit(view->buffer, view->carets); + BeforeEdit(buffer, view->carets); MergeCarets(&view->carets); Array edits = {scratch}; For(view->carets) AddEdit(&edits, it.range, string); - ApplyEdits(view->buffer, edits); - AfterEdit(view->buffer, &edits, &view->carets); + ApplyEdits(buffer, edits); + AfterEdit(buffer, &edits, &view->carets); return; } // Multicursor paste - BeforeEdit(view->buffer, view->carets); + BeforeEdit(buffer, view->carets); MergeCarets(&view->carets); Array edits = {scratch}; for (int64_t i = 0; i < view->carets.len; i += 1) { @@ -62,6 +64,6 @@ void Command_Paste(View *view) { Caret &it = view->carets[i]; AddEdit(&edits, it.range, string); } - ApplyEdits(view->buffer, edits); - AfterEdit(view->buffer, &edits, &view->carets); + ApplyEdits(buffer, edits); + AfterEdit(buffer, &edits, &view->carets); } \ No newline at end of file diff --git a/src/text_editor/view_draw.cpp b/src/text_editor/view_draw.cpp index dbd98a2..b41ca58 100644 --- a/src/text_editor/view_draw.cpp +++ b/src/text_editor/view_draw.cpp @@ -5,7 +5,7 @@ Vec2I GetCellSize() { Rect2I GetVisibleCells(Window &window) { ProfileFunction(); - View &view = *GetActiveView(window); + View &view = *GetActiveView(&window); Vec2I size = GetSize(window.document_rect); Int _cx = size.x / FontCharSpacing; @@ -21,10 +21,11 @@ Rect2I GetVisibleCells(Window &window) { } Scroller ComputeScrollerRect(Window &window) { - View &view = *GetActiveView(window); - Vec2I size = GetSize(window.scrollbar_rect); - Rect2I vis = GetVisibleCells(window); - Int line_count = view.buffer->line_starts.len + GetSize(vis).y - 1; + View &view = *GetActiveView(&window); + Buffer *buffer = GetBuffer(view.buffer_id); + Vec2I size = GetSize(window.scrollbar_rect); + Rect2I vis = GetVisibleCells(window); + Int line_count = buffer->line_starts.len + GetSize(vis).y - 1; double begin = (double)vis.min.y / (double)line_count; double end = (double)vis.max.y / (double)line_count; @@ -39,13 +40,14 @@ Scroller ComputeScrollerRect(Window &window) { void DrawVisibleText(Window &window) { ProfileFunction(); - Color tint = ColorText; - View &view = *GetActiveView(window); + Color tint = ColorText; + View &view = *GetActiveView(&window); + Buffer *buffer = GetBuffer(view.buffer_id); Rect2I visible = GetVisibleCells(window); - for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < view.buffer->line_starts.len; line_index += 1) { - Range line_range = GetLineRange(*view.buffer, line_index); - String16 line_string = GetString(*view.buffer, line_range); + for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < buffer->line_starts.len; line_index += 1) { + Range line_range = GetLineRange(*buffer, line_index); + String16 line_string = GetString(*buffer, line_range); Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing}; pos -= view.scroll; @@ -81,7 +83,7 @@ Rect2I XYToRect(const View &view, XY xy) { } void DrawCaret(Window &window, XY xy, float size, Color color) { - View &view = *GetActiveView(window); + View &view = *GetActiveView(&window); Rect2I _rect = XYToRect(view, xy); Rect2I rect = CutLeft(&_rect, (Int)(size * (float)FontCharSpacing)); rect -= view.scroll; @@ -90,7 +92,7 @@ void DrawCaret(Window &window, XY xy, float size, Color color) { } void DrawLineHighlight(Window &window, XY fxy, Color color) { - View &view = *GetActiveView(window); + View &view = *GetActiveView(&window); Vec2I w = XYToWorldPos(view, XYLine(fxy.line)); w -= view.scroll; w += window.document_rect.min; @@ -103,20 +105,20 @@ void DrawLineHighlight(Window &window, XY fxy, Color color) { void DrawSelection(Window &window, Caret &it) { ProfileFunction(); - View &view = *GetActiveView(window); - Buffer &buf = *view.buffer; - Int front = GetFront(it); - Int back = GetBack(it); + View &view = *GetActiveView(&window); + Buffer *buffer = GetBuffer(view.buffer_id); + Int front = GetFront(it); + Int back = GetBack(it); if (front != back) { - XY bxy = PosToXY(buf, back); - XY min = PosToXY(buf, it.range.min); - XY max = PosToXY(buf, it.range.max); + XY bxy = PosToXY(*buffer, back); + XY min = PosToXY(*buffer, it.range.min); + XY max = PosToXY(*buffer, it.range.max); Color color = ColorSelection; Rect2I vlines = GetVisibleCells(window); - for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < view.buffer->line_starts.len; line += 1) { - Range range = GetLineRange(buf, line); - String16 line_string = GetString(buf, range); + for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < buffer->line_starts.len; line += 1) { + Range range = GetLineRange(*buffer, line); + String16 line_string = GetString(*buffer, range); for (Int col = vlines.min.x; col < vlines.max.x && col >= 0 && col < line_string.len; col += 1) { bool a = line > min.line && line < max.line; @@ -146,13 +148,13 @@ void DrawSelection(Window &window, Caret &it) { } void DrawWindow(Window &window) { - View &view = *GetActiveView(window); - Buffer &buf = *view.buffer; + View &view = *GetActiveView(&window); + Buffer *buffer = GetBuffer(view.buffer_id); BeginScissorMode((int)window.document_rect.min.x, (int)window.document_rect.min.y, (int)window.document_rect.max.x - (int)window.document_rect.min.x, (int)window.document_rect.max.y - (int)window.document_rect.min.y); For(view.carets) { Int front = GetFront(it); - XY fxy = PosToXY(buf, front); + XY fxy = PosToXY(*buffer, front); if (GetSize(it.range)) { DrawSelection(window, it); } else { @@ -164,7 +166,7 @@ void DrawWindow(Window &window) { For(view.carets) { Int front = GetFront(it); - XY fxy = PosToXY(buf, front); + XY fxy = PosToXY(*buffer, front); bool main_caret = &it == &view.carets.data[0]; DrawCaret(window, fxy, 0.3f, main_caret ? ColorMainCaret : ColorSubCaret); } @@ -180,7 +182,7 @@ void DrawWindow(Window &window) { Rect2 rect = Shrink(scroller.rect, 2); Color color = ColorScrollbarScroller; if (!window.mouse_selecting && (window.mouse_selecting_scrollbar || mouse_in_scrollbar)) { - color = ColorScrollbarScrollerSelected; + if (IsActive(&window)) color = ColorScrollbarScrollerSelected; } DrawRectangleRec(ToRectangle(rect), color); } @@ -218,7 +220,7 @@ void DrawWindow(Window &window) { Vec2 p = ToVec2(r.min); Scratch scratch; Caret caret = view.carets[0]; - XY xy = PosToXY(*view.buffer, GetFront(caret)); + XY xy = PosToXY(*buffer, GetFront(caret)); String s = Format(scratch, "-- line: %lld col: %lld", (long long)xy.line + 1ll, (long long)xy.col + 1ll); String16 string = ToString16(scratch, s); DrawString(MenuFont, string, p, MenuFontSize, 1, ColorText); diff --git a/src/text_editor/windows.cpp b/src/text_editor/windows.cpp index eeba825..e69de29 100644 --- a/src/text_editor/windows.cpp +++ b/src/text_editor/windows.cpp @@ -1,21 +0,0 @@ -Array Windows = {}; -Int ActiveWindow = 0; - -Window *GetActiveWindow() { - return &Windows[ActiveWindow]; -} - -View *GetActiveView(Window &window) { - return &window.views[window.active_view]; -} - -bool IsActive(Window *window) { - Window *active_window = GetActiveWindow(); - bool result = window == active_window; - return result; -} - -bool IsActive(Window *window, View *view) { - bool result = view == GetActiveView(*window); - return result; -} \ No newline at end of file