Page up and page down, home and end
This commit is contained in:
@@ -45,7 +45,7 @@ Int LastLine(Buffer &buffer) {
|
||||
}
|
||||
|
||||
const Int LAST_LINE = INT64_MAX;
|
||||
Range GetLine(Buffer &buffer, Int line) {
|
||||
Range GetLineRange(Buffer &buffer, Int line) {
|
||||
Range result = {buffer.line_starts[line], buffer.len};
|
||||
if (line + 1 < buffer.line_starts.len) {
|
||||
result.max = buffer.line_starts[line + 1];
|
||||
@@ -59,7 +59,7 @@ Int CalculateLongestLine(Buffer &buffer) {
|
||||
Int index_max = 0;
|
||||
Int size_max = 0;
|
||||
for (Int i = 0; i < buffer.line_starts.len; i += 1) {
|
||||
Range range = GetLine(buffer, i);
|
||||
Range range = GetLineRange(buffer, i);
|
||||
Int size = GetSize(range);
|
||||
if (size > size_max) {
|
||||
index_max = i;
|
||||
@@ -71,7 +71,7 @@ Int CalculateLongestLine(Buffer &buffer) {
|
||||
|
||||
Int GetCharCountOfLongestLine(Buffer &buffer) {
|
||||
Int line = CalculateLongestLine(buffer);
|
||||
Range range = GetLine(buffer, line);
|
||||
Range range = GetLineRange(buffer, line);
|
||||
Int result = GetSize(range);
|
||||
return result;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ Int PosToLine(Buffer &buffer, Int pos) {
|
||||
|
||||
XY PosToXY(Buffer &buffer, Int pos) {
|
||||
Int line = PosToLine(buffer, pos);
|
||||
Range line_range = GetLine(buffer, line);
|
||||
Range line_range = GetLineRange(buffer, line);
|
||||
Int col = pos - line_range.min;
|
||||
XY result = {col, line};
|
||||
return result;
|
||||
@@ -113,11 +113,18 @@ XY PosToXY(Buffer &buffer, Int pos) {
|
||||
|
||||
Int XYToPos(Buffer &buffer, XY xy) {
|
||||
xy.line = Clamp(xy.line, (Int)0, buffer.line_starts.len - 1);
|
||||
Range line_range = GetLine(buffer, xy.line);
|
||||
Range line_range = GetLineRange(buffer, xy.line);
|
||||
Int pos = Clamp(xy.col + line_range.min, line_range.min, line_range.max);
|
||||
return pos;
|
||||
}
|
||||
|
||||
Int XYToPosWithoutNL(Buffer &buffer, XY xy) {
|
||||
xy.line = Clamp(xy.line, (Int)0, buffer.line_starts.len - 1);
|
||||
Range line_range = GetLineRange(buffer, xy.line);
|
||||
Int pos = Clamp(xy.col + line_range.min, line_range.min, line_range.max - 1);
|
||||
return pos;
|
||||
}
|
||||
|
||||
void ValidateLineStarts(Buffer *buffer) {
|
||||
Int line = 0;
|
||||
for (Int i = 0; i < buffer->len; i += 1) {
|
||||
@@ -203,7 +210,7 @@ void TestBuffer() {
|
||||
Assert(buffer.line_starts.len == 1);
|
||||
String16 test_string = L"Thing itself";
|
||||
{
|
||||
ReplaceText(&buffer, {{}, {}}, test_string);
|
||||
ReplaceText(&buffer, Rng(), test_string);
|
||||
Assert(buffer.cap == 4096);
|
||||
Assert(buffer.len == 12);
|
||||
String16 a = GetString(buffer);
|
||||
|
||||
@@ -8,9 +8,12 @@ struct Buffer {
|
||||
Array<Int> line_starts;
|
||||
};
|
||||
|
||||
struct Range {
|
||||
Int min;
|
||||
Int max;
|
||||
union Range {
|
||||
struct {
|
||||
Int min;
|
||||
Int max;
|
||||
};
|
||||
Int e[2];
|
||||
};
|
||||
|
||||
struct Caret {
|
||||
|
||||
@@ -4,12 +4,12 @@ Int GetSize(Range range) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Range MakeRange(Int a, Int b) {
|
||||
Range Rng(Int a, Int b) {
|
||||
Range result = {Min(a, b), Max(a, b)};
|
||||
return result;
|
||||
}
|
||||
|
||||
Range MakeRange(Int a) {
|
||||
Range Rng(Int a = 0) {
|
||||
Range result = {a, a};
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -51,22 +51,23 @@ int main(void) {
|
||||
view.buffer = CreateBuffer(Perm);
|
||||
{
|
||||
Scratch scratch;
|
||||
for (int i = 0; i < 2; 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);
|
||||
for (int i = 0; i < 150; 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");
|
||||
// ReplaceText(view.buffer, GetEndAsRange(*view.buffer), L" \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!WindowShouldClose()) {
|
||||
view.rect = GetScreenRect();
|
||||
HandleKeybindings(&view);
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
{
|
||||
HandleKeybindings(&view);
|
||||
DrawVisibleCells(view);
|
||||
For(view.carets) DrawCaret(view, it);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ struct View {
|
||||
Rect2 rect;
|
||||
};
|
||||
|
||||
Rect2I GetVisibleCells(const View &view);
|
||||
|
||||
Int MoveOnWhitespaceBoundaryForward(Buffer &buffer, Int pos) {
|
||||
pos = Clamp(pos, (Int)0, buffer.len);
|
||||
bool standing_on_whitespace = IsWhitespace(buffer.str[pos]);
|
||||
@@ -63,7 +65,7 @@ Int MoveOnWhitespaceBoundaryDown(Buffer &buffer, Int pos) {
|
||||
Int result = pos;
|
||||
Int next_line = PosToLine(buffer, pos) + 1;
|
||||
for (Int line = next_line; line < buffer.line_starts.len; line += 1) {
|
||||
Range line_range = GetLine(buffer, line);
|
||||
Range line_range = GetLineRange(buffer, line);
|
||||
result = line_range.min;
|
||||
|
||||
bool whitespace_line = true;
|
||||
@@ -82,7 +84,7 @@ Int MoveOnWhitespaceBoundaryUp(Buffer &buffer, Int pos) {
|
||||
Int result = pos;
|
||||
Int next_line = PosToLine(buffer, pos) - 1;
|
||||
for (Int line = next_line; line >= 0; line -= 1) {
|
||||
Range line_range = GetLine(buffer, line);
|
||||
Range line_range = GetLineRange(buffer, line);
|
||||
result = line_range.min;
|
||||
|
||||
bool whitespace_line = true;
|
||||
@@ -99,7 +101,7 @@ Int MoveOnWhitespaceBoundaryUp(Buffer &buffer, Int pos) {
|
||||
|
||||
Int MovePosByXY(Buffer &buffer, Int pos, XY offset) {
|
||||
XY xy = PosToXY(buffer, pos);
|
||||
Int result = XYToPos(buffer, {xy.col + offset.col, xy.line + offset.line});
|
||||
Int result = XYToPosWithoutNL(buffer, {xy.col + offset.col, xy.line + offset.line});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -114,13 +116,13 @@ Int MoveCaret(Buffer &buffer, Int pos, int direction, bool ctrl_pressed) {
|
||||
default: return pos;
|
||||
}
|
||||
} else {
|
||||
XY offsets[4] = {
|
||||
{ 1, 0},
|
||||
{-1, 0},
|
||||
{ 0, 1},
|
||||
{ 0, -1},
|
||||
};
|
||||
return MovePosByXY(buffer, pos, offsets[direction]);
|
||||
switch (direction) {
|
||||
case 0: return Clamp(pos + 1, (Int)0, buffer.len);
|
||||
case 1: return Clamp(pos - 1, (Int)0, buffer.len);
|
||||
case 2: return MovePosByXY(buffer, pos, {0, 1});
|
||||
case 3: return MovePosByXY(buffer, pos, {0, -1});
|
||||
default: return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,16 +164,52 @@ void HandleKeybindings(View *_view) {
|
||||
view.scroll.y -= GetMouseWheelMove() * 48;
|
||||
}
|
||||
|
||||
int keys[4] = {KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP};
|
||||
for (int i = 0; i < 4; i += 1) {
|
||||
if (IsKeyPressed(keys[i]) || IsKeyPressedRepeat(keys[i])) {
|
||||
For(view.carets) {
|
||||
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||
Int front = GetFront(it);
|
||||
Int new_front = MoveCaret(buf, front, i, IsKeyDown(KEY_LEFT_CONTROL));
|
||||
it = ChangeFront(it, new_front);
|
||||
} else {
|
||||
it.range.max = it.range.min = MoveCaret(buf, it.range.max, i, IsKeyDown(KEY_LEFT_CONTROL));
|
||||
{
|
||||
int keys[4] = {KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP};
|
||||
for (int i = 0; i < 4; i += 1) {
|
||||
if (IsKeyPressed(keys[i]) || IsKeyPressedRepeat(keys[i])) {
|
||||
For(view.carets) {
|
||||
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||
Int front = GetFront(it);
|
||||
Int new_front = MoveCaret(buf, front, i, IsKeyDown(KEY_LEFT_CONTROL));
|
||||
it = ChangeFront(it, new_front);
|
||||
} else {
|
||||
it.range.max = it.range.min = MoveCaret(buf, it.range.max, i, IsKeyDown(KEY_LEFT_CONTROL));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int key_page_down = IsKeyPressed(KEY_PAGE_DOWN) || IsKeyPressedRepeat(KEY_PAGE_DOWN);
|
||||
int key_page_up = IsKeyPressed(KEY_PAGE_UP) || IsKeyPressedRepeat(KEY_PAGE_UP);
|
||||
if (key_page_up || key_page_down) {
|
||||
Rect2I visible_cells_rect = GetVisibleCells(view);
|
||||
Int y = GetSize(visible_cells_rect).y - 2;
|
||||
For(view.carets) {
|
||||
XY xy = PosToXY(buf, GetFront(it));
|
||||
if (key_page_down) xy.line += y;
|
||||
if (key_page_up) xy.line -= y;
|
||||
Int pos = XYToPos(buf, xy);
|
||||
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||
it = ChangeFront(it, pos);
|
||||
} else {
|
||||
it = MakeCaret(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int keys[2] = {KEY_HOME, KEY_END};
|
||||
for (int i = 0; i < 2; i += 1) {
|
||||
if (IsKeyPressed(keys[i]) || IsKeyPressedRepeat(keys[i])) {
|
||||
For(view.carets) {
|
||||
Range line_range = GetLineRange(buf, PosToLine(buf, GetFront(it)));
|
||||
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||
it = ChangeFront(it, line_range.e[i] - i);
|
||||
} else {
|
||||
it.range.max = it.range.min = line_range.e[i] - i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,7 +240,6 @@ void HandleKeybindings(View *_view) {
|
||||
Int front = GetFront(c);
|
||||
XY xy = PosToXY(buf, front);
|
||||
|
||||
Rect2I GetVisibleCells(const View &view);
|
||||
Rect2I visible = GetVisibleCells(view);
|
||||
Vec2I visible_cells = GetSize(visible);
|
||||
Vec2 visible_size = ToVec2(visible_cells) * Vec2{view.char_spacing, view.line_spacing};
|
||||
@@ -245,7 +282,7 @@ void HandleKeybindings(View *_view) {
|
||||
Vec2 mworld = mouse - view.rect.min + view.scroll;
|
||||
Vec2 pos = mworld / Vec2{view.char_spacing, view.line_spacing};
|
||||
XY xy = {(Int)(pos.x), (Int)(pos.y)};
|
||||
Int p = XYToPos(buf, xy);
|
||||
Int p = XYToPosWithoutNL(buf, xy);
|
||||
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
|
||||
if (!IsKeyDown(KEY_LEFT_CONTROL)) {
|
||||
@@ -263,7 +300,5 @@ void HandleKeybindings(View *_view) {
|
||||
}
|
||||
MergeCarets(&view.carets);
|
||||
}
|
||||
|
||||
// Rect2 rect = view.rect + view;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ Rect2I GetVisibleCells(const View &view) {
|
||||
void DrawVisibleCells(const View &view) {
|
||||
Rect2I visible = GetVisibleCells(view);
|
||||
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 = GetLine(*view.buffer, line_index);
|
||||
Range line_range = GetLineRange(*view.buffer, line_index);
|
||||
String16 line_string = GetString(*view.buffer, line_range);
|
||||
line_string = Skip(line_string, visible.min.x);
|
||||
line_string = GetPrefix(line_string, visible.max.x - visible.min.x);
|
||||
@@ -28,7 +28,7 @@ void DrawVisibleCells(const View &view) {
|
||||
|
||||
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 = CutLeft(&_rect, size);
|
||||
Rect2 rect = CutLeft(&_rect, size * view.char_spacing);
|
||||
rect -= view.scroll;
|
||||
DrawRectangleRec(ToRectangle(rect), color);
|
||||
}
|
||||
@@ -37,11 +37,11 @@ void DrawCaret(const View &view, Caret it) {
|
||||
Buffer &buf = *view.buffer;
|
||||
Int front = GetFront(it);
|
||||
XY fxy = PosToXY(buf, front);
|
||||
DrawCaret(view, fxy, 2, RED);
|
||||
DrawCaret(view, fxy, 0.3f, RED);
|
||||
|
||||
Int back = GetBack(it);
|
||||
XY bxy = PosToXY(buf, back);
|
||||
DrawCaret(view, bxy, 1, GREEN);
|
||||
DrawCaret(view, bxy, 0.15f, GREEN);
|
||||
|
||||
// Draw selection
|
||||
if (front != back) {
|
||||
@@ -50,7 +50,7 @@ void DrawCaret(const View &view, Caret it) {
|
||||
|
||||
Rect2I vlines = GetVisibleCells(view);
|
||||
for (Int line = vlines.min.y; line <= vlines.max.y && line >= 0 && line < view.buffer->line_starts.len; line += 1) {
|
||||
Range range = GetLine(buf, line);
|
||||
Range range = GetLineRange(buf, line);
|
||||
range -= range.min;
|
||||
range.min = Clamp(range.min, vlines.min.x, vlines.max.x);
|
||||
range.max = Clamp(range.max, vlines.min.x, vlines.max.x);
|
||||
|
||||
Reference in New Issue
Block a user