View, window and buffer ids

This commit is contained in:
Krzosa Karol
2024-07-23 08:57:09 +02:00
parent bc4fbfd28a
commit 740b0f217f
9 changed files with 267 additions and 217 deletions

View File

@@ -4,16 +4,18 @@ https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation
#define BUFFER_DEBUG 0
void InitBuffer(Allocator allocator, Buffer *buffer) {
buffer->id = AllocBufferID();
buffer->cap = 4096;
buffer->data = AllocArray(allocator, U16, buffer->cap);
buffer->line_starts.allocator = allocator;
Add(&buffer->line_starts, (Int)0);
}
Buffer *CreateBuffer(Allocator allocator) {
Buffer *result = AllocType(allocator, Buffer);
InitBuffer(allocator, result);
return result;
BufferID CreateBuffer(Allocator allocator) {
Buffer result = {};
InitBuffer(allocator, &result);
Add(&Buffers, result);
return result.id;
}
void Grow(Buffer *buffer, Int change_size) {

View File

@@ -1,46 +0,0 @@
union Range {
struct {
Int min;
Int max;
};
Int e[2];
};
struct Caret {
union {
Range range;
Int pos[2];
};
Int ifront;
};
struct XY {
Int col;
Int line;
};
struct Edit {
Range range;
String16 string;
};
// @idea: maybe redo tree?
struct HistoryEntry {
Array<Edit> edits;
Array<Caret> carets;
};
// @todo: gap buffer to improve speed of inserting on big files with only one cursor?
struct Buffer {
union {
U16 *data;
wchar_t *str;
};
Int len;
Int cap;
Array<Int> line_starts;
Array<HistoryEntry> undo_stack;
Array<HistoryEntry> redo_stack;
int debug_edit_phase;
};

View File

@@ -8,7 +8,7 @@
#include "../profiler/profiler.cpp"
#include "buffer.h"
#include "text_editor.h"
#include "buffer_helpers.cpp"
#include "buffer.cpp"
#include "buffer_multi_cursor.cpp"
@@ -30,13 +30,17 @@ Int FontCharSpacing;
#include "commands.cpp"
#include "colors.cpp"
#include "view.h"
#include "windows.cpp"
#include "view_commands_clipboard.cpp"
#include "view_commands.cpp"
#include "view_draw.cpp"
/*
- Window IDS and View IDS and Buffer IDS
- Null Window, Null View, Null Buffer
- Open file (utf8->utf16), process determine line endings, tabs to spaces?, Save file (utf16->utf8)
- move off raylib
- line endings
@@ -44,8 +48,6 @@ Int FontCharSpacing;
- word completion
- Colored strings
- file dock on left side
- multiple Windows
- multiple views per window
- Font cache
*/
@@ -79,26 +81,48 @@ int main(void) {
Font = LoadFontEx("c:\\Windows\\Fonts\\consola.ttf", (int)FontSize, NULL, 500);
FontCharSpacing = GetCharSpacing(Font, FontSize, FontSpacing);
View view = {};
{
Window window = {};
Window window = {AllocWindowID()};
{
View view = {};
view.id = AllocViewID();
Add(&view.carets, {0, 0});
view.buffer = CreateBuffer(Perm);
LoadTextA(view.buffer);
Add(&window.views, view);
view.buffer_id = CreateBuffer(Perm);
Buffer *buffer = GetBuffer(view.buffer_id);
LoadTextA(buffer);
Add(&Views, view);
Add(&window.views, view.id);
window.active_view = view.id;
}
Add(&Windows, window);
}
{
Window window = {};
Window window = {AllocWindowID()};
{
View view = {};
view.id = AllocViewID();
Add(&view.carets, {0, 0});
view.buffer = CreateBuffer(Perm);
LoadUnicode(view.buffer);
Add(&window.views, view);
view.buffer_id = CreateBuffer(Perm);
Buffer *buffer = GetBuffer(view.buffer_id);
LoadUnicode(buffer);
Add(&Views, view);
Add(&window.views, view.id);
window.active_view = view.id;
}
Add(&Windows, window);
}
{
Window window = {AllocWindowID()};
{
View view = {};
view.id = AllocViewID();
Add(&view.carets, {0, 0});
view.buffer_id = CreateBuffer(Perm);
Buffer *buffer = GetBuffer(view.buffer_id);
LoadLine(buffer);
Add(&Views, view);
Add(&window.views, view.id);
window.active_view = view.id;
}
Add(&Windows, window);
}
@@ -109,19 +133,26 @@ int main(void) {
Rect2I screen_rect = GetScreenRect();
float line_numbers_size = MeasureTextEx(Font, "12345", (float)FontSize, (float)FontSpacing).x;
{
Windows[0].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.5));
Windows[0].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.33));
Windows[0].document_rect = Windows[0].total_rect;
Windows[0].scrollbar_rect = CutRight(&Windows[0].document_rect, 10);
Windows[0].infobar_rect = CutBottom(&Windows[0].document_rect, (Int)MenuFontSize);
Windows[0].line_numbers_rect = CutLeft(&Windows[0].document_rect, (Int)line_numbers_size);
}
{
Windows[1].total_rect = screen_rect;
Windows[1].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 0.5));
Windows[1].document_rect = Windows[1].total_rect;
Windows[1].scrollbar_rect = CutRight(&Windows[1].document_rect, 10);
Windows[1].infobar_rect = CutBottom(&Windows[1].document_rect, (Int)MenuFontSize);
Windows[1].line_numbers_rect = CutLeft(&Windows[1].document_rect, (Int)line_numbers_size);
}
{
Windows[2].total_rect = CutLeft(&screen_rect, (Int)((double)GetSize(screen_rect).x * 1.0));
Windows[2].document_rect = Windows[2].total_rect;
Windows[2].scrollbar_rect = CutRight(&Windows[2].document_rect, 10);
Windows[2].infobar_rect = CutBottom(&Windows[2].document_rect, (Int)MenuFontSize);
Windows[2].line_numbers_rect = CutLeft(&Windows[2].document_rect, (Int)line_numbers_size);
}
BeginDrawing();
ClearBackground(ColorBackground);

