From ce93a769f6c8ae894db4f23173a97c8c0df7c1d5 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sat, 20 Dec 2025 09:54:19 +0100 Subject: [PATCH] Remove hooks, file modifications --- src/text_editor/commands.cpp | 93 +++--- src/text_editor/commands_bindings.cpp | 319 -------------------- src/text_editor/globals.cpp | 5 - src/text_editor/management.cpp | 111 ------- src/text_editor/text_editor.cpp | 405 +++++++++++++++++++++++++- 5 files changed, 446 insertions(+), 487 deletions(-) delete mode 100644 src/text_editor/commands_bindings.cpp delete mode 100644 src/text_editor/management.cpp diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index 56854a2..a9ae29d 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -1,3 +1,41 @@ +BSet GetBSet(Window *window) { + BSet set = {window}; + set.view = GetView(set.window->active_view); + set.buffer = GetBuffer(set.view->active_buffer); + return set; +} + +BSet GetBSet(WindowID window_id) { + Window *window = GetWindow(window_id); + BSet result = GetBSet(window); + return result; +} + +BSet GetConsoleSet() { + BSet result = {}; + result.window = GetWindow(NullWindowID); + result.view = GetView(NullViewID); + result.buffer = GetBuffer(NullBufferID); + return result; +} + +String GetCurrentFilename() { + BSet main = GetBSet(LastActiveLayoutWindowID); + return main.buffer->name; +} + +String GetDir(Buffer *buffer) { + String name = ChopLastSlash(buffer->name); + return name; +} + +String GetMainDir() { + BSet main = GetBSet(LastActiveLayoutWindowID); + String name = ChopLastSlash(main.buffer->name); + return name; +} + + void CheckpointBeforeGoto(Window *window, View *view) { if (window->jump_history == false) return; Add(&window->goto_history, {view->id, view->carets[0], GetTimeSeconds()}); @@ -1336,13 +1374,13 @@ void Command_KillSelectedLines() { void Command_IndentSelectedLines() { BSet active = GetBSet(ActiveWindowID); - Event event = *OnCommandEvent; - bool left = false; - if (Press(SDLK_LEFTBRACKET) || ShiftPress(SDLK_TAB)) { - left = true; - } - IndentSelectedLines(active.view, left); -} RegisterCommand(Command_IndentSelectedLines, "ctrl-leftbracket | ctrl-rightbracket | tab | shift-tab"); + IndentSelectedLines(active.view); +} RegisterCommand(Command_IndentSelectedLines, "ctrl-rightbracket | tab"); + +void Command_DedentSelectedLines() { + BSet active = GetBSet(ActiveWindowID); + IndentSelectedLines(active.view, true); +} RegisterCommand(Command_DedentSelectedLines, "ctrl-leftbracket | shift-tab"); void Command_DuplicateLineDown() { BSet active = GetBSet(ActiveWindowID); @@ -1608,44 +1646,3 @@ void Command_ClearCarets() { } } } RegisterCommand(Command_ClearCarets, "escape"); - -void Hook_OnDropFile(String *text) { - BSet active = GetBSet(ActiveWindowID); - WindowOpenBufferView(active.window, *text); -} RegisterHook(&OnDropFileHooks, Hook_OnDropFile); - -void Hook_OnTextInput(String *text) { - BSet active = GetBSet(ActiveWindowID); - Scratch scratch; - String16 string16 = ToString16(scratch, *text); - Replace(active.view, string16); -} RegisterHook(&OnTextInputHooks, Hook_OnTextInput); - -void Hook_PostCommandFuzzySearchUpdate(void *param) { - BSet active = GetBSet(ActiveWindowID); - if (active.view->fuzzy_search) { - if (!ProcessIsActive(active.view->id)) { - Scratch scratch; - String16 last_line_string = GetLineStringWithoutNL(active.buffer, active.buffer->line_starts.len - 1); - if (active.view->prev_search_line != last_line_string) { - active.view->prev_search_line = last_line_string; - Array ratings = FuzzySearchLines(scratch, active.buffer, 0, active.buffer->line_starts.len - 1, last_line_string); - - Buffer *temp_buffer = CreateTempBuffer(scratch, active.buffer->cap); - For(IterateInReverse(&ratings)) { - String16 s = GetLineStringWithoutNL(active.buffer, it.index); - if (s.len == 0) continue; - RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), s); - RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), u"\n"); - } - RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), last_line_string); - - Caret caret = active.view->carets[0]; - SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets); - SelectEntireBuffer(active.view); - Replace(active.view, GetString(temp_buffer)); - active.view->carets[0] = caret; - } - } - } -} RegisterHook(&PostCommandHooks, Hook_PostCommandFuzzySearchUpdate); \ No newline at end of file diff --git a/src/text_editor/commands_bindings.cpp b/src/text_editor/commands_bindings.cpp deleted file mode 100644 index 1853e37..0000000 --- a/src/text_editor/commands_bindings.cpp +++ /dev/null @@ -1,319 +0,0 @@ -void UpdateScroll(Window *window, bool update_caret_scrolling) { - ProfileFunction(); - BSet set = GetBSet(window); - - // Scrolling with caret - if (update_caret_scrolling) { - Caret c = set.view->carets[0]; - Int front = GetFront(c); - XY xy = PosToXY(set.buffer, front); - - Rect2I visible = GetVisibleCells(window); - Vec2I visible_cells = GetSize(visible); - Vec2I visible_size = visible_cells * Vec2I{window->font->char_spacing, window->font->line_spacing}; - Vec2I rect_size = GetSize(window->document_rect); - - if (xy.line >= visible.max.y - 2) { - Int set_view_at_line = xy.line - (visible_cells.y - 1); - Int cut_off_y = Max((Int)0, visible_size.y - rect_size.y); - set.view->scroll.y = (set_view_at_line * window->font->line_spacing) + cut_off_y; - } - - if (xy.line < visible.min.y + 1) { - set.view->scroll.y = xy.line * window->font->line_spacing; - } - - if (xy.col >= visible.max.x - 1) { - Int set_view_at_line = xy.col - (visible_cells.x - 1); - Int cut_off_x = Max((Int)0, visible_size.x - rect_size.x); - set.view->scroll.x = (set_view_at_line * window->font->char_spacing) + cut_off_x; - } - - if (xy.col <= visible.min.x) { - set.view->scroll.x = xy.col * window->font->char_spacing; - } - } - - // Clip scroll - { - Int last_line = LastLine(set.buffer); - set.view->scroll.y = Clamp(set.view->scroll.y, (Int)0, Max((Int)0, (last_line - 1) * window->font->line_spacing)); - - // @note: - // GetCharCountOfLongestLine is a bottleneck, there is probably an algorithm for - // calculating this value incrementally but do we even need X scrollbar or x clipping? - set.view->scroll.x = ClampBottom(set.view->scroll.x, (Int)0); - } -} - -void OnCommand(Event event) { - ProfileFunction(); - // - // Window cursor setting - // - Scratch scratch; - Array order = GetWindowZOrder(scratch); - - - // Handle wheel scrolling - if (event.xwheel || event.ywheel) { - Vec2I mouse = MouseVec2I(); - - For(order) { - if (!it->visible) continue; - - bool mouse_in_window = AreOverlapping(mouse, it->total_rect); - if (mouse_in_window) { - View *view = GetView(it->active_view); - view->scroll.y -= (Int)(event.ywheel * 48); - view->scroll.x += (Int)(event.xwheel * 48); - break; - } - } - } - - // Handle selected window scrollbar - // @note: the order here assumes that we won't run this code on the - // same event as the scroll was pressed - if (IsScrollbarSelectionValid() && Mouse(LEFT_UP)) { - Assert(DocumentSelected.id == -1); - ScrollbarSelected.id = -1; - } else if (IsScrollbarSelectionValid()) { - // :ScrollbarImprovement - // @todo: it generally works ok but it moves the scrollbar a bit on click - // when mouse is not even moving - Assert(DocumentSelected.id == -1); - Window *window = GetWindow(ScrollbarSelected); - View *view = GetView(window->active_view); - Vec2 mouse_vec2 = MouseVec2(); - Scroller s = ComputeScrollerRect(window); - double size_y = (double)GetSize(window->scrollbar_rect).y; - double p = mouse_vec2.y - window->scrollbar_rect.min.y; - double v = p / size_y; - v = v + (window->mouse_scroller_offset); - view->scroll.y = (Int)(v * (double)s.line_count * (double)window->font->line_spacing); - } - - if (DocumentSelected != ActiveWindowID) { - DocumentSelected.id = -1; - } else if (IsDocumentSelectionValid() && MouseUp()) { - Assert(ScrollbarSelected.id == -1); - DocumentSelected.id = -1; - } else if (IsDocumentSelectionValid()) { - Assert(ScrollbarSelected.id == -1); - BSet selected = GetBSet(DocumentSelected); - Vec2I mouse = MouseVec2I(); - // Special case for full-screen where we can have document - // aligned with monitor screen in which case mouse cursor cannot - // be smaller then 0 which means we cannot scroll - if (mouse.y == 0 && selected.window->document_rect.min.y == 0) { - float x, y; - SDL_GetGlobalMouseState(&x, &y); - x = roundf(DPIScale * x); - y = roundf(DPIScale * y); - if (y == 0) { - mouse.y = -10; - } - } - - Int p = ScreenSpaceToBufferPos(selected.window, selected.view, selected.buffer, mouse); - Caret &caret = selected.view->carets[0]; - caret = SetFrontWithAnchor(caret, DocumentAnchor, p); - } - - if (ResizerSelected.id != -1 && Mouse(LEFT_UP)) { - Assert(DocumentSelected.id == -1); - Assert(ScrollbarSelected.id == -1); - ResizerSelected.id = {-1}; - } else if (ResizerSelected.id != -1) { - Window *window = GetWindow(ResizerSelected); - if (window->layout) { - Vec2I mouse = MouseVec2I(); - Int offx = mouse.x - window->resizer_rect.min.x; - window->weight += (double)offx / (double)WindowCalcEvenResizerValue(event.xwindow); - window->weight = Clamp(window->weight, 0.1, 100.0); - } - } else { - ResizerHover = {-1}; - For(Windows) { - Vec2I mouse = MouseVec2I(); - bool mouse_in_rect = AreOverlapping(mouse, it->resizer_rect); - if (mouse_in_rect) { - ResizerHover = it->id; - if (Mouse(LEFT)) { - ResizerSelected = it->id; - } - } - } - } - - // Set active window on click - if (MousePress()) { - Vec2I mouse = MouseVec2I(); - For(order) { - if (!it->visible) { - continue; - } - bool mouse_in_document = AreOverlapping(mouse, it->document_rect); - if (mouse_in_document) { - ActiveWindowID = it->id; - break; - } - } - } - - if (Ctrl() && Shift() && Mouse(RIGHT)) { - - } else if (Alt() && Ctrl() && Mouse(RIGHT)) { - } else if (Ctrl() && Mouse(RIGHT)) { - - } else if (Alt() && Mouse(RIGHT)) { - } else if (Mouse(RIGHT)) { - Vec2I mouse = MouseVec2I(); - BSet active = GetBSet(ActiveWindowID); - bool mouse_in_document = AreOverlapping(mouse, active.window->document_rect); - if (mouse_in_document) { - Int p = ScreenSpaceToBufferPos(active.window, active.view, active.buffer, mouse); - Int saved_front = -1; - - IterRemove(active.view->carets) { - IterRemovePrepare(active.view->carets); - if (InBounds(it.range, p)) { - String16 string = GetString(active.buffer, it.range); - SaveStringInClipboard(string); - - remove_item = true; - saved_front = GetFront(it); - } - } - if (active.view->carets.len == 0) Add(&active.view->carets, MakeCaret(saved_front)); - - if (saved_front == -1) { - Int line = PosToLine(active.buffer, p); - Range line_range = GetLineRangeWithoutNL(active.buffer, line); - String16 string = GetString(active.buffer, line_range); - SaveStringInClipboard(string); - } - } - } - - if (Ctrl() && Mouse(LEFT)) { - MouseLoadWord(event); - } else if (Mouse(LEFT)) { // Uses Alt and shift - Vec2I mouse = MouseVec2I(); - { - Assert(ScrollbarSelected.id == -1); - Assert(DocumentSelected.id == -1); - - BSet active = GetBSet(ActiveWindowID); // using next to make sure mouse works on first click after switching the window - bool mouse_in_document = AreOverlapping(mouse, active.window->document_rect); - bool mouse_in_line_numbers = AreOverlapping(mouse, active.window->line_numbers_rect); - if (mouse_in_document || mouse_in_line_numbers) { - DocumentSelected = active.window->id; - CheckpointBeforeGoto(active.window); - - - Int p = ScreenSpaceToBufferPos(active.window, active.view, active.buffer, mouse); - if (Alt()) Insert(&active.view->carets, MakeCaret(p, p), 0); - if (!Alt() && !Shift()) active.view->carets.len = 1; - - Caret &caret = active.view->carets[0]; - if (Shift()) { - if (p <= caret.range.min) { - caret.range.min = p; - caret.ifront = 0; - } else if (p >= caret.range.max) { - caret.range.max = p; - caret.ifront = 1; - } - } else if (event.clicks >= 2 && InBounds({caret.range.min - 1, caret.range.max + 1}, p)) { - Range range = EncloseWord(active.buffer, p); - if (event.clicks >= 3) { - range = EncloseFullLine(active.buffer, p); - } - caret = MakeCaret(range.max, range.min); - } else { - caret = MakeCaret(p); - } - MergeCarets(active.buffer, &active.view->carets); - DocumentAnchor = caret; - } - } - - // Figure out scrollbar click - // :ScrollbarImprovement - // @todo: it generally works ok but it moves the scrollbar a bit on click - // when mouse is not even moving - For(order) { - if (!it->visible) continue; - bool mouse_in_scrollbar = AreOverlapping(mouse, it->scrollbar_rect); - if (mouse_in_scrollbar) { - ScrollbarSelected = it->id; - - View *view = GetView(it->active_view); - Vec2 mouse_vec2 = MouseVec2(); - Scroller s = ComputeScrollerRect(it); - double size_y = (double)GetSize(it->scrollbar_rect).y; - double p = mouse_vec2.y - it->scrollbar_rect.min.y; - if (mouse_vec2.y < s.rect.min.y || mouse_vec2.y > s.rect.max.y) { - view->scroll.y = (Int)(p / size_y * (double)s.line_count * (double)it->font->line_spacing); - it->mouse_scroller_offset = -(double)GetSize(s.rect).y / 2.0 / size_y; - } else { - it->mouse_scroller_offset = (s.rect.min.y - p) / size_y; - } - break; - } - } - } - - BSet main = GetBSet(LastActiveLayoutWindowID); - BSet active = GetBSet(ActiveWindowID); - - // @todo: somehow detect in post command that buffer changed but random buffer can get changed??? Not sure - // maybe we - Int buffer_change_id = active.buffer->change_id; - String event_text = event.text; - - SkipRemainingCommands = false; - For (CommandFunctions) { - if (it.trigger && MatchEvent(it.trigger, &event)) { - it.function(); - if (SkipRemainingCommands) { - break; - } - } - } - - if (event.kind == EVENT_DROP_FILE) { - SkipRemainingCommands = false; - For (OnDropFileHooks) { - it.function(&event_text); - if (SkipRemainingCommands) { - break; - } - } - } - - if (event.kind == EVENT_TEXT_INPUT) { - SkipRemainingCommands = false; - For (OnTextInputHooks) { - it.function(&event_text); - if (SkipRemainingCommands) { - break; - } - } - } - - MergeCarets(active.buffer, &active.view->carets); - IF_DEBUG(AssertRanges(active.view->carets)); - MergeCarets(main.buffer, &main.view->carets); - IF_DEBUG(AssertRanges(main.view->carets)); - - SkipRemainingCommands = false; - For (PostCommandHooks) { - it.function(NULL); - if (SkipRemainingCommands) { - return; - } - } -} diff --git a/src/text_editor/globals.cpp b/src/text_editor/globals.cpp index 41c0689..b5abfed 100644 --- a/src/text_editor/globals.cpp +++ b/src/text_editor/globals.cpp @@ -51,7 +51,6 @@ RandomSeed UniqueBufferNameSeed = {}; Array EventPlayback; lua_State *LuaState = NULL; BlockArena Perm; -Event *OnCommandEvent; // clipboard BlockArena ClipboardArena; @@ -196,10 +195,6 @@ Array CommandFunctions; Array LuaFunctions; Array TestFunctions; -Array PostCommandHooks; -Array OnTextInputHooks; -Array OnDropFileHooks; - struct Register_Function { Register_Function(Array *functions, String name, Function *f) { int64_t pos = 0; diff --git a/src/text_editor/management.cpp b/src/text_editor/management.cpp deleted file mode 100644 index 5bb1d41..0000000 --- a/src/text_editor/management.cpp +++ /dev/null @@ -1,111 +0,0 @@ -BSet GetBSet(Window *window) { - BSet set = {window}; - set.view = GetView(set.window->active_view); - set.buffer = GetBuffer(set.view->active_buffer); - return set; -} - -BSet GetBSet(WindowID window_id) { - Window *window = GetWindow(window_id); - BSet result = GetBSet(window); - return result; -} - -BSet GetConsoleSet() { - BSet result = {}; - result.window = GetWindow(NullWindowID); - result.view = GetView(NullViewID); - result.buffer = GetBuffer(NullBufferID); - return result; -} - -String GetCurrentFilename() { - BSet main = GetBSet(LastActiveLayoutWindowID); - return main.buffer->name; -} - -String GetDir(Buffer *buffer) { - String name = ChopLastSlash(buffer->name); - return name; -} - -String GetMainDir() { - BSet main = GetBSet(LastActiveLayoutWindowID); - String name = ChopLastSlash(main.buffer->name); - return name; -} - -void GarbageCollect() { - Allocator sys_allocator = GetSystemAllocator(); - - For (Windows) { - if (it->sync_visibility_with_focus) { - if (it->id == ActiveWindowID) { - it->visible = true; - } else { - it->visible = false; - } - } - } - - Window *window = GetWindow(ActiveWindowID); - if (ActiveWindowID.id != LastActiveLayoutWindowID.id) { - if (window->layout) { - LastActiveLayoutWindowID = ActiveWindowID; - } - } - - For(Buffers) { - if (it->file_mod_time) { - int64_t new_file_mod_time = GetFileModTime(it->name); - if (it->file_mod_time != new_file_mod_time) { - it->changed_on_disk = true; - if (it->dirty == false) ReopenBuffer(it); - } - } - } - - IterRemove(Views) { - IterRemovePrepare(Views); - - Buffer *buffer = GetBuffer(it->active_buffer); - if (!buffer->garbage) { - continue; - } - - bool ref = ViewIsReferenced(it->id); - if (ref) { - continue; - } - - remove_item = true; - Dealloc(&it->carets); - Dealloc(sys_allocator, it); - } - - IterRemove(Buffers) { - IterRemovePrepare(Buffers); - - if (!it->garbage) { - continue; - } - - bool ref = BufferIsReferenced(it->id); - if (ref) { - continue; - } - - remove_item = true; - DeallocBuffer(it); - } - - IterRemove(Windows) { - IterRemovePrepare(Windows); - if (it->kill) { - Dealloc(&it->goto_history); - Dealloc(&it->goto_redo); - Dealloc(sys_allocator, it); - remove_item = true; - } - } -} diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 9a473b1..4fcd67b 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -30,7 +30,6 @@ #include "buffer.cpp" #include "view.cpp" #include "window.cpp" -#include "management.cpp" #include "process.cpp" #include "event.cpp" #include "parser.cpp" @@ -38,7 +37,6 @@ #include "commands.cpp" #include "lua_api.cpp" #include "commands_clipboard.cpp" -#include "commands_bindings.cpp" #include "title_bar.cpp" #include "generated_config.cpp" @@ -122,6 +120,407 @@ void SetMouseCursor(Event event) { } SetMouseCursor(SDL_SYSTEM_CURSOR_DEFAULT); } +void UpdateScroll(Window *window, bool update_caret_scrolling) { + ProfileFunction(); + BSet set = GetBSet(window); + + // Scrolling with caret + if (update_caret_scrolling) { + Caret c = set.view->carets[0]; + Int front = GetFront(c); + XY xy = PosToXY(set.buffer, front); + + Rect2I visible = GetVisibleCells(window); + Vec2I visible_cells = GetSize(visible); + Vec2I visible_size = visible_cells * Vec2I{window->font->char_spacing, window->font->line_spacing}; + Vec2I rect_size = GetSize(window->document_rect); + + if (xy.line >= visible.max.y - 2) { + Int set_view_at_line = xy.line - (visible_cells.y - 1); + Int cut_off_y = Max((Int)0, visible_size.y - rect_size.y); + set.view->scroll.y = (set_view_at_line * window->font->line_spacing) + cut_off_y; + } + + if (xy.line < visible.min.y + 1) { + set.view->scroll.y = xy.line * window->font->line_spacing; + } + + if (xy.col >= visible.max.x - 1) { + Int set_view_at_line = xy.col - (visible_cells.x - 1); + Int cut_off_x = Max((Int)0, visible_size.x - rect_size.x); + set.view->scroll.x = (set_view_at_line * window->font->char_spacing) + cut_off_x; + } + + if (xy.col <= visible.min.x) { + set.view->scroll.x = xy.col * window->font->char_spacing; + } + } + + // Clip scroll + { + Int last_line = LastLine(set.buffer); + set.view->scroll.y = Clamp(set.view->scroll.y, (Int)0, Max((Int)0, (last_line - 1) * window->font->line_spacing)); + + // @note: + // GetCharCountOfLongestLine is a bottleneck, there is probably an algorithm for + // calculating this value incrementally but do we even need X scrollbar or x clipping? + set.view->scroll.x = ClampBottom(set.view->scroll.x, (Int)0); + } +} + +void OnCommand(Event event) { + ProfileFunction(); + // + // Window cursor setting + // + Scratch scratch; + Array order = GetWindowZOrder(scratch); + + + // Handle wheel scrolling + if (event.xwheel || event.ywheel) { + Vec2I mouse = MouseVec2I(); + + For(order) { + if (!it->visible) continue; + + bool mouse_in_window = AreOverlapping(mouse, it->total_rect); + if (mouse_in_window) { + View *view = GetView(it->active_view); + view->scroll.y -= (Int)(event.ywheel * 48); + view->scroll.x += (Int)(event.xwheel * 48); + break; + } + } + } + + // Handle selected window scrollbar + // @note: the order here assumes that we won't run this code on the + // same event as the scroll was pressed + if (IsScrollbarSelectionValid() && Mouse(LEFT_UP)) { + Assert(DocumentSelected.id == -1); + ScrollbarSelected.id = -1; + } else if (IsScrollbarSelectionValid()) { + // :ScrollbarImprovement + // @todo: it generally works ok but it moves the scrollbar a bit on click + // when mouse is not even moving + Assert(DocumentSelected.id == -1); + Window *window = GetWindow(ScrollbarSelected); + View *view = GetView(window->active_view); + Vec2 mouse_vec2 = MouseVec2(); + Scroller s = ComputeScrollerRect(window); + double size_y = (double)GetSize(window->scrollbar_rect).y; + double p = mouse_vec2.y - window->scrollbar_rect.min.y; + double v = p / size_y; + v = v + (window->mouse_scroller_offset); + view->scroll.y = (Int)(v * (double)s.line_count * (double)window->font->line_spacing); + } + + if (DocumentSelected != ActiveWindowID) { + DocumentSelected.id = -1; + } else if (IsDocumentSelectionValid() && MouseUp()) { + Assert(ScrollbarSelected.id == -1); + DocumentSelected.id = -1; + } else if (IsDocumentSelectionValid()) { + Assert(ScrollbarSelected.id == -1); + BSet selected = GetBSet(DocumentSelected); + Vec2I mouse = MouseVec2I(); + // Special case for full-screen where we can have document + // aligned with monitor screen in which case mouse cursor cannot + // be smaller then 0 which means we cannot scroll + if (mouse.y == 0 && selected.window->document_rect.min.y == 0) { + float x, y; + SDL_GetGlobalMouseState(&x, &y); + x = roundf(DPIScale * x); + y = roundf(DPIScale * y); + if (y == 0) { + mouse.y = -10; + } + } + + Int p = ScreenSpaceToBufferPos(selected.window, selected.view, selected.buffer, mouse); + Caret &caret = selected.view->carets[0]; + caret = SetFrontWithAnchor(caret, DocumentAnchor, p); + } + + if (ResizerSelected.id != -1 && Mouse(LEFT_UP)) { + Assert(DocumentSelected.id == -1); + Assert(ScrollbarSelected.id == -1); + ResizerSelected.id = {-1}; + } else if (ResizerSelected.id != -1) { + Window *window = GetWindow(ResizerSelected); + if (window->layout) { + Vec2I mouse = MouseVec2I(); + Int offx = mouse.x - window->resizer_rect.min.x; + window->weight += (double)offx / (double)WindowCalcEvenResizerValue(event.xwindow); + window->weight = Clamp(window->weight, 0.1, 100.0); + } + } else { + ResizerHover = {-1}; + For(Windows) { + Vec2I mouse = MouseVec2I(); + bool mouse_in_rect = AreOverlapping(mouse, it->resizer_rect); + if (mouse_in_rect) { + ResizerHover = it->id; + if (Mouse(LEFT)) { + ResizerSelected = it->id; + } + } + } + } + + // Set active window on click + if (MousePress()) { + Vec2I mouse = MouseVec2I(); + For(order) { + if (!it->visible) { + continue; + } + bool mouse_in_document = AreOverlapping(mouse, it->document_rect); + if (mouse_in_document) { + ActiveWindowID = it->id; + break; + } + } + } + + if (Ctrl() && Shift() && Mouse(RIGHT)) { + + } else if (Alt() && Ctrl() && Mouse(RIGHT)) { + } else if (Ctrl() && Mouse(RIGHT)) { + + } else if (Alt() && Mouse(RIGHT)) { + } else if (Mouse(RIGHT)) { + Vec2I mouse = MouseVec2I(); + BSet active = GetBSet(ActiveWindowID); + bool mouse_in_document = AreOverlapping(mouse, active.window->document_rect); + if (mouse_in_document) { + Int p = ScreenSpaceToBufferPos(active.window, active.view, active.buffer, mouse); + Int saved_front = -1; + + IterRemove(active.view->carets) { + IterRemovePrepare(active.view->carets); + if (InBounds(it.range, p)) { + String16 string = GetString(active.buffer, it.range); + SaveStringInClipboard(string); + + remove_item = true; + saved_front = GetFront(it); + } + } + if (active.view->carets.len == 0) Add(&active.view->carets, MakeCaret(saved_front)); + + if (saved_front == -1) { + Int line = PosToLine(active.buffer, p); + Range line_range = GetLineRangeWithoutNL(active.buffer, line); + String16 string = GetString(active.buffer, line_range); + SaveStringInClipboard(string); + } + } + } + + if (Ctrl() && Mouse(LEFT)) { + MouseLoadWord(event); + } else if (Mouse(LEFT)) { // Uses Alt and shift + Vec2I mouse = MouseVec2I(); + { + Assert(ScrollbarSelected.id == -1); + Assert(DocumentSelected.id == -1); + + BSet active = GetBSet(ActiveWindowID); // using next to make sure mouse works on first click after switching the window + bool mouse_in_document = AreOverlapping(mouse, active.window->document_rect); + bool mouse_in_line_numbers = AreOverlapping(mouse, active.window->line_numbers_rect); + if (mouse_in_document || mouse_in_line_numbers) { + DocumentSelected = active.window->id; + CheckpointBeforeGoto(active.window); + + + Int p = ScreenSpaceToBufferPos(active.window, active.view, active.buffer, mouse); + if (Alt()) Insert(&active.view->carets, MakeCaret(p, p), 0); + if (!Alt() && !Shift()) active.view->carets.len = 1; + + Caret &caret = active.view->carets[0]; + if (Shift()) { + if (p <= caret.range.min) { + caret.range.min = p; + caret.ifront = 0; + } else if (p >= caret.range.max) { + caret.range.max = p; + caret.ifront = 1; + } + } else if (event.clicks >= 2 && InBounds({caret.range.min - 1, caret.range.max + 1}, p)) { + Range range = EncloseWord(active.buffer, p); + if (event.clicks >= 3) { + range = EncloseFullLine(active.buffer, p); + } + caret = MakeCaret(range.max, range.min); + } else { + caret = MakeCaret(p); + } + MergeCarets(active.buffer, &active.view->carets); + DocumentAnchor = caret; + } + } + + // Figure out scrollbar click + // :ScrollbarImprovement + // @todo: it generally works ok but it moves the scrollbar a bit on click + // when mouse is not even moving + For(order) { + if (!it->visible) continue; + bool mouse_in_scrollbar = AreOverlapping(mouse, it->scrollbar_rect); + if (mouse_in_scrollbar) { + ScrollbarSelected = it->id; + + View *view = GetView(it->active_view); + Vec2 mouse_vec2 = MouseVec2(); + Scroller s = ComputeScrollerRect(it); + double size_y = (double)GetSize(it->scrollbar_rect).y; + double p = mouse_vec2.y - it->scrollbar_rect.min.y; + if (mouse_vec2.y < s.rect.min.y || mouse_vec2.y > s.rect.max.y) { + view->scroll.y = (Int)(p / size_y * (double)s.line_count * (double)it->font->line_spacing); + it->mouse_scroller_offset = -(double)GetSize(s.rect).y / 2.0 / size_y; + } else { + it->mouse_scroller_offset = (s.rect.min.y - p) / size_y; + } + break; + } + } + } + + BSet main = GetBSet(LastActiveLayoutWindowID); + BSet active = GetBSet(ActiveWindowID); + + // @todo: somehow detect in post command that buffer changed but random buffer can get changed??? Not sure + // maybe we use a timestamo instead ! + Int buffer_change_id = active.buffer->change_id; + + SkipRemainingCommands = false; + For (CommandFunctions) { + if (it.trigger && MatchEvent(it.trigger, &event)) { + it.function(); + if (SkipRemainingCommands) { + break; + } + } + } + + if (event.kind == EVENT_DROP_FILE) { + WindowOpenBufferView(active.window, event.text); + } + + if (event.kind == EVENT_TEXT_INPUT) { + Scratch scratch; + String16 string16 = ToString16(scratch, event.text); + Replace(active.view, string16); + } + + if (active.view->fuzzy_search) { + if (!ProcessIsActive(active.view->id)) { + Scratch scratch; + String16 last_line_string = GetLineStringWithoutNL(active.buffer, active.buffer->line_starts.len - 1); + if (active.view->prev_search_line != last_line_string) { + active.view->prev_search_line = last_line_string; + Array ratings = FuzzySearchLines(scratch, active.buffer, 0, active.buffer->line_starts.len - 1, last_line_string); + + Buffer *temp_buffer = CreateTempBuffer(scratch, active.buffer->cap); + For(IterateInReverse(&ratings)) { + String16 s = GetLineStringWithoutNL(active.buffer, it.index); + if (s.len == 0) continue; + RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), s); + RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), u"\n"); + } + RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), last_line_string); + + Caret caret = active.view->carets[0]; + SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets); + SelectEntireBuffer(active.view); + Replace(active.view, GetString(temp_buffer)); + active.view->carets[0] = caret; + } + } + } + + MergeCarets(active.buffer, &active.view->carets); + IF_DEBUG(AssertRanges(active.view->carets)); + MergeCarets(main.buffer, &main.view->carets); + IF_DEBUG(AssertRanges(main.view->carets)); +} + +void GarbageCollect() { + Allocator sys_allocator = GetSystemAllocator(); + + For (Windows) { + if (it->sync_visibility_with_focus) { + if (it->id == ActiveWindowID) { + it->visible = true; + } else { + it->visible = false; + } + } + } + + Window *window = GetWindow(ActiveWindowID); + if (ActiveWindowID.id != LastActiveLayoutWindowID.id) { + if (window->layout) { + LastActiveLayoutWindowID = ActiveWindowID; + } + } + + For(Buffers) { + if (it->file_mod_time) { + int64_t new_file_mod_time = GetFileModTime(it->name); + if (it->file_mod_time != new_file_mod_time) { + it->changed_on_disk = true; + if (it->dirty == false) ReopenBuffer(it); + } + } + } + + IterRemove(Views) { + IterRemovePrepare(Views); + + Buffer *buffer = GetBuffer(it->active_buffer); + if (!buffer->garbage) { + continue; + } + + bool ref = ViewIsReferenced(it->id); + if (ref) { + continue; + } + + remove_item = true; + Dealloc(&it->carets); + Dealloc(sys_allocator, it); + } + + IterRemove(Buffers) { + IterRemovePrepare(Buffers); + + if (!it->garbage) { + continue; + } + + bool ref = BufferIsReferenced(it->id); + if (ref) { + continue; + } + + remove_item = true; + DeallocBuffer(it); + } + + IterRemove(Windows) { + IterRemovePrepare(Windows); + if (it->kill) { + Dealloc(&it->goto_history); + Dealloc(&it->goto_redo); + Dealloc(sys_allocator, it); + remove_item = true; + } + } +} void Update(Event event) { LayoutWindows(event.xwindow, event.ywindow); @@ -135,9 +534,7 @@ void Update(Event event) { view->update_scroll = true; } - OnCommandEvent = &event; OnCommand(event); - OnCommandEvent = NULL; UpdateProcesses(); CoUpdate(&event); ReloadLuaConfigs();