Tracking allocator, buffer tests

This commit is contained in:
Krzosa Karol
2025-11-28 09:59:09 +01:00
parent d72485a137
commit c19c60fe22
10 changed files with 535 additions and 225 deletions

View File

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

View File

@@ -20,7 +20,9 @@ Things I like:
- Configurable Open
- Lua config files work pretty well
Splits:
- Buffer16.cpp / h
- Block arena and refactor alloc

View File

@@ -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;
}
@@ -246,3 +248,46 @@ Allocator GetSystemAllocator() {
Allocator result = {SystemAllocator_Alloc};
return result;
}
struct MemoryRecord {
size_t size;
void *addr;
bool deallocated;
};
Array<MemoryRecord> 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;
}

View File

@@ -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<FuzzyPair> FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle) {
API Array<FuzzyPair> 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<FuzzyPair> ratings = {allocator};
@@ -615,7 +593,7 @@ Array<FuzzyPair> FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_
return ratings;
}
Int FindRangeByPos(Array<Range> *ranges, Int pos) {
API Int FindRangeByPos(Array<Range> *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<Edit> edits) {
API void ApplyEditsMultiCursor(Buffer *buffer, Array<Edit> edits) {
ProfileFunction();
#if BUFFER_DEBUG
Assert(buffer->line_starts.len);
@@ -930,7 +908,7 @@ void ApplyEditsMultiCursor(Buffer *buffer, Array<Edit> edits) {
}
}
void AddEdit(Array<Edit> *e, Range range, String16 string) {
API void AddEdit(Array<Edit> *e, Range range, String16 string) {
Add(e, {range, string});
}
@@ -980,7 +958,7 @@ void SaveHistoryBeforeApplyEdits(Buffer *buffer, Array<HistoryEntry> *stack, Arr
}
}
void RedoEdit(Buffer *buffer, Array<Caret> *carets) {
API void RedoEdit(Buffer *buffer, Array<Caret> *carets) {
ProfileFunction();
if (buffer->no_history) return;
if (buffer->redo_stack.len <= 0) return;
@@ -999,7 +977,7 @@ void RedoEdit(Buffer *buffer, Array<Caret> *carets) {
Dealloc(&entry.edits);
}
void UndoEdit(Buffer *buffer, Array<Caret> *carets) {
API void UndoEdit(Buffer *buffer, Array<Caret> *carets) {
ProfileFunction();
if (buffer->no_history) return;
if (buffer->undo_stack.len <= 0) return;
@@ -1018,7 +996,7 @@ void UndoEdit(Buffer *buffer, Array<Caret> *carets) {
Dealloc(&entry.edits);
}
void DeallocHistoryEntries(Array<HistoryEntry> *entries) {
API void DeallocHistoryEntries(Array<HistoryEntry> *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<HistoryEntry> *entries) {
API void DeallocHistoryArray(Array<HistoryEntry> *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<Edit> BeginEdit(Allocator allocator, Buffer *buffer, Array<Caret> &carets) {
API Array<Edit> BeginEdit(Allocator allocator, Buffer *buffer, Array<Caret> &carets) {
Assert(buffer->edit_phase == 0 || buffer->edit_phase == 1);
if (buffer->edit_phase == 0) {
buffer->edit_phase += 1;
@@ -1051,17 +1026,17 @@ Array<Edit> BeginEdit(Allocator allocator, Buffer *buffer, Array<Caret> &carets)
return result;
}
void SaveCaretHistoryBeforeBeginEdit(Buffer *buffer, Array<Caret> &carets) {
API void SaveCaretHistoryBeforeBeginEdit(Buffer *buffer, Array<Caret> &carets) {
BeginEdit({}, buffer, carets);
}
void AssertRanges(Array<Caret> carets) {
API void AssertRanges(Array<Caret> carets) {
For(carets) {
Assert(it.range.max >= it.range.min);
}
}
void AdjustCarets(Array<Edit> edits, Array<Caret> *carets) {
API void AdjustCarets(Array<Edit> edits, Array<Caret> *carets) {
Scratch scratch;
Array<Caret> new_carets = TightCopy(scratch, *carets);
ForItem(edit, edits) {
@@ -1083,7 +1058,7 @@ void AdjustCarets(Array<Edit> edits, Array<Caret> *carets) {
for (Int i = 0; i < carets->len; i += 1) carets->data[i] = new_carets[i];
}
void EndEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets, bool kill_selection) {
API void EndEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets, bool kill_selection) {
ProfileFunction();
{
@@ -1151,12 +1126,11 @@ void EndEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *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<Caret> *carets) {
API void MergeCarets(Buffer *buffer, Array<Caret> *carets) {
ProfileFunction();
For(*carets) it.range = Clamp(buffer, it.range);
Caret first_caret = carets->data[0];
@@ -1183,3 +1157,200 @@ void MergeCarets(Buffer *buffer, Array<Caret> *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<Caret> carets = {scratch};
Add(&carets, MakeCaret(0,7));
Add(&carets, MakeCaret(8,9));
Add(&carets, MakeCaret(GetBufferEnd(&buffer)));
Array<Edit> 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<Caret> carets = {scratch};
Add(&carets, MakeCaret(0,7));
Add(&carets, MakeCaret(8,9));
Add(&carets, MakeCaret(GetBufferEnd(&buffer)));
Array<Edit> 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();
}
}

View File

@@ -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<Caret> &carets);
Array<Edit> BeginEdit(Allocator allocator, Buffer *buffer, Array<Caret> &carets);
void EndEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets, bool kill_selection);
void AddEdit(Array<Edit> *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<FuzzyPair> FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle);
API Int FindRangeByPos(Array<Range> *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<Caret> &carets);
API Array<Edit> BeginEdit(Allocator allocator, Buffer *buffer, Array<Caret> &carets);
API void EndEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets, bool kill_selection);
API void AddEdit(Array<Edit> *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<Caret> *carets);
API void MergeCarets(Buffer *buffer, Array<Caret> *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<Edit> edits, Array<Caret> *carets);
API void AdjustCarets(Array<Edit> edits, Array<Caret> *carets);
API void AssertRanges(Array<Caret> carets);
void RedoEdit(Buffer *buffer, Array<Caret> *carets);
void UndoEdit(Buffer *buffer, Array<Caret> *carets);
API void RedoEdit(Buffer *buffer, Array<Caret> *carets);
API void UndoEdit(Buffer *buffer, Array<Caret> *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
API void DeallocHistoryArray(Array<HistoryEntry> *entries);
API void DeallocHistoryEntries(Array<HistoryEntry> *entries);

View File

@@ -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) {

View File

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

View File

@@ -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]));

View File

@@ -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<Edit> 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<Edit> edits = Command_ReplaceEx(scratch, title.view, string);
Command_SelectRangeOneCursor(title.view, Rng(0));
Command_SelectRangeOneCursor(title.view, MakeRange(0));
AdjustCarets(edits, &caret_copy);
}
}

View File

@@ -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() {