Remove hooks, file modifications

This commit is contained in:
Krzosa Karol
2025-12-20 09:54:19 +01:00
parent 7720176e60
commit ce93a769f6
5 changed files with 446 additions and 487 deletions

View File

@@ -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) { void CheckpointBeforeGoto(Window *window, View *view) {
if (window->jump_history == false) return; if (window->jump_history == false) return;
Add(&window->goto_history, {view->id, view->carets[0], GetTimeSeconds()}); Add(&window->goto_history, {view->id, view->carets[0], GetTimeSeconds()});
@@ -1336,13 +1374,13 @@ void Command_KillSelectedLines() {
void Command_IndentSelectedLines() { void Command_IndentSelectedLines() {
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
Event event = *OnCommandEvent; IndentSelectedLines(active.view);
bool left = false; } RegisterCommand(Command_IndentSelectedLines, "ctrl-rightbracket | tab");
if (Press(SDLK_LEFTBRACKET) || ShiftPress(SDLK_TAB)) {
left = true; void Command_DedentSelectedLines() {
} BSet active = GetBSet(ActiveWindowID);
IndentSelectedLines(active.view, left); IndentSelectedLines(active.view, true);
} RegisterCommand(Command_IndentSelectedLines, "ctrl-leftbracket | ctrl-rightbracket | tab | shift-tab"); } RegisterCommand(Command_DedentSelectedLines, "ctrl-leftbracket | shift-tab");
void Command_DuplicateLineDown() { void Command_DuplicateLineDown() {
BSet active = GetBSet(ActiveWindowID); BSet active = GetBSet(ActiveWindowID);
@@ -1608,44 +1646,3 @@ void Command_ClearCarets() {
} }
} }
} RegisterCommand(Command_ClearCarets, "escape"); } 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<FuzzyPair> 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);

View File

@@ -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<Window *> 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;
}
}
}

View File

@@ -51,7 +51,6 @@ RandomSeed UniqueBufferNameSeed = {};
Array<Event> EventPlayback; Array<Event> EventPlayback;
lua_State *LuaState = NULL; lua_State *LuaState = NULL;
BlockArena Perm; BlockArena Perm;
Event *OnCommandEvent;
// clipboard // clipboard
BlockArena ClipboardArena; BlockArena ClipboardArena;
@@ -196,10 +195,6 @@ Array<CommandData> CommandFunctions;
Array<LuaFunctionData> LuaFunctions; Array<LuaFunctionData> LuaFunctions;
Array<FunctionData> TestFunctions; Array<FunctionData> TestFunctions;
Array<PFunctionData> PostCommandHooks;
Array<PFunctionData> OnTextInputHooks;
Array<PFunctionData> OnDropFileHooks;
struct Register_Function { struct Register_Function {
Register_Function(Array<FunctionData> *functions, String name, Function *f) { Register_Function(Array<FunctionData> *functions, String name, Function *f) {
int64_t pos = 0; int64_t pos = 0;

View File

@@ -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;
}
}
}

View File

@@ -30,7 +30,6 @@
#include "buffer.cpp" #include "buffer.cpp"
#include "view.cpp" #include "view.cpp"
#include "window.cpp" #include "window.cpp"
#include "management.cpp"
#include "process.cpp" #include "process.cpp"
#include "event.cpp" #include "event.cpp"
#include "parser.cpp" #include "parser.cpp"
@@ -38,7 +37,6 @@
#include "commands.cpp" #include "commands.cpp"
#include "lua_api.cpp" #include "lua_api.cpp"
#include "commands_clipboard.cpp" #include "commands_clipboard.cpp"
#include "commands_bindings.cpp"
#include "title_bar.cpp" #include "title_bar.cpp"
#include "generated_config.cpp" #include "generated_config.cpp"
@@ -122,6 +120,407 @@ void SetMouseCursor(Event event) {
} }
SetMouseCursor(SDL_SYSTEM_CURSOR_DEFAULT); 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<Window *> 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<FuzzyPair> 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) { void Update(Event event) {
LayoutWindows(event.xwindow, event.ywindow); LayoutWindows(event.xwindow, event.ywindow);
@@ -135,9 +534,7 @@ void Update(Event event) {
view->update_scroll = true; view->update_scroll = true;
} }
OnCommandEvent = &event;
OnCommand(event); OnCommand(event);
OnCommandEvent = NULL;
UpdateProcesses(); UpdateProcesses();
CoUpdate(&event); CoUpdate(&event);
ReloadLuaConfigs(); ReloadLuaConfigs();