View, window and buffer ids
This commit is contained in:
@@ -4,16 +4,18 @@ 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) {
|
void InitBuffer(Allocator allocator, Buffer *buffer) {
|
||||||
|
buffer->id = AllocBufferID();
|
||||||
buffer->cap = 4096;
|
buffer->cap = 4096;
|
||||||
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) {
|
BufferID CreateBuffer(Allocator allocator) {
|
||||||
Buffer *result = AllocType(allocator, Buffer);
|
Buffer result = {};
|
||||||
InitBuffer(allocator, result);
|
InitBuffer(allocator, &result);
|
||||||
return result;
|
Add(&Buffers, result);
|
||||||
|
return result.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grow(Buffer *buffer, Int change_size) {
|
void Grow(Buffer *buffer, Int change_size) {
|
||||||
|
|||||||
@@ -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;
|
|
||||||
};
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "../profiler/profiler.cpp"
|
#include "../profiler/profiler.cpp"
|
||||||
|
|
||||||
#include "buffer.h"
|
#include "text_editor.h"
|
||||||
#include "buffer_helpers.cpp"
|
#include "buffer_helpers.cpp"
|
||||||
#include "buffer.cpp"
|
#include "buffer.cpp"
|
||||||
#include "buffer_multi_cursor.cpp"
|
#include "buffer_multi_cursor.cpp"
|
||||||
@@ -30,13 +30,17 @@ Int FontCharSpacing;
|
|||||||
#include "commands.cpp"
|
#include "commands.cpp"
|
||||||
#include "colors.cpp"
|
#include "colors.cpp"
|
||||||
|
|
||||||
#include "view.h"
|
|
||||||
#include "windows.cpp"
|
#include "windows.cpp"
|
||||||
#include "view_commands_clipboard.cpp"
|
#include "view_commands_clipboard.cpp"
|
||||||
#include "view_commands.cpp"
|
#include "view_commands.cpp"
|
||||||
#include "view_draw.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
|
- move off raylib
|
||||||
- line endings
|
- line endings
|
||||||
@@ -44,8 +48,6 @@ Int FontCharSpacing;
|
|||||||
- word completion
|
- word completion
|
||||||
- Colored strings
|
- Colored strings
|
||||||
- file dock on left side
|
- file dock on left side
|
||||||
- multiple Windows
|
|
||||||
- multiple views per window
|
|
||||||
- Font cache
|
- Font cache
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -79,26 +81,48 @@ int main(void) {
|
|||||||
Font = LoadFontEx("c:\\Windows\\Fonts\\consola.ttf", (int)FontSize, NULL, 500);
|
Font = LoadFontEx("c:\\Windows\\Fonts\\consola.ttf", (int)FontSize, NULL, 500);
|
||||||
FontCharSpacing = GetCharSpacing(Font, FontSize, FontSpacing);
|
FontCharSpacing = GetCharSpacing(Font, FontSize, FontSpacing);
|
||||||
|
|
||||||
View view = {};
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Window window = {};
|
Window window = {AllocWindowID()};
|
||||||
{
|
{
|
||||||
|
View view = {};
|
||||||
|
view.id = AllocViewID();
|
||||||
Add(&view.carets, {0, 0});
|
Add(&view.carets, {0, 0});
|
||||||
view.buffer = CreateBuffer(Perm);
|
view.buffer_id = CreateBuffer(Perm);
|
||||||
LoadTextA(view.buffer);
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
Add(&window.views, view);
|
LoadTextA(buffer);
|
||||||
|
Add(&Views, view);
|
||||||
|
Add(&window.views, view.id);
|
||||||
|
window.active_view = view.id;
|
||||||
}
|
}
|
||||||
Add(&Windows, window);
|
Add(&Windows, window);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Window window = {};
|
Window window = {AllocWindowID()};
|
||||||
{
|
{
|
||||||
View view = {};
|
View view = {};
|
||||||
|
view.id = AllocViewID();
|
||||||
Add(&view.carets, {0, 0});
|
Add(&view.carets, {0, 0});
|
||||||
view.buffer = CreateBuffer(Perm);
|
view.buffer_id = CreateBuffer(Perm);
|
||||||
LoadUnicode(view.buffer);
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
Add(&window.views, view);
|
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);
|
Add(&Windows, window);
|
||||||
}
|
}
|
||||||
@@ -109,19 +133,26 @@ int main(void) {
|
|||||||
Rect2I screen_rect = GetScreenRect();
|
Rect2I screen_rect = GetScreenRect();
|
||||||
float line_numbers_size = MeasureTextEx(Font, "12345", (float)FontSize, (float)FontSpacing).x;
|
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].document_rect = Windows[0].total_rect;
|
||||||
Windows[0].scrollbar_rect = CutRight(&Windows[0].document_rect, 10);
|
Windows[0].scrollbar_rect = CutRight(&Windows[0].document_rect, 10);
|
||||||
Windows[0].infobar_rect = CutBottom(&Windows[0].document_rect, (Int)MenuFontSize);
|
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[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].document_rect = Windows[1].total_rect;
|
||||||
Windows[1].scrollbar_rect = CutRight(&Windows[1].document_rect, 10);
|
Windows[1].scrollbar_rect = CutRight(&Windows[1].document_rect, 10);
|
||||||
Windows[1].infobar_rect = CutBottom(&Windows[1].document_rect, (Int)MenuFontSize);
|
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[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();
|
BeginDrawing();
|
||||||
ClearBackground(ColorBackground);
|
ClearBackground(ColorBackground);
|
||||||
|
|||||||
110
src/text_editor/text_editor.h
Normal file
110
src/text_editor/text_editor.h
Normal 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 ⁢
|
||||||
|
return &NullWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Buffer *GetBuffer(BufferID id) {
|
||||||
|
For(Buffers) if (it.id.id == id.id) return ⁢
|
||||||
|
return &NullBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline View *GetView(ViewID id) {
|
||||||
|
For(Views) if (it.id.id == id.id) return ⁢
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -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);
|
|
||||||
@@ -1,48 +1,50 @@
|
|||||||
void Command_Replace(View *view, String16 string) {
|
void Command_Replace(View *view, String16 string) {
|
||||||
|
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
BeforeEdit(view->buffer, view->carets);
|
BeforeEdit(buffer, view->carets);
|
||||||
MergeCarets(&view->carets);
|
MergeCarets(&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(view->buffer, edits);
|
ApplyEdits(buffer, edits);
|
||||||
AfterEdit(view->buffer, &edits, &view->carets);
|
AfterEdit(buffer, &edits, &view->carets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Command_DuplicateLine(View *view, int direction) {
|
void Command_DuplicateLine(View *view, int direction) {
|
||||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
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));
|
For(view->carets) it = MakeCaret(GetFront(it));
|
||||||
MergeCarets(&view->carets);
|
MergeCarets(&view->carets);
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Edit> edits = {scratch};
|
Array<Edit> edits = {scratch};
|
||||||
For(view->carets) {
|
For(view->carets) {
|
||||||
Int line = PosToLine(*view->buffer, it.range.min);
|
Int line = PosToLine(*buffer, it.range.min);
|
||||||
Range range = GetLineRange(*view->buffer, line);
|
Range range = GetLineRange(*buffer, line);
|
||||||
String16 string = Copy(scratch, GetString(*view->buffer, range));
|
String16 string = Copy(scratch, GetString(*buffer, range));
|
||||||
Int pos = direction == DIR_UP ? range.min : range.max;
|
Int pos = direction == DIR_UP ? range.min : range.max;
|
||||||
AddEdit(&edits, Rng(pos), string);
|
AddEdit(&edits, Rng(pos), string);
|
||||||
}
|
}
|
||||||
ApplyEdits(view->buffer, edits);
|
ApplyEdits(buffer, edits);
|
||||||
AfterEdit(view->buffer, &edits, &view->carets);
|
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;
|
bool SHIFT_PRESSED = true;
|
||||||
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {
|
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {
|
||||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
||||||
View &view = *GetActiveView(*window);
|
View &view = *GetActiveView(window);
|
||||||
Buffer &buf = *view.buffer;
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
|
|
||||||
Rect2I visible_cells_rect = GetVisibleCells(*window);
|
Rect2I visible_cells_rect = GetVisibleCells(*window);
|
||||||
Int y = GetSize(visible_cells_rect).y - 2;
|
Int y = GetSize(visible_cells_rect).y - 2;
|
||||||
if (direction == DIR_UP) y = -y;
|
if (direction == DIR_UP) y = -y;
|
||||||
|
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
XY xy = PosToXY(buf, GetFront(it));
|
XY xy = PosToXY(*buffer, GetFront(it));
|
||||||
xy.line += y;
|
xy.line += y;
|
||||||
Int pos = XYToPos(buf, xy);
|
Int pos = XYToPos(*buffer, xy);
|
||||||
if (shift) {
|
if (shift) {
|
||||||
it = ChangeFront(it, pos);
|
it = ChangeFront(it, pos);
|
||||||
} else {
|
} 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) {
|
void Command_MoveCursorsToSide(Window *window, int direction, bool shift = false) {
|
||||||
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
||||||
View &view = *GetActiveView(*window);
|
View &view = *GetActiveView(window);
|
||||||
Buffer &buf = *view.buffer;
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
|
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
Int end_of_buffer = 0;
|
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;
|
Int pos = line_range.min;
|
||||||
if (direction == DIR_RIGHT) {
|
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) {
|
void Command_Delete(View *_view, int direction, bool ctrl = false) {
|
||||||
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
||||||
View &view = *_view;
|
View &view = *_view;
|
||||||
Buffer &buf = *view.buffer;
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
|
|
||||||
// Select things to delete
|
// Select things to delete
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (GetSize(it.range)) continue;
|
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);
|
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) {
|
void Command_CreateCursorVertical(View *_view, int direction) {
|
||||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
||||||
View &view = *_view;
|
View &view = *_view;
|
||||||
Buffer &buf = *view.buffer;
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Caret> arr = {scratch};
|
Array<Caret> arr = {scratch};
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (PosToLine(buf, it.range.min) == PosToLine(buf, it.range.max)) {
|
if (PosToLine(*buffer, it.range.min) == PosToLine(*buffer, it.range.max)) {
|
||||||
Int f = MovePos(buf, GetFront(it), direction);
|
Int f = MovePos(*buffer, GetFront(it), direction);
|
||||||
Int b = MovePos(buf, GetBack(it), direction);
|
Int b = MovePos(*buffer, GetBack(it), direction);
|
||||||
Add(&arr, MakeCaret(f, b));
|
Add(&arr, MakeCaret(f, b));
|
||||||
} else {
|
} else {
|
||||||
Int pos = direction == DIR_UP ? it.range.min : it.range.max;
|
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));
|
Add(&arr, MakeCaret(min));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,8 +114,8 @@ void Command_CreateCursorVertical(View *_view, int direction) {
|
|||||||
|
|
||||||
void HandleKeybindings(Window *window) {
|
void HandleKeybindings(Window *window) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
View &view = *GetActiveView(*window);
|
View &view = *GetActiveView(window);
|
||||||
Buffer &buf = *view.buffer;
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
Caret main_caret_on_begin_frame = view.carets[0];
|
Caret main_caret_on_begin_frame = view.carets[0];
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -130,7 +132,7 @@ void HandleKeybindings(Window *window) {
|
|||||||
|
|
||||||
if (!IsActive(window)) {
|
if (!IsActive(window)) {
|
||||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
|
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
|
||||||
ActiveWindow = GetIndex(Windows, *window);
|
ActiveWindow = window->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,9 +143,9 @@ void HandleKeybindings(Window *window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlPress(KEY_F2)) {
|
if (CtrlPress(KEY_F2)) {
|
||||||
LoadBigLine(view.buffer);
|
LoadBigLine(buffer);
|
||||||
} else if (Press(KEY_F2)) {
|
} else if (Press(KEY_F2)) {
|
||||||
LoadBigText(view.buffer);
|
LoadBigText(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Press(KEY_ESCAPE)) {
|
if (Press(KEY_ESCAPE)) {
|
||||||
@@ -155,15 +157,15 @@ void HandleKeybindings(Window *window) {
|
|||||||
} else if (AltShiftPress(KEY_DOWN)) {
|
} else if (AltShiftPress(KEY_DOWN)) {
|
||||||
Command_CreateCursorVertical(&view, DIR_DOWN);
|
Command_CreateCursorVertical(&view, DIR_DOWN);
|
||||||
} else if (CtrlShiftPress(KEY_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)) {
|
} 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)) {
|
} 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)) {
|
} else if (Press(KEY_DOWN)) {
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (GetSize(it.range) == 0) {
|
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 {
|
} else {
|
||||||
it = MakeCaret(it.range.max);
|
it = MakeCaret(it.range.max);
|
||||||
}
|
}
|
||||||
@@ -175,15 +177,15 @@ void HandleKeybindings(Window *window) {
|
|||||||
} else if (AltShiftPress(KEY_UP)) {
|
} else if (AltShiftPress(KEY_UP)) {
|
||||||
Command_CreateCursorVertical(&view, DIR_UP);
|
Command_CreateCursorVertical(&view, DIR_UP);
|
||||||
} else if (CtrlShiftPress(KEY_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)) {
|
} 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)) {
|
} 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)) {
|
} else if (Press(KEY_UP)) {
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (GetSize(it.range) == 0) {
|
if (GetSize(it.range) == 0) {
|
||||||
it = MakeCaret(MovePos(buf, it.range.min, DIR_UP));
|
it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP));
|
||||||
} else {
|
} else {
|
||||||
it = MakeCaret(it.range.min);
|
it = MakeCaret(it.range.min);
|
||||||
}
|
}
|
||||||
@@ -191,21 +193,21 @@ void HandleKeybindings(Window *window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlShiftPress(KEY_LEFT)) {
|
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)) {
|
} else if (CtrlPress(KEY_LEFT)) {
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (GetSize(it.range) != 0 && GetFront(it) != it.range.min) {
|
if (GetSize(it.range) != 0 && GetFront(it) != it.range.min) {
|
||||||
it = MakeCaret(it.range.min);
|
it = MakeCaret(it.range.min);
|
||||||
} else {
|
} 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)) {
|
} 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)) {
|
} else if (Press(KEY_LEFT)) {
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (GetSize(it.range) == 0) {
|
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 {
|
} else {
|
||||||
it = MakeCaret(it.range.min);
|
it = MakeCaret(it.range.min);
|
||||||
}
|
}
|
||||||
@@ -213,21 +215,21 @@ void HandleKeybindings(Window *window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlShiftPress(KEY_RIGHT)) {
|
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)) {
|
} else if (CtrlPress(KEY_RIGHT)) {
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (GetSize(it.range) != 0 && GetFront(it) != it.range.max) {
|
if (GetSize(it.range) != 0 && GetFront(it) != it.range.max) {
|
||||||
it = MakeCaret(it.range.max);
|
it = MakeCaret(it.range.max);
|
||||||
} else {
|
} 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)) {
|
} 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)) {
|
} else if (Press(KEY_RIGHT)) {
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (GetSize(it.range) == 0) {
|
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 {
|
} else {
|
||||||
it = MakeCaret(it.range.max);
|
it = MakeCaret(it.range.max);
|
||||||
}
|
}
|
||||||
@@ -235,24 +237,24 @@ void HandleKeybindings(Window *window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlPress(KEY_D)) {
|
if (CtrlPress(KEY_D)) {
|
||||||
Range range = view.carets[0].range;
|
Range range = view.carets[0].range;
|
||||||
String16 string = GetString(buf, range);
|
String16 string = GetString(*buffer, range);
|
||||||
String16 buffer = GetString(buf, {range.max, INT64_MAX});
|
String16 string_buffer = GetString(*buffer, {range.max, INT64_MAX});
|
||||||
Int index = 0;
|
Int index = 0;
|
||||||
if (Seek(buffer, string, &index)) {
|
if (Seek(string_buffer, string, &index)) {
|
||||||
Insert(&view.carets, MakeCaret(range.max + index, range.max + index + string.len), 0);
|
Insert(&view.carets, MakeCaret(range.max + index, range.max + index + string.len), 0);
|
||||||
} else {
|
} else {
|
||||||
String16 buffer = GetString(buf);
|
String16 string_buffer = GetString(*buffer);
|
||||||
if (Seek(buffer, string, &index)) {
|
if (Seek(string_buffer, string, &index)) {
|
||||||
Insert(&view.carets, MakeCaret(index, index + string.len), 0);
|
Insert(&view.carets, MakeCaret(index, index + string.len), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlShiftPress(KEY_Z)) {
|
if (CtrlShiftPress(KEY_Z)) {
|
||||||
RedoEdit(&buf, &view.carets);
|
RedoEdit(buffer, &view.carets);
|
||||||
} else if (CtrlPress(KEY_Z)) {
|
} else if (CtrlPress(KEY_Z)) {
|
||||||
UndoEdit(&buf, &view.carets);
|
UndoEdit(buffer, &view.carets);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlPress(KEY_C)) {
|
if (CtrlPress(KEY_C)) {
|
||||||
@@ -267,7 +269,7 @@ void HandleKeybindings(Window *window) {
|
|||||||
bool dont_update_scroll = false;
|
bool dont_update_scroll = false;
|
||||||
if (CtrlPress(KEY_A)) {
|
if (CtrlPress(KEY_A)) {
|
||||||
view.carets.len = 1;
|
view.carets.len = 1;
|
||||||
view.carets[0] = MakeCaret(0, view.buffer->len);
|
view.carets[0] = MakeCaret(0, buffer->len);
|
||||||
dont_update_scroll = true;
|
dont_update_scroll = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,14 +348,14 @@ void HandleKeybindings(Window *window) {
|
|||||||
Vec2I mworld = mouse - window->document_rect.min + view.scroll;
|
Vec2I mworld = mouse - window->document_rect.min + view.scroll;
|
||||||
Vec2I pos = mworld / Vec2I{FontCharSpacing, FontLineSpacing};
|
Vec2I pos = mworld / Vec2I{FontCharSpacing, FontLineSpacing};
|
||||||
XY xy = {(Int)(pos.x), (Int)(pos.y)};
|
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 (mouse_in_view && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
|
||||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
|
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
|
||||||
if (IsDoubleClick()) {
|
if (IsDoubleClick()) {
|
||||||
Caret *c = GetLast(view.carets);
|
Caret *c = GetLast(view.carets);
|
||||||
if (InBounds({c->range.min - 1, c->range.max + 1}, p)) {
|
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;
|
view.selection_anchor = c->range;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -414,7 +416,7 @@ void HandleKeybindings(Window *window) {
|
|||||||
if (!AreEqual(main_caret_on_begin_frame, view.carets[0]) && !dont_update_scroll) {
|
if (!AreEqual(main_caret_on_begin_frame, view.carets[0]) && !dont_update_scroll) {
|
||||||
Caret c = view.carets[0];
|
Caret c = view.carets[0];
|
||||||
Int front = GetFront(c);
|
Int front = GetFront(c);
|
||||||
XY xy = PosToXY(buf, front);
|
XY xy = PosToXY(*buffer, front);
|
||||||
|
|
||||||
Rect2I visible = GetVisibleCells(*window);
|
Rect2I visible = GetVisibleCells(*window);
|
||||||
Vec2I visible_cells = GetSize(visible);
|
Vec2I visible_cells = GetSize(visible);
|
||||||
@@ -445,7 +447,7 @@ void HandleKeybindings(Window *window) {
|
|||||||
// Clip scroll
|
// Clip scroll
|
||||||
{
|
{
|
||||||
ProfileScope(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));
|
view.scroll.y = Clamp(view.scroll.y, (Int)0, Max((Int)0, (last_line - 1) * FontLineSpacing));
|
||||||
|
|
||||||
// @note:
|
// @note:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ Array<String16> SavedClipboardCursors;
|
|||||||
|
|
||||||
void Command_Copy(View *view) {
|
void Command_Copy(View *view) {
|
||||||
Allocator sys_allocator = GetSystemAllocator();
|
Allocator sys_allocator = GetSystemAllocator();
|
||||||
|
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||||
|
|
||||||
SavedClipboardCursors.allocator = sys_allocator;
|
SavedClipboardCursors.allocator = sys_allocator;
|
||||||
if (SavedClipboardCursors.data) {
|
if (SavedClipboardCursors.data) {
|
||||||
@@ -18,14 +19,14 @@ void Command_Copy(View *view) {
|
|||||||
// First, if there is no selection - select the entire line
|
// First, if there is no selection - select the entire line
|
||||||
For(view->carets) {
|
For(view->carets) {
|
||||||
if (GetSize(it.range) == 0) {
|
if (GetSize(it.range) == 0) {
|
||||||
Int line = PosToLine(*view->buffer, it.range.min);
|
Int line = PosToLine(*buffer, it.range.min);
|
||||||
Range line_range = GetLineRange(*view->buffer, line);
|
Range line_range = GetLineRange(*buffer, line);
|
||||||
it.range = line_range;
|
it.range = line_range;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
For(view->carets) {
|
For(view->carets) {
|
||||||
String16 string = GetString(*view->buffer, it.range);
|
String16 string = GetString(*buffer, it.range);
|
||||||
String16 copy = Copy(sys_allocator, string);
|
String16 copy = Copy(sys_allocator, string);
|
||||||
Add(&SavedClipboardCursors, copy);
|
Add(&SavedClipboardCursors, copy);
|
||||||
}
|
}
|
||||||
@@ -38,23 +39,24 @@ void Command_Copy(View *view) {
|
|||||||
|
|
||||||
void Command_Paste(View *view) {
|
void Command_Paste(View *view) {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
|
Buffer *buffer = GetBuffer(view->buffer_id);
|
||||||
const char *text = GetClipboardText();
|
const char *text = GetClipboardText();
|
||||||
String string_ = text;
|
String string_ = text;
|
||||||
String16 string = ToString16(scratch, string_);
|
String16 string = ToString16(scratch, string_);
|
||||||
|
|
||||||
// Regular paste
|
// Regular paste
|
||||||
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
|
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
|
||||||
BeforeEdit(view->buffer, view->carets);
|
BeforeEdit(buffer, view->carets);
|
||||||
MergeCarets(&view->carets);
|
MergeCarets(&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(view->buffer, edits);
|
ApplyEdits(buffer, edits);
|
||||||
AfterEdit(view->buffer, &edits, &view->carets);
|
AfterEdit(buffer, &edits, &view->carets);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multicursor paste
|
// Multicursor paste
|
||||||
BeforeEdit(view->buffer, view->carets);
|
BeforeEdit(buffer, view->carets);
|
||||||
MergeCarets(&view->carets);
|
MergeCarets(&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) {
|
||||||
@@ -62,6 +64,6 @@ void Command_Paste(View *view) {
|
|||||||
Caret &it = view->carets[i];
|
Caret &it = view->carets[i];
|
||||||
AddEdit(&edits, it.range, string);
|
AddEdit(&edits, it.range, string);
|
||||||
}
|
}
|
||||||
ApplyEdits(view->buffer, edits);
|
ApplyEdits(buffer, edits);
|
||||||
AfterEdit(view->buffer, &edits, &view->carets);
|
AfterEdit(buffer, &edits, &view->carets);
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ Vec2I GetCellSize() {
|
|||||||
|
|
||||||
Rect2I GetVisibleCells(Window &window) {
|
Rect2I GetVisibleCells(Window &window) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
View &view = *GetActiveView(window);
|
View &view = *GetActiveView(&window);
|
||||||
Vec2I size = GetSize(window.document_rect);
|
Vec2I size = GetSize(window.document_rect);
|
||||||
|
|
||||||
Int _cx = size.x / FontCharSpacing;
|
Int _cx = size.x / FontCharSpacing;
|
||||||
@@ -21,10 +21,11 @@ Rect2I GetVisibleCells(Window &window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Scroller ComputeScrollerRect(Window &window) {
|
Scroller ComputeScrollerRect(Window &window) {
|
||||||
View &view = *GetActiveView(window);
|
View &view = *GetActiveView(&window);
|
||||||
Vec2I size = GetSize(window.scrollbar_rect);
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
Rect2I vis = GetVisibleCells(window);
|
Vec2I size = GetSize(window.scrollbar_rect);
|
||||||
Int line_count = view.buffer->line_starts.len + GetSize(vis).y - 1;
|
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 begin = (double)vis.min.y / (double)line_count;
|
||||||
double end = (double)vis.max.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) {
|
void DrawVisibleText(Window &window) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
Color tint = ColorText;
|
Color tint = ColorText;
|
||||||
View &view = *GetActiveView(window);
|
View &view = *GetActiveView(&window);
|
||||||
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
|
|
||||||
Rect2I visible = GetVisibleCells(window);
|
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) {
|
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(*view.buffer, line_index);
|
Range line_range = GetLineRange(*buffer, line_index);
|
||||||
String16 line_string = GetString(*view.buffer, line_range);
|
String16 line_string = GetString(*buffer, line_range);
|
||||||
|
|
||||||
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
||||||
pos -= view.scroll;
|
pos -= view.scroll;
|
||||||
@@ -81,7 +83,7 @@ Rect2I XYToRect(const View &view, XY xy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawCaret(Window &window, XY xy, float size, Color color) {
|
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 = XYToRect(view, xy);
|
||||||
Rect2I rect = CutLeft(&_rect, (Int)(size * (float)FontCharSpacing));
|
Rect2I rect = CutLeft(&_rect, (Int)(size * (float)FontCharSpacing));
|
||||||
rect -= view.scroll;
|
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) {
|
void DrawLineHighlight(Window &window, XY fxy, Color color) {
|
||||||
View &view = *GetActiveView(window);
|
View &view = *GetActiveView(&window);
|
||||||
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
|
Vec2I w = XYToWorldPos(view, XYLine(fxy.line));
|
||||||
w -= view.scroll;
|
w -= view.scroll;
|
||||||
w += window.document_rect.min;
|
w += window.document_rect.min;
|
||||||
@@ -103,20 +105,20 @@ void DrawLineHighlight(Window &window, XY fxy, Color color) {
|
|||||||
|
|
||||||
void DrawSelection(Window &window, Caret &it) {
|
void DrawSelection(Window &window, Caret &it) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
View &view = *GetActiveView(window);
|
View &view = *GetActiveView(&window);
|
||||||
Buffer &buf = *view.buffer;
|
Buffer *buffer = GetBuffer(view.buffer_id);
|
||||||
Int front = GetFront(it);
|
Int front = GetFront(it);
|
||||||
Int back = GetBack(it);
|
Int back = GetBack(it);
|
||||||
if (front != back) {
|
if (front != back) {
|
||||||
XY bxy = PosToXY(buf, back);
|
XY bxy = PosToXY(*buffer, back);
|
||||||
XY min = PosToXY(buf, it.range.min);
|
XY min = PosToXY(*buffer, it.range.min);
|
||||||
XY max = PosToXY(buf, it.range.max);
|
XY max = PosToXY(*buffer, it.range.max);
|
||||||
|
|
||||||
Color color = ColorSelection;
|
Color color = ColorSelection;
|
||||||
Rect2I vlines = GetVisibleCells(window);
|
Rect2I vlines = GetVisibleCells(window);
|
||||||
for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < view.buffer->line_starts.len; line += 1) {
|
for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < buffer->line_starts.len; line += 1) {
|
||||||
Range range = GetLineRange(buf, line);
|
Range range = GetLineRange(*buffer, line);
|
||||||
String16 line_string = GetString(buf, range);
|
String16 line_string = GetString(*buffer, range);
|
||||||
|
|
||||||
for (Int col = vlines.min.x; col < vlines.max.x && col >= 0 && col < line_string.len; col += 1) {
|
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;
|
bool a = line > min.line && line < max.line;
|
||||||
@@ -146,13 +148,13 @@ void DrawSelection(Window &window, Caret &it) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawWindow(Window &window) {
|
void DrawWindow(Window &window) {
|
||||||
View &view = *GetActiveView(window);
|
View &view = *GetActiveView(&window);
|
||||||
Buffer &buf = *view.buffer;
|
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);
|
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) {
|
For(view.carets) {
|
||||||
Int front = GetFront(it);
|
Int front = GetFront(it);
|
||||||
XY fxy = PosToXY(buf, front);
|
XY fxy = PosToXY(*buffer, front);
|
||||||
if (GetSize(it.range)) {
|
if (GetSize(it.range)) {
|
||||||
DrawSelection(window, it);
|
DrawSelection(window, it);
|
||||||
} else {
|
} else {
|
||||||
@@ -164,7 +166,7 @@ void DrawWindow(Window &window) {
|
|||||||
|
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
Int front = GetFront(it);
|
Int front = GetFront(it);
|
||||||
XY fxy = PosToXY(buf, front);
|
XY fxy = PosToXY(*buffer, front);
|
||||||
bool main_caret = &it == &view.carets.data[0];
|
bool main_caret = &it == &view.carets.data[0];
|
||||||
DrawCaret(window, fxy, 0.3f, main_caret ? ColorMainCaret : ColorSubCaret);
|
DrawCaret(window, fxy, 0.3f, main_caret ? ColorMainCaret : ColorSubCaret);
|
||||||
}
|
}
|
||||||
@@ -180,7 +182,7 @@ void DrawWindow(Window &window) {
|
|||||||
Rect2 rect = Shrink(scroller.rect, 2);
|
Rect2 rect = Shrink(scroller.rect, 2);
|
||||||
Color color = ColorScrollbarScroller;
|
Color color = ColorScrollbarScroller;
|
||||||
if (!window.mouse_selecting && (window.mouse_selecting_scrollbar || mouse_in_scrollbar)) {
|
if (!window.mouse_selecting && (window.mouse_selecting_scrollbar || mouse_in_scrollbar)) {
|
||||||
color = ColorScrollbarScrollerSelected;
|
if (IsActive(&window)) color = ColorScrollbarScrollerSelected;
|
||||||
}
|
}
|
||||||
DrawRectangleRec(ToRectangle(rect), color);
|
DrawRectangleRec(ToRectangle(rect), color);
|
||||||
}
|
}
|
||||||
@@ -218,7 +220,7 @@ void DrawWindow(Window &window) {
|
|||||||
Vec2 p = ToVec2(r.min);
|
Vec2 p = ToVec2(r.min);
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Caret caret = view.carets[0];
|
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);
|
String s = Format(scratch, "-- line: %lld col: %lld", (long long)xy.line + 1ll, (long long)xy.col + 1ll);
|
||||||
String16 string = ToString16(scratch, s);
|
String16 string = ToString16(scratch, s);
|
||||||
DrawString(MenuFont, string, p, MenuFontSize, 1, ColorText);
|
DrawString(MenuFont, string, p, MenuFontSize, 1, ColorText);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user