Line highlight improvements and misc

This commit is contained in:
Krzosa Karol
2024-07-21 09:03:30 +02:00
parent ddbee2f0ec
commit 4c1630d61d
8 changed files with 68 additions and 45 deletions

View File

@@ -54,33 +54,6 @@ Range GetLineRange(Buffer &buffer, Int line) {
return result;
}
Int CalculateLongestLine(Buffer &buffer) {
// @optimize: this is the bottleneck
if (buffer.change_id == buffer.longest_line_id) {
return buffer.index_of_longest_line;
}
Int index_max = 0;
Int size_max = 0;
for (Int i = 0; i < buffer.line_starts.len; i += 1) {
Range range = GetLineRange(buffer, i);
Int size = GetSize(range);
if (size > size_max) {
index_max = i;
size_max = size;
}
}
buffer.longest_line_id = buffer.change_id;
buffer.index_of_longest_line = index_max;
return index_max;
}
Int GetCharCountOfLongestLine(Buffer &buffer) {
Int line = CalculateLongestLine(buffer);
Range range = GetLineRange(buffer, line);
Int result = GetSize(range);
return result;
}
Int PosToLine(Buffer &buffer, Int pos) {
Add(&buffer.line_starts, buffer.len + 1);
@@ -131,6 +104,7 @@ Int XYToPosWithoutNL(Buffer &buffer, XY xy) {
}
void UpdateLines(Buffer *buffer, Range range, String16 string) {
ProfileFunction();
Array<Int> &ls = buffer->line_starts;
Int min_line_number = PosToLine(*buffer, range.min);
Assert(min_line_number < ls.len);
@@ -181,6 +155,7 @@ void ValidateLineStarts(Buffer *buffer) {
}
void ReplaceText(Buffer *buffer, Range range, String16 string) {
ProfileFunction();
Assert(range.max >= range.min);
Assert(range.max >= 0 && range.max <= buffer->len);
Assert(range.min >= 0 && range.min <= buffer->len);

View File

@@ -1,3 +1,4 @@
// @todo: gap buffer to improve speed of inserting on big files with only one cursor?
struct Buffer {
union {
U16 *data;
@@ -7,9 +8,6 @@ struct Buffer {
Int cap;
Array<Int> line_starts;
Int change_id;
Int longest_line_id;
Int index_of_longest_line;
};
union Range {

View File

@@ -65,6 +65,12 @@ Caret MakeCaret(Int pos) {
return result;
}
XY XYLine(Int line) {
XY result = {};
result.line = line;
return result;
}
Caret MakeCaret(Int front, Int back) {
Caret result = {};
if (front >= back) {

View File

@@ -1,4 +1,5 @@
void MergeCarets(Array<Caret> *carets) {
ProfileFunction();
Scratch scratch;
// Merge carets that overlap, this needs to be handled before any edits to
// make sure overlapping edits won't happen.
@@ -34,6 +35,7 @@ void MergeCarets(Array<Caret> *carets) {
}
void MergeSort(int64_t Count, Edit *First, Edit *Temp) {
ProfileFunction();
// SortKey = range.min
if (Count == 1) {
// NOTE(casey): No work to do.
@@ -88,6 +90,7 @@ void MergeSort(int64_t Count, Edit *First, Edit *Temp) {
}
void ApplyEdits(Buffer *buffer, Array<Edit> edits) {
ProfileFunction();
#if BUFFER_DEBUG
Assert(buffer->line_starts.len);
Assert(edits.len);

View File

@@ -0,0 +1,14 @@
void LoadBigText(Buffer *buffer) {
for (int i = 0; i < 5000000; i += 1) {
ReplaceText(buffer, GetEndAsRange(*buffer), L"Line number and another meme or something of the sort which is here or there frankly somewhere\n");
}
}
void LoadTextA(Buffer *buffer) {
Scratch scratch;
for (int i = 0; i < 1000; i += 1) {
String s = Format(scratch, "line1: %d line2: %d line3: %d line4: %d line5: %d line6: %d line1: %d line2: %d line3: %d line4: %d line5: %d line6: %d\n", i, i, i, i, i, i, i, i, i, i, i, i);
String16 s16 = ToString16(scratch, s);
ReplaceText(buffer, GetEndAsRange(*buffer), s16);
}
}

View File

@@ -12,6 +12,7 @@
#include "buffer.cpp"
#include "buffer_multi_cursor.cpp"
#include "buffer_history.cpp"
#include "buffer_test_load.cpp"
#include "raylib.h"
#include "raylib_utils.cpp"
@@ -27,11 +28,9 @@
- Backspace, Delete, Enter
- Mouse anchor point and double click
- Mouse cursor changes
- Line highlight
- Color new lines and end of buffer
- Scrollbars
- Line numbers
- Test big files!!
- Colored strings
- multiple windows
@@ -73,16 +72,7 @@ int main(void) {
view.char_spacing = GetCharSpacing(font, font_size, font_spacing);
Add(&view.carets, {0, 0});
view.buffer = CreateBuffer(Perm);
{
Scratch scratch;
for (int i = 0; i < 1500000; i += 1) {
String s = Format(scratch, "line1: %d line2: %d line3: %d line4: %d line5: %d line6: %d line1: %d line2: %d line3: %d line4: %d line5: %d line6: %d\n", i, i, i, i, i, i, i, i, i, i, i, i);
// String s = Format(scratch, "line %d\n", i);
String16 s16 = ToString16(scratch, s);
ReplaceText(view.buffer, GetEndAsRange(*view.buffer), s16);
// ReplaceText(view.buffer, GetEndAsRange(*view.buffer), L" \n");
}
}
LoadTextA(view.buffer);
}
while (!WindowShouldClose()) {

View File

@@ -166,6 +166,10 @@ void HandleKeybindings(View *_view) {
view.scroll.y -= GetMouseWheelMove() * 48;
}
if (IsKeyDown(KEY_F2)) {
LoadBigText(view.buffer);
}
{
int keys[4] = {KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP};
for (int i = 0; i < 4; i += 1) {
@@ -308,8 +312,11 @@ void HandleKeybindings(View *_view) {
Int last_line = LastLine(view.buffer[0]);
view.scroll.y = Clamp(view.scroll.y, 0.f, Max(0.f, (last_line - 1) * view.line_spacing));
// Int line_chars = GetCharCountOfLongestLine(view.buffer[0]);
// @note:
// GetCharCountOfLongestLine is a bottleneck, there is probably an algorithm for
// calculating this value incrementally but do we even need X scrollbar or x clipping?
view.scroll.x = ClampBottom(view.scroll.x, 0.f);
// Int line_chars = GetCharCountOfLongestLine(view.buffer[0]);
// view.scroll.x = Clamp(view.scroll.x, 0.f, Max(0.f, (line_chars - 2) * view.char_spacing));
}
}

View File

@@ -28,14 +28,38 @@ void DrawVisibleCells(const View &view) {
}
}
Vec2 GetCellSize(const View &view) {
Vec2 result = {view.char_spacing, view.line_spacing};
return result;
}
Vec2 XYToWorldPos(const View &view, XY xy) {
Vec2 result = {(float)xy.col * view.char_spacing, (float)xy.line * view.line_spacing};
return result;
}
Rect2 XYToRect(const View &view, XY xy) {
Rect2 result = Rect2FromSize(XYToWorldPos(view, xy), GetCellSize(view));
return result;
}
void DrawCaret(const View &view, XY xy, float size, Color color) {
Rect2 _rect = Rect2FromSize({(float)xy.col * view.char_spacing, (float)xy.line * view.line_spacing}, {view.char_spacing, view.line_spacing});
Rect2 _rect = XYToRect(view, xy);
Rect2 rect = CutLeft(&_rect, size * view.char_spacing);
rect -= view.scroll;
DrawRectangleRec(ToRectangle(rect), color);
}
void DrawCaret(const View &view, Caret it) {
void DrawLineHighlight(const View &view, XY fxy, Color color) {
Vec2 w = XYToWorldPos(view, XYLine(fxy.line));
w -= view.scroll;
Range range = GetLineRange(*view.buffer, fxy.line);
float xsize = view.char_spacing * (float)GetSize(range);
Rect2 rect = Rect2FromSize(w, {xsize, view.line_spacing});
DrawRectangleRec(ToRectangle(rect), color);
}
void DrawCaret(const View &view, Caret &it) {
ProfileFunction();
Buffer &buf = *view.buffer;
Int front = GetFront(it);
@@ -46,6 +70,12 @@ void DrawCaret(const View &view, Caret it) {
XY bxy = PosToXY(buf, back);
DrawCaret(view, bxy, 0.15f, GREEN);
// Line highlight
bool main_caret = &it == &view.carets.data[0];
unsigned char red = main_caret ? 0 : 120;
DrawLineHighlight(view, fxy, {0, red, red, 30});
DrawLineHighlight(view, fxy, {0, red, red, 10});
// Draw selection
if (front != back) {
XY min = PosToXY(buf, it.range.min);