diff --git a/src/render/opengl.cpp b/src/render/opengl.cpp index a88b93a..bde680b 100644 --- a/src/render/opengl.cpp +++ b/src/render/opengl.cpp @@ -388,7 +388,7 @@ GLuint UploadAtlas(Atlas *atlas) { return tex; } -void ReloadFont() { +void ReloadFont(String path, U32 size) { if (PrimaryFont.texture_id) { glDeleteTextures(1, &PrimaryFont.texture_id); Dealloc(&PrimaryFont.glyphs); @@ -397,7 +397,7 @@ void ReloadFont() { Scratch scratch; Atlas atlas = CreateAtlas(scratch, {2048, 2048}); - PrimaryFont = CreateFont(&atlas, (uint32_t)ClampBottom(2u, (U32)StyleFontSize), StyleFont); - SecondaryFont = CreateFont(&atlas, 12, StyleFont); + PrimaryFont = CreateFont(&atlas, (uint32_t)ClampBottom(2u, (U32)size), path); + SecondaryFont = CreateFont(&atlas, 12, path); SecondaryFont.texture_id = PrimaryFont.texture_id = UploadAtlas(&atlas); } diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index 653b3ed..0edd068 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -1202,7 +1202,6 @@ API void DeinitBuffer(Buffer *buffer) { // Indexing starts from 0 not 1 because this routine creates also the zero buffer // which is the buffer that often is defaulted to in case of errors -Int BufferIDs; API Buffer *AllocBuffer(Allocator allocator, String name = "", Int size = 4096) { Buffer *buffer = AllocType(allocator, Buffer); buffer->id = {BufferIDs++, buffer}; @@ -1401,6 +1400,167 @@ void RunBufferTest() { DeinitBuffer(&buffer); TrackingAllocatorCheck(); } +} +/////////////////////////////// +// Management +inline BufferID AllocBufferID(Buffer *buffer) { + return {BufferIDs++, buffer}; +} -} \ No newline at end of file +inline Buffer *GetBuffer(BufferID id) { + For(Buffers) { + if (it->id == id) return it; + } + return Buffers[0]; +} + +inline Buffer *FindBuffer(BufferID id) { + For(Buffers) { + if (it->id == id) return it; + } + return NULL; +} + +inline Buffer *GetBuffer(String name) { + For(Buffers) { + if (it->name == name) return it; + } + return Buffers[0]; +} + +inline Buffer *FindBuffer(String name) { + For(Buffers) { + if (it->name == name) return it; + } + return NULL; +} + +inline bool IsNull(Buffer *buffer) { + return buffer->id.id == 0; +} + +Buffer *CreateBuffer(Allocator allocator, String name, Int size) { + Buffer *result = AllocBuffer(allocator, name, size); + Add(&Buffers, result); + return result; +} + +String GetUniqueBufferName(String working_dir, String prepend_name, String extension = ".log") { + Scratch scratch; + String buffer_name = {}; + for (int i = 1; i < INT_MAX; i += 1) { + buffer_name = Format(scratch, "%S/%S%d%S", working_dir, prepend_name, i, extension); + buffer_name = GetAbsolutePath(scratch, buffer_name); + Buffer *exists = FindBuffer(buffer_name); + if (!exists && !FileExists(buffer_name)) { + break; + } + } + buffer_name = Intern(&GlobalInternTable, buffer_name); + return buffer_name; +} + +void InitBuffers() { + Allocator sys_allocator = GetSystemAllocator(); + Scratch scratch; + Buffer *null_buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(GetWorkingDir(scratch), "console")); + View *null_view = CreateView(null_buffer->id); + Assert(null_buffer->id == NullBufferID && null_view->id == NullViewID); + + TraceBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "trace")); + TraceView = CreateView(TraceBuffer->id); + GCInfoBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "gc")); + EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "events")); + ScratchBuffer = BufferOpenFile(GetUniqueBufferName(WorkDir, "scratch")); + + EventBuffer->no_history = true; + GCInfoBuffer->no_history = true; +} + +Int ConvertUTF8ToUTF16UnixLine(String string, char16_t *buffer, Int buffer_cap) { + if (string.len == 0) { + return 0; + } + + Int buffer_len = 0; + Assert(buffer_cap > string.len * 2); + for (Int i = 0; i < string.len;) { + if (string.data[i] == '\r') { + i += 1; + continue; + } + if (string.data[i] == '\t') { + // @WARNING: DONT INCREASE THE SIZE CARELESSLY, WE NEED TO ADJUST BUFFER SIZE + for (Int i = 0; i < 4; i += 1) buffer[buffer_len++] = u' '; + i += 1; + continue; + } + + uint32_t u32 = '?'; + UTF32Result decode = UTF8ToUTF32((uint8_t *)(string.data + i), (int64_t)(string.len - i)); + if (!decode.error) { + i += decode.advance; + u32 = decode.out_str; + } else { + i += 1; + } + + UTF16Result encode = UTF32ToUTF16(u32); + if (!encode.error) { + for (int64_t encode_i = 0; encode_i < encode.len; encode_i += 1) { + buffer[buffer_len++] = encode.out_str[encode_i]; + Assert(buffer_len < buffer_cap); + } + } else { + buffer[buffer_len++] = u'?'; + } + } + return buffer_len; +} + +String16 ToUnixString16(Allocator allocator, String string_) { + Int cap = string_.len * 3; + char16_t *string16_buffer = AllocArray(allocator, char16_t, cap); + Int len = ConvertUTF8ToUTF16UnixLine(string_, string16_buffer, cap); + String16 string = {string16_buffer, len}; + return string; +} + +Buffer *BufferOpenFile(String path) { + Allocator sys_allocator = GetSystemAllocator(); + Scratch scratch; + + path = GetAbsolutePath(scratch, path); + Buffer *buffer = GetBuffer(path); + if (!IsNull(buffer) || (IsNull(buffer) && buffer->name == path)) { + return buffer; + } + + if (!FileExists(path)) { + buffer = CreateBuffer(sys_allocator, path); + } else if (IsDir(path)) { + ReportWarningf("failed to open, it's a directory: %S", path); + return GetBuffer(NullBufferID); + } else { + String string = ReadFile(scratch, path); + buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096); + buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap); + buffer->file_mod_time = GetFileModTime(path); + UpdateLines(buffer, {}, String16{(char16_t *)buffer->data, buffer->len}); + } + + return buffer; +} + +bool BufferIsReferenced(BufferID buffer_id) { + if (buffer_id == NullBufferID) { + return true; + } + + if (FindView(buffer_id)) { + return true; + } + + return false; +} diff --git a/src/text_editor/buffer.h b/src/text_editor/buffer.h index b0f4c2b..48a7acb 100644 --- a/src/text_editor/buffer.h +++ b/src/text_editor/buffer.h @@ -160,4 +160,5 @@ API void UndoEdit(Buffer *buffer, Array *carets); API void ResetHistory(Buffer *buffer); API void DeallocHistoryArray(Array *entries); -API void DeallocHistoryEntries(Array *entries); \ No newline at end of file +API void DeallocHistoryEntries(Array *entries); + diff --git a/src/text_editor/commands_bindings.cpp b/src/text_editor/commands_bindings.cpp index 1ae804a..f151817 100644 --- a/src/text_editor/commands_bindings.cpp +++ b/src/text_editor/commands_bindings.cpp @@ -524,12 +524,12 @@ void OnCommand(Event event) { if (CtrlPress(SDLK_EQUALS)) { StyleFontSize += 1; - ReloadFont(); + ReloadFont(StyleFont, (U32)StyleFontSize); } if (CtrlPress(SDLK_MINUS)) { if (StyleFontSize > 4) { StyleFontSize -= 1; - ReloadFont(); + ReloadFont(StyleFont, (U32)StyleFontSize); } } diff --git a/src/text_editor/window_draw.cpp b/src/text_editor/draw.cpp similarity index 100% rename from src/text_editor/window_draw.cpp rename to src/text_editor/draw.cpp diff --git a/src/text_editor/event.cpp b/src/text_editor/event.cpp index bbbdf16..1e17c61 100644 --- a/src/text_editor/event.cpp +++ b/src/text_editor/event.cpp @@ -1,60 +1,3 @@ -#define EVENT_KINDS \ - X(EVENT_NONE) \ - X(EVENT_UPDATE) \ - X(EVENT_QUIT) \ - X(EVENT_MOUSE_LEFT) \ - X(EVENT_MOUSE_RIGHT) \ - X(EVENT_MOUSE_MIDDLE) \ - X(EVENT_MOUSE_X1) \ - X(EVENT_MOUSE_X2) \ - X(EVENT_MOUSE_LEFT_UP) \ - X(EVENT_MOUSE_RIGHT_UP) \ - X(EVENT_MOUSE_MIDDLE_UP) \ - X(EVENT_MOUSE_X1_UP) \ - X(EVENT_MOUSE_X2_UP) \ - X(EVENT_MOUSE_WHEEL) \ - X(EVENT_KEY_PRESS) \ - X(EVENT_TEXT_INPUT) \ - X(EVENT_DROP_FILE) - -enum EventKind { -#define X(TYPE) TYPE, - EVENT_KINDS -#undef X - EVENT_KIND_COUNT, - EVENT_KIND_INVALID = 111, -}; - -const char *EventKindStrings[] = { -#define X(TYPE) #TYPE, - EVENT_KINDS -#undef X -}; - -#define EVENT_FIELDS \ - X(EventKind, Int, kind) \ - X(SDL_Keycode, Int, key) \ - X(int16_t, Int, xwindow) \ - X(int16_t, Int, ywindow) \ - X(int16_t, Int, xmouse) \ - X(int16_t, Int, ymouse) \ - X(uint8_t, Int, clicks) \ - X(uint8_t, Int, shift) \ - X(uint8_t, Int, ctrl) \ - X(uint8_t, Int, alt) \ - X(uint8_t, Int, super) \ - X(float, Float, xwheel) \ - X(float, Float, ywheel) \ - X(char *, String, text) -#define EVENT_FIELD_COUNT 14 - -struct Event { -#define X(TYPE, KIND, NAME) TYPE NAME; - EVENT_FIELDS -#undef X -}; -Array EventPlayback; - const char *SDLKeycodeToName(SDL_Keycode keycode) { switch(keycode) { case SDLK_UNKNOWN: return "SDLK_UNKNOWN"; break; @@ -317,6 +260,145 @@ const char *SDLKeycodeToName(SDL_Keycode keycode) { } } + +void FillEventWithBasicData(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; + + float xmouse, ymouse; + SDL_GetMouseState(&xmouse, &ymouse); + event->xmouse = (int16_t)xmouse; + event->ymouse = (int16_t)ymouse; + + int xwindow, ywindow; + SDL_GetWindowSize(SDLWindow, &xwindow, &ywindow); + event->xwindow = xwindow; + event->ywindow = ywindow; + event->text = ""; +} + +Event TranslateSDLEvent(SDL_Event *input_event) { + ProfileFunction(); + Event event = {}; + FillEventWithBasicData(&event); + + switch (input_event->type) { + case SDL_EVENT_QUIT: { + event.kind = EVENT_QUIT; + } break; + + case SDL_EVENT_KEY_DOWN: { + event.kind = EVENT_KEY_PRESS; + SDL_KeyboardEvent &key = input_event->key; + event.key = key.key; + } break; + + case SDL_EVENT_TEXT_INPUT: { + event.kind = EVENT_TEXT_INPUT; + SDL_TextInputEvent &b = input_event->text; + String string = b.text; + event.text = Intern(&GlobalInternTable, string).data; + } 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; + event.clicks = b.clicks; + if (b.button == SDL_BUTTON_LEFT) { + event.kind = EVENT_MOUSE_LEFT; + } else if (b.button == SDL_BUTTON_RIGHT) { + event.kind = EVENT_MOUSE_RIGHT; + } else if (b.button == SDL_BUTTON_MIDDLE) { + event.kind = EVENT_MOUSE_MIDDLE; + } else if (b.button == SDL_BUTTON_X1) { + event.kind = EVENT_MOUSE_X1; + } else if (b.button == SDL_BUTTON_X2) { + event.kind = EVENT_MOUSE_X2; + } else { + event.kind = EVENT_NONE; + event.clicks = 0; + } + } 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.kind = EVENT_MOUSE_LEFT_UP; + } else if (b.button == SDL_BUTTON_RIGHT) { + event.kind = EVENT_MOUSE_RIGHT_UP; + } else if (b.button == SDL_BUTTON_MIDDLE) { + event.kind = EVENT_MOUSE_MIDDLE_UP; + } else if (b.button == SDL_BUTTON_X1) { + event.kind = EVENT_MOUSE_X1_UP; + } else if (b.button == SDL_BUTTON_X2) { + event.kind = EVENT_MOUSE_X2_UP; + } else { + event.kind = EVENT_NONE; + } + } break; + + case SDL_EVENT_MOUSE_WHEEL: { + event.kind = EVENT_MOUSE_WHEEL; + SDL_MouseWheelEvent &b = input_event->wheel; + event.xmouse = (int16_t)b.mouse_x; + event.ymouse = (int16_t)b.mouse_y; + event.xwheel = b.x; + event.ywheel = b.y; + } break; + + case SDL_EVENT_MOUSE_MOTION: { + event.kind = EVENT_UPDATE; + } break; + + case SDL_EVENT_DROP_FILE: { + event.kind = EVENT_DROP_FILE; + SDL_DropEvent &b = input_event->drop; + String string = b.data; + event.text = Intern(&GlobalInternTable, string).data; + } break; + default: { + }; + } + + return event; +} + +Array GetEventsForFrame(Allocator allocator) { + Array result = {allocator}; + if (EventPlayback.len) { + result = TightCopy(allocator, EventPlayback); + EventPlayback.len = 0; + } + + SDL_Event event; + if (WaitForEvents) { + SDL_WaitEvent(&event); + Event ev = TranslateSDLEvent(&event); + if (ev.kind != EVENT_NONE) Add(&result, ev); + } + + while (SDL_PollEvent(&event)) { + Event ev = TranslateSDLEvent(&event); + if (ev.kind != EVENT_NONE) Add(&result, ev); + } + + if (result.len == 0) { + Event event = {}; + FillEventWithBasicData(&event); + event.kind = EVENT_UPDATE; + Add(&result, event); + } + + Assert(result.len); + return result; +} + struct Serializer { Buffer *buffer; // for writing }; @@ -386,17 +468,14 @@ void Serialize(Serializer *s, Event *e) { SerializeEnd(s); } -const int DIR_RIGHT = 0; -const int DIR_LEFT = 1; -const int DIR_DOWN = 2; -const int DIR_UP = 3; -const int DIR_COUNT = 4; -const bool CTRL_PRESSED = true; +const int DIR_RIGHT = 0; +const int DIR_LEFT = 1; +const int DIR_DOWN = 2; +const int DIR_UP = 3; +const int DIR_COUNT = 4; +const bool CTRL_PRESSED = true; const bool SHIFT_PRESS = true; -bool AppIsRunning = true; -bool WaitForEvents = true; - #define Ctrl() event.ctrl #define Alt() event.alt #define Shift() event.shift diff --git a/src/text_editor/generated.cpp b/src/text_editor/generated.cpp deleted file mode 100644 index fe57599..0000000 --- a/src/text_editor/generated.cpp +++ /dev/null @@ -1,33 +0,0 @@ -void ReloadStyle() { - ColorText = GetColor("Text", ColorText); - ColorLoadTextHighlight = GetColor("LoadTextHighlight", ColorLoadTextHighlight); - ColorBackground = GetColor("Background", ColorBackground); - ColorInactiveWindow = GetColor("InactiveWindow", ColorInactiveWindow); - ColorTextLineNumbers = GetColor("TextLineNumbers", ColorTextLineNumbers); - ColorLineHighlight = GetColor("LineHighlight", ColorLineHighlight); - ColorMainCaret = GetColor("MainCaret", ColorMainCaret); - ColorSubCaret = GetColor("SubCaret", ColorSubCaret); - ColorSelection = GetColor("Selection", ColorSelection); - ColorWhitespaceDuringSelection = GetColor("WhitespaceDuringSelection", ColorWhitespaceDuringSelection); - ColorMouseUnderline = GetColor("MouseUnderline", ColorMouseUnderline); - ColorCaretUnderline = GetColor("CaretUnderline", ColorCaretUnderline); - ColorFuzzySearchLineHighlight = GetColor("FuzzySearchLineHighlight", ColorFuzzySearchLineHighlight); - ColorScrollbarBackground = GetColor("ScrollbarBackground", ColorScrollbarBackground); - ColorScrollbarScroller = GetColor("ScrollbarScroller", ColorScrollbarScroller); - ColorScrollbarScrollerSelected = GetColor("ScrollbarScrollerSelected", ColorScrollbarScrollerSelected); - ColorTitleBarText = GetColor("TitleBarText", ColorTitleBarText); - ColorTitleBarBackground = GetColor("TitleBarBackground", ColorTitleBarBackground); - ColorTitleBarActiveBackground = GetColor("TitleBarActiveBackground", ColorTitleBarActiveBackground); - ColorTitleBarSelection = GetColor("TitleBarSelection", ColorTitleBarSelection); - ColorResizerBackground = GetColor("ResizerBackground", ColorResizerBackground); - ColorResizerOutline = GetColor("ResizerOutline", ColorResizerOutline); - StyleWaitForEvents = GetStyleInt("WaitForEvents", StyleWaitForEvents); - StyleDrawLineNumbers = GetStyleInt("DrawLineNumbers", StyleDrawLineNumbers); - StyleDrawScrollbar = GetStyleInt("DrawScrollbar", StyleDrawScrollbar); - StyleIndentSize = GetStyleInt("IndentSize", StyleIndentSize); - StyleFontSize = GetStyleInt("FontSize", StyleFontSize); - StyleFontFilter = GetStyleInt("FontFilter", StyleFontFilter); - StyleFont = GetStyleString("Font", StyleFont); - StyleVCVarsall = GetStyleString("VCVarsall", StyleVCVarsall); - StyleUndoMergeTimeout = GetStyleFloat("UndoMergeTimeout", StyleUndoMergeTimeout); -} \ No newline at end of file diff --git a/src/text_editor/generated_variables.cpp b/src/text_editor/generated_variables.cpp deleted file mode 100644 index 768d060..0000000 --- a/src/text_editor/generated_variables.cpp +++ /dev/null @@ -1,68 +0,0 @@ -Color GruvboxDark0Hard = {0x1d, 0x20, 0x21, 0xff}; -Color GruvboxDark0 = {0x28, 0x28, 0x28, 0xff}; -Color GruvboxDark0Soft = {0x32, 0x30, 0x2f, 0xff}; -Color GruvboxDark1 = {0x3c, 0x38, 0x36, 0xff}; -Color GruvboxDark2 = {0x50, 0x49, 0x45, 0xff}; -Color GruvboxDark3 = {0x66, 0x5c, 0x54, 0xff}; -Color GruvboxDark4 = {0x7c, 0x6f, 0x64, 0xff}; -Color GruvboxGray245 = {0x92, 0x83, 0x74, 0xff}; -Color GruvboxGray244 = {0x92, 0x83, 0x74, 0xff}; -Color GruvboxLight0Hard = {0xf9, 0xf5, 0xd7, 0xff}; -Color GruvboxLight0 = {0xfb, 0xf1, 0xc7, 0xff}; -Color GruvboxLight0Soft = {0xf2, 0xe5, 0xbc, 0xff}; -Color GruvboxLight1 = {0xeb, 0xdb, 0xb2, 0xff}; -Color GruvboxLight2 = {0xd5, 0xc4, 0xa1, 0xff}; -Color GruvboxLight3 = {0xbd, 0xae, 0x93, 0xff}; -Color GruvboxLight4 = {0xa8, 0x99, 0x84, 0xff}; -Color GruvboxBrightRed = {0xfb, 0x49, 0x34, 0xff}; -Color GruvboxBrightGreen = {0xb8, 0xbb, 0x26, 0xff}; -Color GruvboxBrightYellow = {0xfa, 0xbd, 0x2f, 0xff}; -Color GruvboxBrightBlue = {0x83, 0xa5, 0x98, 0xff}; -Color GruvboxBrightPurple = {0xd3, 0x86, 0x9b, 0xff}; -Color GruvboxBrightAqua = {0x8e, 0xc0, 0x7c, 0xff}; -Color GruvboxBrightOrange = {0xfe, 0x80, 0x19, 0xff}; -Color GruvboxNeutralRed = {0xcc, 0x24, 0x1d, 0xff}; -Color GruvboxNeutralGreen = {0x98, 0x97, 0x1a, 0xff}; -Color GruvboxNeutralYellow = {0xd7, 0x99, 0x21, 0xff}; -Color GruvboxNeutralBlue = {0x45, 0x85, 0x88, 0xff}; -Color GruvboxNeutralPurple = {0xb1, 0x62, 0x86, 0xff}; -Color GruvboxNeutralAqua = {0x68, 0x9d, 0x6a, 0xff}; -Color GruvboxNeutralOrange = {0xd6, 0x5d, 0x0e, 0xff}; -Color GruvboxFadedRed = {0x9d, 0x00, 0x06, 0xff}; -Color GruvboxFadedGreen = {0x79, 0x74, 0x0e, 0xff}; -Color GruvboxFadedYellow = {0xb5, 0x76, 0x14, 0xff}; -Color GruvboxFadedBlue = {0x07, 0x66, 0x78, 0xff}; -Color GruvboxFadedPurple = {0x8f, 0x3f, 0x71, 0xff}; -Color GruvboxFadedAqua = {0x42, 0x7b, 0x58, 0xff}; -Color GruvboxFadedOrange = {0xaf, 0x3a, 0x03, 0xff}; -Color ColorText = GruvboxDark0Hard; -Color ColorLoadTextHighlight = {0x00, 0x00, 0x00, 0x0F}; -Color ColorBackground = GruvboxLight0Hard; -Color ColorInactiveWindow = {0x00, 0x00, 0x00, 0x0F}; -Color ColorTextLineNumbers = GruvboxDark4; -Color ColorLineHighlight = GruvboxLight0Soft; -Color ColorMainCaret = GruvboxDark0Hard; -Color ColorSubCaret = GruvboxGray245; -Color ColorSelection = GruvboxLight1; -Color ColorWhitespaceDuringSelection = GruvboxLight4; -Color ColorMouseUnderline = GruvboxDark0Hard; -Color ColorCaretUnderline = GruvboxGray245; -Color ColorFuzzySearchLineHighlight = GruvboxDark0; -Color ColorScrollbarBackground = GruvboxLight2; -Color ColorScrollbarScroller = GruvboxLight1; -Color ColorScrollbarScrollerSelected = GruvboxLight0Hard; -Color ColorTitleBarText = GruvboxDark2; -Color ColorTitleBarBackground = GruvboxLight1; -Color ColorTitleBarActiveBackground = {0xfe, 0xfe, 0xfe, 0xfe}; -Color ColorTitleBarSelection = GruvboxLight3; -Color ColorResizerBackground = GruvboxLight0Hard; -Color ColorResizerOutline = GruvboxLight3; -Int StyleWaitForEvents = 1; -Int StyleDrawLineNumbers = 1; -Int StyleDrawScrollbar = 1; -Int StyleIndentSize = 4; -Int StyleFontSize = 15; -Int StyleFontFilter = 0; -String StyleFont = "/home/krz/text_editor/package/CascadiaMono.ttf"; -String StyleVCVarsall = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat"; -double StyleUndoMergeTimeout = 0.3; \ No newline at end of file diff --git a/src/text_editor/globals.cpp b/src/text_editor/globals.cpp new file mode 100644 index 0000000..d334c05 --- /dev/null +++ b/src/text_editor/globals.cpp @@ -0,0 +1,187 @@ +SDL_Window *SDLWindow; +bool IsInFullscreen; +int FullScreenSizeX, FullScreenSizeY; +int FullScreenPositionX, FullScreenPositionY; +bool Testing = false; +bool AppIsRunning = true; +bool WaitForEvents = true; + +WindowID WindowIDs; +ViewID ViewIDs; +Int BufferIDs; + +Array Windows; +Array Views; +Array Buffers; + +// console +BufferID NullBufferID; +ViewID NullViewID; +WindowID NullWindowID; + +// hidden floating window +WindowID DebugWindowID; +ViewID DebugViewID; +BufferID DebugBufferID; + +WindowID CommandBarWindowID; +WindowID StatusBarWindowID; +WindowID SearchBarWindowID; +ViewID SearchViewID; +BufferID SearchBufferID; + +WindowID ActiveWindowID; +WindowID NextActiveWindowID; +WindowID LastActiveLayoutWindowID; +WindowID ScrollbarSelected = {-1}; +WindowID DocumentSelected = {-1}; +WindowID ResizerSelected = {-1}; +WindowID ResizerHover = {-1}; +Caret DocumentAnchor; + +Buffer *LuaProjectBuffer; +Buffer *LuaConfigBuffer; +Buffer *GCInfoBuffer; +Buffer *EventBuffer; +Buffer *ScratchBuffer; +Buffer *TraceBuffer; +View *TraceView; + +String WorkDir; +RandomSeed UniqueBufferNameSeed = {}; +Array EventPlayback; + +// lua +lua_State *LuaState = NULL; +String16 LuaCommandResult = {}; +extern luaL_Reg LuaFunctions[]; + +// clipboard +BlockArena ClipboardArena; +String16 SavedClipboardString; +Array SavedClipboardCarets = {SysAllocator}; + +struct InternTable { + HashTable strings; // general allocator + BlockArena arena; +}; + +String Intern(InternTable *table, String string) { + String *value = table->strings.get(string); + if (!value) { + String copy = Copy(table->arena, string); + table->strings.put(copy, copy); + return copy; + } + return *value; +} + +// We use the intern table to optimize for space, I don't want to worry about freeing +// buffer names and event text data so let it all accumulate and interning will at least +// optimize worst offenders (like event text) +InternTable GlobalInternTable; + +/////////////////////////////// +// CONFIG +Color GruvboxDark0Hard = {0x1d, 0x20, 0x21, 0xff}; +Color GruvboxDark0 = {0x28, 0x28, 0x28, 0xff}; +Color GruvboxDark0Soft = {0x32, 0x30, 0x2f, 0xff}; +Color GruvboxDark1 = {0x3c, 0x38, 0x36, 0xff}; +Color GruvboxDark2 = {0x50, 0x49, 0x45, 0xff}; +Color GruvboxDark3 = {0x66, 0x5c, 0x54, 0xff}; +Color GruvboxDark4 = {0x7c, 0x6f, 0x64, 0xff}; +Color GruvboxGray245 = {0x92, 0x83, 0x74, 0xff}; +Color GruvboxGray244 = {0x92, 0x83, 0x74, 0xff}; +Color GruvboxLight0Hard = {0xf9, 0xf5, 0xd7, 0xff}; +Color GruvboxLight0 = {0xfb, 0xf1, 0xc7, 0xff}; +Color GruvboxLight0Soft = {0xf2, 0xe5, 0xbc, 0xff}; +Color GruvboxLight1 = {0xeb, 0xdb, 0xb2, 0xff}; +Color GruvboxLight2 = {0xd5, 0xc4, 0xa1, 0xff}; +Color GruvboxLight3 = {0xbd, 0xae, 0x93, 0xff}; +Color GruvboxLight4 = {0xa8, 0x99, 0x84, 0xff}; +Color GruvboxBrightRed = {0xfb, 0x49, 0x34, 0xff}; +Color GruvboxBrightGreen = {0xb8, 0xbb, 0x26, 0xff}; +Color GruvboxBrightYellow = {0xfa, 0xbd, 0x2f, 0xff}; +Color GruvboxBrightBlue = {0x83, 0xa5, 0x98, 0xff}; +Color GruvboxBrightPurple = {0xd3, 0x86, 0x9b, 0xff}; +Color GruvboxBrightAqua = {0x8e, 0xc0, 0x7c, 0xff}; +Color GruvboxBrightOrange = {0xfe, 0x80, 0x19, 0xff}; +Color GruvboxNeutralRed = {0xcc, 0x24, 0x1d, 0xff}; +Color GruvboxNeutralGreen = {0x98, 0x97, 0x1a, 0xff}; +Color GruvboxNeutralYellow = {0xd7, 0x99, 0x21, 0xff}; +Color GruvboxNeutralBlue = {0x45, 0x85, 0x88, 0xff}; +Color GruvboxNeutralPurple = {0xb1, 0x62, 0x86, 0xff}; +Color GruvboxNeutralAqua = {0x68, 0x9d, 0x6a, 0xff}; +Color GruvboxNeutralOrange = {0xd6, 0x5d, 0x0e, 0xff}; +Color GruvboxFadedRed = {0x9d, 0x00, 0x06, 0xff}; +Color GruvboxFadedGreen = {0x79, 0x74, 0x0e, 0xff}; +Color GruvboxFadedYellow = {0xb5, 0x76, 0x14, 0xff}; +Color GruvboxFadedBlue = {0x07, 0x66, 0x78, 0xff}; +Color GruvboxFadedPurple = {0x8f, 0x3f, 0x71, 0xff}; +Color GruvboxFadedAqua = {0x42, 0x7b, 0x58, 0xff}; +Color GruvboxFadedOrange = {0xaf, 0x3a, 0x03, 0xff}; +Color ColorText = GruvboxDark0Hard; +Color ColorLoadTextHighlight = {0x00, 0x00, 0x00, 0x0F}; +Color ColorBackground = GruvboxLight0Hard; +Color ColorInactiveWindow = {0x00, 0x00, 0x00, 0x0F}; +Color ColorTextLineNumbers = GruvboxDark4; +Color ColorLineHighlight = GruvboxLight0Soft; +Color ColorMainCaret = GruvboxDark0Hard; +Color ColorSubCaret = GruvboxGray245; +Color ColorSelection = GruvboxLight1; +Color ColorWhitespaceDuringSelection = GruvboxLight4; +Color ColorMouseUnderline = GruvboxDark0Hard; +Color ColorCaretUnderline = GruvboxGray245; +Color ColorFuzzySearchLineHighlight = GruvboxDark0; +Color ColorScrollbarBackground = GruvboxLight2; +Color ColorScrollbarScroller = GruvboxLight1; +Color ColorScrollbarScrollerSelected = GruvboxLight0Hard; +Color ColorTitleBarText = GruvboxDark2; +Color ColorTitleBarBackground = GruvboxLight1; +Color ColorTitleBarActiveBackground = {0xfe, 0xfe, 0xfe, 0xfe}; +Color ColorTitleBarSelection = GruvboxLight3; +Color ColorResizerBackground = GruvboxLight0Hard; +Color ColorResizerOutline = GruvboxLight3; +Int StyleWaitForEvents = 1; +Int StyleDrawLineNumbers = 1; +Int StyleDrawScrollbar = 1; +Int StyleIndentSize = 4; +Int StyleFontSize = 15; +Int StyleFontFilter = 0; +String StyleFont = "/home/krz/text_editor/package/CascadiaMono.ttf"; +String StyleVCVarsall = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat"; +double StyleUndoMergeTimeout = 0.3; + +void ReloadStyle() { + ColorText = GetColor("Text", ColorText); + ColorLoadTextHighlight = GetColor("LoadTextHighlight", ColorLoadTextHighlight); + ColorBackground = GetColor("Background", ColorBackground); + ColorInactiveWindow = GetColor("InactiveWindow", ColorInactiveWindow); + ColorTextLineNumbers = GetColor("TextLineNumbers", ColorTextLineNumbers); + ColorLineHighlight = GetColor("LineHighlight", ColorLineHighlight); + ColorMainCaret = GetColor("MainCaret", ColorMainCaret); + ColorSubCaret = GetColor("SubCaret", ColorSubCaret); + ColorSelection = GetColor("Selection", ColorSelection); + ColorWhitespaceDuringSelection = GetColor("WhitespaceDuringSelection", ColorWhitespaceDuringSelection); + ColorMouseUnderline = GetColor("MouseUnderline", ColorMouseUnderline); + ColorCaretUnderline = GetColor("CaretUnderline", ColorCaretUnderline); + ColorFuzzySearchLineHighlight = GetColor("FuzzySearchLineHighlight", ColorFuzzySearchLineHighlight); + ColorScrollbarBackground = GetColor("ScrollbarBackground", ColorScrollbarBackground); + ColorScrollbarScroller = GetColor("ScrollbarScroller", ColorScrollbarScroller); + ColorScrollbarScrollerSelected = GetColor("ScrollbarScrollerSelected", ColorScrollbarScrollerSelected); + ColorTitleBarText = GetColor("TitleBarText", ColorTitleBarText); + ColorTitleBarBackground = GetColor("TitleBarBackground", ColorTitleBarBackground); + ColorTitleBarActiveBackground = GetColor("TitleBarActiveBackground", ColorTitleBarActiveBackground); + ColorTitleBarSelection = GetColor("TitleBarSelection", ColorTitleBarSelection); + ColorResizerBackground = GetColor("ResizerBackground", ColorResizerBackground); + ColorResizerOutline = GetColor("ResizerOutline", ColorResizerOutline); + StyleWaitForEvents = GetStyleInt("WaitForEvents", StyleWaitForEvents); + StyleDrawLineNumbers = GetStyleInt("DrawLineNumbers", StyleDrawLineNumbers); + StyleDrawScrollbar = GetStyleInt("DrawScrollbar", StyleDrawScrollbar); + StyleIndentSize = GetStyleInt("IndentSize", StyleIndentSize); + StyleFontSize = GetStyleInt("FontSize", StyleFontSize); + StyleFontFilter = GetStyleInt("FontFilter", StyleFontFilter); + StyleFont = GetStyleString("Font", StyleFont); + StyleVCVarsall = GetStyleString("VCVarsall", StyleVCVarsall); + StyleUndoMergeTimeout = GetStyleFloat("UndoMergeTimeout", StyleUndoMergeTimeout); +} \ No newline at end of file diff --git a/src/text_editor/intern_table.cpp b/src/text_editor/intern_table.cpp deleted file mode 100644 index 5f68f03..0000000 --- a/src/text_editor/intern_table.cpp +++ /dev/null @@ -1,19 +0,0 @@ -struct InternTable { - HashTable strings; // general allocator - BlockArena arena; -}; - -String Intern(InternTable *table, String string) { - String *value = table->strings.get(string); - if (!value) { - String copy = Copy(table->arena, string); - table->strings.put(copy, copy); - return copy; - } - return *value; -} - -// We use the intern table to optimize for space, I don't want to worry about freeing -// buffer names and event text data so let it all accumulate and interning will at least -// optimize worst offenders (like event text) -InternTable GlobalInternTable; \ No newline at end of file diff --git a/src/text_editor/lua.cpp b/src/text_editor/lua.cpp new file mode 100644 index 0000000..2819bc3 --- /dev/null +++ b/src/text_editor/lua.cpp @@ -0,0 +1,255 @@ +static void HookLuaForceExit(lua_State *L, lua_Debug *debug) { + SDL_PumpEvents(); + int numkeys = 0; + const bool *keys = SDL_GetKeyboardState(&numkeys); + if (keys[SDL_SCANCODE_F9]) + luaL_error(L, "lua execution got interrupted"); +} + +API double GetStyleFloat(String name, double default_float) { + double result = default_float; + lua_getglobal(LuaState, "Style"); + defer { lua_pop(LuaState, 1); }; + if (lua_istable(LuaState, -1)) { + lua_pushlstring(LuaState, name.data, name.len); + lua_gettable(LuaState, -2); + defer { lua_pop(LuaState, 1); }; + if (lua_isnumber(LuaState, -1) || lua_isboolean(LuaState, -1) || lua_isinteger(LuaState, -1)) { + lua_Number num = lua_tonumber(LuaState, -1); + result = (double)num; + } + } + return result; +} + +API Int GetStyleInt(String name, Int default_int) { + Int result = default_int; + lua_getglobal(LuaState, "Style"); + defer { lua_pop(LuaState, 1); }; + if (lua_istable(LuaState, -1)) { + lua_pushlstring(LuaState, name.data, name.len); + lua_gettable(LuaState, -2); + defer { lua_pop(LuaState, 1); }; + if (lua_isnumber(LuaState, -1) || lua_isboolean(LuaState, -1) || lua_isinteger(LuaState, -1)) { + lua_Integer num = lua_tointeger(LuaState, -1); + result = (Int)num; + } + } + return result; +} + +API String GetStyleString(String name, String default_string) { + String result = default_string; + lua_getglobal(LuaState, "Style"); + defer { lua_pop(LuaState, 1); }; + if (lua_istable(LuaState, -1)) { + lua_pushlstring(LuaState, name.data, name.len); + lua_gettable(LuaState, -2); + defer { lua_pop(LuaState, 1); }; + if (lua_isstring(LuaState, -1)) { + const char *string = lua_tostring(LuaState, -1); + result = Intern(&GlobalInternTable, string); + } + } + return result; +} + +API Color GetColor(String name, Color default_color) { + Color result = default_color; + lua_getglobal(LuaState, "Color"); + defer { lua_pop(LuaState, 1); }; + if (lua_istable(LuaState, -1)) { + lua_pushlstring(LuaState, name.data, name.len); + lua_gettable(LuaState, -2); + defer { lua_pop(LuaState, 1); }; + if (lua_isnumber(LuaState, -1)) { + lua_Integer num = lua_tointeger(LuaState, -1); + result.r = (uint8_t)((0xFF000000 & num) >> 24); + result.g = (uint8_t)((0x00FF0000 & num) >> 16); + result.b = (uint8_t)((0x0000FF00 & num) >> 8); + result.a = (uint8_t)((0x000000FF & num) >> 0); + } + } + return result; +} + +API String GetFieldString(lua_State *L, String name) { + String result = {}; + if (lua_istable(L, -1)) { + lua_pushlstring(L, name.data, name.len); + lua_gettable(L, -2); + defer { lua_pop(L, 1); }; + if (lua_isstring(L, -1)) { + result = lua_tostring(L, -1); + } + } + return result; +} + +Int GetFieldAInt(lua_State *L, const char *name) { + lua_getfield(L, -1, name); + lua_Integer num = lua_tointeger(L, -1); + lua_pop(L, 1); + return (Int)num; +} + +double GetFieldAFloat(lua_State *L, const char *name) { + lua_getfield(L, -1, name); + double num = lua_tonumber(L, -1); + lua_pop(L, 1); + return num; +} + +const char *GetFieldAString(lua_State *L, const char *name) { + lua_getfield(L, -1, name); + const char *result = lua_tostring(L, -1); + + lua_pop(L, 1); + return result; +} + +API void PushEvent(lua_State *L, Event *event) { + lua_createtable(L, 0, EVENT_FIELD_COUNT); +#define lua_pushInt lua_pushinteger +#define lua_pushString lua_pushstring +#define lua_pushFloat lua_pushnumber +#define X(TYPE, KIND, NAME) \ + lua_push##KIND(L, event->NAME); \ + lua_setfield(L, -2, #NAME); + EVENT_FIELDS +#undef X +} + +// :Event +API int Lua_Play(lua_State *L) { + if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events"); + defer { lua_pop(L, 1); }; + + int size = (int)lua_rawlen(L, -1); + for (int i = 0; i < size; i += 1) { + lua_geti(L, -1, i + 1); + if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events"); + defer { lua_pop(L, 1); }; + + Event event = {}; +#define X(TYPE, KIND, NAME) event.NAME = (TYPE)GetFieldA##KIND(L, #NAME); + EVENT_FIELDS +#undef X + Add(&EventPlayback, event); + } + + return 0; +} + +void ReloadStyle(); +extern String BaseLuaConfig; + +API void LoadLuaBuffer(Buffer *lua_buffer) { + if (!lua_buffer) return; + ReportConsolef("reloading config: %S", lua_buffer->name); + + Scratch scratch; + String string = AllocCharString(scratch, lua_buffer); + if (luaL_dostring(LuaState, string.data) == LUA_OK) { + if (lua_isstring(LuaState, -1)) { + const char *text = lua_tostring(LuaState, -1); + ReportConsolef(text); + lua_pop(LuaState, 1); + } + } else { + const char *error_message = lua_tostring(LuaState, -1); + ReportWarningf("Failed to load user config! %s", error_message); + lua_pop(LuaState, 1); + } + lua_buffer->user_change_id = lua_buffer->change_id; +} + +API void ReloadLuaConfigs(bool reload) { + if (LuaConfigBuffer && !LuaConfigBuffer->dirty && LuaConfigBuffer->change_id != LuaConfigBuffer->user_change_id) { + reload = true; + } + if (LuaProjectBuffer && !LuaProjectBuffer->dirty && LuaProjectBuffer->change_id != LuaProjectBuffer->user_change_id) { + reload = true; + } + if (reload == false) { + return; + } + + LoadLuaBuffer(LuaConfigBuffer); + LoadLuaBuffer(LuaProjectBuffer); + + ReloadStyle(); + ReloadFont(StyleFont, (U32)StyleFontSize); + For(Windows) { + it->draw_scrollbar = StyleDrawScrollbar; + it->draw_line_numbers = StyleDrawLineNumbers; + } +} + +API bool CallLuaFunc(char *func_name, int arg_count, int ret_count) { + if (lua_pcall(LuaState, arg_count, ret_count, 0) != 0) { + const char *error_message = lua_tostring(LuaState, -1); + ReportWarningf("Failed to call a lua function: %s! %s", func_name, error_message); + lua_pop(LuaState, 1); + return false; + } + return true; +} + +void CallLuaOnInit() { + lua_getglobal(LuaState, "OnInit"); + CallLuaFunc("OnInit", 0, 0); +} + +API void InitLuaConfig() { + LuaState = luaL_newstate(); + luaL_openlibs(LuaState); + lua_sethook(LuaState, HookLuaForceExit, LUA_MASKCOUNT, 100000000); + + for (int i = 0; LuaFunctions[i].name; i += 1) { + lua_pushcfunction(LuaState, LuaFunctions[i].func); + lua_setglobal(LuaState, LuaFunctions[i].name); + } + +#if OS_WINDOWS + lua_pushinteger(LuaState, 0); +#else + lua_pushinteger(LuaState, 1); +#endif + lua_setglobal(LuaState, "OS_VALUE"); + + // Init base config, test that it works and initialize the lua stuff + if (!luaL_dostring(LuaState, BaseLuaConfig.data) == LUA_OK) { + const char *error_message = lua_tostring(LuaState, -1); + ReportErrorf("Failed to load base lua config! %s", error_message); + lua_pop(LuaState, 1); + Assert(!"Invalid codepath"); + } + + // Init user config + Buffer *lua_buffer = NULL; + + Scratch scratch; + String lua_config_exe = Format(scratch, "%S/init.lua", GetExeDir(scratch)); + if (FileExists(lua_config_exe)) { + lua_buffer = BufferOpenFile(lua_config_exe); + } + + if (lua_buffer == NULL) { + String lua_config_remote = Format(scratch, "%S/init.lua", ConfigDir); +// #if DEBUG_BUILD +// // WARNING! Delete config to make sure we are running this code more frequently +// SDL_RemovePath(lua_config_remote.data); +// ReportConsolef("deleting config for debug purposes!"); +// #endif + lua_buffer = BufferOpenFile(lua_config_remote); + if (lua_buffer->len == 0) { + String16 string16 = ToString16(scratch, BaseLuaConfig); + RawReplaceText(lua_buffer, {}, string16); + ReportConsolef("no config at: %S - creating config buffer", lua_config_remote); + } + } + LuaConfigBuffer = lua_buffer; + ReloadLuaConfigs(true); + CallLuaOnInit(); +} diff --git a/src/text_editor/lua.h b/src/text_editor/lua.h new file mode 100644 index 0000000..b712f0b --- /dev/null +++ b/src/text_editor/lua.h @@ -0,0 +1,10 @@ +API double GetStyleFloat(String name, double default_float); +API Int GetStyleInt(String name, Int default_int); +API String GetStyleString(String name, String default_string); +API Color GetColor(String name, Color default_color); +API String GetFieldString(lua_State *L, String name); +API int Lua_Play(lua_State *L); +API void LoadLuaBuffer(Buffer *lua_buffer); +API void ReloadLuaConfigs(bool reload = false); +API bool CallLuaFunc(char *func_name, int arg_count, int ret_count); +API void InitLuaConfig(); \ No newline at end of file diff --git a/src/text_editor/lua_api.cpp b/src/text_editor/lua_api.cpp index 5cbdf0d..f8a0512 100644 --- a/src/text_editor/lua_api.cpp +++ b/src/text_editor/lua_api.cpp @@ -110,204 +110,6 @@ int Lua_GetMainDir(lua_State *L) { return 1; } -static void HookLuaForceExit(lua_State *L, lua_Debug *debug) { - SDL_PumpEvents(); - int numkeys = 0; - const bool *keys = SDL_GetKeyboardState(&numkeys); - if (keys[SDL_SCANCODE_F9]) - luaL_error(L, "lua execution got interrupted"); -} - -double GetStyleFloat(String name, double default_float) { - double result = default_float; - lua_getglobal(LuaState, "Style"); - defer { lua_pop(LuaState, 1); }; - if (lua_istable(LuaState, -1)) { - lua_pushlstring(LuaState, name.data, name.len); - lua_gettable(LuaState, -2); - defer { lua_pop(LuaState, 1); }; - if (lua_isnumber(LuaState, -1) || lua_isboolean(LuaState, -1) || lua_isinteger(LuaState, -1)) { - lua_Number num = lua_tonumber(LuaState, -1); - result = (double)num; - } - } - return result; -} - -Int GetStyleInt(String name, Int default_int) { - Int result = default_int; - lua_getglobal(LuaState, "Style"); - defer { lua_pop(LuaState, 1); }; - if (lua_istable(LuaState, -1)) { - lua_pushlstring(LuaState, name.data, name.len); - lua_gettable(LuaState, -2); - defer { lua_pop(LuaState, 1); }; - if (lua_isnumber(LuaState, -1) || lua_isboolean(LuaState, -1) || lua_isinteger(LuaState, -1)) { - lua_Integer num = lua_tointeger(LuaState, -1); - result = (Int)num; - } - } - return result; -} - -String GetStyleString(String name, String default_string) { - String result = default_string; - lua_getglobal(LuaState, "Style"); - defer { lua_pop(LuaState, 1); }; - if (lua_istable(LuaState, -1)) { - lua_pushlstring(LuaState, name.data, name.len); - lua_gettable(LuaState, -2); - defer { lua_pop(LuaState, 1); }; - if (lua_isstring(LuaState, -1)) { - const char *string = lua_tostring(LuaState, -1); - result = Intern(&GlobalInternTable, string); - } - } - return result; -} - -Color GetColor(String name, Color default_color) { - Color result = default_color; - lua_getglobal(LuaState, "Color"); - defer { lua_pop(LuaState, 1); }; - if (lua_istable(LuaState, -1)) { - lua_pushlstring(LuaState, name.data, name.len); - lua_gettable(LuaState, -2); - defer { lua_pop(LuaState, 1); }; - if (lua_isnumber(LuaState, -1)) { - lua_Integer num = lua_tointeger(LuaState, -1); - result.r = (uint8_t)((0xFF000000 & num) >> 24); - result.g = (uint8_t)((0x00FF0000 & num) >> 16); - result.b = (uint8_t)((0x0000FF00 & num) >> 8); - result.a = (uint8_t)((0x000000FF & num) >> 0); - } - } - return result; -} - -String GetFieldString(lua_State *L, String name) { - String result = {}; - if (lua_istable(L, -1)) { - lua_pushlstring(L, name.data, name.len); - lua_gettable(L, -2); - defer { lua_pop(L, 1); }; - if (lua_isstring(L, -1)) { - result = lua_tostring(L, -1); - } - } - return result; -} - -Int GetFieldAInt(lua_State *L, const char *name) { - lua_getfield(L, -1, name); - lua_Integer num = lua_tointeger(L, -1); - lua_pop(L, 1); - return (Int)num; -} - -double GetFieldAFloat(lua_State *L, const char *name) { - lua_getfield(L, -1, name); - double num = lua_tonumber(L, -1); - lua_pop(L, 1); - return num; -} - -const char *GetFieldAString(lua_State *L, const char *name) { - lua_getfield(L, -1, name); - const char *result = lua_tostring(L, -1); - - lua_pop(L, 1); - return result; -} - -void PushEvent(lua_State *L, Event *event) { - lua_createtable(L, 0, EVENT_FIELD_COUNT); -#define lua_pushInt lua_pushinteger -#define lua_pushString lua_pushstring -#define lua_pushFloat lua_pushnumber -#define X(TYPE, KIND, NAME) \ - lua_push##KIND(L, event->NAME); \ - lua_setfield(L, -2, #NAME); - EVENT_FIELDS -#undef X -} - -// :Event -int Lua_Play(lua_State *L) { - if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events"); - defer { lua_pop(L, 1); }; - - int size = (int)lua_rawlen(L, -1); - for (int i = 0; i < size; i += 1) { - lua_geti(L, -1, i + 1); - if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events"); - defer { lua_pop(L, 1); }; - - Event event = {}; -#define X(TYPE, KIND, NAME) event.NAME = (TYPE)GetFieldA##KIND(L, #NAME); - EVENT_FIELDS -#undef X - Add(&EventPlayback, event); - } - - return 0; -} - -void ReloadStyle(); -extern String BaseLuaConfig; - -void LoadLuaBuffer(Buffer *lua_buffer) { - if (!lua_buffer) return; - ReportConsolef("reloading config: %S", lua_buffer->name); - - Scratch scratch; - String string = AllocCharString(scratch, lua_buffer); - if (luaL_dostring(LuaState, string.data) == LUA_OK) { - if (lua_isstring(LuaState, -1)) { - const char *text = lua_tostring(LuaState, -1); - ReportConsolef(text); - lua_pop(LuaState, 1); - } - } else { - const char *error_message = lua_tostring(LuaState, -1); - ReportWarningf("Failed to load user config! %s", error_message); - lua_pop(LuaState, 1); - } - lua_buffer->user_change_id = lua_buffer->change_id; -} - -void ReloadLuaConfigs(bool reload = false) { - if (LuaConfigBuffer && !LuaConfigBuffer->dirty && LuaConfigBuffer->change_id != LuaConfigBuffer->user_change_id) { - reload = true; - } - if (LuaProjectBuffer && !LuaProjectBuffer->dirty && LuaProjectBuffer->change_id != LuaProjectBuffer->user_change_id) { - reload = true; - } - if (reload == false) { - return; - } - - LoadLuaBuffer(LuaConfigBuffer); - LoadLuaBuffer(LuaProjectBuffer); - - ReloadStyle(); - ReloadFont(); - For(Windows) { - it->draw_scrollbar = StyleDrawScrollbar; - it->draw_line_numbers = StyleDrawLineNumbers; - } -} - -bool CallLuaFunc(char *func_name, int arg_count, int ret_count) { - if (lua_pcall(LuaState, arg_count, ret_count, 0) != 0) { - const char *error_message = lua_tostring(LuaState, -1); - ReportWarningf("Failed to call a lua function: %s! %s", func_name, error_message); - lua_pop(LuaState, 1); - return false; - } - return true; -} - struct OnOpenResult { String kind; String file_path; @@ -388,65 +190,3 @@ void CallLuaOnUpdate(Event *event) { PushEvent(LuaState, event); CallLuaFunc("OnUpdate", 1, 0); } - -void CallLuaOnInit() { - lua_getglobal(LuaState, "OnInit"); - CallLuaFunc("OnInit", 0, 0); -} - -void InitLuaConfig() { - LuaState = luaL_newstate(); - luaL_openlibs(LuaState); - lua_sethook(LuaState, HookLuaForceExit, LUA_MASKCOUNT, 100000000); - - for (int i = 0; LuaFunctions[i].name; i += 1) { - lua_pushcfunction(LuaState, LuaFunctions[i].func); - lua_setglobal(LuaState, LuaFunctions[i].name); - } - -#if OS_WINDOWS - lua_pushinteger(LuaState, 0); -#else - lua_pushinteger(LuaState, 1); -#endif - lua_setglobal(LuaState, "OS_VALUE"); - - // Init base config, test that it works and initialize the lua stuff - if (!luaL_dostring(LuaState, BaseLuaConfig.data) == LUA_OK) { - const char *error_message = lua_tostring(LuaState, -1); - ReportErrorf("Failed to load base lua config! %s", error_message); - lua_pop(LuaState, 1); - Assert(!"Invalid codepath"); - } - - // Init user config - Buffer *lua_buffer = NULL; - - Scratch scratch; - String lua_config_exe = Format(scratch, "%S/init.lua", GetExeDir(scratch)); - if (FileExists(lua_config_exe)) { - lua_buffer = BufferOpenFile(lua_config_exe); - } - - if (lua_buffer == NULL) { - String lua_config_remote = Format(scratch, "%S/init.lua", ConfigDir); -// #if DEBUG_BUILD -// // WARNING! Delete config to make sure we are running this code more frequently -// SDL_RemovePath(lua_config_remote.data); -// ReportConsolef("deleting config for debug purposes!"); -// #endif - lua_buffer = BufferOpenFile(lua_config_remote); - if (lua_buffer->len == 0) { - String16 string16 = ToString16(scratch, BaseLuaConfig); - RawReplaceText(lua_buffer, {}, string16); - ReportConsolef("no config at: %S - creating config buffer", lua_config_remote); - } - } - - - - - LuaConfigBuffer = lua_buffer; - ReloadLuaConfigs(true); - CallLuaOnInit(); -} diff --git a/src/text_editor/management.cpp b/src/text_editor/management.cpp index 4b418fd..4d03d52 100644 --- a/src/text_editor/management.cpp +++ b/src/text_editor/management.cpp @@ -1,237 +1,3 @@ -WindowID WindowIDs; -ViewID ViewIDs; - -Array Windows; -Array Views; -Array Buffers; - -// console -BufferID NullBufferID; -ViewID NullViewID; -WindowID NullWindowID; - -// hidden floating window -WindowID DebugWindowID; -ViewID DebugViewID; -BufferID DebugBufferID; - -WindowID CommandBarWindowID; -WindowID StatusBarWindowID; -WindowID SearchBarWindowID; -ViewID SearchViewID; -BufferID SearchBufferID; - -WindowID ActiveWindowID; -WindowID NextActiveWindowID; -WindowID LastActiveLayoutWindowID; -WindowID ScrollbarSelected = {-1}; -WindowID DocumentSelected = {-1}; -WindowID ResizerSelected = {-1}; -WindowID ResizerHover = {-1}; -Caret DocumentAnchor; - -Buffer *LuaProjectBuffer; -Buffer *LuaConfigBuffer; -Buffer *GCInfoBuffer; -Buffer *EventBuffer; -Buffer *ScratchBuffer; -Buffer *TraceBuffer; -View *TraceView; - -String WorkDir; -RandomSeed UniqueBufferNameSeed = {}; - -// lua -lua_State *LuaState = NULL; -String16 LuaCommandResult = {}; -extern luaL_Reg LuaFunctions[]; - -// clipboard -BlockArena ClipboardArena; -String16 SavedClipboardString; -Array SavedClipboardCarets = {SysAllocator}; - - -String GetUniqueBufferName(String working_dir, String prepend_name, String extension = ".log") { - Scratch scratch; - String buffer_name = {}; - for (int i = 1; i < INT_MAX; i += 1) { - buffer_name = Format(scratch, "%S/%S%d%S", working_dir, prepend_name, i, extension); - buffer_name = GetAbsolutePath(scratch, buffer_name); - Buffer *exists = FindBuffer(buffer_name); - if (!exists && !FileExists(buffer_name)) { - break; - } - } - buffer_name = Intern(&GlobalInternTable, buffer_name); - return buffer_name; -} - -void InitBuffers() { - Allocator sys_allocator = GetSystemAllocator(); - Scratch scratch; - Buffer *null_buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(GetWorkingDir(scratch), "console")); - View *null_view = CreateView(null_buffer->id); - Assert(null_buffer->id == NullBufferID && null_view->id == NullViewID); - - TraceBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "trace")); - TraceView = CreateView(TraceBuffer->id); - GCInfoBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "gc")); - EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "events")); - ScratchBuffer = BufferOpenFile(GetUniqueBufferName(WorkDir, "scratch")); - - EventBuffer->no_history = true; - GCInfoBuffer->no_history = true; -} - -inline bool IsDocumentSelectionValid() { - if (DocumentSelected.id == -1) return false; - return true; -} - -inline bool IsScrollbarSelectionValid() { - if (ScrollbarSelected.id == -1) return false; - return true; -} - -inline ViewID AllocViewID(View *view) { return {ViewIDs.id++, view}; } -inline WindowID AllocWindowID(Window *window) { return {WindowIDs.id++, window}; } -inline BufferID AllocBufferID(Buffer *buffer) { return {BufferIDs++, buffer}; } - -inline Window *GetWindow(WindowID id, Window *default_window = Windows[0]) { - For(Windows) { - if (it->id == id) return it; - } - return default_window; -} - -inline Buffer *GetBuffer(BufferID id) { - For(Buffers) { - if (it->id == id) return it; - } - return Buffers[0]; -} - -inline Buffer *FindBuffer(BufferID id) { - For(Buffers) { - if (it->id == id) return it; - } - return NULL; -} - -inline Buffer *GetBuffer(String name) { - For(Buffers) { - if (it->name == name) return it; - } - return Buffers[0]; -} - -inline Buffer *FindBuffer(String name) { - For(Buffers) { - if (it->name == name) return it; - } - return NULL; -} - -inline View *GetView(ViewID id) { - For(Views) { - if (it->id == id) return it; - } - return Views[0]; -} - -inline bool IsNull(Buffer *buffer) { return buffer->id.id == NullBufferID.id; } -inline Window *GetActiveWind() { return GetWindow(ActiveWindowID); } - -Buffer *CreateBuffer(Allocator allocator, String name, Int size) { - Buffer *result = AllocBuffer(allocator, name, size); - Add(&Buffers, result); - return result; -} - -Window *CreateWind() { - Allocator allocator = GetSystemAllocator(); - Window *w = AllocType(allocator, Window); - w->font = &PrimaryFont; - w->visible = true; - w->layout = true; - w->draw_scrollbar = StyleDrawScrollbar; - w->draw_line_numbers = StyleDrawLineNumbers; - w->draw_line_highlight = true; - w->jump_history = true; - w->id = AllocWindowID(w); - w->weight = 1.0; - Add(&Windows, w); - return w; -} - -View *CreateView(BufferID active_buffer) { - Allocator al = GetSystemAllocator(); - View *view = AllocType(al, View); - view->id = AllocViewID(view); - view->active_buffer = active_buffer; - view->carets.allocator = al; - Add(&view->carets, {0, 0}); - Add(&Views, view); - return view; -} - -View *FindView(ViewID view_id, View *default_view = NULL) { - For(Views) { - if (it->id == view_id) { - return it; - } - } - return default_view; -} - -View *FindView(BufferID buffer_id, View *default_view = NULL) { - For(Views) { - if (it->active_buffer == buffer_id) { - return it; - } - } - return default_view; -} - -Window *FindWindow(ViewID view_id, Window *default_window = NULL) { - For(Windows) { - if (it->active_view == view_id) { - return it; - } - } - return default_window; -} - -Window *FindWindow(String buffer_name, Window *default_window = NULL) { - For(Windows) { - View *it_view = GetView(it->active_view); - Buffer *it_buffer = GetBuffer(it_view->active_buffer); - if (it_buffer->name == buffer_name) { - return it; - } - } - return default_window; -} - -Window *FindWindow(BufferID buffer_id) { - For(Windows) { - View *view = GetView(it->active_view); - if (view->active_buffer == buffer_id) return it; - } - return NULL; -} - -View *FindView(String name, View *default_view = NULL) { - For(Views) { - Buffer *buffer = GetBuffer(it->active_buffer); - if (buffer->name == name) { - return it; - } - } - return default_view; -} - BSet GetBSet(Window *window) { BSet set = {window}; set.view = GetView(set.window->active_view); @@ -269,147 +35,6 @@ String GetMainDir() { return name; } -Int ConvertUTF8ToUTF16UnixLine(String string, char16_t *buffer, Int buffer_cap) { - if (string.len == 0) { - return 0; - } - - Int buffer_len = 0; - Assert(buffer_cap > string.len * 2); - for (Int i = 0; i < string.len;) { - if (string.data[i] == '\r') { - i += 1; - continue; - } - if (string.data[i] == '\t') { - // @WARNING: DONT INCREASE THE SIZE CARELESSLY, WE NEED TO ADJUST BUFFER SIZE - for (Int i = 0; i < 4; i += 1) buffer[buffer_len++] = u' '; - i += 1; - continue; - } - - uint32_t u32 = '?'; - UTF32Result decode = UTF8ToUTF32((uint8_t *)(string.data + i), (int64_t)(string.len - i)); - if (!decode.error) { - i += decode.advance; - u32 = decode.out_str; - } else { - i += 1; - } - - UTF16Result encode = UTF32ToUTF16(u32); - if (!encode.error) { - for (int64_t encode_i = 0; encode_i < encode.len; encode_i += 1) { - buffer[buffer_len++] = encode.out_str[encode_i]; - Assert(buffer_len < buffer_cap); - } - } else { - buffer[buffer_len++] = u'?'; - } - } - return buffer_len; -} - -String16 ToUnixString16(Allocator allocator, String string_) { - Int cap = string_.len * 3; - char16_t *string16_buffer = AllocArray(allocator, char16_t, cap); - Int len = ConvertUTF8ToUTF16UnixLine(string_, string16_buffer, cap); - String16 string = {string16_buffer, len}; - return string; -} - -Buffer *BufferOpenFile(String path) { - Allocator sys_allocator = GetSystemAllocator(); - Scratch scratch; - - path = GetAbsolutePath(scratch, path); - Buffer *buffer = GetBuffer(path); - if (!IsNull(buffer) || (IsNull(buffer) && buffer->name == path)) { - return buffer; - } - - if (!FileExists(path)) { - buffer = CreateBuffer(sys_allocator, path); - } else if (IsDir(path)) { - ReportWarningf("failed to open, it's a directory: %S", path); - return GetBuffer(NullBufferID); - } else { - String string = ReadFile(scratch, path); - buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096); - buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap); - buffer->file_mod_time = GetFileModTime(path); - UpdateLines(buffer, {}, String16{(char16_t *)buffer->data, buffer->len}); - } - - return buffer; -} - -View *OpenBufferView(String name) { - Buffer *buffer = BufferOpenFile(name); - View *view = CreateView(buffer->id); - return view; -} - -View *WindowOpenBufferView(Window *new_parent_window, String name) { - View *view = FindView(name); - if (!view) { - View *result = OpenBufferView(name); - new_parent_window->active_view = result->id; - return result; - } - - Window *window = FindWindow(view->id); - if (!window) { - new_parent_window->active_view = view->id; - return view; - } - if (window == new_parent_window) { - return view; - } - - Assert(window->active_view.id == view->id.id); - View *result = OpenBufferView(name); - new_parent_window->active_view = result->id; - return result; -} - -bool ViewIsCrumb(ViewID view_id) { - ForItem(window, Windows) { - For(window->goto_history) if (it.view_id == view_id) return true; - For(window->goto_redo) if (it.view_id == view_id) return true; - } - return false; -} - -bool ViewIsReferenced(ViewID view) { - if (view == NullViewID) { - return true; - } - - if (ViewIsCrumb(view)) { - return true; - } - - For(Windows) { - if (it->active_view == view) { - return true; - } - } - return false; -} - -bool BufferIsReferenced(BufferID buffer_id) { - if (buffer_id == NullBufferID) { - return true; - } - - if (FindView(buffer_id)) { - return true; - } - - return false; -} - void GarbageCollect() { Allocator sys_allocator = GetSystemAllocator(); diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 086a659..c32c49d 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -12,24 +12,22 @@ #define LUA_USE_LONGJMP #include "external/luaunity.c" -SDL_Window *SDLWindow; -bool IsInFullscreen; -int FullScreenSizeX, FullScreenSizeY; -int FullScreenPositionX, FullScreenPositionY; -bool Testing = false; - -#include "generated_variables.cpp" #include "render/generated_font.cpp" #include "render/font.cpp" #include "render/opengl.cpp" #include "buffer.h" +#include "view.h" +#include "window.h" #include "text_editor.h" -#include "intern_table.cpp" -#include "buffer.cpp" +#include "lua.h" -#include "management.cpp" +#include "globals.cpp" +#include "lua.cpp" +#include "buffer.cpp" +#include "view.cpp" #include "window.cpp" +#include "management.cpp" #include "process.cpp" #include "event.cpp" @@ -41,119 +39,11 @@ bool Testing = false; #include "lua_api_generated.cpp" #include "generated_config.cpp" -#include "generated.cpp" -#include "window_draw.cpp" +#include "draw.cpp" #include "coroutines.cpp" #include "test/tests.cpp" -void FillEventWithBasicData(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; - - float xmouse, ymouse; - SDL_GetMouseState(&xmouse, &ymouse); - event->xmouse = (int16_t)xmouse; - event->ymouse = (int16_t)ymouse; - - int xwindow, ywindow; - SDL_GetWindowSize(SDLWindow, &xwindow, &ywindow); - event->xwindow = xwindow; - event->ywindow = ywindow; - event->text = ""; -} - -Event TranslateSDLEvent(SDL_Event *input_event) { - ProfileFunction(); - Event event = {}; - FillEventWithBasicData(&event); - - switch (input_event->type) { - case SDL_EVENT_QUIT: { - event.kind = EVENT_QUIT; - } break; - - case SDL_EVENT_KEY_DOWN: { - event.kind = EVENT_KEY_PRESS; - SDL_KeyboardEvent &key = input_event->key; - event.key = key.key; - } break; - - case SDL_EVENT_TEXT_INPUT: { - event.kind = EVENT_TEXT_INPUT; - SDL_TextInputEvent &b = input_event->text; - String string = b.text; - event.text = Intern(&GlobalInternTable, string).data; - } 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; - event.clicks = b.clicks; - if (b.button == SDL_BUTTON_LEFT) { - event.kind = EVENT_MOUSE_LEFT; - } else if (b.button == SDL_BUTTON_RIGHT) { - event.kind = EVENT_MOUSE_RIGHT; - } else if (b.button == SDL_BUTTON_MIDDLE) { - event.kind = EVENT_MOUSE_MIDDLE; - } else if (b.button == SDL_BUTTON_X1) { - event.kind = EVENT_MOUSE_X1; - } else if (b.button == SDL_BUTTON_X2) { - event.kind = EVENT_MOUSE_X2; - } else { - event.kind = EVENT_NONE; - event.clicks = 0; - } - } 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.kind = EVENT_MOUSE_LEFT_UP; - } else if (b.button == SDL_BUTTON_RIGHT) { - event.kind = EVENT_MOUSE_RIGHT_UP; - } else if (b.button == SDL_BUTTON_MIDDLE) { - event.kind = EVENT_MOUSE_MIDDLE_UP; - } else if (b.button == SDL_BUTTON_X1) { - event.kind = EVENT_MOUSE_X1_UP; - } else if (b.button == SDL_BUTTON_X2) { - event.kind = EVENT_MOUSE_X2_UP; - } else { - event.kind = EVENT_NONE; - } - } break; - - case SDL_EVENT_MOUSE_WHEEL: { - event.kind = EVENT_MOUSE_WHEEL; - SDL_MouseWheelEvent &b = input_event->wheel; - event.xmouse = (int16_t)b.mouse_x; - event.ymouse = (int16_t)b.mouse_y; - event.xwheel = b.x; - event.ywheel = b.y; - } break; - - case SDL_EVENT_MOUSE_MOTION: { - event.kind = EVENT_UPDATE; - } break; - - case SDL_EVENT_DROP_FILE: { - event.kind = EVENT_DROP_FILE; - SDL_DropEvent &b = input_event->drop; - String string = b.data; - event.text = Intern(&GlobalInternTable, string).data; - } break; - default: { - }; - } - - return event; -} #if OS_WASM EM_JS(void, JS_SetMouseCursor, (const char *cursor_str), { @@ -262,36 +152,6 @@ void Update(Event event) { } } -Array GetEventsForFrame(Allocator allocator) { - Array result = {allocator}; - if (EventPlayback.len) { - result = TightCopy(allocator, EventPlayback); - EventPlayback.len = 0; - } - - SDL_Event event; - if (WaitForEvents) { - SDL_WaitEvent(&event); - Event ev = TranslateSDLEvent(&event); - if (ev.kind != EVENT_NONE) Add(&result, ev); - } - - while (SDL_PollEvent(&event)) { - Event ev = TranslateSDLEvent(&event); - if (ev.kind != EVENT_NONE) Add(&result, ev); - } - - if (result.len == 0) { - Event event = {}; - FillEventWithBasicData(&event); - event.kind = EVENT_UPDATE; - Add(&result, event); - } - - Assert(result.len); - return result; -} - void Windows_SetupVCVarsall(mco_coro *co) { View *view = NULL; { @@ -486,7 +346,7 @@ int main(int argc, char **argv) InitBuffers(); InitRender(); - ReloadFont(); + ReloadFont(StyleFont, (U32)StyleFontSize); InitWindows(); InitOS(ReportWarningf); diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h index 57a47aa..01310a1 100644 --- a/src/text_editor/text_editor.h +++ b/src/text_editor/text_editor.h @@ -1,72 +1,61 @@ -struct Window; struct View; struct WindowSplit; -struct ViewID { Int id; View *o; }; -struct WindowID { Int id; Window *o; }; +#define EVENT_KINDS \ + X(EVENT_NONE) \ + X(EVENT_UPDATE) \ + X(EVENT_QUIT) \ + X(EVENT_MOUSE_LEFT) \ + X(EVENT_MOUSE_RIGHT) \ + X(EVENT_MOUSE_MIDDLE) \ + X(EVENT_MOUSE_X1) \ + X(EVENT_MOUSE_X2) \ + X(EVENT_MOUSE_LEFT_UP) \ + X(EVENT_MOUSE_RIGHT_UP) \ + X(EVENT_MOUSE_MIDDLE_UP) \ + X(EVENT_MOUSE_X1_UP) \ + X(EVENT_MOUSE_X2_UP) \ + X(EVENT_MOUSE_WHEEL) \ + X(EVENT_KEY_PRESS) \ + X(EVENT_TEXT_INPUT) \ + X(EVENT_DROP_FILE) -struct View { - ViewID id; - BufferID active_buffer; - Vec2I scroll; - Array carets; - - // window | view - Caret main_caret_on_begin_frame; - bool update_scroll; - - bool fuzzy_search; - String16 prev_search_line; +enum EventKind { +#define X(TYPE) TYPE, + EVENT_KINDS +#undef X + EVENT_KIND_COUNT, + EVENT_KIND_INVALID = 111, }; -struct GotoCrumb { - ViewID view_id; - Caret caret; - double time; +const char *EventKindStrings[] = { +#define X(TYPE) #TYPE, + EVENT_KINDS +#undef X }; -struct Window { - WindowID id; - ViewID active_view; +#define EVENT_FIELDS \ + X(EventKind, Int, kind) \ + X(SDL_Keycode, Int, key) \ + X(int16_t, Int, xwindow) \ + X(int16_t, Int, ywindow) \ + X(int16_t, Int, xmouse) \ + X(int16_t, Int, ymouse) \ + X(uint8_t, Int, clicks) \ + X(uint8_t, Int, shift) \ + X(uint8_t, Int, ctrl) \ + X(uint8_t, Int, alt) \ + X(uint8_t, Int, super) \ + X(float, Float, xwheel) \ + X(float, Float, ywheel) \ + X(char *, String, text) +#define EVENT_FIELD_COUNT 14 - Rect2I total_rect; - Rect2I document_rect; - Rect2I scrollbar_rect; - Rect2I line_numbers_rect; - Rect2I resizer_rect; - - Font *font; - double mouse_scroller_offset; - int z; - double weight; - Int status_bar_last_buffer_change_id; - - Array goto_history; - Array goto_redo; - - ViewID active_goto_list; - Int goto_list_pos; - - struct { - bool draw_scrollbar : 1; - bool draw_line_numbers : 1; - bool draw_darker : 1; - bool draw_line_highlight : 1; - bool visible : 1; - bool layout : 1; - bool kill : 1; - bool sync_visibility_with_focus : 1; - bool lose_focus_on_escape : 1; - bool jump_history : 1; - }; -}; - -struct Scroller { - Rect2 rect; - double begin; - double end; - Int line_count; +struct Event { +#define X(TYPE, KIND, NAME) TYPE NAME; + EVENT_FIELDS +#undef X }; struct BSet { - Window *window; + struct Window *window; View *view; Buffer *buffer; }; @@ -81,7 +70,6 @@ Allocator SysAllocator = {SystemAllocatorProc}; String ConfigDir; float DPIScale = 1.0f; -Rect2I GetVisibleCells(Window *window); void AfterEdit(View *view, Array edits); Scroller ComputeScrollerRect(Window *window); BSet Open(String path, String meta = ""); @@ -112,10 +100,8 @@ View *CreateView(BufferID active_buffer); void ReopenBuffer(Buffer *buffer); inline Buffer *FindBuffer(String name); -inline bool operator==(WindowID a, WindowID b) { return a.id == b.id; } inline bool operator==(BufferID a, BufferID b) { return a.id == b.id; } inline bool operator==(ViewID a, ViewID b) { return a.id == b.id; } -inline bool operator!=(WindowID a, WindowID b) { return a.id != b.id; } inline bool operator!=(BufferID a, BufferID b) { return a.id != b.id; } inline bool operator!=(ViewID a, ViewID b) { return a.id != b.id; } diff --git a/src/text_editor/view.cpp b/src/text_editor/view.cpp new file mode 100644 index 0000000..fc3894c --- /dev/null +++ b/src/text_editor/view.cpp @@ -0,0 +1,77 @@ +API ViewID AllocViewID(View *view) { + return {ViewIDs.id++, view}; +} + +API View *CreateView(BufferID active_buffer) { + Allocator al = GetSystemAllocator(); + View *view = AllocType(al, View); + view->id = AllocViewID(view); + view->active_buffer = active_buffer; + view->carets.allocator = al; + Add(&view->carets, {0, 0}); + Add(&Views, view); + return view; +} + +API View *FindView(ViewID view_id, View *default_view) { + For(Views) { + if (it->id == view_id) { + return it; + } + } + return default_view; +} + +API View *FindView(BufferID buffer_id, View *default_view) { + For(Views) { + if (it->active_buffer == buffer_id) { + return it; + } + } + return default_view; +} + +API View *FindView(String name, View *default_view) { + For(Views) { + Buffer *buffer = GetBuffer(it->active_buffer); + if (buffer->name == name) { + return it; + } + } + return default_view; +} + +API View *GetView(ViewID id) { + return FindView(id, Views[0]); +} + +API View *OpenBufferView(String name) { + Buffer *buffer = BufferOpenFile(name); + View *view = CreateView(buffer->id); + return view; +} + +API bool ViewIsCrumb(ViewID view_id) { + ForItem(window, Windows) { + For(window->goto_history) if (it.view_id == view_id) return true; + For(window->goto_redo) if (it.view_id == view_id) return true; + } + return false; +} + +API bool ViewIsReferenced(ViewID view) { + if (view == NullViewID) { + return true; + } + + if (ViewIsCrumb(view)) { + return true; + } + + For(Windows) { + if (it->active_view == view) { + return true; + } + } + return false; +} diff --git a/src/text_editor/view.h b/src/text_editor/view.h new file mode 100644 index 0000000..f1447a0 --- /dev/null +++ b/src/text_editor/view.h @@ -0,0 +1,32 @@ +struct View; +struct ViewID { Int id; View *o; }; + +struct View { + ViewID id; + BufferID active_buffer; + Vec2I scroll; + Array carets; + + // window | view + Caret main_caret_on_begin_frame; + bool update_scroll; + + bool fuzzy_search; + String16 prev_search_line; +}; + +struct GotoCrumb { + ViewID view_id; + Caret caret; + double time; +}; + +API ViewID AllocViewID(View *view); +API View *CreateView(BufferID active_buffer); +API View *FindView(ViewID view_id, View *default_view = NULL); +API View *FindView(BufferID buffer_id, View *default_view = NULL); +API View *FindView(String name, View *default_view = NULL); +API View *GetView(ViewID id); +API View *OpenBufferView(String name); +API bool ViewIsCrumb(ViewID view_id); +API bool ViewIsReferenced(ViewID view); \ No newline at end of file diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index baafaf6..b553920 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -1,3 +1,72 @@ +inline WindowID AllocWindowID(Window *window) { + return {WindowIDs.id++, window}; +} + +Window *CreateWind() { + Allocator allocator = GetSystemAllocator(); + Window *w = AllocType(allocator, Window); + w->font = &PrimaryFont; + w->visible = true; + w->layout = true; + w->draw_scrollbar = StyleDrawScrollbar; + w->draw_line_numbers = StyleDrawLineNumbers; + w->draw_line_highlight = true; + w->jump_history = true; + w->id = AllocWindowID(w); + w->weight = 1.0; + Add(&Windows, w); + return w; +} + +inline Window *GetWindow(WindowID id, Window *default_window = Windows[0]) { + For(Windows) { + if (it->id == id) return it; + } + return default_window; +} + +Window *FindWindow(ViewID view_id, Window *default_window = NULL) { + For(Windows) { + if (it->active_view == view_id) { + return it; + } + } + return default_window; +} + +Window *FindWindow(String buffer_name, Window *default_window = NULL) { + For(Windows) { + View *it_view = GetView(it->active_view); + Buffer *it_buffer = GetBuffer(it_view->active_buffer); + if (it_buffer->name == buffer_name) { + return it; + } + } + return default_window; +} + +Window *FindWindow(BufferID buffer_id) { + For(Windows) { + View *view = GetView(it->active_view); + if (view->active_buffer == buffer_id) return it; + } + return NULL; +} + +inline Window *GetActiveWind() { + return GetWindow(ActiveWindowID); +} + +inline bool IsDocumentSelectionValid() { + if (DocumentSelected.id == -1) return false; + return true; +} + +inline bool IsScrollbarSelectionValid() { + if (ScrollbarSelected.id == -1) return false; + return true; +} + Array GetWindowZOrder(Allocator allocator) { Array order = {allocator}; For(Windows) if (it->z == 2) Add(&order, it); @@ -13,6 +82,29 @@ Int GetExpandingBarSize(Window *window) { return (Int)result; } +View *WindowOpenBufferView(Window *new_parent_window, String name) { + View *view = FindView(name); + if (!view) { + View *result = OpenBufferView(name); + new_parent_window->active_view = result->id; + return result; + } + + Window *window = FindWindow(view->id); + if (!window) { + new_parent_window->active_view = view->id; + return view; + } + if (window == new_parent_window) { + return view; + } + + Assert(window->active_view.id == view->id.id); + View *result = OpenBufferView(name); + new_parent_window->active_view = result->id; + return result; +} + void InitWindows() { Scratch scratch; @@ -187,4 +279,4 @@ void LayoutWindows(int16_t wx, int16_t wy) { CalcNiceties(n); i += 1; } -} \ No newline at end of file +} diff --git a/src/text_editor/window.h b/src/text_editor/window.h new file mode 100644 index 0000000..696c29d --- /dev/null +++ b/src/text_editor/window.h @@ -0,0 +1,49 @@ +struct Window; +struct WindowID { Int id; Window *o; }; + +struct Window { + WindowID id; + ViewID active_view; + + Rect2I total_rect; + Rect2I document_rect; + Rect2I scrollbar_rect; + Rect2I line_numbers_rect; + Rect2I resizer_rect; + + Font *font; + double mouse_scroller_offset; + int z; + double weight; + Int status_bar_last_buffer_change_id; + + Array goto_history; + Array goto_redo; + + ViewID active_goto_list; + Int goto_list_pos; + + struct { + bool draw_scrollbar : 1; + bool draw_line_numbers : 1; + bool draw_darker : 1; + bool draw_line_highlight : 1; + bool visible : 1; + bool layout : 1; + bool kill : 1; + bool sync_visibility_with_focus : 1; + bool lose_focus_on_escape : 1; + bool jump_history : 1; + }; +}; + +struct Scroller { + Rect2 rect; + double begin; + double end; + Int line_count; +}; + +inline bool operator==(WindowID a, WindowID b) { return a.id == b.id; } +inline bool operator!=(WindowID a, WindowID b) { return a.id != b.id; } +Rect2I GetVisibleCells(Window *window); \ No newline at end of file