View File

@@ -0,0 +1,110 @@
// clang-format off
struct BufferID { Int id; };
struct ViewID { Int id; };
struct WindowID { Int id; };
union Range { struct { Int min; Int max; }; Int e[2]; };
struct Caret { union { Range range; Int pos[2]; }; Int ifront;};
struct XY { Int col; Int line; };
// clang-format on
struct Edit {
Range range;
String16 string;
};
// @idea: maybe redo tree?
struct HistoryEntry {
Array<Edit> edits;
Array<Caret> carets;
};
// @todo: gap buffer to improve speed of inserting on big files with only one cursor?
struct Buffer {
BufferID id;
union {
U16 *data;
wchar_t *str;
};
Int len;
Int cap;
Array<Int> line_starts;
Array<HistoryEntry> undo_stack;
Array<HistoryEntry> redo_stack;
int debug_edit_phase;
};
struct View {
ViewID id;
BufferID buffer_id;
Vec2I scroll;
Array<Caret> carets;
Range selection_anchor;
};
struct Window {
WindowID id;
ViewID active_view;
Array<ViewID> views;
Rect2I total_rect;
Rect2I scrollbar_rect;
Rect2I infobar_rect;
Rect2I line_numbers_rect;
Rect2I document_rect;
int mouse_selecting_scrollbar;
bool mouse_selecting;
double mouse_scroller_offset;
};
struct Scroller {
Rect2 rect;
double begin;
double end;
Int line_count;
};
Rect2I GetVisibleCells(Window &window);
void AfterEdit(View *view, Array<Edit> edits);
Scroller ComputeScrollerRect(Window &window);
WindowID WindowIDs = {1};
BufferID BufferIDs = {1};
ViewID ViewIDs = {1};
Window NullWindow = {};
View NullView = {};
Buffer NullBuffer = {};
Array<Buffer> Buffers = {};
Array<View> Views = {};
Array<Window> Windows = {};
WindowID ActiveWindow = {};
inline Window *GetWindow(WindowID id) {
For(Windows) if (it.id.id == id.id) return &it;
return &NullWindow;
}
inline Buffer *GetBuffer(BufferID id) {
For(Buffers) if (it.id.id == id.id) return &it;
return &NullBuffer;
}
inline View *GetView(ViewID id) {
For(Views) if (it.id.id == id.id) return &it;
return &NullView;
}
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);
}

