diff --git a/build_file.cpp b/build_file.cpp index 24914fc..eb46069 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -128,7 +128,7 @@ int CompileTextEditor() { AddCommonFlags(&cmd); For2(lib, libs) For(lib.defines) cmd.add(it); - cmd.add("../src/text_editor/new_text_editor.cpp"); + cmd.add("../src/text_editor/text_editor.cpp"); cmd.add("../src/basic/win32.cpp"); For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it))); diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index 0ac4ba7..15dc5fe 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -303,7 +303,7 @@ bool GlobalCommand(Event event) { run_window_command = false; } - if (Ctrl(SDLK_P)) { + if (Ctrl(SDLK_F)) { Window *search_window = GetWindow(SearchWindowID); if (search_window->visible) { SetActiveWindow(GetLastActiveWindow()); diff --git a/src/text_editor/new_text_editor.cpp b/src/text_editor/new_text_editor.cpp deleted file mode 100644 index c1d31dc..0000000 --- a/src/text_editor/new_text_editor.cpp +++ /dev/null @@ -1,277 +0,0 @@ -#include - -#define BASIC_IMPL -#include "basic/basic.h" -#include "basic/filesystem.h" -#include "basic/string16.cpp" -#include "basic/math_int.cpp" -#include "basic/math.cpp" -#include "profiler/profiler.cpp" - -#include "SDL3/SDL.h" -#include "external/glad/glad.h" -#include "external/stb_truetype.h" -#include "external/stb_truetype.c" - -#include "platform/font.cpp" -#include "platform/render_opengl.cpp" - -#include "text_editor.h" -#include "buffer_helpers.cpp" -#include "buffer.cpp" -#include "buffer_multi_cursor.cpp" -#include "buffer_history.cpp" -#include "buffer_fuzzy_search.cpp" -#include "buffer_test_load.cpp" - -#include "management.cpp" -#include "window.cpp" -#include "commands.cpp" -#include "commands_clipboard.cpp" -#include "commands_window.cpp" - -#include "colors.cpp" -#include "window_draw.cpp" - -#include "lua.hpp" -#include "lua_api.cpp" - -void HandleEvent(Event event) { - bool run_window_command = GlobalCommand(event); - if (run_window_command) { - Window *window = GetActiveWindow(); - View *view = GetActiveView(window); - WindowCommand(event, window, view); - MergeCarets(view); - } -} - -void ProcessSDLEvent(SDL_Event *input_event) { - ProfileFunction(); - Event event = {}; - SDL_Keymod mod = SDL_GetModState(); - event.shift = (mod & SDL_KMOD_SHIFT) != 0; - event.ctrl = (mod & SDL_KMOD_CTRL) != 0; - event.alt = (mod & SDL_KMOD_ALT) != 0; - event.super = (mod & SDL_KMOD_GUI) != 0; - - switch (input_event->type) { - case SDL_EVENT_QUIT: AppIsRunning = false; return; - case SDL_EVENT_KEY_DOWN: { - SDL_KeyboardEvent &key = input_event->key; - event.key = key.key; - } break; - case SDL_EVENT_TEXT_INPUT: { - SDL_TextInputEvent &b = input_event->text; - event.text = b.text; - } break; - case SDL_EVENT_MOUSE_BUTTON_DOWN: { - SDL_MouseButtonEvent &b = input_event->button; - event.xmouse = (int16_t)b.x; - event.ymouse = (int16_t)b.y; - if (b.button == SDL_BUTTON_LEFT) { - event.mouse = MOUSE_LEFT; - if (b.clicks == 2) { - event.mouse_double_click = 1; - } - } else if (b.button == SDL_BUTTON_RIGHT) { - event.mouse = MOUSE_RIGHT; - } else if (b.button == SDL_BUTTON_MIDDLE) { - event.mouse = MOUSE_MIDDLE; - } - } break; - case SDL_EVENT_MOUSE_BUTTON_UP: { - SDL_MouseButtonEvent &b = input_event->button; - event.xmouse = (int16_t)b.x; - event.ymouse = (int16_t)b.y; - if (b.button == SDL_BUTTON_LEFT) { - event.mouse = MOUSE_LEFT_UP; - } else if (b.button == SDL_BUTTON_RIGHT) { - event.mouse = MOUSE_RIGHT_UP; - } else if (b.button == SDL_BUTTON_MIDDLE) { - event.mouse = MOUSE_MIDDLE_UP; - } - } break; - case SDL_EVENT_MOUSE_WHEEL: { - SDL_MouseWheelEvent &b = input_event->wheel; - event.xmouse = (int16_t)b.mouse_x; - event.ymouse = (int16_t)b.mouse_y; - event.wheel = b.y; - } break; - default: return; - } - - HandleEvent(event); -} - -#if _WIN32 -int WinMain(void *hInstance, void *hPrevInstance, const char *lpCmdLine, int nShowCmd) -#else -int main() -#endif -{ - BeginProfiler(); - - InitScratch(); - InitArena(&Perm); - WorkingDir = GetWorkingDir(Perm); - - if (SDL_Init(SDL_INIT_VIDEO) == -1) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL); - return 1; - } - - const char *glsl_version = "#version 450"; - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); - - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; - SDL_Window *window = SDL_CreateWindow("Text editor", 1280, 720, window_flags); - if (window == NULL) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window!", SDL_GetError(), NULL); - return 1; - } - - SDL_GLContext gl_context = SDL_GL_CreateContext(window); - SDL_GL_MakeCurrent(window, gl_context); - SDL_GL_SetSwapInterval(1); // Enable vsync - SDL_ShowWindow(window); - - // Set icon - { - uint32_t data = 0xddddddff; - SDL_Surface *surface = SDL_CreateSurfaceFrom(1, 1, SDL_PIXELFORMAT_RGBA8888, &data, sizeof(uint32_t)); - SDL_SetWindowIcon(window, surface); - SDL_DestroySurface(surface); - } - - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load opengl!", SDL_GetError(), NULL); - return 1; - } - - SDL_StartTextInput(window); - SDL_GL_SetSwapInterval(1); // vsync - InitRender(); - ReloadFont(16); - InitLua(); - - InitWindows(); - while (AppIsRunning) { - FrameID += 1; - int window_x, window_y; - SDL_GetWindowSize(window, &window_x, &window_y); - WindowSize = {(float)window_x, (float)window_y}; - BeginFrameRender(); - LayoutWindows(); - - Scratch scratch; - Array order = GetWindowZOrder(scratch); - For(order) { - Window *window = &Windows[it]; - if (window->invisible_when_inactive) { - if (IsActive(window)) window->visible = true; - else window->visible = false; - } - if (!window->visible) continue; - View *view = GetActiveView(window); - view->main_caret_on_begin_frame = view->carets[0]; - view->update_scroll = true; - } - - SDL_Event event; - if (WaitForEvents) { - SDL_WaitEvent(&event); - ProcessSDLEvent(&event); - } - WaitForEvents = true; - while (SDL_PollEvent(&event)) { - ProcessSDLEvent(&event); - } - - { - Event event = {}; - float xmouse, ymouse; - SDL_GetMouseState(&xmouse, &ymouse); - event.xmouse = (int16_t)xmouse; - event.ymouse = (int16_t)ymouse; - event.mouse = MOUSE_MOVE; - HandleEvent(event); - } - - ReplaceInfobarData(); - - For(order) { - Window *window = &Windows[it]; - if (!window->visible) continue; - View *view = GetActiveView(window); - Buffer *buffer = GetBuffer(view->active_buffer); - - // Scrolling with caret - if (!AreEqual(view->main_caret_on_begin_frame, view->carets[0]) && view->update_scroll) { - Caret c = view->carets[0]; - Int front = GetFront(c); - XY xy = PosToXY(*buffer, front); - - Rect2I visible = GetVisibleCells(*window); - Vec2I visible_cells = GetSize(visible); - Vec2I visible_size = visible_cells * Vec2I{FontCharSpacing, FontLineSpacing}; - 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); - view->scroll.y = (set_view_at_line * FontLineSpacing) + cut_off_y; - } - - if (xy.line < visible.min.y + 1) { - view->scroll.y = xy.line * FontLineSpacing; - } - - 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); - view->scroll.x = (set_view_at_line * FontCharSpacing) + cut_off_x; - } - - if (xy.col <= visible.min.x) { - view->scroll.x = xy.col * FontCharSpacing; - } - } - - // Clip scroll - { - ProfileScope(clip_scroll); - Int last_line = LastLine(*buffer); - view->scroll.y = Clamp(view->scroll.y, (Int)0, Max((Int)0, (last_line)*FontLineSpacing)); - - // @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? - view->scroll.x = ClampBottom(view->scroll.x, (Int)0); - } - } - - For(IterateInReverse(&order)) { - Window &window = Windows[it]; - if (!window.visible) continue; - // HandleWindowBindings(&window); - DrawWindow(window); - } - EndFrameRender(ColorBackground); - SDL_GL_SwapWindow(window); - } - - SDL_DestroyWindow(window); - SDL_Quit(); - - EndProfileScope(); - EndProfiler(); - - return 0; -} \ No newline at end of file diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index bd78a57..c1d31dc 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -6,14 +6,17 @@ #include "basic/string16.cpp" #include "basic/math_int.cpp" #include "basic/math.cpp" - -#include "raylib.h" -#include "colors.cpp" -#include "raylib_utils.cpp" - #include "profiler/profiler.cpp" -#include "text_editor.h" +#include "SDL3/SDL.h" +#include "external/glad/glad.h" +#include "external/stb_truetype.h" +#include "external/stb_truetype.c" + +#include "platform/font.cpp" +#include "platform/render_opengl.cpp" + +#include "text_editor.h" #include "buffer_helpers.cpp" #include "buffer.cpp" #include "buffer_multi_cursor.cpp" @@ -22,62 +25,253 @@ #include "buffer_test_load.cpp" #include "management.cpp" +#include "window.cpp" #include "commands.cpp" #include "commands_clipboard.cpp" #include "commands_window.cpp" -#include "window.cpp" + +#include "colors.cpp" #include "window_draw.cpp" #include "lua.hpp" #include "lua_api.cpp" -int main(void) { - InitScratch(); - BeginProfiler(); - BeginProfileScope("main"); +void HandleEvent(Event event) { + bool run_window_command = GlobalCommand(event); + if (run_window_command) { + Window *window = GetActiveWindow(); + View *view = GetActiveView(window); + WindowCommand(event, window, view); + MergeCarets(view); + } +} - Arena Perm = {}; - InitArena(&Perm); +void ProcessSDLEvent(SDL_Event *input_event) { + ProfileFunction(); + Event event = {}; + SDL_Keymod mod = SDL_GetModState(); + event.shift = (mod & SDL_KMOD_SHIFT) != 0; + event.ctrl = (mod & SDL_KMOD_CTRL) != 0; + event.alt = (mod & SDL_KMOD_ALT) != 0; + event.super = (mod & SDL_KMOD_GUI) != 0; - WorkingDir = GetWorkingDir(Perm); - SetWindowState(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_MSAA_4X_HINT); - InitWindow(1280, 720, "hello :)"); - SetExitKey(KEY_F5); - SetTargetFPS(60); - { - uint32_t data = 0xffdddddd; - Image window_icon_image = {(void *)&data, 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8}; - SetWindowIcon(window_icon_image); + switch (input_event->type) { + case SDL_EVENT_QUIT: AppIsRunning = false; return; + case SDL_EVENT_KEY_DOWN: { + SDL_KeyboardEvent &key = input_event->key; + event.key = key.key; + } break; + case SDL_EVENT_TEXT_INPUT: { + SDL_TextInputEvent &b = input_event->text; + event.text = b.text; + } break; + case SDL_EVENT_MOUSE_BUTTON_DOWN: { + SDL_MouseButtonEvent &b = input_event->button; + event.xmouse = (int16_t)b.x; + event.ymouse = (int16_t)b.y; + if (b.button == SDL_BUTTON_LEFT) { + event.mouse = MOUSE_LEFT; + if (b.clicks == 2) { + event.mouse_double_click = 1; + } + } else if (b.button == SDL_BUTTON_RIGHT) { + event.mouse = MOUSE_RIGHT; + } else if (b.button == SDL_BUTTON_MIDDLE) { + event.mouse = MOUSE_MIDDLE; + } + } break; + case SDL_EVENT_MOUSE_BUTTON_UP: { + SDL_MouseButtonEvent &b = input_event->button; + event.xmouse = (int16_t)b.x; + event.ymouse = (int16_t)b.y; + if (b.button == SDL_BUTTON_LEFT) { + event.mouse = MOUSE_LEFT_UP; + } else if (b.button == SDL_BUTTON_RIGHT) { + event.mouse = MOUSE_RIGHT_UP; + } else if (b.button == SDL_BUTTON_MIDDLE) { + event.mouse = MOUSE_MIDDLE_UP; + } + } break; + case SDL_EVENT_MOUSE_WHEEL: { + SDL_MouseWheelEvent &b = input_event->wheel; + event.xmouse = (int16_t)b.mouse_x; + event.ymouse = (int16_t)b.mouse_y; + event.wheel = b.y; + } break; + default: return; } - MenuFontSize = 19; - MenuFont = LoadFontEx("c:\\Windows\\Fonts\\Segoeui.ttf", (int)MenuFontSize, NULL, 500); - ReloadFont(16); + HandleEvent(event); +} +#if _WIN32 +int WinMain(void *hInstance, void *hPrevInstance, const char *lpCmdLine, int nShowCmd) +#else +int main() +#endif +{ + BeginProfiler(); + + InitScratch(); + InitArena(&Perm); + WorkingDir = GetWorkingDir(Perm); + + if (SDL_Init(SDL_INIT_VIDEO) == -1) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL); + return 1; + } + + const char *glsl_version = "#version 450"; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; + SDL_Window *window = SDL_CreateWindow("Text editor", 1280, 720, window_flags); + if (window == NULL) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window!", SDL_GetError(), NULL); + return 1; + } + + SDL_GLContext gl_context = SDL_GL_CreateContext(window); + SDL_GL_MakeCurrent(window, gl_context); + SDL_GL_SetSwapInterval(1); // Enable vsync + SDL_ShowWindow(window); + + // Set icon + { + uint32_t data = 0xddddddff; + SDL_Surface *surface = SDL_CreateSurfaceFrom(1, 1, SDL_PIXELFORMAT_RGBA8888, &data, sizeof(uint32_t)); + SDL_SetWindowIcon(window, surface); + SDL_DestroySurface(surface); + } + + if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load opengl!", SDL_GetError(), NULL); + return 1; + } + + SDL_StartTextInput(window); + SDL_GL_SetSwapInterval(1); // vsync + InitRender(); + ReloadFont(16); InitLua(); - while (!WindowShouldClose()) { - - BeginDrawing(); - ClearBackground(ColorBackground); + InitWindows(); + while (AppIsRunning) { + FrameID += 1; + int window_x, window_y; + SDL_GetWindowSize(window, &window_x, &window_y); + WindowSize = {(float)window_x, (float)window_y}; + BeginFrameRender(); + LayoutWindows(); Scratch scratch; Array order = GetWindowZOrder(scratch); - HandleGlobalCommands(); - ChangeActiveWindowAndScroll(order); + For(order) { + Window *window = &Windows[it]; + if (window->invisible_when_inactive) { + if (IsActive(window)) window->visible = true; + else window->visible = false; + } + if (!window->visible) continue; + View *view = GetActiveView(window); + view->main_caret_on_begin_frame = view->carets[0]; + view->update_scroll = true; + } + + SDL_Event event; + if (WaitForEvents) { + SDL_WaitEvent(&event); + ProcessSDLEvent(&event); + } + WaitForEvents = true; + while (SDL_PollEvent(&event)) { + ProcessSDLEvent(&event); + } + + { + Event event = {}; + float xmouse, ymouse; + SDL_GetMouseState(&xmouse, &ymouse); + event.xmouse = (int16_t)xmouse; + event.ymouse = (int16_t)ymouse; + event.mouse = MOUSE_MOVE; + HandleEvent(event); + } + ReplaceInfobarData(); - For(IterateInReverse(&order)) { - Window &window = Windows[it]; - if (window.visible) { - HandleWindowBindings(&window); - DrawWindow(window); + + For(order) { + Window *window = &Windows[it]; + if (!window->visible) continue; + View *view = GetActiveView(window); + Buffer *buffer = GetBuffer(view->active_buffer); + + // Scrolling with caret + if (!AreEqual(view->main_caret_on_begin_frame, view->carets[0]) && view->update_scroll) { + Caret c = view->carets[0]; + Int front = GetFront(c); + XY xy = PosToXY(*buffer, front); + + Rect2I visible = GetVisibleCells(*window); + Vec2I visible_cells = GetSize(visible); + Vec2I visible_size = visible_cells * Vec2I{FontCharSpacing, FontLineSpacing}; + 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); + view->scroll.y = (set_view_at_line * FontLineSpacing) + cut_off_y; + } + + if (xy.line < visible.min.y + 1) { + view->scroll.y = xy.line * FontLineSpacing; + } + + 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); + view->scroll.x = (set_view_at_line * FontCharSpacing) + cut_off_x; + } + + if (xy.col <= visible.min.x) { + view->scroll.x = xy.col * FontCharSpacing; + } + } + + // Clip scroll + { + ProfileScope(clip_scroll); + Int last_line = LastLine(*buffer); + view->scroll.y = Clamp(view->scroll.y, (Int)0, Max((Int)0, (last_line)*FontLineSpacing)); + + // @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? + view->scroll.x = ClampBottom(view->scroll.x, (Int)0); } } - SetMouseCursor(); - EndDrawing(); + + For(IterateInReverse(&order)) { + Window &window = Windows[it]; + if (!window.visible) continue; + // HandleWindowBindings(&window); + DrawWindow(window); + } + EndFrameRender(ColorBackground); + SDL_GL_SwapWindow(window); } - CloseWindow(); + + SDL_DestroyWindow(window); + SDL_Quit(); + EndProfileScope(); EndProfiler(); + return 0; -} +} \ No newline at end of file diff --git a/src/text_editor/window_draw.cpp b/src/text_editor/window_draw.cpp index 53ebb26..8e65094 100644 --- a/src/text_editor/window_draw.cpp +++ b/src/text_editor/window_draw.cpp @@ -125,11 +125,11 @@ void DrawWindow(Window &window) { DrawRect(rect, ColorSelection); if (line_string[col] == ' ' || line_string[col] == '\t') { - DrawCircle({pos.x + (float)FontCharSpacing / 2.f, (float)pos.y + MainFont.descent}, MainFont.size / 8.f, ColorWhitespaceDuringSelection); + DrawCircle({pos.x + (float)FontCharSpacing / 2.f, (float)pos.y - MainFont.ascent / 2.f}, MainFont.size / 8.f, ColorWhitespaceDuringSelection); } else if (line_string[col] == '\n') { - DrawCircle({pos.x + (float)FontCharSpacing / 2.f, pos.y + (float)FontLineSpacing / 2.f}, MainFont.size / 8.f, ColorWhitespaceDuringSelection); + DrawCircle({pos.x + (float)FontCharSpacing / 2.f, pos.y - MainFont.ascent / 2.f}, MainFont.size / 8.f, ColorWhitespaceDuringSelection); } else if (line_string[col] == '\r') { - DrawCircle({pos.x + (float)FontCharSpacing / 2.f, pos.y + (float)FontLineSpacing / 2.f}, MainFont.size / 8.f, ColorWhitespaceDuringSelection); + DrawCircle({pos.x + (float)FontCharSpacing / 2.f, pos.y - MainFont.ascent / 2.f}, MainFont.size / 8.f, ColorWhitespaceDuringSelection); } } }