Optimizing search, buggy BlockArena on emscripten, cleanup MergeSort, address sanitizer, compile web on linux
This commit is contained in:
6
build.sh
6
build.sh
@@ -3,10 +3,12 @@
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
FLAGS="-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g -Wno-writable-strings -I../src -DDEBUG_BUILD=1"
|
||||
FLAGS="-Wall -Wno-missing-braces -Wno-writable-strings -nostdlib++ -fsanitize=address -fno-exceptions -fdiagnostics-absolute-paths -g -Wno-writable-strings -I../src -DDEBUG_BUILD=1"
|
||||
# clang -o metaprogram $FLAGS ../src/metaprogram/metaprogram.cpp
|
||||
# ./metaprogram
|
||||
|
||||
I="-I../src/external/SDL/include -I../src/external/lua/src -I../src/external/glad"
|
||||
clang -o te $FLAGS ../src/text_editor/text_editor.cpp $I -lSDL3 -lm -lbacktrace
|
||||
cp te ../data/te
|
||||
cp te ../data/te
|
||||
|
||||
# -v -Wl,--verbose
|
||||
@@ -6,10 +6,4 @@ set flags=-Wall -Wno-missing-braces -Wno-writable-strings -nostdlib++ -fno-excep
|
||||
set dbg=-g -DDEBUG_BUILD=1 -gsource-map
|
||||
set rel=-O3 -DDEBUG_BUILD=0
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
clang ../src/metaprogram/metaprogram.cpp -o metaprogram.exe %flags% -g -DDEBUG_BUILD=1 -I../src
|
||||
metaprogram.exe
|
||||
cd ..
|
||||
|
||||
emcc -o text_editor.html --shell-file=data/shell.html %flags% %incs% %wasmflags% %dbg% -lm -lSDL3 src/text_editor/text_editor.cpp
|
||||
emcc -o text_editor.html --shell-file=data/shell.html %flags% %incs% %wasmflags% %dbg% -lm -lSDL3 src/text_editor/text_editor.cpp
|
||||
|
||||
11
build_web.sh
11
build_web.sh
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
incs="-Isrc/external/SDL/include -Isrc/external/lua/src -Isrc/external/glad -Lsrc/external/SDL/build_web -Isrc"
|
||||
wasmflags="-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1gb -msimd128 -sTOTAL_STACK=5MB -sINITIAL_MEMORY=256mb -sUSE_WEBGL2 -sFULL_ES3=1 -sUSE_SDL=3 -sASYNCIFY -sASSERTIONS=2"
|
||||
flags="-Wall -Wno-missing-braces -Wno-writable-strings -nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths"
|
||||
dbg="-g -DDEBUG_BUILD=1 -gsource-map"
|
||||
rel="-O3 -DDEBUG_BUILD=0"
|
||||
|
||||
echo todo
|
||||
|
||||
cd ..
|
||||
emcc -o text_editor.html --shell-file=data/shell.html $flags $incs $wasmflags $dbg -lm -lSDL3 src/text_editor/text_editor.cpp
|
||||
|
||||
@@ -20,6 +20,8 @@ Debug session:
|
||||
- Should highlight main buffer when clicking on status?
|
||||
- Report errorf - use coroutine dialogs
|
||||
- Replace in render layer also
|
||||
- BlockAllocator something is not working there which only showed after executing OpenCode on many files
|
||||
- Some bad allocating happening in Clipboard for sure
|
||||
|
||||
New UI Session
|
||||
- Move CommandWindow hooks to hooks
|
||||
|
||||
@@ -268,7 +268,7 @@ void AddBlock(BlockArena *arena, size_t size = MiB(1)) {
|
||||
if (arena->allocator.proc == NULL) {
|
||||
arena->allocator = GetSystemAllocator();
|
||||
}
|
||||
BlockArenaNode *new_block = (BlockArenaNode *)AllocSize(arena->allocator, block_size + sizeof(BlockArenaNode) + 16);
|
||||
BlockArenaNode *new_block = (BlockArenaNode *)AllocSize(arena->allocator, block_size + sizeof(BlockArenaNode));
|
||||
Assert(GetAlignOffset((size_t)new_block->start, DEFAULT_ALIGNMENT) == 0);
|
||||
arena->start = new_block->start;
|
||||
new_block->end = arena->end = new_block->start + block_size;
|
||||
@@ -294,9 +294,7 @@ API void Release(BlockArena *arena) {
|
||||
next = it->next;
|
||||
Dealloc(arena->allocator, it);
|
||||
}
|
||||
bool safe = arena->when_unwinding_make_sure_to_keep_last_block_alive;
|
||||
MemoryZero(arena, sizeof(BlockArena));
|
||||
arena->when_unwinding_make_sure_to_keep_last_block_alive = safe;
|
||||
}
|
||||
|
||||
API void Unwind(BlockArena *arena, U8 *pos) {
|
||||
@@ -307,16 +305,11 @@ API void Unwind(BlockArena *arena, U8 *pos) {
|
||||
contains = true;
|
||||
break;
|
||||
} else {
|
||||
bool keep = arena->when_unwinding_make_sure_to_keep_last_block_alive && arena->blocks->next == NULL;
|
||||
if (keep) {
|
||||
pos = arena->blocks->start;
|
||||
} else {
|
||||
arena->blocks = arena->blocks->next;
|
||||
Dealloc(arena->allocator, it);
|
||||
}
|
||||
arena->blocks = arena->blocks->next;
|
||||
Dealloc(arena->allocator, it);
|
||||
}
|
||||
}
|
||||
Assert(contains || pos == NULL || (arena->when_unwinding_make_sure_to_keep_last_block_alive && pos == arena->blocks->start));
|
||||
Assert(contains || pos == NULL);
|
||||
arena->start = pos;
|
||||
arena->end = arena->blocks ? arena->blocks->end : NULL;
|
||||
}
|
||||
@@ -332,8 +325,11 @@ API void *BlockArenaAllocatorProc(void *object, int kind, void *p, size_t size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if OS_WASM
|
||||
API void InitScratch() {
|
||||
}
|
||||
#else
|
||||
thread_local VirtualArena ScratchArenas[4];
|
||||
|
||||
API void InitScratch() {
|
||||
for (int i = 0; i < 4; i += 1) {
|
||||
InitArena(&ScratchArenas[i]);
|
||||
@@ -362,6 +358,7 @@ API VirtualArena *GetScratchEx(VirtualArena **conflicts, int conflict_count) {
|
||||
Assert(unoccupied);
|
||||
return unoccupied;
|
||||
}
|
||||
#endif
|
||||
|
||||
void RunArenaTest() {
|
||||
Allocator memory_tracking_allocator = GetTrackingAllocator();
|
||||
@@ -380,7 +377,6 @@ void RunArenaTest() {
|
||||
|
||||
{
|
||||
BlockArena arena = {};
|
||||
U8 *start = arena.start;
|
||||
arena.allocator = memory_tracking_allocator;
|
||||
int *vals = (int *)PushSize(&arena, sizeof(int) * 32);
|
||||
for (int i = 0; i < 32; i += 1) vals[i] = i;
|
||||
@@ -402,7 +398,7 @@ void RunArenaTest() {
|
||||
|
||||
U8 *p = arena.start;
|
||||
U8 *a = (U8 *)PushSize(&arena, KiB(32));
|
||||
U8 *b = (U8 *)PushSize(&arena, KiB(1000));
|
||||
PushSize(&arena, KiB(1000));
|
||||
Assert(arena.blocks);
|
||||
Assert(arena.blocks->next);
|
||||
Assert(arena.blocks->next->next == NULL);
|
||||
@@ -418,7 +414,7 @@ void RunArenaTest() {
|
||||
{
|
||||
BlockArena arena = {};
|
||||
arena.allocator = memory_tracking_allocator;
|
||||
U8 *a = (U8 *)PushSize(&arena, KiB(2000));
|
||||
PushSize(&arena, KiB(2000));
|
||||
Assert((size_t)(arena.blocks[0].end - arena.blocks[0].start) == KiB(2000));
|
||||
Release(&arena);
|
||||
Assert(MemoryTrackingRecord.len == 0);
|
||||
@@ -427,15 +423,14 @@ void RunArenaTest() {
|
||||
{
|
||||
BlockArena arena = {};
|
||||
arena.allocator = memory_tracking_allocator;
|
||||
arena.when_unwinding_make_sure_to_keep_last_block_alive = true;
|
||||
PushSize(&arena, KiB(2000));
|
||||
Unwind(&arena, 0);
|
||||
Assert(MemoryTrackingRecord.len == 1);
|
||||
Assert(MemoryTrackingRecord.len == 0);
|
||||
PushSize(&arena, MiB(1));
|
||||
PushSize(&arena, MiB(3));
|
||||
Assert(MemoryTrackingRecord.len == 2);
|
||||
Unwind(&arena, 0);
|
||||
Assert(MemoryTrackingRecord.len == 1);
|
||||
Assert(MemoryTrackingRecord.len == 0);
|
||||
Release(&arena);
|
||||
Assert(MemoryTrackingRecord.len == 0);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ struct BlockArena {
|
||||
U8 *end;
|
||||
BlockArenaNode *blocks;
|
||||
Allocator allocator;
|
||||
bool when_unwinding_make_sure_to_keep_last_block_alive;
|
||||
|
||||
operator Allocator() { return {BlockArenaAllocatorProc, this}; }
|
||||
};
|
||||
@@ -96,9 +95,24 @@ API void Release(VirtualArena *arena);
|
||||
|
||||
///////////////////////////////
|
||||
// Scratch
|
||||
#if OS_WASM
|
||||
struct Scratch {
|
||||
BlockArena arena = {};
|
||||
Scratch() {}
|
||||
Scratch(BlockArena *conflict) {}
|
||||
Scratch(BlockArena *c1, BlockArena *c2) {}
|
||||
Scratch(Allocator conflict) {}
|
||||
Scratch(Allocator c1, Allocator c2) {}
|
||||
~Scratch() { Release(&arena); }
|
||||
operator BlockArena *() { return &arena; }
|
||||
operator Allocator() { return arena; }
|
||||
private: // @Note: Disable copy constructors, cause its error prone
|
||||
Scratch(Scratch &arena);
|
||||
Scratch(Scratch &arena, Scratch &a2);
|
||||
};
|
||||
#else
|
||||
extern thread_local VirtualArena ScratchArenas[4];
|
||||
API VirtualArena *GetScratchEx(VirtualArena **conflicts, int conflict_count);
|
||||
|
||||
struct Scratch {
|
||||
VirtualArena *arena;
|
||||
U64 p;
|
||||
@@ -131,6 +145,7 @@ struct Scratch {
|
||||
Scratch(Scratch &arena);
|
||||
Scratch(Scratch &arena, Scratch &a2);
|
||||
};
|
||||
#endif
|
||||
|
||||
const int PAGE_SIZE = 4096;
|
||||
const int DEFAULT_ALIGNMENT = sizeof(void *);
|
||||
|
||||
@@ -408,6 +408,7 @@ API bool IsValid(Process *process) {
|
||||
int res = poll(&p, 1, 0);
|
||||
if (res > 0) {
|
||||
pid_t result = waitpid(plat->pid, &status, 0);
|
||||
Assert(result != -1);
|
||||
process->exit_code = WEXITSTATUS(status);
|
||||
return false;
|
||||
}
|
||||
@@ -1104,9 +1105,9 @@ API void Advance(FileIter *it) {
|
||||
|
||||
const char *dir_char_ending = it->is_directory ? "/" : "";
|
||||
const char *separator = it->path.data[it->path.len - 1] == '/' ? "" : "/";
|
||||
it->relative_path = Format(it->allocator, "%.*s%s%s%s", FmtString(it->path), separator, file->d_name, dir_char_ending);
|
||||
it->relative_path = Format(it->allocator, "%S%s%s%s", it->path, separator, file->d_name, dir_char_ending);
|
||||
it->absolute_path = GetAbsolutePath(it->allocator, it->relative_path);
|
||||
if (it->is_directory) it->absolute_path = Format(it->allocator, "%.*s/", FmtString(it->absolute_path));
|
||||
if (it->is_directory) it->absolute_path = Format(it->allocator, "%S/", it->absolute_path);
|
||||
it->is_valid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
4
src/external/minicoro.h
vendored
4
src/external/minicoro.h
vendored
@@ -539,8 +539,8 @@ static void mco_dealloc(void *ptr, size_t size, void *allocator_data) {
|
||||
#define _MCO_USE_TSAN
|
||||
#endif
|
||||
#ifdef _MCO_USE_ASAN
|
||||
void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size);
|
||||
void __sanitizer_finish_switch_fiber(void *fake_stack_save, const void **bottom_old, size_t *size_old);
|
||||
extern "C" void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size);
|
||||
extern "C" void __sanitizer_finish_switch_fiber(void *fake_stack_save, const void **bottom_old, size_t *size_old);
|
||||
#endif
|
||||
#ifdef _MCO_USE_TSAN
|
||||
void *__tsan_get_current_fiber(void);
|
||||
|
||||
@@ -712,98 +712,52 @@ API void RawAppendf(Buffer *buffer, const char *fmt, ...) {
|
||||
// multicursor
|
||||
///////////////////////////////
|
||||
|
||||
void MergeSort(int64_t Count, Caret *First, Caret *Temp) {
|
||||
ProfileFunction();
|
||||
// SortKey = range.min
|
||||
if (Count == 1) {
|
||||
// NOTE(casey): No work to do.
|
||||
} else if (Count == 2) {
|
||||
Caret *EntryA = First;
|
||||
Caret *EntryB = First + 1;
|
||||
if (EntryA->range.min > EntryB->range.min) {
|
||||
Swap(EntryA, EntryB);
|
||||
}
|
||||
} else {
|
||||
int64_t Half0 = Count / 2;
|
||||
int64_t Half1 = Count - Half0;
|
||||
|
||||
Assert(Half0 >= 1);
|
||||
Assert(Half1 >= 1);
|
||||
|
||||
Caret *InHalf0 = First;
|
||||
Caret *InHalf1 = First + Half0;
|
||||
Caret *End = First + Count;
|
||||
|
||||
MergeSort(Half0, InHalf0, Temp);
|
||||
MergeSort(Half1, InHalf1, Temp);
|
||||
|
||||
Caret *ReadHalf0 = InHalf0;
|
||||
Caret *ReadHalf1 = InHalf1;
|
||||
|
||||
Caret *Out = Temp;
|
||||
for (int64_t Index = 0;
|
||||
Index < Count;
|
||||
++Index) {
|
||||
if (ReadHalf0 == InHalf1) {
|
||||
*Out++ = *ReadHalf1++;
|
||||
} else if (ReadHalf1 == End) {
|
||||
*Out++ = *ReadHalf0++;
|
||||
} else if (ReadHalf0->range.min < ReadHalf1->range.min) {
|
||||
*Out++ = *ReadHalf0++;
|
||||
} else {
|
||||
*Out++ = *ReadHalf1++;
|
||||
}
|
||||
}
|
||||
Assert(Out == (Temp + Count));
|
||||
Assert(ReadHalf0 == InHalf1);
|
||||
Assert(ReadHalf1 == End);
|
||||
|
||||
// TODO(casey): Not really necessary if we ping-pong
|
||||
for (int64_t Index = 0;
|
||||
Index < Count;
|
||||
++Index) {
|
||||
First[Index] = Temp[Index];
|
||||
}
|
||||
}
|
||||
inline bool MergeSortCompare(Caret *EntryA, Caret *EntryB) {
|
||||
bool result = EntryA->range.min > EntryB->range.min;
|
||||
return result;
|
||||
}
|
||||
|
||||
void MergeSort(int64_t Count, Edit *First, Edit *Temp) {
|
||||
inline bool MergeSortCompare(Edit *EntryA, Edit *EntryB) {
|
||||
bool result = EntryA->range.min > EntryB->range.min;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void MergeSort(int64_t Count, T *First, T *Temp) {
|
||||
ProfileFunction();
|
||||
// SortKey = range.min
|
||||
if (Count == 1) {
|
||||
// NOTE(casey): No work to do.
|
||||
} else if (Count == 2) {
|
||||
Edit *EntryA = First;
|
||||
Edit *EntryB = First + 1;
|
||||
if (EntryA->range.min > EntryB->range.min) {
|
||||
T *EntryA = First;
|
||||
T *EntryB = First + 1;
|
||||
if (MergeSortCompare(EntryA, EntryB)) {
|
||||
Swap(EntryA, EntryB);
|
||||
}
|
||||
} else {
|
||||
int64_t Half0 = Count / 2;
|
||||
int64_t Half1 = Count - Half0;
|
||||
Int Half0 = Count / 2;
|
||||
Int Half1 = Count - Half0;
|
||||
|
||||
Assert(Half0 >= 1);
|
||||
Assert(Half1 >= 1);
|
||||
|
||||
Edit *InHalf0 = First;
|
||||
Edit *InHalf1 = First + Half0;
|
||||
Edit *End = First + Count;
|
||||
T *InHalf0 = First;
|
||||
T *InHalf1 = First + Half0;
|
||||
T *End = First + Count;
|
||||
|
||||
MergeSort(Half0, InHalf0, Temp);
|
||||
MergeSort(Half1, InHalf1, Temp);
|
||||
|
||||
Edit *ReadHalf0 = InHalf0;
|
||||
Edit *ReadHalf1 = InHalf1;
|
||||
T *ReadHalf0 = InHalf0;
|
||||
T *ReadHalf1 = InHalf1;
|
||||
|
||||
Edit *Out = Temp;
|
||||
for (int64_t Index = 0;
|
||||
Index < Count;
|
||||
++Index) {
|
||||
T *Out = Temp;
|
||||
for (Int Index = 0; Index < Count; ++Index) {
|
||||
if (ReadHalf0 == InHalf1) {
|
||||
*Out++ = *ReadHalf1++;
|
||||
} else if (ReadHalf1 == End) {
|
||||
*Out++ = *ReadHalf0++;
|
||||
} else if (ReadHalf0->range.min < ReadHalf1->range.min) {
|
||||
} else if (!MergeSortCompare(ReadHalf0, ReadHalf1)) {
|
||||
*Out++ = *ReadHalf0++;
|
||||
} else {
|
||||
*Out++ = *ReadHalf1++;
|
||||
@@ -814,9 +768,7 @@ void MergeSort(int64_t Count, Edit *First, Edit *Temp) {
|
||||
Assert(ReadHalf1 == End);
|
||||
|
||||
// TODO(casey): Not really necessary if we ping-pong
|
||||
for (int64_t Index = 0;
|
||||
Index < Count;
|
||||
++Index) {
|
||||
for (Int Index = 0; Index < Count; ++Index) {
|
||||
First[Index] = Temp[Index];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ struct Buffer {
|
||||
};
|
||||
|
||||
struct FuzzyPair {
|
||||
Int index;
|
||||
Int rating;
|
||||
int32_t index;
|
||||
int32_t rating;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -130,9 +130,7 @@ 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);
|
||||
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);
|
||||
|
||||
@@ -669,7 +669,6 @@ String Coro_OpenCodeDir;
|
||||
void Coro_OpenCode(mco_coro *co) {
|
||||
Array<String> dirs = {CoCurr->arena};
|
||||
Add(&dirs, Coro_OpenCodeDir);
|
||||
int i = 0;
|
||||
for (int diri = 0; diri < dirs.len; diri += 1) {
|
||||
for (FileIter it = IterateFiles(CoCurr->arena, dirs[diri]); IsValid(it); Advance(&it)) {
|
||||
bool match = false;
|
||||
|
||||
@@ -134,7 +134,6 @@ Trigger *ParseKeyChord(Lexer *lex) {
|
||||
Trigger *left = ParseKeyAtom(lex);
|
||||
EatWhitespace(lex);
|
||||
while (IsAlphanumeric(At(lex))) {
|
||||
int op = At(lex);
|
||||
left = TriggerBinary(lex, left, ParseKeyChord(lex), ' ');
|
||||
EatWhitespace(lex);
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ void DrawWindow(Window *window, Event &event) {
|
||||
}
|
||||
|
||||
// darken the inactive windows
|
||||
if (!is_active) {
|
||||
if (!is_active && !active_layed_out_doc) {
|
||||
ProfileScope(DarkenInactiveRect);
|
||||
SetScissor(screen_rect);
|
||||
DrawRect(window->total_rect, ColorInactiveWindow);
|
||||
|
||||
@@ -27,13 +27,13 @@ void CommandWindowLayout(Rect2I *rect, Int wx, Int wy) {
|
||||
n->document_rect = n->total_rect = CutBottom(rect, barsize);
|
||||
}
|
||||
|
||||
Int FuzzyRate(String16 string, String16 with) {
|
||||
int32_t FuzzyRate(String16 string, String16 with) {
|
||||
ProfileFunction();
|
||||
if (with.len == 0) return 0;
|
||||
Int points = 0;
|
||||
Int consecutive = 0;
|
||||
Int with_i = 0;
|
||||
for (Int i = 0; i < string.len; i++) {
|
||||
int32_t points = 0;
|
||||
int32_t consecutive = 0;
|
||||
int32_t with_i = 0;
|
||||
for (int32_t i = 0; i < string.len; i++) {
|
||||
if (ToLowerCase(string.data[i]) == ToLowerCase(with[with_i])) {
|
||||
consecutive += 1;
|
||||
with_i += 1;
|
||||
@@ -49,33 +49,25 @@ Int FuzzyRate(String16 string, String16 with) {
|
||||
return points;
|
||||
}
|
||||
|
||||
inline bool MergeSortCompare(FuzzyPair *a, FuzzyPair *b) {
|
||||
bool result = a->rating > b->rating;
|
||||
return result;
|
||||
}
|
||||
|
||||
Array<FuzzyPair> FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle) {
|
||||
ProfileFunction();
|
||||
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};
|
||||
Reserve(&ratings, line_max - line_min + 4);
|
||||
for (Int i = line_min; i < line_max; i += 1) {
|
||||
String16 s = GetLineStringWithoutNL(buffer, i);
|
||||
Int idx = 0;
|
||||
if (Seek(s, u" || ", &idx)) {
|
||||
s.len = idx;
|
||||
}
|
||||
s = Trim(s);
|
||||
Int rating = FuzzyRate(s, needle);
|
||||
Add(&ratings, {i, rating});
|
||||
}
|
||||
|
||||
// bubble sort
|
||||
for (Int i = 0; i < ratings.len - 1; i++) {
|
||||
for (Int j = 0; j < ratings.len - 1; j++) {
|
||||
if (ratings[j].rating > ratings[j + 1].rating) {
|
||||
FuzzyPair temp = ratings[j];
|
||||
ratings[j] = ratings[j + 1];
|
||||
ratings[j + 1] = temp;
|
||||
}
|
||||
}
|
||||
int32_t rating = FuzzyRate(s, needle);
|
||||
Add(&ratings, {(int32_t)i, rating});
|
||||
}
|
||||
|
||||
Array<FuzzyPair> temp = Copy(allocator, ratings);
|
||||
MergeSort(ratings.len, ratings.data, temp.data);
|
||||
return ratings;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ void StatusWindowUpdate() {
|
||||
String16 string_to_replace = GetString(title.buffer, replace_range);
|
||||
if (string_to_replace != string) {
|
||||
SelectRange(title.view, replace_range);
|
||||
Array<Edit> edits = ReplaceEx(scratch, title.view, string);
|
||||
ReplaceEx(scratch, title.view, string);
|
||||
}
|
||||
|
||||
SelectRange(title.view, MakeRange(0));
|
||||
|
||||
Reference in New Issue
Block a user