From c19c60fe2279a9a259b868cd78004af3822956aa Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 28 Nov 2025 09:59:09 +0100 Subject: [PATCH] Tracking allocator, buffer tests --- build.bat | 1 + src/backup/todo.txt | 4 +- src/basic/basic_alloc.cpp | 45 +++ src/text_editor/buffer.cpp | 539 +++++++++++++++++--------- src/text_editor/buffer.h | 115 +++++- src/text_editor/commands.cpp | 28 +- src/text_editor/commands_bindings.cpp | 10 +- src/text_editor/text_editor.cpp | 6 + src/text_editor/title_bar.cpp | 4 +- src/text_editor/window.cpp | 8 +- 10 files changed, 535 insertions(+), 225 deletions(-) diff --git a/build.bat b/build.bat index 1521669..fba6894 100644 --- a/build.bat +++ b/build.bat @@ -12,4 +12,5 @@ set libs=../src/external/SDL/win32-static/SDL3-static.lib ../src/external/SDL/wi cl %flags% ../src/text_editor/text_editor.cpp -Fe:te.exe -I../src/external/SDL/include -I../src/external/lua/src -I../src/external/glad -I../src/ %libs% -link /SUBSYSTEM:WINDOWS /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:MSVCRTD copy te.exe ..\data\te.exe +copy te.pdb ..\data\te.pdb echo written ..\data\te.exe diff --git a/src/backup/todo.txt b/src/backup/todo.txt index 2215f52..fda7893 100644 --- a/src/backup/todo.txt +++ b/src/backup/todo.txt @@ -20,7 +20,9 @@ Things I like: - Configurable Open - Lua config files work pretty well - +Splits: +- Buffer16.cpp / h +- Block arena and refactor alloc diff --git a/src/basic/basic_alloc.cpp b/src/basic/basic_alloc.cpp index 19b2c14..079467a 100644 --- a/src/basic/basic_alloc.cpp +++ b/src/basic/basic_alloc.cpp @@ -238,6 +238,8 @@ void *SystemAllocator_Alloc(void *object, int kind, void *p, size_t size) { Assert(result); } else if (kind == AllocatorKind_Deallocate) { free(p); + } else { + InvalidCodepath(); } return result; } @@ -245,4 +247,47 @@ void *SystemAllocator_Alloc(void *object, int kind, void *p, size_t size) { Allocator GetSystemAllocator() { Allocator result = {SystemAllocator_Alloc}; return result; +} + +struct MemoryRecord { + size_t size; + void *addr; + bool deallocated; +}; +Array MemoryTrackingRecord; + + +void *TrackingAllocatorProc(void *object, int kind, void *p, size_t size) { + void *result = NULL; + + if (kind == AllocatorKind_Allocate) { + result = malloc(size); + Add(&MemoryTrackingRecord, {size, result}); + Assert(result); + } else if (kind == AllocatorKind_Deallocate) { + free(p); + + bool found = false; + For(MemoryTrackingRecord){ + if (it.addr == p) { + it.deallocated = true; + found = true; + } + } + Assert(found); + } else { + InvalidCodepath(); + } + return result; +} + +void TrackingAllocatorCheck() { + For (MemoryTrackingRecord) { + Assert(it.deallocated); + } +} + +Allocator GetTrackingAllocator() { + Allocator result = {TrackingAllocatorProc}; + return result; } \ No newline at end of file diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index bf37df2..a12b106 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -1,94 +1,106 @@ #define BUFFER_DEBUG 0 -/////////////////////////////// -// helpers -/////////////////////////////// -Int GetSize(Range range) { +API Range MakeRange(Int a, Int b) { + Range result = {Min(a, b), Max(a, b)}; + return result; +} + +API Range MakeRange(Int a) { + Range result = {a, a}; + return result; +} + +API Int GetSize(Range range) { Assert(range.max >= range.min); Int result = range.max - range.min; return result; } -Range Rng(Int a, Int b) { - Range result = {Min(a, b), Max(a, b)}; +API bool AreEqual(Range a, Range b) { + bool result = a.min == b.min && a.max == b.max; return result; } -Range Rng(Int a = 0) { - Range result = {a, a}; +API bool AreOverlapping(Range a, Range b) { + bool r1 = (a.max >= b.min && a.max <= b.max) || (a.min >= b.min && a.min <= b.max); + bool r2 = (b.max >= a.min && b.max <= a.max) || (b.min >= a.min && b.min <= a.max); + return r1 || r2; +} + +API bool InBounds(Range range, Int pos) { + bool result = pos >= range.min && pos < range.max; return result; } -String16 GetString(Buffer *buffer, Range range = {0, INT64_MAX}) { - range.min = Clamp(range.min, (Int)0, buffer->len); - range.max = Clamp(range.max, (Int)0, buffer->len); - String16 result = {(char16_t *)buffer->data + range.min, GetSize(range)}; +API Range operator-(Range a, Int value) { + a.min -= value; + a.max -= value; + return a; +} + +API Range operator-=(Range &range, Int value) { + range = range - value; + return range; +} + +API Range operator+(Range a, Int value) { + a.min += value; + a.max += value; + return a; +} + +API Range operator+=(Range &range, Int value) { + range = range + value; + return range; +} + +API Range GetBufferEndAsRange(Buffer *buffer) { + Range result = {buffer->len, buffer->len}; return result; } -String AllocCharString(Allocator allocator, Buffer *buffer, Range range = {0, INT64_MAX}) { - String16 string16 = GetString(buffer, range); - String result = ToString(allocator, string16); +API Range GetBufferBeginAsRange(Buffer *buffer) { + Range result = {0, 0}; return result; } -Int Clamp(const Buffer *buffer, Int pos) { +API Range GetRange(Buffer *buffer) { + Range result = {0, buffer->len}; + return result; +} + +API Int Clamp(const Buffer *buffer, Int pos) { Int result = Clamp(pos, (Int)0, buffer->len); return result; } -Range Clamp(const Buffer *buffer, Range range) { +API Range Clamp(const Buffer *buffer, Range range) { Range result = {}; result.min = Clamp(buffer, range.min); result.max = Clamp(buffer, range.max); return result; } -Range GetEndAsRange(Buffer *buffer) { - Range result = {buffer->len, buffer->len}; - return result; -} - -Range GetBeginAsRange(Buffer *buffer) { - Range result = {0, 0}; - return result; -} - -Range GetRange(Buffer *buffer) { - Range result = {0, buffer->len}; - return result; -} - -Int GetFront(Caret caret) { +// Caret +API Int GetFront(Caret caret) { Int result = caret.pos[caret.ifront]; return result; } -Int GetBack(Caret caret) { +API Int GetBack(Caret caret) { Int index = (caret.ifront + 1) % 2; Int result = caret.pos[index]; return result; } -Caret MakeCaret(Int pos) { +API Caret MakeCaret(Int pos) { Caret result = {}; result.range.min = result.range.max = pos; return result; } -XY XYLine(Int line) { - XY result = {}; - result.line = line; - return result; -} - -char16_t GetChar(Buffer *buffer, Int pos) { - if (pos >= 0 && pos < buffer->len) return buffer->str[pos]; - return 0; -} - -Caret MakeCaret(Int front, Int back) { +API Caret MakeCaret(Int front, Int back) { Caret result = {}; if (front >= back) { result.range.min = back; @@ -102,19 +114,19 @@ Caret MakeCaret(Int front, Int back) { return result; } -Caret SetBack(Caret caret, Int back) { +API Caret SetBack(Caret caret, Int back) { Int front = GetFront(caret); Caret result = MakeCaret(front, back); return result; } -Caret SetFront(Caret caret, Int front) { +API Caret SetFront(Caret caret, Int front) { Int back = GetBack(caret); Caret result = MakeCaret(front, back); return result; } -Caret SetFrontWithAnchor(Caret caret, Caret anchor, Int p) { +API Caret SetFrontWithAnchor(Caret caret, Caret anchor, Int p) { if (anchor.range.min > p) { caret = MakeCaret(p, anchor.range.max); } else if (anchor.range.max < p) { @@ -125,60 +137,17 @@ Caret SetFrontWithAnchor(Caret caret, Caret anchor, Int p) { return caret; } -bool InBounds(const Buffer *buffer, Int pos) { - bool result = pos >= 0 && pos < buffer->len; - return result; -} - -bool InBounds(Range range, Int pos) { - bool result = pos >= range.min && pos < range.max; - return result; -} - -bool AreEqual(Range a, Range b) { - bool result = a.min == b.min && a.max == b.max; - return result; -} - -bool AreEqual(Caret a, Caret b) { +API bool AreEqual(Caret a, Caret b) { bool result = AreEqual(a.range, b.range) && a.ifront == b.ifront; return result; } -bool AreOverlapping(Range a, Range b) { - bool r1 = (a.max >= b.min && a.max <= b.max) || (a.min >= b.min && a.min <= b.max); - bool r2 = (b.max >= a.min && b.max <= a.max) || (b.min >= a.min && b.min <= a.max); - return r1 || r2; -} - -bool AreOverlapping(Caret a, Caret b) { +API bool AreOverlapping(Caret a, Caret b) { bool result = AreOverlapping(a.range, b.range); return result; } -bool InRange(Int a, Range b) { - bool result = a >= b.min && a < b.max; - return result; -} - -Range operator-(Range a, Int value) { - a.min -= value; - a.max -= value; - return a; -} - -Range operator-=(Range &range, Int value) { - range = range - value; - return range; -} - -Int LastLine(Buffer *buffer) { - Int result = buffer->line_starts.len - 1; - return result; -} - -const Int LAST_LINE = INT64_MAX; -Range GetLineRange(Buffer *buffer, Int line, Int *end_of_buffer = NULL) { +API Range GetLineRange(Buffer *buffer, Int line, Int *end_of_buffer) { Range result = {buffer->line_starts[line], buffer->len}; if (line + 1 < buffer->line_starts.len) { result.max = buffer->line_starts[line + 1]; @@ -188,26 +157,60 @@ Range GetLineRange(Buffer *buffer, Int line, Int *end_of_buffer = NULL) { return result; } -Range GetLineRangeWithoutNL(Buffer *buffer, Int line) { +API Range GetLineRangeWithoutNL(Buffer *buffer, Int line) { Int end_of_buffer = 0; Range line_range = GetLineRange(buffer, line, &end_of_buffer); line_range.max = line_range.max - 1 + end_of_buffer; return line_range; } -String16 GetLineString(Buffer *buffer, Int line, Int *end_of_buffer = NULL) { +API String16 GetString(Buffer *buffer, Range range) { + range.min = Clamp(range.min, (Int)0, buffer->len); + range.max = Clamp(range.max, (Int)0, buffer->len); + String16 result = {(char16_t *)buffer->data + range.min, GetSize(range)}; + return result; +} + +API String AllocCharString(Allocator allocator, Buffer *buffer, Range range) { + String16 string16 = GetString(buffer, range); + String result = ToString(allocator, string16); + return result; +} + +API XY XYLine(Int line) { + XY result = {}; + result.line = line; + return result; +} + +API char16_t GetChar(Buffer *buffer, Int pos) { + if (pos >= 0 && pos < buffer->len) return buffer->str[pos]; + return 0; +} + +API bool InBounds(const Buffer *buffer, Int pos) { + bool result = pos >= 0 && pos < buffer->len; + return result; +} + +API Int LastLine(Buffer *buffer) { + Int result = buffer->line_starts.len - 1; + return result; +} + +API String16 GetLineString(Buffer *buffer, Int line, Int *end_of_buffer) { Range range = GetLineRange(buffer, line, end_of_buffer); String16 string = GetString(buffer, range); return string; } -String16 GetLineStringWithoutNL(Buffer *buffer, Int line) { +API String16 GetLineStringWithoutNL(Buffer *buffer, Int line) { Range range = GetLineRangeWithoutNL(buffer, line); String16 string = GetString(buffer, range); return string; } -Int PosToLine(Buffer *buffer, Int pos) { +API Int PosToLine(Buffer *buffer, Int pos) { Add(&buffer->line_starts, buffer->len + 1); // binary search @@ -237,7 +240,7 @@ Int PosToLine(Buffer *buffer, Int pos) { return result; } -XY PosToXY(Buffer *buffer, Int pos) { +API XY PosToXY(Buffer *buffer, Int pos) { Int line = PosToLine(buffer, pos); Range line_range = GetLineRange(buffer, line); Int col = pos - line_range.min; @@ -245,14 +248,14 @@ XY PosToXY(Buffer *buffer, Int pos) { return result; } -Int XYToPos(Buffer *buffer, XY xy) { +API Int XYToPos(Buffer *buffer, XY xy) { xy.line = Clamp(xy.line, (Int)0, buffer->line_starts.len - 1); Range line_range = GetLineRange(buffer, xy.line); Int pos = Clamp(xy.col + line_range.min, line_range.min, line_range.max); return pos; } -Int XYToPosWithoutNL(Buffer *buffer, XY xy) { +API Int XYToPosWithoutNL(Buffer *buffer, XY xy) { xy.line = Clamp(xy.line, (Int)0, buffer->line_starts.len - 1); Int end_of_buffer = 0; Range line_range = GetLineRange(buffer, xy.line, &end_of_buffer); @@ -260,7 +263,7 @@ Int XYToPosWithoutNL(Buffer *buffer, XY xy) { return pos; } -Int XYToPosErrorOutOfBounds(Buffer *buffer, XY xy) { +API Int XYToPosErrorOutOfBounds(Buffer *buffer, XY xy) { if (xy.line < 0 || xy.line >= buffer->line_starts.len) return -1; Range line_range = GetLineRange(buffer, xy.line); Int pos = xy.col + line_range.min; @@ -268,7 +271,7 @@ Int XYToPosErrorOutOfBounds(Buffer *buffer, XY xy) { return pos; } -Int GetWordStart(Buffer *buffer, Int pos) { +API Int GetWordStart(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); for (Int i = pos - 1; i >= 0; i -= 1) { if (!IsWord(buffer->str[i])) break; @@ -277,7 +280,7 @@ Int GetWordStart(Buffer *buffer, Int pos) { return pos; } -Int GetWordEnd(Buffer *buffer, Int pos) { +API Int GetWordEnd(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); for (Int i = pos;; i += 1) { pos = i; @@ -290,7 +293,7 @@ Int GetWordEnd(Buffer *buffer, Int pos) { return pos; } -bool IsLoadWord(char16_t w) { +API bool IsLoadWord(char16_t w) { bool result = w == u'(' || w == u')' || w == u'/' || w == u'\\' || w == u':' || w == u'$' || w == u'_' || w == u'.' || w == u'@' || w == u','; if (!result) { result = !(IsSymbol(w) || IsWhitespace(w)); @@ -298,7 +301,7 @@ bool IsLoadWord(char16_t w) { return result; } -Int GetLoadWordStart(Buffer *buffer, Int pos) { +API Int GetLoadWordStart(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); for (Int i = pos - 1; i >= 0; i -= 1) { if (!IsLoadWord(buffer->str[i])) break; @@ -307,7 +310,7 @@ Int GetLoadWordStart(Buffer *buffer, Int pos) { return pos; } -Int GetLoadWordEnd(Buffer *buffer, Int pos) { +API Int GetLoadWordEnd(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); for (Int i = pos;; i += 1) { pos = i; @@ -320,36 +323,12 @@ Int GetLoadWordEnd(Buffer *buffer, Int pos) { return pos; } -Range EncloseLoadWord(Buffer *buffer, Int pos) { +API Range EncloseLoadWord(Buffer *buffer, Int pos) { Range result = {GetLoadWordStart(buffer, pos), GetLoadWordEnd(buffer, pos)}; return result; } -Int GetExecWordStart(Buffer *buffer, Int pos) { - pos = Clamp(pos, (Int)0, buffer->len); - for (Int i = pos - 1; i >= 0; i -= 1) { - if (IsWhitespace(buffer->str[i])) break; - if (GetChar(buffer, i) == u'|' && GetChar(buffer, i + 1) == u'>') break; - pos = i; - } - return pos; -} - -Int GetExecWordEnd(Buffer *buffer, Int pos) { - pos = Clamp(pos, (Int)0, buffer->len); - for (Int i = pos;; i += 1) { - pos = i; - // this is because buffer end terminates the loop - // too early and we cannot establish the proper range - // semantics - proper max is one past last index - if (!(i < buffer->len)) break; - if (IsWhitespace(buffer->str[i])) break; - if (GetChar(buffer, i - 1) == u'<' && GetChar(buffer, i) == u'|') break; - } - return pos; -} - -Int GetNextWordEnd(Buffer *buffer, Int pos) { +API Int GetNextWordEnd(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); char16_t prev = 0; for (Int i = pos;; i += 1) { @@ -367,7 +346,7 @@ Int GetNextWordEnd(Buffer *buffer, Int pos) { return result; } -Int GetPrevWordStart(Buffer *buffer, Int pos) { +API Int GetPrevWordStart(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); char16_t prev = 0; Int i = pos - 1; @@ -383,43 +362,43 @@ Int GetPrevWordStart(Buffer *buffer, Int pos) { return result; } -Int GetLineStart(Buffer *buffer, Int pos) { +API Int GetLineStart(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); Int line = PosToLine(buffer, pos); Range range = GetLineRangeWithoutNL(buffer, line); return range.min; } -Int GetLineEnd(Buffer *buffer, Int pos) { +API Int GetLineEnd(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); Int line = PosToLine(buffer, pos); Range range = GetLineRangeWithoutNL(buffer, line); return range.max; } -Int GetFullLineStart(Buffer *buffer, Int pos) { +API Int GetFullLineStart(Buffer *buffer, Int pos) { pos = Clamp(pos, (Int)0, buffer->len); Int line = PosToLine(buffer, pos); Range range = GetLineRange(buffer, line); return range.min; } -Int GetFullLineEnd(Buffer *buffer, Int pos, Int *eof = NULL) { +API Int GetFullLineEnd(Buffer *buffer, Int pos, Int *eof) { pos = Clamp(pos, (Int)0, buffer->len); Int line = PosToLine(buffer, pos); Range range = GetLineRange(buffer, line, eof); return range.max; } -Int GetBufferEnd(Buffer *buffer) { +API Int GetBufferEnd(Buffer *buffer) { return buffer->len; } -Int GetBufferStart(Buffer *buffer) { +API Int GetBufferStart(Buffer *buffer) { return 0; } -Int GetNextEmptyLineStart(Buffer *buffer, Int pos) { +API Int GetNextEmptyLineStart(Buffer *buffer, Int pos) { Int result = pos; Int next_line = PosToLine(buffer, pos) + 1; for (Int line = next_line; line < buffer->line_starts.len; line += 1) { @@ -438,7 +417,7 @@ Int GetNextEmptyLineStart(Buffer *buffer, Int pos) { return result; } -Int GetPrevEmptyLineStart(Buffer *buffer, Int pos) { +API Int GetPrevEmptyLineStart(Buffer *buffer, Int pos) { Int result = pos; Int next_line = PosToLine(buffer, pos) - 1; for (Int line = next_line; line >= 0; line -= 1) { @@ -457,12 +436,12 @@ Int GetPrevEmptyLineStart(Buffer *buffer, Int pos) { return result; } -Range EncloseWord(Buffer *buffer, Int pos) { +API Range EncloseWord(Buffer *buffer, Int pos) { Range result = {GetWordStart(buffer, pos), GetWordEnd(buffer, pos)}; return result; } -Int SkipSpaces(Buffer *buffer, Int seek) { +API Int SkipSpaces(Buffer *buffer, Int seek) { for (; seek < buffer->len; seek += 1) { char16_t c = GetChar(buffer, seek); if (c != u' ') break; @@ -470,7 +449,7 @@ Int SkipSpaces(Buffer *buffer, Int seek) { return seek; } -Int FindScopeEnd(Buffer *buffer, Int seek, Int max_seek, char16_t open, char16_t close) { +API Int FindScopeEnd(Buffer *buffer, Int seek, Int max_seek, char16_t open, char16_t close) { char16_t right = GetChar(buffer, seek); if (right == open) { int scope = 1; @@ -496,7 +475,7 @@ Int FindScopeEnd(Buffer *buffer, Int seek, Int max_seek, char16_t open, char16_t return seek; } -Range EncloseScope(Buffer *buffer, Int pos_min, Int pos_max, char16_t open, char16_t close) { +API Range EncloseScope(Buffer *buffer, Int pos_min, Int pos_max, char16_t open, char16_t close) { Range result = {pos_min, pos_max}; for (Int i = pos_min - 1; i >= 0; i -= 1) { if (buffer->str[i] == open) { @@ -513,33 +492,33 @@ Range EncloseScope(Buffer *buffer, Int pos_min, Int pos_max, char16_t open, char return result; } -Range EncloseLine(Buffer *buffer, Int pos) { +API Range EncloseLine(Buffer *buffer, Int pos) { Range result = {GetLineStart(buffer, pos), GetLineEnd(buffer, pos)}; return result; } -Range EncloseFullLine(Buffer *buffer, Int pos) { +API Range EncloseFullLine(Buffer *buffer, Int pos) { Range result = {GetFullLineStart(buffer, pos), GetFullLineEnd(buffer, pos)}; return result; } -Int OffsetByLine(Buffer *buffer, Int pos, Int line_offset) { +API Int OffsetByLine(Buffer *buffer, Int pos, Int line_offset) { XY xy = PosToXY(buffer, pos); Int result = XYToPosWithoutNL(buffer, {xy.col, xy.line + line_offset}); return result; } -Int GetNextChar(Buffer *buffer, Int pos) { +API Int GetNextChar(Buffer *buffer, Int pos) { Int result = Clamp(pos + 1, (Int)0, buffer->len); return result; } -Int GetPrevChar(Buffer *buffer, Int pos) { +API Int GetPrevChar(Buffer *buffer, Int pos) { Int result = Clamp(pos - 1, (Int)0, buffer->len); return result; } -Int GetLineIndent(Buffer *buffer, Int line) { +API Int GetLineIndent(Buffer *buffer, Int line) { String16 string = GetLineStringWithoutNL(buffer, line); Int indent = 0; for (Int i = 0; i < string.len; i += 1) { @@ -552,23 +531,22 @@ Int GetLineIndent(Buffer *buffer, Int line) { return indent; } -Int GetIndentAtPos(Buffer *buffer, Int pos) { +API Int GetIndentAtPos(Buffer *buffer, Int pos) { Int line = PosToLine(buffer, pos); Int result = GetLineIndent(buffer, line); return result; } -Range GetIndentRangeAtPos(Buffer *buffer, Int pos) { +API Range GetIndentRangeAtPos(Buffer *buffer, Int pos) { Int line = PosToLine(buffer, pos); Int indent = GetLineIndent(buffer, line); Range range = GetLineRangeWithoutNL(buffer, line); return {range.min, range.min + indent}; } - -Int FuzzyCloserWordBegin = 5; -Int FuzzyConsecutiveMultiplier = 3; -Int FuzzyRate(String16 string, String16 with) { +const Int FuzzyCloserWordBegin = 5; +const Int FuzzyConsecutiveMultiplier = 3; +API Int FuzzyRate(String16 string, String16 with) { if (with.len == 0) return 0; Int points = 0; Int consecutive = 0; @@ -591,7 +569,7 @@ Int FuzzyRate(String16 string, String16 with) { return points; } -Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle) { +API Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle) { if (line_min < 0 || line_min >= buffer->line_starts.len) return {}; if (line_max < 0 || line_min > buffer->line_starts.len) return {}; Array ratings = {allocator}; @@ -615,7 +593,7 @@ Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_ return ratings; } -Int FindRangeByPos(Array *ranges, Int pos) { +API Int FindRangeByPos(Array *ranges, Int pos) { // binary search Int low = 0; Int high = ranges->len - 1; @@ -718,7 +696,7 @@ void RawValidateLineStarts(Buffer *buffer) { } } -void RawReplaceText(Buffer *buffer, Range range, String16 string) { +API void RawReplaceText(Buffer *buffer, Range range, String16 string) { ProfileFunction(); Assert(range.max >= range.min); Assert(range.max >= 0 && range.max <= buffer->len); @@ -750,20 +728,20 @@ void RawReplaceText(Buffer *buffer, Range range, String16 string) { #endif } -void RawAppend(Buffer *buffer, String16 string) { - RawReplaceText(buffer, GetEndAsRange(buffer), string); +API void RawAppend(Buffer *buffer, String16 string) { + RawReplaceText(buffer, GetBufferEndAsRange(buffer), string); } -void RawAppend(Buffer *buffer, String string) { +API void RawAppend(Buffer *buffer, String string) { Scratch scratch(buffer->line_starts.allocator); RawAppend(buffer, ToString16(scratch, string)); } -void RawAppendf(Buffer *buffer, const char *fmt, ...) { +API void RawAppendf(Buffer *buffer, const char *fmt, ...) { Scratch scratch(buffer->line_starts.allocator); STRING_FORMAT(scratch, fmt, string); String16 string16 = ToString16(scratch, string); - RawReplaceText(buffer, GetEndAsRange(buffer), string16); + RawReplaceText(buffer, GetBufferEndAsRange(buffer), string16); } /////////////////////////////// @@ -880,7 +858,7 @@ void MergeSort(int64_t Count, Edit *First, Edit *Temp) { } } -void ApplyEditsMultiCursor(Buffer *buffer, Array edits) { +API void ApplyEditsMultiCursor(Buffer *buffer, Array edits) { ProfileFunction(); #if BUFFER_DEBUG Assert(buffer->line_starts.len); @@ -930,7 +908,7 @@ void ApplyEditsMultiCursor(Buffer *buffer, Array edits) { } } -void AddEdit(Array *e, Range range, String16 string) { +API void AddEdit(Array *e, Range range, String16 string) { Add(e, {range, string}); } @@ -980,7 +958,7 @@ void SaveHistoryBeforeApplyEdits(Buffer *buffer, Array *stack, Arr } } -void RedoEdit(Buffer *buffer, Array *carets) { +API void RedoEdit(Buffer *buffer, Array *carets) { ProfileFunction(); if (buffer->no_history) return; if (buffer->redo_stack.len <= 0) return; @@ -999,7 +977,7 @@ void RedoEdit(Buffer *buffer, Array *carets) { Dealloc(&entry.edits); } -void UndoEdit(Buffer *buffer, Array *carets) { +API void UndoEdit(Buffer *buffer, Array *carets) { ProfileFunction(); if (buffer->no_history) return; if (buffer->undo_stack.len <= 0) return; @@ -1018,7 +996,7 @@ void UndoEdit(Buffer *buffer, Array *carets) { Dealloc(&entry.edits); } -void DeallocHistoryEntries(Array *entries) { +API void DeallocHistoryEntries(Array *entries) { For(*entries) { Dealloc(&it.carets); ForItem(edit, it.edits) Dealloc(it.edits.allocator, &edit.string.data); @@ -1031,15 +1009,12 @@ void ClearRedoStack(Buffer *buffer) { DeallocHistoryEntries(&buffer->redo_stack); } -void DeallocHistoryArray(Array *entries) { +API void DeallocHistoryArray(Array *entries) { DeallocHistoryEntries(entries); Dealloc(entries); } -// @note: !! -// We can invoke this before caret altering commands to save caret history -// and then call some editing command to edit which is not going to save carets -Array BeginEdit(Allocator allocator, Buffer *buffer, Array &carets) { +API Array BeginEdit(Allocator allocator, Buffer *buffer, Array &carets) { Assert(buffer->edit_phase == 0 || buffer->edit_phase == 1); if (buffer->edit_phase == 0) { buffer->edit_phase += 1; @@ -1051,17 +1026,17 @@ Array BeginEdit(Allocator allocator, Buffer *buffer, Array &carets) return result; } -void SaveCaretHistoryBeforeBeginEdit(Buffer *buffer, Array &carets) { +API void SaveCaretHistoryBeforeBeginEdit(Buffer *buffer, Array &carets) { BeginEdit({}, buffer, carets); } -void AssertRanges(Array carets) { +API void AssertRanges(Array carets) { For(carets) { Assert(it.range.max >= it.range.min); } } -void AdjustCarets(Array edits, Array *carets) { +API void AdjustCarets(Array edits, Array *carets) { Scratch scratch; Array new_carets = TightCopy(scratch, *carets); ForItem(edit, edits) { @@ -1083,7 +1058,7 @@ void AdjustCarets(Array edits, Array *carets) { for (Int i = 0; i < carets->len; i += 1) carets->data[i] = new_carets[i]; } -void EndEdit(Buffer *buffer, Array *edits, Array *carets, bool kill_selection) { +API void EndEdit(Buffer *buffer, Array *edits, Array *carets, bool kill_selection) { ProfileFunction(); { @@ -1151,12 +1126,11 @@ void EndEdit(Buffer *buffer, Array *edits, Array *carets, bool kill } } - // Merge carets that overlap, this needs to be handled before any edits to // make sure overlapping edits won't happen. // // mouse_selection_anchor is special case for mouse handling ! -void MergeCarets(Buffer *buffer, Array *carets) { +API void MergeCarets(Buffer *buffer, Array *carets) { ProfileFunction(); For(*carets) it.range = Clamp(buffer, it.range); Caret first_caret = carets->data[0]; @@ -1182,4 +1156,201 @@ void MergeCarets(Buffer *buffer, Array *carets) { } Swap(&carets->data[first_caret_index], &carets->data[0]); +} + +API void InitBuffer(Allocator allocator, Buffer *buffer, BufferID id = {}, String name = "", Int size = 4096) { + buffer->id = id; + buffer->name = name; + buffer->cap = size; + buffer->data = AllocArray(allocator, U16, buffer->cap); + buffer->line_starts.allocator = allocator; + buffer->undo_stack.allocator = allocator; + buffer->redo_stack.allocator = allocator; + if (!buffer->no_line_starts) { + Add(&buffer->line_starts, (Int)0); + } +} + +API void DeinitBuffer(Buffer *buffer) { + Assert(buffer->next == NULL); + Assert(buffer->prev == NULL); + Allocator allocator = buffer->line_starts.allocator; + Dealloc(allocator, &buffer->data); + Dealloc(&buffer->line_starts); + DeallocHistoryArray(&buffer->undo_stack); + DeallocHistoryArray(&buffer->redo_stack); +} + +void TestBuffer() { + Scratch scratch; + { + Buffer buffer = {}; + InitBuffer(scratch, &buffer); + Assert(buffer.line_starts.len == 1); + String16 test_string = u"Thing itself"; + { + RawReplaceText(&buffer, {}, test_string); + Assert(buffer.cap == 4096); + Assert(buffer.len == 12); + String16 a = GetString(&buffer); + Assert(a == test_string); + Assert(buffer.line_starts.len == 1); + Assert(buffer.line_starts[0] == 0); + Assert(PosToLine(&buffer, 4) == 0); + } + { + RawReplaceText(&buffer, {0, 5}, u""); + Assert(buffer.cap == 4096); + Assert(buffer.len == 12 - 5); + String16 a = GetString(&buffer); + Assert(a == u" itself"); + Assert(buffer.line_starts.len == 1); + Assert(buffer.line_starts[0] == 0); + Assert(PosToLine(&buffer, 4) == 0); + } + { + RawReplaceText(&buffer, GetBufferEndAsRange(&buffer), u" and"); + Assert(buffer.cap == 4096); + Assert(buffer.len == 12 - 5 + 4); + String16 a = GetString(&buffer); + Assert(a == u" itself and"); + Assert(buffer.line_starts.len == 1); + Assert(buffer.line_starts[0] == 0); + Assert(PosToLine(&buffer, 4) == 0); + } + { + RawReplaceText(&buffer, GetRange(&buffer), u""); + Assert(buffer.cap == 4096); + Assert(buffer.len == 0); + String16 a = GetString(&buffer); + Assert(a == u""); + Assert(buffer.line_starts.len == 1); + Assert(buffer.line_starts[0] == 0); + } + { + RawReplaceText(&buffer, GetBufferEndAsRange(&buffer), u"Memes and other\nthings"); + Assert(buffer.line_starts.len == 2); + Assert(PosToLine(&buffer, 17) == 1); + Assert(PosToLine(&buffer, 16) == 1); + Assert(PosToLine(&buffer, 15) == 0); + Assert(buffer.data[15] == L'\n'); + Assert(buffer.data[16] == L't'); + + RawReplaceText(&buffer, GetBufferBeginAsRange(&buffer), u"Things as is\nand stuff\n"); + Assert(buffer.line_starts.len == 4); + Assert(PosToLine(&buffer, 12) == 0); + Assert(buffer.data[12] == L'\n'); + Assert(PosToLine(&buffer, 13) == 1); + Assert(PosToLine(&buffer, 21) == 1); + Assert(PosToLine(&buffer, 22) == 1); + Assert(buffer.data[22] == L'\n'); + Assert(PosToLine(&buffer, 23) == 2); + Assert(PosToLine(&buffer, 37) == 2); + Assert(PosToLine(&buffer, 38) == 2); + Assert(buffer.data[38] == L'\n'); + Assert(PosToLine(&buffer, 39) == 3); + Assert(buffer.data[39] == L't'); + + RawReplaceText(&buffer, GetBufferBeginAsRange(&buffer), u"a"); + Assert(buffer.line_starts.len == 4); + Assert(PosToLine(&buffer, 13) == 0); + Assert(PosToLine(&buffer, 14) == 1); + } + } + + { + Buffer buffer = {}; + InitBuffer(scratch, &buffer); + RawReplaceText(&buffer, {}, u"Thing\nmeme"); + Assert(PosToLine(&buffer, 5) == 0); + Assert(PosToLine(&buffer, 6) == 1); + RawReplaceText(&buffer, {0, 1}, u""); + Assert(PosToLine(&buffer, 4) == 0); + Assert(PosToLine(&buffer, 5) == 1); + RawReplaceText(&buffer, {4, 5}, u""); + Assert(buffer.line_starts.len == 1); + RawValidateLineStarts(&buffer); + } + + { + Buffer buffer = {}; + InitBuffer(scratch, &buffer); + RawReplaceText(&buffer, {}, u"Thing\nmeme"); + RawReplaceText(&buffer, {0, 5}, u"per\ncop"); + Assert(buffer.line_starts.len == (Int)3); + Assert(PosToLine(&buffer, 3) == 0); + Assert(PosToLine(&buffer, 4) == 1); + RawValidateLineStarts(&buffer); + + RawReplaceText(&buffer, {0, 8}, u"Thing\nmeme"); + RawReplaceText(&buffer, {0, 3}, u"Thing\nmeme"); + RawReplaceText(&buffer, {9, 13}, u"Thing\nmeme"); + RawReplaceText(&buffer, {4, 5}, u"Thing\nmeme\n\n\n"); + RawReplaceText(&buffer, {22, 23}, u"\n\n\nThing\nmeme\n\n\n"); + RawReplaceText(&buffer, {22, 23}, u"\n\n\nThing\nmeme\n\n\n"); + RawReplaceText(&buffer, {22, 23}, u"\n\n\nThing\nmeme\n\n\n"); + RawReplaceText(&buffer, {22, 23}, u"\n\n\nThing\nmeme\n\n\n"); + RawValidateLineStarts(&buffer); + } + + { + Buffer buffer = {}; + InitBuffer(GetTrackingAllocator(), &buffer); + RawReplaceText(&buffer, {}, u"Thing\nmeme"); + RawReplaceText(&buffer, GetBufferEndAsRange(&buffer), u"\nnewThing"); + DeinitBuffer(&buffer); + TrackingAllocatorCheck(); + } + + // + { + Buffer buffer = {}; + InitBuffer(GetTrackingAllocator(), &buffer); + RawReplaceText(&buffer, {}, u"Testing\nthings"); + Array carets = {scratch}; + Add(&carets, MakeCaret(0,7)); + Add(&carets, MakeCaret(8,9)); + Add(&carets, MakeCaret(GetBufferEnd(&buffer))); + Array edits = BeginEdit(scratch, &buffer, carets); + MergeCarets(&buffer, &carets); + AddEdit(&edits, {0, 7}, u"t"); + AddEdit(&edits, {8, 9}, u"T"); + AddEdit(&edits, GetBufferEndAsRange(&buffer), u"\nnewThing"); + EndEdit(&buffer, &edits, &carets, KILL_SELECTION); + String16 s = GetString(&buffer); + Assert(s == u"t\nThings\nnewThing"); + DeinitBuffer(&buffer); + TrackingAllocatorCheck(); + } + + // Make sure no_history and no line_starts properly makes sure of these + { + Buffer buffer = {}; + buffer.no_history = true; + buffer.no_line_starts = true; + InitBuffer(GetTrackingAllocator(), &buffer); + RawReplaceText(&buffer, {}, u"Testing\nthings"); + Array carets = {scratch}; + Add(&carets, MakeCaret(0,7)); + Add(&carets, MakeCaret(8,9)); + Add(&carets, MakeCaret(GetBufferEnd(&buffer))); + Array edits = BeginEdit(scratch, &buffer, carets); + MergeCarets(&buffer, &carets); + AddEdit(&edits, {0, 7}, u"t"); + AddEdit(&edits, {8, 9}, u"T"); + AddEdit(&edits, GetBufferEndAsRange(&buffer), u"\nnewThing"); + EndEdit(&buffer, &edits, &carets, KILL_SELECTION); + String16 s = GetString(&buffer); + Assert(s == u"t\nThings\nnewThing"); + Assert(buffer.line_starts.len == 0); + Assert(buffer.line_starts.data == 0); + Assert(buffer.redo_stack.len == 0); + Assert(buffer.redo_stack.data == 0); + Assert(buffer.undo_stack.len == 0); + Assert(buffer.undo_stack.data == 0); + DeinitBuffer(&buffer); + TrackingAllocatorCheck(); + } + + } \ No newline at end of file diff --git a/src/text_editor/buffer.h b/src/text_editor/buffer.h index 04ae69d..6e50466 100644 --- a/src/text_editor/buffer.h +++ b/src/text_editor/buffer.h @@ -17,7 +17,7 @@ struct HistoryEntry { struct Buffer { BufferID id; Buffer *next; - Buffer *prev; + Buffer *prev; String name; Int change_id; Int user_change_id; @@ -51,30 +51,113 @@ struct FuzzyPair { enum { KILL_SELECTION = 1, }; +constexpr Int LAST_LINE = INT64_MAX; -void SaveCaretHistoryBeforeBeginEdit(Buffer *buffer, Array &carets); -Array BeginEdit(Allocator allocator, Buffer *buffer, Array &carets); -void EndEdit(Buffer *buffer, Array *edits, Array *carets, bool kill_selection); -void AddEdit(Array *e, Range range, String16 string); +// @todo: buffer init, deinit +API Range MakeRange(Int a, Int b); +API Range MakeRange(Int a); +API Int GetSize(Range range); +API bool AreEqual(Range a, Range b); +API bool AreOverlapping(Range a, Range b); +API bool InBounds(Range range, Int pos); +API Range operator-(Range a, Int value); +API Range operator-=(Range &range, Int value); +API Range operator+(Range a, Int value); +API Range operator+=(Range &range, Int value); +API Range GetBufferEndAsRange(Buffer *buffer); +API Range GetBufferBeginAsRange(Buffer *buffer); +API Range GetRange(Buffer *buffer); +API Int Clamp(const Buffer *buffer, Int pos); +API Range Clamp(const Buffer *buffer, Range range); + +API Int GetFront(Caret caret); +API Int GetBack(Caret caret); +API Caret MakeCaret(Int pos); +API Caret MakeCaret(Int front, Int back); +API Caret SetBack(Caret caret, Int back); +API Caret SetFront(Caret caret, Int front); +API Caret SetFrontWithAnchor(Caret caret, Caret anchor, Int p); +API bool AreEqual(Caret a, Caret b); +API bool AreOverlapping(Caret a, Caret b); + +API Range GetLineRange(Buffer *buffer, Int line, Int *end_of_buffer = NULL); +API Range GetLineRangeWithoutNL(Buffer *buffer, Int line); +API String16 GetString(Buffer *buffer, Range range = {0, INT64_MAX}); +API String AllocCharString(Allocator allocator, Buffer *buffer, Range range = {0, INT64_MAX}); +API String16 GetLineString(Buffer *buffer, Int line, Int *end_of_buffer = NULL); +API String16 GetLineStringWithoutNL(Buffer *buffer, Int line); + +API XY XYLine(Int line); +API Int LastLine(Buffer *buffer); +API Int PosToLine(Buffer *buffer, Int pos); +API XY PosToXY(Buffer *buffer, Int pos); +API Int XYToPos(Buffer *buffer, XY xy); +API Int XYToPosWithoutNL(Buffer *buffer, XY xy); +API Int XYToPosErrorOutOfBounds(Buffer *buffer, XY xy); + +API char16_t GetChar(Buffer *buffer, Int pos); +API bool InBounds(const Buffer *buffer, Int pos); +API Int GetWordStart(Buffer *buffer, Int pos); +API Int GetWordEnd(Buffer *buffer, Int pos); +API bool IsLoadWord(char16_t w); +API Int GetLoadWordStart(Buffer *buffer, Int pos); +API Int GetLoadWordEnd(Buffer *buffer, Int pos); +API Range EncloseLoadWord(Buffer *buffer, Int pos); +API Int GetNextWordEnd(Buffer *buffer, Int pos); +API Int GetPrevWordStart(Buffer *buffer, Int pos); +API Int GetLineStart(Buffer *buffer, Int pos); +API Int GetLineEnd(Buffer *buffer, Int pos); +API Int GetFullLineStart(Buffer *buffer, Int pos); +API Int GetFullLineEnd(Buffer *buffer, Int pos, Int *eof = NULL); +API Int GetBufferEnd(Buffer *buffer); +API Int GetBufferStart(Buffer *buffer); +API Int GetNextEmptyLineStart(Buffer *buffer, Int pos); +API Int GetPrevEmptyLineStart(Buffer *buffer, Int pos); +API Range EncloseWord(Buffer *buffer, Int pos); +API Int SkipSpaces(Buffer *buffer, Int seek); +API Int FindScopeEnd(Buffer *buffer, Int seek, Int max_seek, char16_t open, char16_t close); +API Range EncloseScope(Buffer *buffer, Int pos_min, Int pos_max, char16_t open, char16_t close); +API Range EncloseLine(Buffer *buffer, Int pos); +API Range EncloseFullLine(Buffer *buffer, Int pos); +API Int OffsetByLine(Buffer *buffer, Int pos, Int line_offset); +API Int GetNextChar(Buffer *buffer, Int pos); +API Int GetPrevChar(Buffer *buffer, Int pos); +API Int GetLineIndent(Buffer *buffer, Int line); +API Int GetIndentAtPos(Buffer *buffer, Int pos); +API Range GetIndentRangeAtPos(Buffer *buffer, Int pos); + +API Int FuzzyRate(String16 string, String16 with); +API Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle); +API Int FindRangeByPos(Array *ranges, Int pos); + +// These don't handle history, just raw operations on buffer memory +API void RawReplaceText(Buffer *buffer, Range range, String16 string); +API void RawAppend(Buffer *buffer, String16 string); +API void RawAppend(Buffer *buffer, String string); +API void RawAppendf(Buffer *buffer, const char *fmt, ...); + +// We can invoke SaveCaretHistoryBeforeBeginEdit(which is basically BeginEdit with +// different name before caret altering commands to save caret history +// and then call some editing command to edit which is not going to save carets +API void SaveCaretHistoryBeforeBeginEdit(Buffer *buffer, Array &carets); +API Array BeginEdit(Allocator allocator, Buffer *buffer, Array &carets); +API void EndEdit(Buffer *buffer, Array *edits, Array *carets, bool kill_selection); +API void AddEdit(Array *e, Range range, String16 string); // Merge carets that overlap, this needs to be handled before any edits to // make sure overlapping edits won't happen. // // mouse_selection_anchor is special case for mouse handling ! -void MergeCarets(Buffer *buffer, Array *carets); +API void MergeCarets(Buffer *buffer, Array *carets); // Adjusts caret copies after edit to make them not move after for example // a bar modification. Sometimes works, sometimes doesn't, depends, not an all solving tool. // For example in case of ReopenBuffer, when we select and replace entire buffer, it didn't quite work. -void AdjustCarets(Array edits, Array *carets); +API void AdjustCarets(Array edits, Array *carets); +API void AssertRanges(Array carets); -void RedoEdit(Buffer *buffer, Array *carets); -void UndoEdit(Buffer *buffer, Array *carets); +API void RedoEdit(Buffer *buffer, Array *carets); +API void UndoEdit(Buffer *buffer, Array *carets); -// Raw buffer operations -void RawReplaceText(Buffer *buffer, Range range, String16 string); -void RawAppend(Buffer *buffer, String16 string); -void RawAppend(Buffer *buffer, String string); -void RawAppendf(Buffer *buffer, const char *fmt, ...); - -// @todo: buffer init, deinit \ No newline at end of file +API void DeallocHistoryArray(Array *entries); +API void DeallocHistoryEntries(Array *entries); \ No newline at end of file diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index af42ed2..5832480 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -174,12 +174,12 @@ void Command_Append(View *view, String16 string, bool scroll_to_end_if_cursor_on Add(&view_info, vi); } - Command_SelectRangeOneCursor(view, GetEndAsRange(buffer)); + Command_SelectRangeOneCursor(view, GetBufferEndAsRange(buffer)); Command_Replace(view, string); For (view_info) { if (it.scroll_to_end) { - it.view->carets[0] = MakeCaret(GetEndAsRange(buffer).min); + it.view->carets[0] = MakeCaret(GetBufferEndAsRange(buffer).min); } else { Dealloc(&it.view->carets); it.view->carets = it.carets; @@ -204,8 +204,10 @@ void ReportErrorf(const char *fmt, ...) { STRING_FORMAT(scratch, fmt, string); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error!", string.data, NULL); View *view = GetView(NullViewID); - Command_Appendf(view, "%S\n", string); - ActiveWindow = NullWindowID; + if (view) { + Command_Appendf(view, "%S\n", string); + ActiveWindow = NullWindowID; + } } void ReportConsolef(const char *fmt, ...) { @@ -427,9 +429,9 @@ void Command_MoveLine(View *view, int direction) { AddEdit(&edits, lines_to_move_range, {}); if (direction == DIR_DOWN) { - AddEdit(&edits, Rng(next_line_end), string); + AddEdit(&edits, MakeRange(next_line_end), string); } else { - AddEdit(&edits, Rng(prev_line_start), string); + AddEdit(&edits, MakeRange(prev_line_start), string); } Add(&saved_xy, {PosToXY(buffer, GetFront(it)), PosToXY(buffer, GetBack(it))}); @@ -481,7 +483,7 @@ void Command_DuplicateLine(View *view, int direction) { String16 string = Copy16(scratch, GetString(buffer, range)); Int pos = direction == DIR_UP ? range.min : range.max; - AddEdit(&edits, Rng(pos), string); + AddEdit(&edits, MakeRange(pos), string); } EndEdit(buffer, &edits, &view->carets, !KILL_SELECTION); @@ -945,13 +947,13 @@ void Command_FuzzySort(View *view, String16 needle) { For(ratings) { String16 s = GetLineStringWithoutNL(buffer, it.index); if (s.len == 0) continue; - RawReplaceText(temp_buffer, GetEndAsRange(temp_buffer), s); - RawReplaceText(temp_buffer, GetEndAsRange(temp_buffer), u"\n"); + RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), s); + RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), u"\n"); } Command_SelectEntireBuffer(view); Command_Replace(view, GetString(temp_buffer)); - Command_SelectRangeOneCursor(view, Rng(0)); + Command_SelectRangeOneCursor(view, MakeRange(0)); } void ReopenBuffer(Buffer *buffer) { @@ -1081,7 +1083,7 @@ void Command_ListCode(String dir = WorkDir) { ListFilesRecursive(main.buffer, dir); main.view->fuzzy_search = true; main.view->update_scroll = true; - Command_SelectRangeOneCursor(main.view, GetEndAsRange(main.buffer)); + Command_SelectRangeOneCursor(main.view, GetBufferEndAsRange(main.buffer)); } int Lua_ListCode(lua_State *L) { @@ -1205,7 +1207,7 @@ int Lua_Cmd(lua_State *L) { BSet set = GetConsoleSet(); main.window->active_goto_list = set.view->id; main.window->goto_list_pos = set.buffer->len; - Command_SelectRangeOneCursor(set.view, Rng(set.buffer->len)); + Command_SelectRangeOneCursor(set.view, MakeRange(set.buffer->len)); Command_BeginJump(&set); Exec(set.view->id, true, cmd, working_dir); Command_EndJump(set); @@ -1234,7 +1236,7 @@ void Command_ListBuffers() { } main.view->fuzzy_search = true; main.view->update_scroll = true; - Command_SelectRangeOneCursor(main.view, GetEndAsRange(main.buffer)); + Command_SelectRangeOneCursor(main.view, GetBufferEndAsRange(main.buffer)); } int Lua_ListBuffers(lua_State *L) { diff --git a/src/text_editor/commands_bindings.cpp b/src/text_editor/commands_bindings.cpp index 7df33b6..2452bf8 100644 --- a/src/text_editor/commands_bindings.cpp +++ b/src/text_editor/commands_bindings.cpp @@ -431,7 +431,7 @@ void OnCommand(Event event) { if (ShiftPress(SDLK_PAGEUP)) { Command_MoveCursorsByPageSize(active.window, DIR_UP, SHIFT_PRESS); } else if (CtrlPress(SDLK_PAGEUP)) { - Command_SelectRangeOneCursor(active.view, Rng(0)); + Command_SelectRangeOneCursor(active.view, MakeRange(0)); } else if (Press(SDLK_PAGEUP)) { Command_MoveCursorsByPageSize(active.window, DIR_UP); } @@ -439,7 +439,7 @@ void OnCommand(Event event) { if (ShiftPress(SDLK_PAGEDOWN)) { Command_MoveCursorsByPageSize(active.window, DIR_DOWN, SHIFT_PRESS); } else if (CtrlPress(SDLK_PAGEDOWN)) { - Command_SelectRangeOneCursor(active.view, Rng(active.buffer->len)); + Command_SelectRangeOneCursor(active.view, MakeRange(active.buffer->len)); } else if (Press(SDLK_PAGEDOWN)) { Command_MoveCursorsByPageSize(active.window, DIR_DOWN); } @@ -575,10 +575,10 @@ void OnCommand(Event event) { For(IterateInReverse(&ratings)) { String16 s = GetLineStringWithoutNL(active.buffer, it.index); if (s.len == 0) continue; - RawReplaceText(temp_buffer, GetEndAsRange(temp_buffer), s); - RawReplaceText(temp_buffer, GetEndAsRange(temp_buffer), u"\n"); + RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), s); + RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), u"\n"); } - RawReplaceText(temp_buffer, GetEndAsRange(temp_buffer), last_line_string); + RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), last_line_string); Caret caret = active.view->carets[0]; Command_SelectEntireBuffer(active.view); diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index b939877..4289c17 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -390,6 +390,12 @@ int main(int argc, char **argv) BeginProfiler(); InitScratch(); + if (1) { + TestBuffer(); + ReportErrorf("Testing DONE\n"); + return 0; + } + #if !OS_WINDOWS for (int i = 0; environ[i]; i += 1) { Add(&Enviroment, Copy(GetSystemAllocator(), environ[i])); diff --git a/src/text_editor/title_bar.cpp b/src/text_editor/title_bar.cpp index aa37ed9..e553cea 100644 --- a/src/text_editor/title_bar.cpp +++ b/src/text_editor/title_bar.cpp @@ -107,7 +107,7 @@ void ReplaceTitleBarData(Window *window) { // add separator at the end of buffer if (!found_separator) { - Command_SelectRangeOneCursor(title.view, GetEndAsRange(title.buffer)); + Command_SelectRangeOneCursor(title.view, GetBufferEndAsRange(title.buffer)); Array edits = Command_ReplaceEx(scratch, title.view, u" |"); AdjustCarets(edits, &caret_copy); } @@ -127,7 +127,7 @@ void ReplaceTitleBarData(Window *window) { if (string_to_replace != string) { Command_SelectRangeOneCursor(title.view, replace_range); Array edits = Command_ReplaceEx(scratch, title.view, string); - Command_SelectRangeOneCursor(title.view, Rng(0)); + Command_SelectRangeOneCursor(title.view, MakeRange(0)); AdjustCarets(edits, &caret_copy); } } \ No newline at end of file diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index d794cc5..7224f4a 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -112,13 +112,13 @@ bool ToggleVisibility(WindowID window_id) { void LoadBigText(Buffer *buffer, int size = 5000000) { for (int i = 0; i < size; i += 1) { - RawReplaceText(buffer, GetEndAsRange(buffer), u"Line number or something of the sort which is here or there or maybe somewhere else\n"); + RawReplaceText(buffer, GetBufferEndAsRange(buffer), u"Line number or something of the sort which is here or there or maybe somewhere else\n"); } } void LoadBigLine(Buffer *buffer, int size = 5000000) { for (int i = 0; i < size; i += 1) { - RawReplaceText(buffer, GetEndAsRange(buffer), u"Line number or something of the sort which is here or there or maybe somewhere else | "); + RawReplaceText(buffer, GetBufferEndAsRange(buffer), u"Line number or something of the sort which is here or there or maybe somewhere else | "); } } @@ -132,7 +132,7 @@ void LoadTextA(Buffer *buffer) { for (int i = 0; i < 1000; i += 1) { String s = Format(scratch, "line1: %d line2: %d line3: %d line4: %d line5: %d line6: %d line1: %d line2: %d line3: %d line4: %d line5: %d line6: %d\r\n", i, i, i, i, i, i, i, i, i, i, i, i); String16 s16 = ToString16(scratch, s); - RawReplaceText(buffer, GetEndAsRange(buffer), s16); + RawReplaceText(buffer, GetBufferEndAsRange(buffer), s16); } } @@ -152,7 +152,7 @@ https://www.lua.org/manual/5.4/ Scratch scratch; RawReplaceText(buffer, {}, ToString16(scratch, text)); - // RawReplaceText(buffer, GetEndAsRange(buffer), ToString16(scratch, text)); + // RawReplaceText(buffer, GetBufferEndAsRange(buffer), ToString16(scratch, text)); } void InitWindows() {