View File

@@ -1,32 +0,0 @@
struct View {
Vec2I scroll;
Buffer *buffer;
Array<Caret> carets;
Range selection_anchor;
};
struct Window {
Int active_view;
Array<View> views;
Rect2I total_rect;
Rect2I scrollbar_rect;
Rect2I infobar_rect;
Rect2I line_numbers_rect;
Rect2I document_rect;
int mouse_selecting_scrollbar;
bool mouse_selecting;
double mouse_scroller_offset;
};
struct Scroller {
Rect2 rect;
double begin;
double end;
Int line_count;
};
Rect2I GetVisibleCells(Window &window);
void AfterEdit(View *view, Array<Edit> edits);
Scroller ComputeScrollerRect(Window &window);

View File

@@ -1,48 +1,50 @@
void Command_Replace(View *view, String16 string) {
Buffer *buffer = GetBuffer(view->buffer_id);
Scratch scratch;
BeforeEdit(view->buffer, view->carets);
BeforeEdit(buffer, view->carets);
MergeCarets(&view->carets);
Array<Edit> edits = {scratch};
For(view->carets) AddEdit(&edits, it.range, string);
ApplyEdits(view->buffer, edits);
AfterEdit(view->buffer, &edits, &view->carets);
ApplyEdits(buffer, edits);
AfterEdit(buffer, &edits, &view->carets);
}
void Command_DuplicateLine(View *view, int direction) {
Assert(direction == DIR_UP || direction == DIR_DOWN);
BeforeEdit(view->buffer, view->carets);
Buffer *buffer = GetBuffer(view->buffer_id);
BeforeEdit(buffer, view->carets);
For(view->carets) it = MakeCaret(GetFront(it));
MergeCarets(&view->carets);
Scratch scratch;
Array<Edit> edits = {scratch};
For(view->carets) {
Int line = PosToLine(*view->buffer, it.range.min);
Range range = GetLineRange(*view->buffer, line);
String16 string = Copy(scratch, GetString(*view->buffer, range));
Int line = PosToLine(*buffer, it.range.min);
Range range = GetLineRange(*buffer, line);
String16 string = Copy(scratch, GetString(*buffer, range));
Int pos = direction == DIR_UP ? range.min : range.max;
AddEdit(&edits, Rng(pos), string);
}
ApplyEdits(view->buffer, edits);
AfterEdit(view->buffer, &edits, &view->carets);
ApplyEdits(buffer, edits);
AfterEdit(buffer, &edits, &view->carets);
For(view->carets) it = MakeCaret(MovePos(*view->buffer, it.range.min, direction, false));
For(view->carets) it = MakeCaret(MovePos(*buffer, it.range.min, direction, false));
}
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 &buf = *view.buffer;
View &view = *GetActiveView(window);
Buffer *buffer = GetBuffer(view.buffer_id);
Rect2I visible_cells_rect = GetVisibleCells(*window);
Int y = GetSize(visible_cells_rect).y - 2;
if (direction == DIR_UP) y = -y;
For(view.carets) {
XY xy = PosToXY(buf, GetFront(it));
XY xy = PosToXY(*buffer, GetFront(it));
xy.line += y;
Int pos = XYToPos(buf, xy);
Int pos = XYToPos(*buffer, xy);
if (shift) {
it = ChangeFront(it, pos);
} else {
@@ -53,12 +55,12 @@ 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 &buf = *view.buffer;
View &view = *GetActiveView(window);
Buffer *buffer = GetBuffer(view.buffer_id);
For(view.carets) {
Int end_of_buffer = 0;
Range line_range = GetLineRange(buf, PosToLine(buf, GetFront(it)), &end_of_buffer);
Range line_range = GetLineRange(*buffer, PosToLine(*buffer, GetFront(it)), &end_of_buffer);
Int pos = line_range.min;
if (direction == DIR_RIGHT) {
@@ -75,13 +77,13 @@ 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 &buf = *view.buffer;
View &view = *_view;
Buffer *buffer = GetBuffer(view.buffer_id);
// Select things to delete
For(view.carets) {
if (GetSize(it.range)) continue;
Int pos = MovePos(buf, it.range.min, direction, ctrl);
Int pos = MovePos(*buffer, it.range.min, direction, ctrl);
it = MakeCaret(pos, it.range.min);
}
@@ -90,19 +92,19 @@ void Command_Delete(View *_view, int direction, bool ctrl = false) {
void Command_CreateCursorVertical(View *_view, int direction) {
Assert(direction == DIR_UP || direction == DIR_DOWN);
View &view = *_view;
Buffer &buf = *view.buffer;
View &view = *_view;
Buffer *buffer = GetBuffer(view.buffer_id);
Scratch scratch;
Array<Caret> arr = {scratch};
For(view.carets) {
if (PosToLine(buf, it.range.min) == PosToLine(buf, it.range.max)) {
Int f = MovePos(buf, GetFront(it), direction);
Int b = MovePos(buf, GetBack(it), direction);
if (PosToLine(*buffer, it.range.min) == PosToLine(*buffer, it.range.max)) {
Int f = MovePos(*buffer, GetFront(it), direction);
Int b = MovePos(*buffer, GetBack(it), direction);
Add(&arr, MakeCaret(f, b));
} else {
Int pos = direction == DIR_UP ? it.range.min : it.range.max;
Int min = MovePos(buf, pos, direction);
Int min = MovePos(*buffer, pos, direction);
Add(&arr, MakeCaret(min));
}
}
@@ -112,8 +114,8 @@ void Command_CreateCursorVertical(View *_view, int direction) {
void HandleKeybindings(Window *window) {
ProfileFunction();
View &view = *GetActiveView(*window);
Buffer &buf = *view.buffer;
View &view = *GetActiveView(window);
Buffer *buffer = GetBuffer(view.buffer_id);
Caret main_caret_on_begin_frame = view.carets[0];
{
@@ -130,7 +132,7 @@ void HandleKeybindings(Window *window) {
if (!IsActive(window)) {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
ActiveWindow = GetIndex(Windows, *window);
ActiveWindow = window->id;
}
}
}
@@ -141,9 +143,9 @@ void HandleKeybindings(Window *window) {
}
if (CtrlPress(KEY_F2)) {
LoadBigLine(view.buffer);
LoadBigLine(buffer);
} else if (Press(KEY_F2)) {
LoadBigText(view.buffer);
LoadBigText(buffer);
}
if (Press(KEY_ESCAPE)) {
@@ -155,15 +157,15 @@ void HandleKeybindings(Window *window) {
} else if (AltShiftPress(KEY_DOWN)) {
Command_CreateCursorVertical(&view, DIR_DOWN);
} else if (CtrlShiftPress(KEY_DOWN)) {
For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_DOWN, true));
For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_DOWN, true));
} else if (CtrlPress(KEY_DOWN)) {
For(view.carets) it = MakeCaret(MovePos(buf, it.range.max, DIR_DOWN, true));
For(view.carets) it = MakeCaret(MovePos(*buffer, it.range.max, DIR_DOWN, true));
} else if (ShiftPress(KEY_DOWN)) {
For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_DOWN, false));
For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_DOWN, false));
} else if (Press(KEY_DOWN)) {
For(view.carets) {
if (GetSize(it.range) == 0) {
it = MakeCaret(MovePos(buf, it.range.max, DIR_DOWN, false));
it = MakeCaret(MovePos(*buffer, it.range.max, DIR_DOWN, false));
} else {
it = MakeCaret(it.range.max);
}
@@ -175,15 +177,15 @@ void HandleKeybindings(Window *window) {
} else if (AltShiftPress(KEY_UP)) {
Command_CreateCursorVertical(&view, DIR_UP);
} else if (CtrlShiftPress(KEY_UP)) {
For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_UP, CTRL_PRESSED));
For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_UP, CTRL_PRESSED));
} else if (CtrlPress(KEY_UP)) {
For(view.carets) it = MakeCaret(MovePos(buf, it.range.min, DIR_UP, CTRL_PRESSED));
For(view.carets) it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP, CTRL_PRESSED));
} else if (ShiftPress(KEY_UP)) {
For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_UP));
For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_UP));
} else if (Press(KEY_UP)) {
For(view.carets) {
if (GetSize(it.range) == 0) {
it = MakeCaret(MovePos(buf, it.range.min, DIR_UP));
it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP));
} else {
it = MakeCaret(it.range.min);
}
@@ -191,21 +193,21 @@ void HandleKeybindings(Window *window) {
}
if (CtrlShiftPress(KEY_LEFT)) {
For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_LEFT, true));
For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_LEFT, true));
} else if (CtrlPress(KEY_LEFT)) {
For(view.carets) {
if (GetSize(it.range) != 0 && GetFront(it) != it.range.min) {
it = MakeCaret(it.range.min);
} else {
it = MakeCaret(MovePos(buf, it.range.min, DIR_LEFT, true));
it = MakeCaret(MovePos(*buffer, it.range.min, DIR_LEFT, true));
}
}
} else if (ShiftPress(KEY_LEFT)) {
For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_LEFT, false));
For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_LEFT, false));
} else if (Press(KEY_LEFT)) {
For(view.carets) {
if (GetSize(it.range) == 0) {
it = MakeCaret(MovePos(buf, it.range.min, DIR_LEFT, false));
it = MakeCaret(MovePos(*buffer, it.range.min, DIR_LEFT, false));
} else {
it = MakeCaret(it.range.min);
}
@@ -213,21 +215,21 @@ void HandleKeybindings(Window *window) {
}
if (CtrlShiftPress(KEY_RIGHT)) {
For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_RIGHT, true));
For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_RIGHT, true));
} else if (CtrlPress(KEY_RIGHT)) {
For(view.carets) {
if (GetSize(it.range) != 0 && GetFront(it) != it.range.max) {
it = MakeCaret(it.range.max);
} else {
it = MakeCaret(MovePos(buf, it.range.max, DIR_RIGHT, true));
it = MakeCaret(MovePos(*buffer, it.range.max, DIR_RIGHT, true));
}
}
} else if (ShiftPress(KEY_RIGHT)) {
For(view.carets) it = ChangeFront(it, MovePos(buf, GetFront(it), DIR_RIGHT, false));
For(view.carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_RIGHT, false));
} else if (Press(KEY_RIGHT)) {
For(view.carets) {
if (GetSize(it.range) == 0) {
it = MakeCaret(MovePos(buf, it.range.max, DIR_RIGHT, false));
it = MakeCaret(MovePos(*buffer, it.range.max, DIR_RIGHT, false));
} else {
it = MakeCaret(it.range.max);
}
@@ -235,24 +237,24 @@ void HandleKeybindings(Window *window) {
}
if (CtrlPress(KEY_D)) {
Range range = view.carets[0].range;
String16 string = GetString(buf, range);
String16 buffer = GetString(buf, {range.max, INT64_MAX});
Int index = 0;
if (Seek(buffer, string, &index)) {
Range range = view.carets[0].range;
String16 string = GetString(*buffer, range);
String16 string_buffer = GetString(*buffer, {range.max, INT64_MAX});
Int index = 0;
if (Seek(string_buffer, string, &index)) {
Insert(&view.carets, MakeCaret(range.max + index, range.max + index + string.len), 0);
} else {
String16 buffer = GetString(buf);
if (Seek(buffer, string, &index)) {
String16 string_buffer = GetString(*buffer);
if (Seek(string_buffer, string, &index)) {
Insert(&view.carets, MakeCaret(index, index + string.len), 0);
}
}
}
if (CtrlShiftPress(KEY_Z)) {
RedoEdit(&buf, &view.carets);
RedoEdit(buffer, &view.carets);
} else if (CtrlPress(KEY_Z)) {
UndoEdit(&buf, &view.carets);
UndoEdit(buffer, &view.carets);
}
if (CtrlPress(KEY_C)) {
@@ -267,7 +269,7 @@ void HandleKeybindings(Window *window) {
bool dont_update_scroll = false;
if (CtrlPress(KEY_A)) {
view.carets.len = 1;
view.carets[0] = MakeCaret(0, view.buffer->len);
view.carets[0] = MakeCaret(0, buffer->len);
dont_update_scroll = true;
}
@@ -346,14 +348,14 @@ void HandleKeybindings(Window *window) {
Vec2I mworld = mouse - window->document_rect.min + view.scroll;
Vec2I pos = mworld / Vec2I{FontCharSpacing, FontLineSpacing};
XY xy = {(Int)(pos.x), (Int)(pos.y)};
Int p = XYToPosWithoutNL(buf, xy);
Int p = XYToPosWithoutNL(*buffer, xy);
if (mouse_in_view && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
if (IsDoubleClick()) {
Caret *c = GetLast(view.carets);
if (InBounds({c->range.min - 1, c->range.max + 1}, p)) {
c->range = EncloseWord(buf, p);
c->range = EncloseWord(*buffer, p);
view.selection_anchor = c->range;
}
} else {
@@ -414,7 +416,7 @@ void HandleKeybindings(Window *window) {
if (!AreEqual(main_caret_on_begin_frame, view.carets[0]) && !dont_update_scroll) {
Caret c = view.carets[0];
Int front = GetFront(c);
XY xy = PosToXY(buf, front);
XY xy = PosToXY(*buffer, front);
Rect2I visible = GetVisibleCells(*window);
Vec2I visible_cells = GetSize(visible);
@@ -445,7 +447,7 @@ void HandleKeybindings(Window *window) {
// Clip scroll
{
ProfileScope(clip_scroll);
Int last_line = LastLine(view.buffer[0]);
Int last_line = LastLine(*buffer);
view.scroll.y = Clamp(view.scroll.y, (Int)0, Max((Int)0, (last_line - 1) * FontLineSpacing));
// @note:

View File

@@ -3,6 +3,7 @@ Array<String16> SavedClipboardCursors;
void Command_Copy(View *view) {
Allocator sys_allocator = GetSystemAllocator();
Buffer *buffer = GetBuffer(view->buffer_id);
SavedClipboardCursors.allocator = sys_allocator;
if (SavedClipboardCursors.data) {
@@ -18,14 +19,14 @@ void Command_Copy(View *view) {
// First, if there is no selection - select the entire line
For(view->carets) {
if (GetSize(it.range) == 0) {
Int line = PosToLine(*view->buffer, it.range.min);
Range line_range = GetLineRange(*view->buffer, line);
Int line = PosToLine(*buffer, it.range.min);
Range line_range = GetLineRange(*buffer, line);
it.range = line_range;
}
}
For(view->carets) {
String16 string = GetString(*view->buffer, it.range);
String16 string = GetString(*buffer, it.range);
String16 copy = Copy(sys_allocator, string);
Add(&SavedClipboardCursors, copy);
}
@@ -38,23 +39,24 @@ void Command_Copy(View *view) {
void Command_Paste(View *view) {
Scratch scratch;
Buffer *buffer = GetBuffer(view->buffer_id);
const char *text = GetClipboardText();
String string_ = text;
String16 string = ToString16(scratch, string_);
// Regular paste
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
BeforeEdit(view->buffer, view->carets);
BeforeEdit(buffer, view->carets);
MergeCarets(&view->carets);
Array<Edit> edits = {scratch};
For(view->carets) AddEdit(&edits, it.range, string);
ApplyEdits(view->buffer, edits);
AfterEdit(view->buffer, &edits, &view->carets);
ApplyEdits(buffer, edits);
AfterEdit(buffer, &edits, &view->carets);
return;
}
// Multicursor paste
BeforeEdit(view->buffer, view->carets);
BeforeEdit(buffer, view->carets);
MergeCarets(&view->carets);
Array<Edit> edits = {scratch};
for (int64_t i = 0; i < view->carets.len; i += 1) {
@@ -62,6 +64,6 @@ void Command_Paste(View *view) {
Caret &it = view->carets[i];
AddEdit(&edits, it.range, string);
}
ApplyEdits(view->buffer, edits);
AfterEdit(view->buffer, &edits, &view->carets);
ApplyEdits(buffer, edits);
AfterEdit(buffer, &edits, &view->carets);
}

View File

@@ -5,7 +5,7 @@ Vec2I GetCellSize() {
Rect2I GetVisibleCells(Window &window) {
ProfileFunction();
View &view = *GetActiveView(window);
View &view = *GetActiveView(&window);
Vec2I size = GetSize(window.document_rect);
Int _cx = size.x / FontCharSpacing;
@@ -21,10 +21,11 @@ Rect2I GetVisibleCells(Window &window) {
}
Scroller ComputeScrollerRect(Window &window) {
View &view = *GetActiveView(window);
Vec2I size = GetSize(window.scrollbar_rect);
Rect2I vis = GetVisibleCells(window);
Int line_count = view.buffer->line_starts.len + GetSize(vis).y - 1;
View &view = *GetActiveView(&window);
Buffer *buffer = GetBuffer(view.buffer_id);
Vec2I size = GetSize(window.scrollbar_rect);
Rect2I vis = GetVisibleCells(window);
Int line_count = buffer->line_starts.len + GetSize(vis).y - 1;
double begin = (double)vis.min.y / (double)line_count;
double end = (double)vis.max.y / (double)line_count;
@@ -39,13 +40,14 @@ Scroller ComputeScrollerRect(Window &window) {
void DrawVisibleText(Window &window) {
ProfileFunction();
Color tint = ColorText;
View &view = *GetActiveView(window);
Color tint = ColorText;
View &view = *GetActiveView(&window);
Buffer *buffer = GetBuffer(view.buffer_id);
Rect2I visible = GetVisibleCells(window);
for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < view.buffer->line_starts.len; line_index += 1) {
Range line_range = GetLineRange(*view.buffer, line_index);
String16 line_string = GetString(*view.buffer, line_range);
for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < buffer->line_starts.len; line_index += 1) {
Range line_range = GetLineRange(*buffer, line_index);
String16 line_string = GetString(*buffer, line_range);
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
pos -= view.scroll;
@@ -81,7 +83,7 @@ Rect2I XYToRect(const View &view, XY xy) {
}
void DrawCaret(Window &window, XY xy, float size, Color color) {
View &view = *GetActiveView(window);
View &view = *GetActiveView(&window);
Rect2I _rect = XYToRect(view, xy);
Rect2I rect = CutLeft(&_rect, (Int)(size * (float)FontCharSpacing));
rect -= view.scroll;
@@ -90,7 +92,7 @@ void DrawCaret(Window &window, XY xy, float size, Color color) {
}
void DrawLineHighlight(Window &window, XY fxy, Color color) {
View &view = *GetActiveView(window);
View &view = *GetActiveView(&window);
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
w -= view.scroll;
w += window.document_rect.min;
@@ -103,20 +105,20 @@ void DrawLineHighlight(Window &window, XY fxy, Color color) {
void DrawSelection(Window &window, Caret &it) {
ProfileFunction();
View &view = *GetActiveView(window);
Buffer &buf = *view.buffer;
Int front = GetFront(it);
Int back = GetBack(it);
View &view = *GetActiveView(&window);
Buffer *buffer = GetBuffer(view.buffer_id);
Int front = GetFront(it);
Int back = GetBack(it);
if (front != back) {
XY bxy = PosToXY(buf, back);
XY min = PosToXY(buf, it.range.min);
XY max = PosToXY(buf, it.range.max);
XY bxy = PosToXY(*buffer, back);
XY min = PosToXY(*buffer, it.range.min);
XY max = PosToXY(*buffer, it.range.max);
Color color = ColorSelection;
Rect2I vlines = GetVisibleCells(window);
for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < view.buffer->line_starts.len; line += 1) {
Range range = GetLineRange(buf, line);
String16 line_string = GetString(buf, range);
for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < buffer->line_starts.len; line += 1) {
Range range = GetLineRange(*buffer, line);
String16 line_string = GetString(*buffer, range);
for (Int col = vlines.min.x; col < vlines.max.x && col >= 0 && col < line_string.len; col += 1) {
bool a = line > min.line && line < max.line;
@@ -146,13 +148,13 @@ void DrawSelection(Window &window, Caret &it) {
}
void DrawWindow(Window &window) {
View &view = *GetActiveView(window);
Buffer &buf = *view.buffer;
View &view = *GetActiveView(&window);
Buffer *buffer = GetBuffer(view.buffer_id);
BeginScissorMode((int)window.document_rect.min.x, (int)window.document_rect.min.y, (int)window.document_rect.max.x - (int)window.document_rect.min.x, (int)window.document_rect.max.y - (int)window.document_rect.min.y);
For(view.carets) {
Int front = GetFront(it);
XY fxy = PosToXY(buf, front);
XY fxy = PosToXY(*buffer, front);
if (GetSize(it.range)) {
DrawSelection(window, it);
} else {
@@ -164,7 +166,7 @@ void DrawWindow(Window &window) {
For(view.carets) {
Int front = GetFront(it);
XY fxy = PosToXY(buf, front);
XY fxy = PosToXY(*buffer, front);
bool main_caret = &it == &view.carets.data[0];
DrawCaret(window, fxy, 0.3f, main_caret ? ColorMainCaret : ColorSubCaret);
}
@@ -180,7 +182,7 @@ void DrawWindow(Window &window) {
Rect2 rect = Shrink(scroller.rect, 2);
Color color = ColorScrollbarScroller;
if (!window.mouse_selecting && (window.mouse_selecting_scrollbar || mouse_in_scrollbar)) {
color = ColorScrollbarScrollerSelected;
if (IsActive(&window)) color = ColorScrollbarScrollerSelected;
}
DrawRectangleRec(ToRectangle(rect), color);
}
@@ -218,7 +220,7 @@ void DrawWindow(Window &window) {
Vec2 p = ToVec2(r.min);
Scratch scratch;
Caret caret = view.carets[0];
XY xy = PosToXY(*view.buffer, GetFront(caret));
XY xy = PosToXY(*buffer, GetFront(caret));
String s = Format(scratch, "-- line: %lld col: %lld", (long long)xy.line + 1ll, (long long)xy.col + 1ll);
String16 string = ToString16(scratch, s);
DrawString(MenuFont, string, p, MenuFontSize, 1, ColorText);

View File

@@ -1,21 +0,0 @@
Array<Window> Windows = {};
Int ActiveWindow = 0;
Window *GetActiveWindow() {
return &Windows[ActiveWindow];
}
View *GetActiveView(Window &window) {
return &window.views[window.active_view];
}
bool IsActive(Window *window) {
Window *active_window = GetActiveWindow();
bool result = window == active_window;
return result;
}
bool IsActive(Window *window, View *view) {
bool result = view == GetActiveView(*window);
return result;
}