From d3abcbc146916624b16050900de485a322360f5c Mon Sep 17 00:00:00 2001 From: Matthew Date: Sat, 27 Jun 2026 12:21:14 +1000 Subject: [PATCH] more cleaning up --- src/dlib | 2 +- src/editor/buffer.d | 132 +++++++++++++++++++++++++++----------------- src/editor/editor.d | 99 ++++++++++++++++++--------------- src/editor/ui.d | 102 +++++++++++++++++++++++++++++----- 4 files changed, 223 insertions(+), 112 deletions(-) diff --git a/src/dlib b/src/dlib index f3d1f55..a12e8c2 160000 --- a/src/dlib +++ b/src/dlib @@ -1 +1 @@ -Subproject commit f3d1f551ccfa37de73d626479252bada0fc17cb2 +Subproject commit a12e8c21e21b65e16af06675b6c2d1696e23bfa7 diff --git a/src/editor/buffer.d b/src/editor/buffer.d index 7e2e0ce..1c48caf 100644 --- a/src/editor/buffer.d +++ b/src/editor/buffer.d @@ -8,23 +8,75 @@ import std.math.algebraic : abs; import editor; import buffer : Reset; +enum BufferFlags +{ + None = 0x0000, + NoFile = 0x0001, + Modified = 0x0002, + Fixed = 0x0004, +} alias BFRF = BufferFlags; + struct FlatBuffer { - Tokenizer tokenizer; - Arena arena; - Arena line_start_arena; - LineBuffers linebufs; + Tokenizer tokenizer; + Arena arena; + Arena line_start_arena; + LineBuffers linebufs; - string file_name; - u8[] data; - u64 length; + string file_name; + u8[] data; + u64 length; - Line[] lines; - u64 line_count; + Line[] lines; + u64 line_count; - bool fixed; - bool changed; - FlatBuffer* list_next; + BufferFlags flags; + FlatBuffer* list_next; + + void + FreeBuffer() + { + Free(this.data); + Free(&this.arena); + Free(&this.line_start_arena); + Free(cast(char*)this.file_name.ptr); + + Free(&this.linebufs.arena); + + Free(this.tokenizer.tokens); + Free(&this.tokenizer.arena); + + memset(&this, 0, FlatBuffer.sizeof); + } + + void + Overwrite(FlatBuffer* src) + { + string file_name = ScratchAlloc(this.file_name); + + this.FreeBuffer(); + this.LoadBuffer(src.data, file_name); + } + + void + LoadBuffer(u8[] data, string file_name) + { + u64 capacity = data.length > 0 ? RoundUp(cast(u64)(data.length)*2, KB(4)) : KB(4); + u8[] buffer = Alloc!(u8)(capacity); + + MemCpy(buffer.ptr, data.ptr, data.length); + + this.arena = CreateArena(MB(1)); + this.line_start_arena = CreateArena(KB(512)); + this.file_name = file_name; + this.line_count = CountLF(data); + this.length = data.length; + this.linebufs = CreateLineBuffers(MB(1)); + this.data = buffer; + this.tokenizer = CreateTokenizer(&this); + + Fix(&this); + } } struct BufferViewInfo @@ -116,32 +168,20 @@ const u64 BUF_START = 1; FlatBuffer* CreateFlatBuffer(ref Ctx ctx, u8[] data = [], string file_name = "") { - if(ctx.text_buffer_count == ctx.text_buffers.length) + FlatBuffer* buffer = ctx.free_text_buffers; + if(!buffer) { - ctx.text_buffers = Realloc(ctx.text_buffers, ctx.text_buffers.length+ARRAY_COUNT_INCREMENT); + if(ctx.text_buffer_count == ctx.text_buffers.length) + { + ctx.text_buffers = Realloc(ctx.text_buffers, ctx.text_buffers.length+ARRAY_COUNT_INCREMENT); + } + + buffer = &ctx.text_buffers[ctx.text_buffer_count++]; } - FlatBuffer* fb = &ctx.text_buffers[ctx.text_buffer_count++]; + buffer.LoadBuffer(data, file_name); - fb.arena = CreateArena(MB(1)); - fb.line_start_arena = CreateArena(KB(512)); - - u64 capacity = data.length > 0 ? RoundUp(cast(u64)(data.length)*2, KB(4)) : KB(4); - - u8[] buffer = Alloc!(u8)(capacity); - - MemCpy(buffer.ptr, data.ptr, data.length); - - fb.file_name = file_name; - fb.line_count = CountLF(data); - fb.length = data.length; - fb.linebufs = CreateLineBuffers(MB(1)); - fb.data = buffer; - fb.tokenizer = CreateTokenizer(fb); - - Fix(fb); - - return fb; + return buffer; } void @@ -216,31 +256,19 @@ ResetViewInfo(BufferViewInfo* info) info.selection_mode = SM.None; info.pos = 0; info.column_position = 0; + info.line_offset = 0; } -/* -void -Change(FlatBuffer* fb, u8[] data, string file_name) -{ - Free(fb.data); - Reset(&fb.linebufs.arena); - - Init(fb, data, file_name); - ResetTokenizer(&fb.tk, fb.data.length); - Fix(fb); -} -*/ - u64 CountLF(u8[] data) { - u64 lf_count = 1; + u64 line_feed_count = 1; for(u64 i = 0; i < data.length; i += 1) { - lf_count += u64(data.ptr[i] == '\n'); + line_feed_count += u64(data.ptr[i] == '\n'); } - return lf_count; + return line_feed_count; } pragma(inline, true) bool @@ -330,7 +358,7 @@ Fix(T)(T* buffer) buffer.lines[buffer.line_count-1].length = buffer.length - buffer.lines[buffer.line_count-1].pos; - buffer.fixed = true; + buffer.flags &= BFRF.Fixed; TokenizeD(buffer); } @@ -344,7 +372,7 @@ CreateLineBuffers(u64 arena_size) void Insert(Editor* editor, u8[] insert, u64 length, u64 insert_position) { - editor.changed = true; + editor.flags &= BFRF.Modified; if(editor.length + length > editor.data.length-SPACING) { diff --git a/src/editor/editor.d b/src/editor/editor.d index 8b09216..8fe632c 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -15,7 +15,9 @@ import std.stdio; import std.exception; import std.file; import std.string; -import core.stdc.stdio; +import core.stdc.stdio : File = FILE, FOpen = fopen, FFlush = fflush, FWrite = fwrite, FSeek = fseek, FTell = ftell, FClose = fclose, FRead = fread, SeekSet = SEEK_SET, SeekEnd = SEEK_END; + +// TODO: add function for moving data within text buffer using SIMD and moving in batches that fit within CPU cache const u64 ARRAY_COUNT_INCREMENT = 32; @@ -101,8 +103,9 @@ struct Ctx FlatBuffer[] text_buffers; u64 text_buffer_count; FlatBuffer* free_text_buffers; + u64 new_buffer_count; // files that are not yet files (you know) - @property ref DescSet desc_set() => this.rd_ctx.desc_sets[this.frame_index]; + @property ref DescSet desc_set() => this.rd_ctx.desc_sets[this.frame_index]; debug bool dbg; @@ -257,7 +260,7 @@ const Command NO_CMD = { type: CT.None, }; -Command[21] CMD_LIST = [ +Command[22] CMD_LIST = [ { name: "Open", cmd: "open", @@ -268,14 +271,21 @@ Command[21] CMD_LIST = [ { name: "Save", cmd: "save", - desc: "Save the current file in the focused editor view.", + desc: "Save the current file.", type: CT.Callback, - fn: &SaveFileWindow, + fn: &CmdSaveFile, + }, + { + name: "Save As", + cmd: "save as", + desc: "Save the current file as a specified name.", + type: CT.Callback, + fn: &CmdSaveFileWindow, }, { name: "New File", cmd: "new file", - desc: "Create a new file with a specified name and location.", + desc: "Open an empty buffer", type: CT.Callback, fn: &NotImplementedCallback, }, @@ -595,53 +605,54 @@ InitCtx(PlatformWindow* window) } } -void -SaveFile(Editor* ed, string file_name) +bool +SaveBufferToFile(Editor* editor) { - import core.stdc.stdio; + bool saved; - file_name = file_name.length == 0 ? Str(ed.file_name) : file_name; + assert(editor.buffer); + assert(editor.file_name.length); - if(file_name.length > 0) + auto f = FOpen(editor.file_name.ptr, "wb"); + if(f != null) { - string file_path = AbsolutePath(file_name); - auto f = fopen(cast(char*)file_path.ptr, "wb"); - if(f != null) + u64 tab_count; + for(u64 i = 0; i < editor.length; i += 1) { - u64 tab_count; - for(u64 i = 0; i < ed.length; i += 1) + if(editor.data[i] == '\t') { - if(ed.data[i] == '\t') - { - tab_count += 1; - } + tab_count += 1; } - - u64 tab_width = GetCtx().tab_width; - u64 buf_size = ed.length + ((tab_width-1) * tab_count); - u8[] temp_buf = ScratchAlloc!(u8)(buf_size); - - u64 buf_pos; - for(u64 i = 0; i < ed.length; i += 1) - { - if(ed.data[i] == '\t') - { - for(u64 j = 0; j < tab_width; j += 1) - { - temp_buf[buf_pos++] = ' '; - } - } - else - { - temp_buf[buf_pos++] = ed.data[i]; - } - } - - fwrite(temp_buf.ptr, 1, buf_size, f); - fflush(f); - fclose(f); } + + u64 tab_width = GetCtx().tab_width; + u64 buffer_size = editor.length + ((tab_width-1) * tab_count); + u8[] temp_buf = ScratchAlloc!(u8)(buffer_size); + + u64 buf_pos; + for(u64 i = 0; i < editor.length; i += 1) + { + if(editor.data[i] == '\t') + { + for(u64 j = 0; j < tab_width; j += 1) + { + temp_buf[buf_pos++] = ' '; + } + } + else + { + temp_buf[buf_pos++] = editor.data[i]; + } + } + + FWrite(temp_buf.ptr, 1, buffer_size, f); + FFlush(f); + FClose(f); + + saved = true; } + + return saved; } string diff --git a/src/editor/ui.d b/src/editor/ui.d index 4e24479..ed50077 100644 --- a/src/editor/ui.d +++ b/src/editor/ui.d @@ -335,6 +335,14 @@ struct Rect }; }; + this(Vec2 p0, Vec2 p1) + { + this.v[0].x = p0.x; + this.v[0].y = p0.y; + this.v[1].x = p1.x; + this.v[1].y = p1.y; + } + ref Vec2 opIndex(usize index) { return this.v[index]; @@ -344,8 +352,28 @@ struct Rect { return this.v[index] = value; } + + Rect opBinary(string op)(Rect rhs) + if(op == "*" || op == "+" || op == "-" || op == "+" || op == "/") + { + Rect result; + static foreach(i; 0 .. this.v.length) + { + mixin("result.v[", i, "].x = this.v[", i, "].x"~op~"rhs.v[", i, "].x;"); + mixin("result.v[", i, "].y = this.v[", i, "].y"~op~"rhs.v[", i, "].y;"); + } + + return result; + } } +Rect RectX0(f32 value) => Rect(Vec2(value, 0.0), Vec2(0.0, 0.0)); +Rect RectY0(f32 value) => Rect(Vec2(0.0, value), Vec2(0.0, 0.0)); +Rect RectX1(f32 value) => Rect(Vec2(0.0, 0.0), Vec2(value, 0.0)); +Rect RectY1(f32 value) => Rect(Vec2(0.0, 0.0), Vec2(0.0, value)); +Rect RectXY0(f32 x, f32 y) => Rect(Vec2(x, y), Vec2(0.0, 0.0)); +Rect RectXY1(f32 x, f32 y) => Rect(Vec2(0.0, 0.0), Vec2(x, y)); + alias UIHash = u64; alias UIPair = KVPair!(UIHash, UIItem*); @@ -1029,24 +1057,40 @@ SearchInputWindow(T)(string hash_text, SearchWindowCtx!(T)* window_ctx, bool rea } bool -SaveFileWindow(ref Ctx ctx) +CmdSaveFile(ref Ctx ctx) +{ + bool result = true; + Editor* editor = ctx.focused_panel.ed; + if(editor.file_name.length) + { + SaveBufferToFile(editor); + } + else + { + result = CmdSaveFileWindow(ctx); + } + + return result; +} + +bool +CmdSaveFileWindow(ref Ctx ctx) { bool exit; - Editor* ed = ctx.focused_panel.ed; + Editor* editor = ctx.focused_panel.ed; static bool init = false; if(!init) { - ctx.cmd.exec_cmd_input.data[0 .. ed.file_name.length] = Arr!(u8)(ed.file_name[0 .. $]); - ctx.cmd.exec_cmd_input.length = ed.file_name.length; + ctx.cmd.exec_cmd_input.data[0 .. editor.file_name.length] = Arr!(u8)(editor.file_name[0 .. $]); + ctx.cmd.exec_cmd_input.length = editor.file_name.length; } const PAD = 4.0f; Vec2 extent = GetExtent(); - // TODO: fix: This breaks when setting GetFontSet input to not 12, probably incorrect draw call boundaries (again) - FontSet* fs = GetFontSet(12); + FontSet* fs = GetFontSet(14); f32 x = extent.x * 0.1; f32 w = extent.x * 0.8; @@ -1072,8 +1116,7 @@ SaveFileWindow(ref Ctx ctx) DrawRect(ctx, inner_rect, &CMD_STYLE); - Rect text_rect = inner_rect; - text_rect.p0.x += PAD; + Rect text_rect = inner_rect + RectX0(PAD); DrawText(ctx, Str(ctx.cmd.exec_cmd_input), WHITE, fs, text_rect, TA.Left, -1); DrawBorder(ctx, inner_rect, &CMD_STYLE); @@ -1085,15 +1128,44 @@ SaveFileWindow(ref Ctx ctx) { switch(ev.key) with(Input) { - case Enter: + case Enter: { - SaveFile(ed, Str(ctx.cmd.exec_cmd_input)); + if(!ctx.cmd.exec_cmd_input.length) break; + + // TODO: continue here, create new flat buffer then put in new save function + + string file_name = AbsolutePath(Str(ctx.cmd.exec_cmd_input)); + if(file_name != editor.file_name) + { + bool found; + foreach(i; 0 .. ctx.text_buffer_count) + { + if(file_name == ctx.text_buffers[i].file_name) + { + ctx.text_buffers[i].Overwrite(editor.buffer); + editor.buffer = &ctx.text_buffers[i]; + found = true; + break; + } + } + + if(!found) + { + editor.buffer = CreateFlatBuffer(ctx, editor.buffer.data, file_name); + } + } + + if(SaveBufferToFile(editor)) + { + editor.flags &= ~(BFRF.Modified & BFRF.NoFile); + } + else + { + // TODO: show error.. + } } goto case; - case Escape: - { - exit = taken = true; - } break; - default: taken = HandleTextInput(&ctx.cmd.exec_cmd_input, ev); break; + case Escape: exit = taken = true; break; + default: taken = HandleTextInput(&ctx.cmd.exec_cmd_input, ev); break; } }