Working on resource management stuff
This commit is contained in:
@@ -555,7 +555,7 @@ void Remove(Array<T> *arr, T &item) {
|
|||||||
template <class T>
|
template <class T>
|
||||||
void UnorderedRemove(Array<T> *arr, T &item) {
|
void UnorderedRemove(Array<T> *arr, T &item) {
|
||||||
Assert(arr->len > 0);
|
Assert(arr->len > 0);
|
||||||
Assert(&item >= arr->begin && &item < arr->end);
|
Assert((&item >= arr->begin()) && (&item < arr->end()));
|
||||||
item = arr->data[--arr->len];
|
item = arr->data[--arr->len];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ bool InitOS();
|
|||||||
|
|
||||||
String GetExePath(Allocator allocator);
|
String GetExePath(Allocator allocator);
|
||||||
String GetExeDir(Allocator allocator);
|
String GetExeDir(Allocator allocator);
|
||||||
|
bool FileExists(String path);
|
||||||
|
bool IsDir(String path);
|
||||||
|
bool IsFile(String path);
|
||||||
|
|
||||||
struct Process {
|
struct Process {
|
||||||
bool is_valid;
|
bool is_valid;
|
||||||
|
|||||||
@@ -276,3 +276,26 @@ String GetExeDir(Allocator allocator) {
|
|||||||
path = Copy(allocator, path);
|
path = Copy(allocator, path);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileExists(String path) {
|
||||||
|
wchar_t wbuff[1024];
|
||||||
|
CreateWidecharFromChar(wbuff, Lengthof(wbuff), path.data, path.len);
|
||||||
|
DWORD attribs = GetFileAttributesW(wbuff);
|
||||||
|
bool result = attribs == INVALID_FILE_ATTRIBUTES ? false : true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDir(String path) {
|
||||||
|
wchar_t wbuff[1024];
|
||||||
|
CreateWidecharFromChar(wbuff, Lengthof(wbuff), path.data, path.len);
|
||||||
|
DWORD dwAttrib = GetFileAttributesW(wbuff);
|
||||||
|
return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFile(String path) {
|
||||||
|
wchar_t wbuff[1024];
|
||||||
|
CreateWidecharFromChar(wbuff, Lengthof(wbuff), path.data, path.len);
|
||||||
|
DWORD dwAttrib = GetFileAttributesW(wbuff);
|
||||||
|
bool is_file = (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == 0;
|
||||||
|
return dwAttrib != INVALID_FILE_ATTRIBUTES && is_file;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,17 +3,24 @@ https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation
|
|||||||
*/
|
*/
|
||||||
#define BUFFER_DEBUG 0
|
#define BUFFER_DEBUG 0
|
||||||
|
|
||||||
void InitBuffer(Allocator allocator, Buffer *buffer, Int size = 4096) {
|
void InitBuffer(Allocator allocator, Buffer *buffer, String name, Int size = 4096) {
|
||||||
buffer->id = AllocBufferID();
|
buffer->id = AllocBufferID();
|
||||||
|
buffer->name = name;
|
||||||
buffer->cap = size;
|
buffer->cap = size;
|
||||||
buffer->data = AllocArray(allocator, U16, buffer->cap);
|
buffer->data = AllocArray(allocator, U16, buffer->cap);
|
||||||
buffer->line_starts.allocator = allocator;
|
buffer->line_starts.allocator = allocator;
|
||||||
Add(&buffer->line_starts, (Int)0);
|
Add(&buffer->line_starts, (Int)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer *CreateBuffer(Allocator allocator, Int size = 4096) {
|
Buffer *CreateBuffer(Allocator allocator, String name, Int size = 4096) {
|
||||||
Buffer *result = Alloc(&Buffers);
|
Buffer *result = Alloc(&Buffers);
|
||||||
InitBuffer(allocator, result, size);
|
InitBuffer(allocator, result, name, size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer *CreateTempBuffer(Allocator allocator, Int size = 4096) {
|
||||||
|
Buffer *result = AllocType(allocator, Buffer);
|
||||||
|
InitBuffer(allocator, result, "*temp*", size);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,166 +194,3 @@ void ReplaceText(Buffer *buffer, Range range, String16 string) {
|
|||||||
ValidateLineStarts(buffer);
|
ValidateLineStarts(buffer);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer *OpenFile(String path) {
|
|
||||||
Scratch scratch;
|
|
||||||
String string = ReadFile(scratch, path);
|
|
||||||
|
|
||||||
Allocator sys_allocator = GetSystemAllocator();
|
|
||||||
Buffer *buffer = CreateBuffer(sys_allocator, string.len * 4);
|
|
||||||
|
|
||||||
for (Int i = 0; i < string.len;) {
|
|
||||||
if (string.data[i] == '\r') {
|
|
||||||
i += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (string.data[i] == '\t') {
|
|
||||||
// @WARNING: DONT INCREASE THE SIZE CARELESSLY, WE NEED TO ADJUST BUFFER SIZE
|
|
||||||
for (Int i = 0; i < 4; i += 1) buffer->data[buffer->len++] = L' ';
|
|
||||||
i += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t u32 = '?';
|
|
||||||
UTF32Result decode = UTF8ToUTF32(string.data + i, (int64_t)(string.len - i));
|
|
||||||
if (!decode.error) {
|
|
||||||
i += decode.advance;
|
|
||||||
u32 = decode.out_str;
|
|
||||||
} else {
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
UTF16Result encode = UTF32ToUTF16(decode.out_str);
|
|
||||||
if (!encode.error) {
|
|
||||||
for (int64_t encode_i = 0; encode_i < encode.len; encode_i += 1) {
|
|
||||||
buffer->data[buffer->len++] = encode.out_str[encode_i];
|
|
||||||
Assert(buffer->len < buffer->cap);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buffer->data[buffer->len++] = L'?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UpdateLines(buffer, {}, String16{(wchar_t *)buffer->data, buffer->len});
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestBuffer() {
|
|
||||||
Scratch scratch;
|
|
||||||
{
|
|
||||||
Buffer buffer = {};
|
|
||||||
InitBuffer(scratch, &buffer);
|
|
||||||
Assert(buffer.line_starts.len == 1);
|
|
||||||
String16 test_string = L"Thing itself";
|
|
||||||
{
|
|
||||||
ReplaceText(&buffer, Rng(), 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);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
ReplaceText(&buffer, {0, 5}, L"");
|
|
||||||
Assert(buffer.cap == 4096);
|
|
||||||
Assert(buffer.len == 12 - 5);
|
|
||||||
String16 a = GetString(buffer);
|
|
||||||
Assert(a == L" itself");
|
|
||||||
Assert(buffer.line_starts.len == 1);
|
|
||||||
Assert(buffer.line_starts[0] == 0);
|
|
||||||
Assert(PosToLine(buffer, 4) == 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
ReplaceText(&buffer, GetEndAsRange(buffer), L" and");
|
|
||||||
Assert(buffer.cap == 4096);
|
|
||||||
Assert(buffer.len == 12 - 5 + 4);
|
|
||||||
String16 a = GetString(buffer);
|
|
||||||
Assert(a == L" itself and");
|
|
||||||
Assert(buffer.line_starts.len == 1);
|
|
||||||
Assert(buffer.line_starts[0] == 0);
|
|
||||||
Assert(PosToLine(buffer, 4) == 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
ReplaceText(&buffer, GetRange(buffer), L"");
|
|
||||||
Assert(buffer.cap == 4096);
|
|
||||||
Assert(buffer.len == 0);
|
|
||||||
String16 a = GetString(buffer);
|
|
||||||
Assert(a == L"");
|
|
||||||
Assert(buffer.line_starts.len == 1);
|
|
||||||
Assert(buffer.line_starts[0] == 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
ReplaceText(&buffer, GetEndAsRange(buffer), L"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');
|
|
||||||
|
|
||||||
ReplaceText(&buffer, GetBeginAsRange(buffer), L"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');
|
|
||||||
|
|
||||||
ReplaceText(&buffer, GetBeginAsRange(buffer), L"a");
|
|
||||||
Assert(buffer.line_starts.len == 4);
|
|
||||||
Assert(PosToLine(buffer, 13) == 0);
|
|
||||||
Assert(PosToLine(buffer, 14) == 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Buffer buffer = {};
|
|
||||||
InitBuffer(scratch, &buffer);
|
|
||||||
ReplaceText(&buffer, {}, L"Thing\nmeme");
|
|
||||||
Assert(PosToLine(buffer, 5) == 0);
|
|
||||||
Assert(PosToLine(buffer, 6) == 1);
|
|
||||||
ReplaceText(&buffer, {0, 1}, L"");
|
|
||||||
Assert(PosToLine(buffer, 4) == 0);
|
|
||||||
Assert(PosToLine(buffer, 5) == 1);
|
|
||||||
ReplaceText(&buffer, {4, 5}, L"");
|
|
||||||
Assert(buffer.line_starts.len == 1);
|
|
||||||
ValidateLineStarts(&buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Buffer buffer = {};
|
|
||||||
InitBuffer(scratch, &buffer);
|
|
||||||
ReplaceText(&buffer, {}, L"Thing\nmeme");
|
|
||||||
ReplaceText(&buffer, {0, 5}, L"per\ncop");
|
|
||||||
Assert(buffer.line_starts.len == (Int)3);
|
|
||||||
Assert(PosToLine(buffer, 3) == 0);
|
|
||||||
Assert(PosToLine(buffer, 4) == 1);
|
|
||||||
ValidateLineStarts(&buffer);
|
|
||||||
|
|
||||||
ReplaceText(&buffer, {0, 8}, L"Thing\nmeme");
|
|
||||||
ReplaceText(&buffer, {0, 3}, L"Thing\nmeme");
|
|
||||||
ReplaceText(&buffer, {9, 13}, L"Thing\nmeme");
|
|
||||||
ReplaceText(&buffer, {4, 5}, L"Thing\nmeme\n\n\n");
|
|
||||||
ReplaceText(&buffer, {22, 23}, L"\n\n\nThing\nmeme\n\n\n");
|
|
||||||
ReplaceText(&buffer, {22, 23}, L"\n\n\nThing\nmeme\n\n\n");
|
|
||||||
ReplaceText(&buffer, {22, 23}, L"\n\n\nThing\nmeme\n\n\n");
|
|
||||||
ReplaceText(&buffer, {22, 23}, L"\n\n\nThing\nmeme\n\n\n");
|
|
||||||
ValidateLineStarts(&buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Buffer buffer = {};
|
|
||||||
InitBuffer(scratch, &buffer);
|
|
||||||
ReplaceText(&buffer, {}, L"Thing\nmeme");
|
|
||||||
ReplaceText(&buffer, GetEndAsRange(buffer), L"\nnewThing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
void MergeCarets(Array<Caret> *_carets, Range *mouse_selection_anchor = NULL) {
|
void MergeCarets(Buffer &buffer, Array<Caret> *_carets, Range *mouse_selection_anchor = NULL) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
Array<Caret> &carets = *_carets;
|
Array<Caret> &carets = *_carets;
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
|
|
||||||
|
// Clamp carets
|
||||||
|
For(carets) it.range = Clamp(buffer, it.range);
|
||||||
|
|
||||||
// Merge carets that overlap, this needs to be handled before any edits to
|
// Merge carets that overlap, this needs to be handled before any edits to
|
||||||
// make sure overlapping edits won't happen.
|
// make sure overlapping edits won't happen.
|
||||||
|
|
||||||
@@ -145,21 +149,3 @@ void _ApplyEdits(Buffer *buffer, Array<Edit> edits) {
|
|||||||
void AddEdit(Array<Edit> *e, Range range, String16 string) {
|
void AddEdit(Array<Edit> *e, Range range, String16 string) {
|
||||||
Add(e, {range, string});
|
Add(e, {range, string});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestBufferMultiCaret() {
|
|
||||||
Scratch scratch;
|
|
||||||
|
|
||||||
{
|
|
||||||
Buffer buffer = {};
|
|
||||||
InitBuffer(scratch, &buffer);
|
|
||||||
ReplaceText(&buffer, {}, L"Testing\nthings");
|
|
||||||
|
|
||||||
Array<Edit> edits = {scratch};
|
|
||||||
AddEdit(&edits, {0, 7}, L"t");
|
|
||||||
AddEdit(&edits, {8, 9}, L"T");
|
|
||||||
AddEdit(&edits, GetEndAsRange(buffer), L"\nnewThing");
|
|
||||||
_ApplyEdits(&buffer, edits);
|
|
||||||
String16 s = GetString(buffer);
|
|
||||||
Assert(s == L"t\nThings\nnewThing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -219,11 +219,11 @@ void HandleGlobalCommands() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlPress(KEY_ONE)) {
|
if (CtrlPress(KEY_ONE)) {
|
||||||
SetActiveWindow({1});
|
SetActiveWindow({0});
|
||||||
} else if (CtrlPress(KEY_TWO)) {
|
} else if (CtrlPress(KEY_TWO)) {
|
||||||
SetActiveWindow({2});
|
SetActiveWindow({1});
|
||||||
} else if (CtrlPress(KEY_THREE)) {
|
} else if (CtrlPress(KEY_THREE)) {
|
||||||
SetActiveWindow({3});
|
SetActiveWindow({2});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void Command_Paste(View *view) {
|
|||||||
// Regular paste
|
// Regular paste
|
||||||
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
|
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
|
||||||
BeforeEdit(buffer, view->carets);
|
BeforeEdit(buffer, view->carets);
|
||||||
MergeCarets(&view->carets);
|
MergeCarets(*buffer, &view->carets);
|
||||||
Array<Edit> edits = {scratch};
|
Array<Edit> edits = {scratch};
|
||||||
For(view->carets) AddEdit(&edits, it.range, string);
|
For(view->carets) AddEdit(&edits, it.range, string);
|
||||||
ApplyEdits(buffer, edits);
|
ApplyEdits(buffer, edits);
|
||||||
@@ -57,7 +57,7 @@ void Command_Paste(View *view) {
|
|||||||
|
|
||||||
// Multicursor paste
|
// Multicursor paste
|
||||||
BeforeEdit(buffer, view->carets);
|
BeforeEdit(buffer, view->carets);
|
||||||
MergeCarets(&view->carets);
|
MergeCarets(*buffer, &view->carets);
|
||||||
Array<Edit> edits = {scratch};
|
Array<Edit> edits = {scratch};
|
||||||
for (int64_t i = 0; i < view->carets.len; i += 1) {
|
for (int64_t i = 0; i < view->carets.len; i += 1) {
|
||||||
String16 string = SavedClipboardCursors[i];
|
String16 string = SavedClipboardCursors[i];
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ void Command_Replace(View *view, String16 string) {
|
|||||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
BeforeEdit(buffer, view->carets);
|
BeforeEdit(buffer, view->carets);
|
||||||
MergeCarets(&view->carets);
|
MergeCarets(*buffer, &view->carets);
|
||||||
Array<Edit> edits = {scratch};
|
Array<Edit> edits = {scratch};
|
||||||
For(view->carets) AddEdit(&edits, it.range, string);
|
For(view->carets) AddEdit(&edits, it.range, string);
|
||||||
ApplyEdits(buffer, edits);
|
ApplyEdits(buffer, edits);
|
||||||
@@ -14,7 +14,7 @@ void Command_DuplicateLine(View *view, int direction) {
|
|||||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||||
BeforeEdit(buffer, view->carets);
|
BeforeEdit(buffer, view->carets);
|
||||||
For(view->carets) it = MakeCaret(GetFront(it));
|
For(view->carets) it = MakeCaret(GetFront(it));
|
||||||
MergeCarets(&view->carets);
|
MergeCarets(*buffer, &view->carets);
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Edit> edits = {scratch};
|
Array<Edit> edits = {scratch};
|
||||||
@@ -109,7 +109,31 @@ void Command_CreateCursorVertical(View *_view, int direction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
For(arr) Add(&view.carets, it);
|
For(arr) Add(&view.carets, it);
|
||||||
MergeCarets(&view.carets);
|
MergeCarets(*buffer, &view.carets);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t FuzzyCloserWordBegin = 5;
|
||||||
|
int64_t FuzzyConsecutiveMultiplier = 3;
|
||||||
|
int64_t FuzzyRate(String16 string, String16 with) {
|
||||||
|
int64_t points = 0;
|
||||||
|
int64_t consecutive = 0;
|
||||||
|
int64_t with_i = 0;
|
||||||
|
for (int64_t i = 0; i < string.len; i++) {
|
||||||
|
if (string.data[i] == with[with_i]) {
|
||||||
|
int64_t closer_begin = ClampBottom((int64_t)0, FuzzyCloserWordBegin - i);
|
||||||
|
points += closer_begin;
|
||||||
|
consecutive++;
|
||||||
|
with_i += 1;
|
||||||
|
} else {
|
||||||
|
points += consecutive * FuzzyConsecutiveMultiplier;
|
||||||
|
consecutive = 0;
|
||||||
|
with_i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (with_i >= with.len) with_i = 0;
|
||||||
|
}
|
||||||
|
points += consecutive * FuzzyConsecutiveMultiplier;
|
||||||
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleActiveWindowBindings(Window *window) {
|
void HandleActiveWindowBindings(Window *window) {
|
||||||
@@ -271,15 +295,6 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
Command_MoveCursorsToSide(window, DIR_RIGHT);
|
Command_MoveCursorsToSide(window, DIR_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlPress(KEY_ENTER)) {
|
|
||||||
Int line = PosToLine(*buffer, GetFront(view.carets[0]));
|
|
||||||
Range range = GetLineRange(*buffer, line);
|
|
||||||
String16 string = GetString(*buffer, range);
|
|
||||||
EvalString(string);
|
|
||||||
} else if (Press(KEY_ENTER)) {
|
|
||||||
Command_Replace(&view, L"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Press(KEY_TAB)) {
|
if (Press(KEY_TAB)) {
|
||||||
Command_Replace(&view, L" ");
|
Command_Replace(&view, L" ");
|
||||||
}
|
}
|
||||||
@@ -296,6 +311,7 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
Command_Delete(&view, DIR_RIGHT);
|
Command_Delete(&view, DIR_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool search = false;
|
||||||
for (int c = GetCharPressed(); c; c = GetCharPressed()) {
|
for (int c = GetCharPressed(); c; c = GetCharPressed()) {
|
||||||
// we interpret 2 byte sequences as 1 byte when rendering but we still
|
// we interpret 2 byte sequences as 1 byte when rendering but we still
|
||||||
// want to read them properly.
|
// want to read them properly.
|
||||||
@@ -303,8 +319,65 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
UTF16Result result = UTF32ToUTF16((uint32_t)c);
|
UTF16Result result = UTF32ToUTF16((uint32_t)c);
|
||||||
if (!result.error) string = {(wchar_t *)result.out_str, result.len};
|
if (!result.error) string = {(wchar_t *)result.out_str, result.len};
|
||||||
Command_Replace(&view, string);
|
Command_Replace(&view, string);
|
||||||
|
search = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->fuzzy_search && search) {
|
||||||
|
Range line_range = GetLineRange(*buffer, 0);
|
||||||
|
String16 string = GetString(*buffer, line_range);
|
||||||
|
|
||||||
|
Scratch scratch;
|
||||||
|
struct Pair {
|
||||||
|
Int index;
|
||||||
|
Int rating;
|
||||||
|
};
|
||||||
|
Array<Pair> ratings = {scratch};
|
||||||
|
for (Int i = 1; i < buffer->line_starts.len; i += 1) {
|
||||||
|
Range l = GetLineRange(*buffer, i);
|
||||||
|
String16 s = GetString(*buffer, l);
|
||||||
|
int64_t rating = FuzzyRate(s, string);
|
||||||
|
Add(&ratings, {i, rating});
|
||||||
|
}
|
||||||
|
|
||||||
|
// bubble sort
|
||||||
|
for (int64_t i = 0; i < ratings.len - 1; i++) {
|
||||||
|
for (int64_t j = 0; j < ratings.len - 1; j++) {
|
||||||
|
if (ratings[j].rating < ratings[j + 1].rating) {
|
||||||
|
Pair temp = ratings[j];
|
||||||
|
ratings[j] = ratings[j + 1];
|
||||||
|
ratings[j + 1] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new buffer with
|
||||||
|
Buffer *temp_buffer = CreateTempBuffer(scratch, buffer->cap);
|
||||||
|
ReplaceText(temp_buffer, {}, string);
|
||||||
|
For(ratings) {
|
||||||
|
Range l = GetLineRange(*buffer, it.index);
|
||||||
|
String16 s = GetString(*buffer, l);
|
||||||
|
ReplaceText(temp_buffer, GetEndAsRange(*temp_buffer), s);
|
||||||
|
}
|
||||||
|
ReplaceText(buffer, {0, buffer->len}, GetString(*temp_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->fuzzy_search) {
|
||||||
|
if (Press(KEY_ENTER)) {
|
||||||
|
Int line = PosToLine(*buffer, GetFront(view.carets[0]));
|
||||||
|
Range range = GetLineRange(*buffer, line);
|
||||||
|
String16 string = GetString(*buffer, range);
|
||||||
|
EvalString(string);
|
||||||
|
if (window->id.id == CommandWindowID.id) {
|
||||||
|
Window *command_window = GetWindow(CommandWindowID);
|
||||||
|
command_window->visible = !command_window->visible;
|
||||||
|
ActiveWindow = LastActiveWindow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Press(KEY_ENTER)) {
|
||||||
|
Command_Replace(&view, L"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
ProfileScope(mouse);
|
ProfileScope(mouse);
|
||||||
|
|
||||||
@@ -335,7 +408,7 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
view.selection_anchor = GetLast(view.carets)->range;
|
view.selection_anchor = GetLast(view.carets)->range;
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeCarets(&view.carets);
|
MergeCarets(*buffer, &view.carets);
|
||||||
} else if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
|
} else if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
|
||||||
window->mouse_selecting = true;
|
window->mouse_selecting = true;
|
||||||
}
|
}
|
||||||
@@ -351,7 +424,7 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
} else {
|
} else {
|
||||||
caret = MakeCaret(view.selection_anchor.max, view.selection_anchor.min);
|
caret = MakeCaret(view.selection_anchor.max, view.selection_anchor.min);
|
||||||
}
|
}
|
||||||
MergeCarets(&view.carets, &view.selection_anchor);
|
MergeCarets(*buffer, &view.carets, &view.selection_anchor);
|
||||||
}
|
}
|
||||||
} else if (!(mouse_in_view || window->mouse_selecting) && mouse_in_scrollbar || window->mouse_selecting_scrollbar) {
|
} else if (!(mouse_in_view || window->mouse_selecting) && mouse_in_scrollbar || window->mouse_selecting_scrollbar) {
|
||||||
Scroller s = ComputeScrollerRect(*window);
|
Scroller s = ComputeScrollerRect(*window);
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
lua_State *LuaState = NULL;
|
lua_State *LuaState = NULL;
|
||||||
|
|
||||||
int LuaOpenFile(lua_State *L) {
|
int LuaOpenFile(lua_State *L) {
|
||||||
const char *text = luaL_checkstring(L, 1);
|
const char *text = luaL_checkstring(L, 1);
|
||||||
String string = text;
|
|
||||||
Buffer *buffer = OpenFile(string);
|
View *view = ViewOpenFile(text);
|
||||||
View *view = CreateView(buffer->id);
|
Window *window = GetWindow(LastActiveWindow);
|
||||||
Window *window = GetWindow(LastActiveWindow);
|
|
||||||
AddView(window, view->id);
|
AddView(window, view->id);
|
||||||
window->active_view = view->id;
|
window->active_view = view->id;
|
||||||
SetActiveWindow(window->id);
|
SetActiveWindow(window->id);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "buffer_multi_cursor.cpp"
|
#include "buffer_multi_cursor.cpp"
|
||||||
#include "buffer_history.cpp"
|
#include "buffer_history.cpp"
|
||||||
#include "buffer_test_load.cpp"
|
#include "buffer_test_load.cpp"
|
||||||
|
#include "management.cpp"
|
||||||
|
|
||||||
#include "commands.cpp"
|
#include "commands.cpp"
|
||||||
#include "commands_clipboard.cpp"
|
#include "commands_clipboard.cpp"
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
#include "lua_api.cpp"
|
#include "lua_api.cpp"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
- replace info bar with 2 windows
|
||||||
- Save file (utf16->utf8)
|
- Save file (utf16->utf8)
|
||||||
- reuse buffers!!
|
- reuse buffers!!
|
||||||
- resize windows
|
- resize windows
|
||||||
@@ -54,8 +56,6 @@
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
InitScratch();
|
InitScratch();
|
||||||
Test();
|
Test();
|
||||||
TestBuffer();
|
|
||||||
TestBufferMultiCaret();
|
|
||||||
BeginProfiler();
|
BeginProfiler();
|
||||||
BeginProfileScope("main");
|
BeginProfileScope("main");
|
||||||
|
|
||||||
@@ -82,18 +82,18 @@ int main(void) {
|
|||||||
FontCharSpacing = GetCharSpacing(MainFont, FontSize, FontSpacing);
|
FontCharSpacing = GetCharSpacing(MainFont, FontSize, FontSpacing);
|
||||||
|
|
||||||
Allocator sys_allocator = GetSystemAllocator();
|
Allocator sys_allocator = GetSystemAllocator();
|
||||||
// Create null
|
// Create null
|
||||||
{
|
{
|
||||||
Buffer *buffer = CreateBuffer(sys_allocator);
|
Buffer *buffer = CreateBuffer(sys_allocator, "*scratch*");
|
||||||
View *view = CreateView(buffer->id);
|
// View *view = CreateView(buffer->id);
|
||||||
Window *window = CreateWindow();
|
// Window *window = CreateWindow();
|
||||||
window->visible = false;
|
// window->visible = false;
|
||||||
AddView(window, view->id);
|
// AddView(window, view->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Window *w = CreateWindow();
|
Window *w = CreateWindow();
|
||||||
Buffer *b = CreateBuffer(sys_allocator);
|
Buffer *b = CreateBuffer(sys_allocator, "*load_text_a*");
|
||||||
View *v = CreateView(b->id);
|
View *v = CreateView(b->id);
|
||||||
LoadTextA(b);
|
LoadTextA(b);
|
||||||
AddView(w, v->id);
|
AddView(w, v->id);
|
||||||
@@ -102,14 +102,14 @@ int main(void) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
Window *w = CreateWindow();
|
Window *w = CreateWindow();
|
||||||
Buffer *b = CreateBuffer(sys_allocator);
|
Buffer *b = CreateBuffer(sys_allocator, "*load_unicode*");
|
||||||
View *v = CreateView(b->id);
|
View *v = CreateView(b->id);
|
||||||
LoadUnicode(b);
|
LoadUnicode(b);
|
||||||
AddView(w, v->id);
|
AddView(w, v->id);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Window *w = CreateWindow();
|
Window *w = CreateWindow();
|
||||||
Buffer *b = CreateBuffer(sys_allocator);
|
Buffer *b = CreateBuffer(sys_allocator, "*load_line*");
|
||||||
LoadLine(b);
|
LoadLine(b);
|
||||||
View *v = CreateView(b->id);
|
View *v = CreateView(b->id);
|
||||||
AddView(w, v->id);
|
AddView(w, v->id);
|
||||||
@@ -119,9 +119,14 @@ int main(void) {
|
|||||||
w->draw_scrollbar = false;
|
w->draw_scrollbar = false;
|
||||||
w->draw_line_numbers = false;
|
w->draw_line_numbers = false;
|
||||||
w->visible = false;
|
w->visible = false;
|
||||||
Buffer *b = CreateBuffer(sys_allocator);
|
w->fuzzy_search = true;
|
||||||
|
Buffer *b = CreateBuffer(sys_allocator, "*commands*");
|
||||||
View *v = CreateView(b->id);
|
View *v = CreateView(b->id);
|
||||||
ReplaceText(b, {}, L"open \"C:/Work/text_editor/src/text_editor/text_editor.cpp\"");
|
ReplaceText(b, GetEndAsRange(*b), L"\n");
|
||||||
|
ReplaceText(b, GetEndAsRange(*b), L"open \"C:/Work/text_editor/src/text_editor/text_editor.cpp\"\n");
|
||||||
|
ReplaceText(b, GetEndAsRange(*b), L"open \"C:/Work/text_editor/src/text_editor/text_editor.h\"\n");
|
||||||
|
ReplaceText(b, GetEndAsRange(*b), L"open \"C:/Work/text_editor/src/text_editor/commands.cpp\"\n");
|
||||||
|
ReplaceText(b, GetEndAsRange(*b), L"open \"C:/Work/text_editor/src/text_editor/commands_clipboard.cpp\"\n");
|
||||||
AddView(w, v->id);
|
AddView(w, v->id);
|
||||||
CommandWindowID = w->id;
|
CommandWindowID = w->id;
|
||||||
}
|
}
|
||||||
@@ -134,28 +139,28 @@ int main(void) {
|
|||||||
Rect2I infobar_rect = CutBottom(&screen_rect, (Int)MenuFontSize);
|
Rect2I infobar_rect = CutBottom(&screen_rect, (Int)MenuFontSize);
|
||||||
float line_numbers_size = MeasureTextEx(MainFont, "12345", (float)FontSize, (float)FontSpacing).x;
|
float line_numbers_size = MeasureTextEx(MainFont, "12345", (float)FontSize, (float)FontSpacing).x;
|
||||||
{
|
{
|
||||||
int i = 1;
|
int i = 0;
|
||||||
Windows[i].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.33));
|
Windows[i].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.33));
|
||||||
Windows[i].document_rect = Windows[i].total_rect;
|
Windows[i].document_rect = Windows[i].total_rect;
|
||||||
if (Windows[i].draw_scrollbar) Windows[i].scrollbar_rect = CutRight(&Windows[i].document_rect, 10);
|
if (Windows[i].draw_scrollbar) Windows[i].scrollbar_rect = CutRight(&Windows[i].document_rect, 10);
|
||||||
if (Windows[i].draw_line_numbers) Windows[i].line_numbers_rect = CutLeft(&Windows[i].document_rect, (Int)line_numbers_size);
|
if (Windows[i].draw_line_numbers) Windows[i].line_numbers_rect = CutLeft(&Windows[i].document_rect, (Int)line_numbers_size);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int i = 2;
|
int i = 1;
|
||||||
Windows[i].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.5));
|
Windows[i].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.5));
|
||||||
Windows[i].document_rect = Windows[i].total_rect;
|
Windows[i].document_rect = Windows[i].total_rect;
|
||||||
if (Windows[i].draw_scrollbar) Windows[i].scrollbar_rect = CutRight(&Windows[i].document_rect, 10);
|
if (Windows[i].draw_scrollbar) Windows[i].scrollbar_rect = CutRight(&Windows[i].document_rect, 10);
|
||||||
if (Windows[i].draw_line_numbers) Windows[i].line_numbers_rect = CutLeft(&Windows[i].document_rect, (Int)line_numbers_size);
|
if (Windows[i].draw_line_numbers) Windows[i].line_numbers_rect = CutLeft(&Windows[i].document_rect, (Int)line_numbers_size);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int i = 3;
|
int i = 2;
|
||||||
Windows[i].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 1.0));
|
Windows[i].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 1.0));
|
||||||
Windows[i].document_rect = Windows[i].total_rect;
|
Windows[i].document_rect = Windows[i].total_rect;
|
||||||
if (Windows[i].draw_scrollbar) Windows[i].scrollbar_rect = CutRight(&Windows[i].document_rect, 10);
|
if (Windows[i].draw_scrollbar) Windows[i].scrollbar_rect = CutRight(&Windows[i].document_rect, 10);
|
||||||
if (Windows[i].draw_line_numbers) Windows[i].line_numbers_rect = CutLeft(&Windows[i].document_rect, (Int)line_numbers_size);
|
if (Windows[i].draw_line_numbers) Windows[i].line_numbers_rect = CutLeft(&Windows[i].document_rect, (Int)line_numbers_size);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int i = 4;
|
int i = 3;
|
||||||
Rect2 screen_rect = GetScreenRectF();
|
Rect2 screen_rect = GetScreenRectF();
|
||||||
Vec2 size = GetSize(screen_rect);
|
Vec2 size = GetSize(screen_rect);
|
||||||
CutTop(&screen_rect, size.y * 0.05f);
|
CutTop(&screen_rect, size.y * 0.05f);
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ struct HistoryEntry {
|
|||||||
// @todo: gap buffer to improve speed of inserting on big files with only one cursor?
|
// @todo: gap buffer to improve speed of inserting on big files with only one cursor?
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
BufferID id;
|
BufferID id;
|
||||||
|
String name;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
U16 *data;
|
U16 *data;
|
||||||
wchar_t *str;
|
wchar_t *str;
|
||||||
@@ -62,6 +64,7 @@ struct Window {
|
|||||||
bool draw_scrollbar : 1;
|
bool draw_scrollbar : 1;
|
||||||
bool draw_line_numbers : 1;
|
bool draw_line_numbers : 1;
|
||||||
bool visible : 1;
|
bool visible : 1;
|
||||||
|
bool fuzzy_search : 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,34 +104,11 @@ Int LastFrameIDWhenScrolled;
|
|||||||
WindowID LastActiveWindow;
|
WindowID LastActiveWindow;
|
||||||
Int LastFrameIDWhenSwitchedActiveWindow;
|
Int LastFrameIDWhenSwitchedActiveWindow;
|
||||||
|
|
||||||
inline Window *GetWindow(WindowID id) {
|
|
||||||
For(Windows) if (it.id.id == id.id) return ⁢
|
|
||||||
return &Windows[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Buffer *GetBuffer(BufferID id) {
|
|
||||||
For(Buffers) if (it.id.id == id.id) return ⁢
|
|
||||||
return &Buffers[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline View *GetView(ViewID id) {
|
|
||||||
For(Views) if (it.id.id == id.id) return ⁢
|
|
||||||
return &Views[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetActiveWindow(WindowID window);
|
|
||||||
inline ViewID AllocViewID() { return {ViewIDs.id++}; }
|
|
||||||
inline WindowID AllocWindowID() { return {WindowIDs.id++}; }
|
|
||||||
inline BufferID AllocBufferID() { return {BufferIDs.id++}; }
|
|
||||||
inline bool IsActive(Window *window) { return window->id.id == ActiveWindow.id; }
|
|
||||||
inline bool IsActive(Window *window, View *view) { return window->active_view.id == view->id.id; }
|
|
||||||
inline Window *GetActiveWindow() { return GetWindow(ActiveWindow); }
|
|
||||||
inline View *GetActiveView(Window *window) {
|
|
||||||
if (window->active_view.id == 0) return GetView(window->views[0]);
|
|
||||||
else return GetView(window->active_view);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EvalString(String16 string16);
|
void EvalString(String16 string16);
|
||||||
Rect2I GetVisibleCells(Window &window);
|
Rect2I GetVisibleCells(Window &window);
|
||||||
void AfterEdit(View *view, Array<Edit> edits);
|
void AfterEdit(View *view, Array<Edit> edits);
|
||||||
Scroller ComputeScrollerRect(Window &window);
|
Scroller ComputeScrollerRect(Window &window);
|
||||||
|
|
||||||
|
inline ViewID AllocViewID() { return {ViewIDs.id++}; }
|
||||||
|
inline WindowID AllocWindowID() { return {WindowIDs.id++}; }
|
||||||
|
inline BufferID AllocBufferID() { return {BufferIDs.id++}; }
|
||||||
|
|||||||
@@ -1,26 +1,3 @@
|
|||||||
Window *CreateWindow() {
|
|
||||||
Window *w = Alloc(&Windows);
|
|
||||||
w->visible = true;
|
|
||||||
w->draw_scrollbar = true;
|
|
||||||
w->draw_line_numbers = true;
|
|
||||||
w->id = AllocWindowID();
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddView(Window *w, ViewID view) {
|
|
||||||
if (w->active_view.id == 0) w->active_view = view;
|
|
||||||
For(w->views) if (it.id == view.id) return;
|
|
||||||
Add(&w->views, view);
|
|
||||||
}
|
|
||||||
|
|
||||||
View *CreateView(BufferID buffer_id) {
|
|
||||||
View *w = Alloc(&Views);
|
|
||||||
w->id = AllocViewID();
|
|
||||||
w->buffer_id = buffer_id;
|
|
||||||
Add(&w->carets, {0, 0});
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetMouseCursor() {
|
void SetMouseCursor() {
|
||||||
Window *w = GetActiveWindow();
|
Window *w = GetActiveWindow();
|
||||||
Vec2 mouse = GetMousePosition();
|
Vec2 mouse = GetMousePosition();
|
||||||
@@ -45,13 +22,3 @@ Array<Int> GetWindowZOrder(Allocator allocator) {
|
|||||||
For(Windows) if (it.z == 0 && it.visible) Add(&order, GetIndex(Windows, it));
|
For(Windows) if (it.z == 0 && it.visible) Add(&order, GetIndex(Windows, it));
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetActiveWindow(WindowID window) {
|
|
||||||
if (LastFrameIDWhenSwitchedActiveWindow != FrameID) {
|
|
||||||
if (ActiveWindow.id != CommandWindowID.id) {
|
|
||||||
LastActiveWindow = ActiveWindow;
|
|
||||||
}
|
|
||||||
ActiveWindow = window;
|
|
||||||
LastFrameIDWhenSwitchedActiveWindow = FrameID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user