Fix merge carets
This commit is contained in:
@@ -213,3 +213,14 @@ void ReplaceText(Buffer *buffer, Range range, String16 string) {
|
||||
ValidateLineStarts(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Append(Buffer *buffer, String16 string) {
|
||||
ReplaceText(buffer, GetEndAsRange(*buffer), string);
|
||||
}
|
||||
|
||||
void Appendf(Buffer *buffer, const char *fmt, ...) {
|
||||
Scratch scratch;
|
||||
STRING_FORMAT(scratch, fmt, string);
|
||||
String16 string16 = ToString16(scratch, string);
|
||||
ReplaceText(buffer, GetEndAsRange(*buffer), string16);
|
||||
}
|
||||
@@ -117,6 +117,17 @@ bool AreEqual(Caret a, Caret b) {
|
||||
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) {
|
||||
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;
|
||||
|
||||
@@ -1,45 +1,56 @@
|
||||
// mouse_selection_anchor is special case for mouse handling !
|
||||
void MergeCarets(Buffer &buffer, Array<Caret> *_carets, Range *mouse_selection_anchor = NULL) {
|
||||
void MergeSort(int64_t Count, Caret *First, Caret *Temp) {
|
||||
ProfileFunction();
|
||||
Array<Caret> &carets = *_carets;
|
||||
Scratch scratch;
|
||||
// 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;
|
||||
|
||||
// Clamp carets
|
||||
For(carets) it.range = Clamp(buffer, it.range);
|
||||
Assert(Half0 >= 1);
|
||||
Assert(Half1 >= 1);
|
||||
|
||||
// Merge carets that overlap, this needs to be handled before any edits to
|
||||
// make sure overlapping edits won't happen.
|
||||
Caret *InHalf0 = First;
|
||||
Caret *InHalf1 = First + Half0;
|
||||
Caret *End = First + Count;
|
||||
|
||||
// @optimize @refactor: this is retarded, I hit so many array removal bugs here
|
||||
Array<Caret *> deleted_carets = {scratch};
|
||||
ForItem(caret, carets) {
|
||||
if (Contains(deleted_carets, &caret)) goto end_of_caret_loop;
|
||||
MergeSort(Half0, InHalf0, Temp);
|
||||
MergeSort(Half1, InHalf1, Temp);
|
||||
|
||||
For(carets) {
|
||||
if (&it == &caret) continue;
|
||||
bool a = caret.range.max >= it.range.min && caret.range.max <= it.range.max;
|
||||
bool b = caret.range.min >= it.range.min && caret.range.min <= it.range.max;
|
||||
if ((a || b) && !Contains(deleted_carets, &it)) {
|
||||
Add(&deleted_carets, &it);
|
||||
caret.range.max = Max(caret.range.max, it.range.max);
|
||||
caret.range.min = Min(caret.range.min, it.range.min);
|
||||
if (mouse_selection_anchor) *mouse_selection_anchor = caret.range;
|
||||
goto end_of_caret_loop;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
end_of_caret_loop:;
|
||||
}
|
||||
Assert(Out == (Temp + Count));
|
||||
Assert(ReadHalf0 == InHalf1);
|
||||
Assert(ReadHalf1 == End);
|
||||
|
||||
Array<Caret> new_carets = {scratch};
|
||||
For(carets) {
|
||||
if (Contains(deleted_carets, &it) == false) {
|
||||
Add(&new_carets, it);
|
||||
// TODO(casey): Not really necessary if we ping-pong
|
||||
for (int64_t Index = 0;
|
||||
Index < Count;
|
||||
++Index) {
|
||||
First[Index] = Temp[Index];
|
||||
}
|
||||
}
|
||||
Assert(new_carets.len <= carets.len);
|
||||
|
||||
carets.len = 0;
|
||||
For(new_carets) Add(&carets, it);
|
||||
}
|
||||
|
||||
void MergeSort(int64_t Count, Edit *First, Edit *Temp) {
|
||||
|
||||
@@ -3,7 +3,7 @@ Array<String16> SavedClipboardCursors;
|
||||
|
||||
void Command_Copy(View *view) {
|
||||
Allocator sys_allocator = GetSystemAllocator();
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
|
||||
SavedClipboardCursors.allocator = sys_allocator;
|
||||
if (SavedClipboardCursors.data) {
|
||||
@@ -39,7 +39,7 @@ void Command_Copy(View *view) {
|
||||
|
||||
void Command_Paste(View *view) {
|
||||
Scratch scratch;
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
const char *text = GetClipboardText();
|
||||
String string_ = text;
|
||||
String16 string = ToString16(scratch, string_);
|
||||
@@ -47,7 +47,7 @@ void Command_Paste(View *view) {
|
||||
// Regular paste
|
||||
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
|
||||
BeforeEdit(buffer, view->carets);
|
||||
MergeCarets(*buffer, &view->carets);
|
||||
MergeCarets(view);
|
||||
Array<Edit> edits = {scratch};
|
||||
For(view->carets) AddEdit(&edits, it.range, string);
|
||||
ApplyEdits(buffer, edits);
|
||||
@@ -57,7 +57,7 @@ void Command_Paste(View *view) {
|
||||
|
||||
// Multicursor paste
|
||||
BeforeEdit(buffer, view->carets);
|
||||
MergeCarets(*buffer, &view->carets);
|
||||
MergeCarets(view);
|
||||
Array<Edit> edits = {scratch};
|
||||
for (int64_t i = 0; i < view->carets.len; i += 1) {
|
||||
String16 string = SavedClipboardCursors[i];
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
void Command_Replace(View *view, String16 string) {
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
Scratch scratch;
|
||||
BeforeEdit(buffer, view->carets);
|
||||
MergeCarets(*buffer, &view->carets);
|
||||
MergeCarets(view);
|
||||
Array<Edit> edits = {scratch};
|
||||
For(view->carets) AddEdit(&edits, it.range, string);
|
||||
ApplyEdits(buffer, edits);
|
||||
@@ -11,10 +11,10 @@ void Command_Replace(View *view, String16 string) {
|
||||
|
||||
void Command_DuplicateLine(View *view, int direction) {
|
||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
BeforeEdit(buffer, view->carets);
|
||||
For(view->carets) it = MakeCaret(GetFront(it));
|
||||
MergeCarets(*buffer, &view->carets);
|
||||
MergeCarets(view);
|
||||
|
||||
Scratch scratch;
|
||||
Array<Edit> edits = {scratch};
|
||||
@@ -35,7 +35,7 @@ bool SHIFT_PRESSED = true;
|
||||
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {
|
||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
||||
View &view = *GetActiveView(window);
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
|
||||
Rect2I visible_cells_rect = GetVisibleCells(*window);
|
||||
Int y = GetSize(visible_cells_rect).y - 2;
|
||||
@@ -63,7 +63,7 @@ void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = f
|
||||
void Command_MoveCursorsToSide(Window *window, int direction, bool shift = false) {
|
||||
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
||||
View &view = *GetActiveView(window);
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
|
||||
For(view.carets) {
|
||||
Range line_range = GetLineRangeWithoutNL(*buffer, PosToLine(*buffer, GetFront(it)));
|
||||
@@ -84,7 +84,7 @@ void Command_MoveCursorsToSide(Window *window, int direction, bool shift = false
|
||||
void Command_Delete(View *_view, int direction, bool ctrl = false) {
|
||||
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
||||
View &view = *_view;
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
|
||||
// Select things to delete
|
||||
For(view.carets) {
|
||||
@@ -96,10 +96,29 @@ void Command_Delete(View *_view, int direction, bool ctrl = false) {
|
||||
Command_Replace(&view, {});
|
||||
}
|
||||
|
||||
void Command_SelectAll(View *view, String16 needle) {
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
String16 string_buffer = GetString(*buffer);
|
||||
|
||||
Int debug_id = 0;
|
||||
for (Int pos = 0;;) {
|
||||
Int index = 0;
|
||||
String16 medium = Skip(string_buffer, pos);
|
||||
if (!Seek(medium, needle, &index)) {
|
||||
break;
|
||||
}
|
||||
|
||||
Add(&view->carets, MakeCaret(pos + index + needle.len, pos + index));
|
||||
pos += needle.len;
|
||||
debug_id += 1;
|
||||
}
|
||||
MergeCarets(view);
|
||||
}
|
||||
|
||||
void Command_CreateCursorVertical(View *_view, int direction) {
|
||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
||||
View &view = *_view;
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
|
||||
Scratch scratch;
|
||||
Array<Caret> arr = {scratch};
|
||||
@@ -115,24 +134,24 @@ void Command_CreateCursorVertical(View *_view, int direction) {
|
||||
}
|
||||
}
|
||||
For(arr) Add(&view.carets, it);
|
||||
MergeCarets(*buffer, &view.carets);
|
||||
MergeCarets(_view);
|
||||
}
|
||||
|
||||
void Command_SelectRangeOneCursor(View *view, Range range) {
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
view->carets.len = 1;
|
||||
view->carets[0] = MakeCaret(range.min, range.max);
|
||||
}
|
||||
|
||||
void Command_SelectEntireBuffer(View *view) {
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
view->carets.len = 1;
|
||||
view->carets[0] = MakeCaret(0, buffer->len);
|
||||
}
|
||||
|
||||
void Command_EvalLua(View *view, String16 string) {
|
||||
Scratch scratch;
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
String16 eval_result = EvalString(scratch, string);
|
||||
|
||||
if (eval_result.len) {
|
||||
@@ -156,15 +175,62 @@ void Command_EvalLua(View *view, String16 string) {
|
||||
}
|
||||
|
||||
void Command_EvalLua(View *view) {
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
Int line = PosToLine(*buffer, GetFront(view->carets[0]));
|
||||
String16 string = GetLineStringWithoutNL(*buffer, line);
|
||||
Command_EvalLua(view, string);
|
||||
}
|
||||
|
||||
void PrintDebugCarets(View *view, const char *msg) {
|
||||
Buffer *null_buffer = GetBuffer(NullBufferID);
|
||||
Appendf(null_buffer, "%s id: %d sel_anchor(%d, %d)\n", msg, view->caret_change_id, view->selection_anchor.min, view->selection_anchor.max);
|
||||
For(view->carets) {
|
||||
Appendf(null_buffer, " min: %lld max: %lld front: %d\n", (long long)it.range.min, (long long)it.range.max, it.ifront);
|
||||
}
|
||||
}
|
||||
|
||||
// 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(View *view, Range *mouse_selection_anchor) {
|
||||
ProfileFunction();
|
||||
PrintDebugCarets(view, "before");
|
||||
|
||||
view->caret_change_id = CaretChangeID++;
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
For(view->carets) it.range = Clamp(*buffer, it.range);
|
||||
Caret first_caret = view->carets.data[0];
|
||||
|
||||
Scratch scratch;
|
||||
Array<Caret> c1 = TightCopy(scratch, view->carets);
|
||||
MergeSort(view->carets.len, c1.data, view->carets.data);
|
||||
view->carets.len = 0;
|
||||
|
||||
Int first_caret_index = 0;
|
||||
Add(&view->carets, c1[0]);
|
||||
for (Int i = 1; i < c1.len; i += 1) {
|
||||
Caret &it = c1[i];
|
||||
Caret *last = GetLast(view->carets);
|
||||
|
||||
if (AreOverlapping(*last, it)) {
|
||||
last->range.max = Max(last->range.max, it.range.max);
|
||||
if (mouse_selection_anchor) *mouse_selection_anchor = last->range;
|
||||
} else {
|
||||
Add(&view->carets, it);
|
||||
}
|
||||
|
||||
if (AreEqual(it, first_caret)) first_caret_index = view->carets.len - 1;
|
||||
}
|
||||
|
||||
Swap(&view->carets[first_caret_index], &view->carets[0]);
|
||||
|
||||
PrintDebugCarets(view, "after");
|
||||
}
|
||||
|
||||
void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
View &view = *GetActiveView(window);
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
if (CtrlPress(KEY_F2)) {
|
||||
LoadBigLine(buffer);
|
||||
} else if (Press(KEY_F2)) {
|
||||
@@ -343,7 +409,7 @@ void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
String16 string = GetString(*buffer, view.carets[0].range);
|
||||
Caret caret = FindInBuffer(buffer, string, view.carets[0], true);
|
||||
Insert(&view.carets, caret, 0);
|
||||
MergeCarets(*buffer, &view.carets);
|
||||
MergeCarets(&view);
|
||||
}
|
||||
|
||||
if (Press(KEY_F3)) {
|
||||
@@ -352,7 +418,7 @@ void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
Caret caret = FindInBuffer(buffer, search_string, view.carets[0], true);
|
||||
if (Ctrl()) {
|
||||
Insert(&view.carets, caret, 0);
|
||||
MergeCarets(*buffer, &view.carets);
|
||||
MergeCarets(&view);
|
||||
} else {
|
||||
view.carets.len = 1;
|
||||
view.carets[0] = caret;
|
||||
@@ -362,22 +428,20 @@ void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
if (window->id.id == SearchWindowID.id) {
|
||||
Window *seek_window = GetWindow(GetLastActiveWindow());
|
||||
View *seek_view = GetView(seek_window->active_view);
|
||||
Buffer *seek_buffer = GetBuffer(seek_view->buffer_id);
|
||||
Buffer *seek_buffer = GetBuffer(seek_view->active_buffer);
|
||||
String16 needle = GetString(*buffer);
|
||||
if (search) {
|
||||
seek_view->carets[0] = FindInBuffer(seek_buffer, needle, seek_view->carets[0]);
|
||||
seek_view->carets.len = 1;
|
||||
}
|
||||
if (AltPress(KEY_ENTER)) {
|
||||
Scratch scratch;
|
||||
Array<Range> finds = FindAllInBuffer(scratch, seek_buffer, needle);
|
||||
For(finds) Add(&seek_view->carets, MakeCaret(it.max, it.min));
|
||||
MergeCarets(*buffer, &view.carets);
|
||||
Command_SelectAll(seek_view, needle);
|
||||
} else if (Press(KEY_ENTER)) {
|
||||
Caret caret = FindInBuffer(seek_buffer, needle, seek_view->carets[0], true);
|
||||
SetActiveWindow(seek_window->id);
|
||||
if (Ctrl()) {
|
||||
Insert(&seek_view->carets, caret, 0);
|
||||
MergeCarets(*buffer, &view.carets);
|
||||
MergeCarets(seek_view);
|
||||
} else {
|
||||
seek_view->carets.len = 1;
|
||||
seek_view->carets[0] = caret;
|
||||
@@ -436,7 +500,7 @@ void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
if (mouse_in_view && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
|
||||
if (IsDoubleClick()) {
|
||||
Caret *c = GetLast(view.carets);
|
||||
Caret *c = &view.carets[0];
|
||||
if (InBounds({c->range.min - 1, c->range.max + 1}, p)) {
|
||||
c->range = EncloseWord(*buffer, p);
|
||||
view.selection_anchor = c->range;
|
||||
@@ -445,11 +509,11 @@ void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
if (!IsKeyDown(KEY_LEFT_CONTROL)) {
|
||||
view.carets.len = 0;
|
||||
}
|
||||
Add(&view.carets, MakeCaret(p, p));
|
||||
view.selection_anchor = GetLast(view.carets)->range;
|
||||
Insert(&view.carets, MakeCaret(p, p), 0);
|
||||
view.selection_anchor = view.carets[0].range;
|
||||
}
|
||||
|
||||
MergeCarets(*buffer, &view.carets);
|
||||
MergeCarets(&view, &view.selection_anchor);
|
||||
} else if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
|
||||
window->mouse_selecting = true;
|
||||
}
|
||||
@@ -457,7 +521,7 @@ void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
|
||||
if (window->mouse_selecting) {
|
||||
if (!IsMouseButtonDown(MOUSE_BUTTON_LEFT)) window->mouse_selecting = false;
|
||||
Caret &caret = *GetLast(view.carets);
|
||||
Caret &caret = view.carets[0];
|
||||
if (view.selection_anchor.min > p) {
|
||||
caret = MakeCaret(p, view.selection_anchor.max);
|
||||
} else if (view.selection_anchor.max < p) {
|
||||
@@ -465,7 +529,7 @@ void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
} else {
|
||||
caret = MakeCaret(view.selection_anchor.max, view.selection_anchor.min);
|
||||
}
|
||||
MergeCarets(*buffer, &view.carets, &view.selection_anchor);
|
||||
MergeCarets(&view, &view.selection_anchor);
|
||||
}
|
||||
} else if (!(mouse_in_view || window->mouse_selecting) && mouse_in_scrollbar || window->mouse_selecting_scrollbar) {
|
||||
Scroller s = ComputeScrollerRect(*window);
|
||||
@@ -499,7 +563,7 @@ void HandleActiveWindowBindings(Window *window, bool *update_scroll) {
|
||||
void HandleWindowBindings(Window *window) {
|
||||
ProfileFunction();
|
||||
View *view = GetActiveView(window);
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
bool update_scroll = true;
|
||||
|
||||
if (IsActive(window)) {
|
||||
@@ -587,11 +651,11 @@ void ReplaceInfobarData() {
|
||||
if (IsActive(window)) return;
|
||||
|
||||
View *view = GetView(window->active_view);
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
|
||||
Window *last_window = GetWindow(GetLastActiveWindow());
|
||||
View *last_view = GetActiveView(last_window);
|
||||
Buffer *last_buffer = GetBuffer(last_view->buffer_id);
|
||||
Buffer *last_buffer = GetBuffer(last_view->active_buffer);
|
||||
Scratch scratch;
|
||||
Caret caret = last_view->carets[0];
|
||||
XY xy = PosToXY(*last_buffer, GetFront(caret));
|
||||
|
||||
@@ -56,7 +56,7 @@ int LuaListViews(lua_State *L) {
|
||||
Scratch scratch;
|
||||
Array<String> strings = {scratch};
|
||||
For(Views) {
|
||||
Buffer *buffer = GetBuffer(it.buffer_id);
|
||||
Buffer *buffer = GetBuffer(it.active_buffer);
|
||||
String string = Format(scratch, "view = %lld buffer = %lld name = %.*s", (long long)it.id.id, (long long)buffer->id.id, FmtString(buffer->name));
|
||||
Add(&strings, string);
|
||||
}
|
||||
@@ -70,12 +70,12 @@ int LuaListWindows(lua_State *L) {
|
||||
Array<String> strings = {scratch};
|
||||
For(Windows) {
|
||||
View *view = GetActiveView(&it);
|
||||
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
String string = Format(scratch, "window = %lld active_view = %lld buffer_name = %.*s", (long long)it.id.id, (long long)it.active_view.id, FmtString(buffer->name));
|
||||
Add(&strings, string);
|
||||
ForItem(child_view_id, it.views) {
|
||||
View *child_view = GetView(child_view_id);
|
||||
Buffer *child_buffer = GetBuffer(child_view->buffer_id);
|
||||
Buffer *child_buffer = GetBuffer(child_view->active_buffer);
|
||||
String child_string = Format(scratch, " view = %lld buffer = %lld name = %.*s", (long long)child_view->id.id, (long long)child_buffer->id.id, FmtString(child_buffer->name));
|
||||
Add(&strings, child_string);
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ void AddView(Window *w, ViewID view) {
|
||||
Add(&w->views, view);
|
||||
}
|
||||
|
||||
View *CreateView(BufferID buffer_id) {
|
||||
View *w = Alloc(&Views);
|
||||
w->id = AllocViewID();
|
||||
w->buffer_id = buffer_id;
|
||||
View *CreateView(BufferID active_buffer) {
|
||||
View *w = Alloc(&Views);
|
||||
w->id = AllocViewID();
|
||||
w->active_buffer = active_buffer;
|
||||
Add(&w->carets, {0, 0});
|
||||
return w;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ Window *FindParentWindow(ViewID view_id) {
|
||||
|
||||
View *FindViewWithBufferName(String name) {
|
||||
For(Views) {
|
||||
Buffer *buffer = GetBuffer(it.buffer_id);
|
||||
Buffer *buffer = GetBuffer(it.active_buffer);
|
||||
if (buffer->name == name) {
|
||||
return ⁢
|
||||
}
|
||||
@@ -175,7 +175,7 @@ void UnlinkView(Window *window, ViewID view) {
|
||||
View *ViewOpenFile(Window *new_parent_window, String name) {
|
||||
For(new_parent_window->views) {
|
||||
View *it_view = GetView(it);
|
||||
Buffer *it_buffer = GetBuffer(it_view->buffer_id);
|
||||
Buffer *it_buffer = GetBuffer(it_view->active_buffer);
|
||||
if (it_buffer->name == name) {
|
||||
new_parent_window->active_view = it;
|
||||
return it_view;
|
||||
|
||||
@@ -97,9 +97,8 @@ int main(void) {
|
||||
}
|
||||
{
|
||||
Window *w = CreateWindow();
|
||||
Buffer *b = CreateBuffer(sys_allocator, "*load_line*");
|
||||
LoadLine(b);
|
||||
View *v = CreateView(b->id);
|
||||
Buffer *b = GetBuffer({0});
|
||||
View *v = CreateView(b->id);
|
||||
AddView(w, v->id);
|
||||
}
|
||||
{
|
||||
|
||||
@@ -39,9 +39,11 @@ struct Buffer {
|
||||
};
|
||||
|
||||
struct View {
|
||||
ViewID id;
|
||||
BufferID buffer_id;
|
||||
Vec2I scroll;
|
||||
ViewID id;
|
||||
BufferID active_buffer;
|
||||
Vec2I scroll;
|
||||
|
||||
Int caret_change_id; // @debug
|
||||
Array<Caret> carets;
|
||||
|
||||
// window | view
|
||||
@@ -111,16 +113,18 @@ Int FontCharSpacing;
|
||||
Int FrameID;
|
||||
Int LastFrameIDWhenScrolled = -1;
|
||||
|
||||
Int CaretChangeID;
|
||||
String WorkingDir;
|
||||
Int LastFrameIDWhenSwitchedActiveWindow;
|
||||
Array<WindowID> WindowSwitchHistory; // @todo: probably better as a circular buffer
|
||||
WindowID ActiveWindow;
|
||||
WindowID ActiveWindow; // @todo: maybe NextActiveWindow and change at end of frame
|
||||
|
||||
String16 EvalString(Allocator allocator, String16 string16);
|
||||
Rect2I GetVisibleCells(Window &window);
|
||||
void AfterEdit(View *view, Array<Edit> edits);
|
||||
Scroller ComputeScrollerRect(Window &window);
|
||||
void Command_EvalLua(View *view, String16 string);
|
||||
void MergeCarets(View *view, Range *mouse_selection_anchor = NULL);
|
||||
|
||||
inline ViewID AllocViewID() { return {ViewIDs.id++}; }
|
||||
inline WindowID AllocWindowID() { return {WindowIDs.id++}; }
|
||||
|
||||
@@ -22,7 +22,7 @@ Rect2I GetVisibleCells(Window &window) {
|
||||
|
||||
Scroller ComputeScrollerRect(Window &window) {
|
||||
View &view = *GetActiveView(&window);
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
Vec2I size = GetSize(window.scrollbar_rect);
|
||||
Rect2I vis = GetVisibleCells(window);
|
||||
Int line_count = buffer->line_starts.len + GetSize(vis).y - 1;
|
||||
@@ -42,7 +42,7 @@ void DrawVisibleText(Window &window) {
|
||||
ProfileFunction();
|
||||
Color tint = ColorText;
|
||||
View &view = *GetActiveView(&window);
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
|
||||
Rect2I visible = GetVisibleCells(window);
|
||||
for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < buffer->line_starts.len; line_index += 1) {
|
||||
@@ -107,7 +107,7 @@ void DrawLineHighlight(Window &window, XY fxy, Color color) {
|
||||
void DrawSelection(Window &window, Caret &it) {
|
||||
ProfileFunction();
|
||||
View &view = *GetActiveView(&window);
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
Int front = GetFront(it);
|
||||
Int back = GetBack(it);
|
||||
if (front != back) {
|
||||
@@ -151,7 +151,7 @@ void DrawSelection(Window &window, Caret &it) {
|
||||
|
||||
void DrawWindow(Window &window) {
|
||||
View &view = *GetActiveView(&window);
|
||||
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||
DrawRectangleRec(ToRectangle(window.total_rect), ColorBackground);
|
||||
bool is_active = IsActive(&window) || window.id.id == GetLastActiveWindow().id;
|
||||
|
||||
@@ -175,10 +175,11 @@ void DrawWindow(Window &window) {
|
||||
For(view.carets) {
|
||||
Int front = GetFront(it);
|
||||
XY fxy = PosToXY(*buffer, front);
|
||||
if (fxy.col >= visible.min.x && fxy.col < visible.min.x && fxy.line >= visible.min.y && fxy.line <= visible.max.y) {
|
||||
bool main_caret = &it == &view.carets.data[0];
|
||||
DrawCaret(window, fxy, 0.3f, main_caret ? ColorMainCaret : ColorSubCaret);
|
||||
}
|
||||
// @todo:
|
||||
// if (fxy.col >= visible.min.x && fxy.col < visible.min.x && fxy.line >= visible.min.y && fxy.line <= visible.max.y) {
|
||||
bool main_caret = &it == &view.carets.data[0];
|
||||
DrawCaret(window, fxy, 0.3f, main_caret ? ColorMainCaret : ColorSubCaret);
|
||||
// }
|
||||
}
|
||||
EndProfileScope();
|
||||
EndScissorMode();
|
||||
|
||||
Reference in New Issue
Block a user