142 lines
3.9 KiB
Zig
142 lines
3.9 KiB
Zig
const std = @import("std");
|
|
const cbor = @import("cbor");
|
|
const Buffer = @import("Buffer.zig");
|
|
const Cursor = @import("Cursor.zig");
|
|
const Selection = @import("Selection.zig");
|
|
|
|
row: usize = 0,
|
|
col: usize = 0,
|
|
rows: usize = 0,
|
|
cols: usize = 0,
|
|
|
|
const scroll_cursor_min_border_distance = 5;
|
|
const scroll_cursor_min_border_distance_mouse = 1;
|
|
|
|
const Self = @This();
|
|
|
|
pub inline fn invalid() Self {
|
|
return .{
|
|
.row = std.math.maxInt(u32),
|
|
.col = std.math.maxInt(u32),
|
|
};
|
|
}
|
|
|
|
inline fn reset(self: *Self) void {
|
|
self.* = .{};
|
|
}
|
|
|
|
pub inline fn eql(self: Self, other: Self) bool {
|
|
return self.row == other.row and self.col == other.col and self.rows == other.rows and self.cols == other.cols;
|
|
}
|
|
|
|
pub fn move_left(self: *Self) !void {
|
|
if (self.col > 0) {
|
|
self.col -= 1;
|
|
} else return error.Stop;
|
|
}
|
|
|
|
pub fn move_right(self: *Self) !void {
|
|
self.col += 1;
|
|
}
|
|
|
|
pub fn move_up(self: *Self) !void {
|
|
if (!self.is_at_top()) {
|
|
self.row -= 1;
|
|
} else return error.Stop;
|
|
}
|
|
|
|
pub fn move_down(self: *Self, root: Buffer.Root) !void {
|
|
if (!self.is_at_bottom(root)) {
|
|
self.row += 1;
|
|
} else return error.Stop;
|
|
}
|
|
|
|
pub fn move_to(self: *Self, root: Buffer.Root, row: usize) !void {
|
|
if (row < root.lines() - self.rows - 1) {
|
|
self.row = row;
|
|
} else return error.Stop;
|
|
}
|
|
|
|
inline fn is_at_top(self: *const Self) bool {
|
|
return self.row == 0;
|
|
}
|
|
|
|
inline fn is_at_bottom(self: *const Self, root: Buffer.Root) bool {
|
|
if (root.lines() < self.rows) return true;
|
|
return self.row >= root.lines() - scroll_cursor_min_border_distance;
|
|
}
|
|
|
|
pub inline fn is_visible(self: *const Self, cursor: *const Cursor) bool {
|
|
const row_min = self.row;
|
|
const row_max = row_min + self.rows;
|
|
const col_min = self.col;
|
|
const col_max = col_min + self.cols;
|
|
return row_min <= cursor.row and cursor.row <= row_max and
|
|
col_min <= cursor.col and cursor.col < col_max;
|
|
}
|
|
|
|
inline fn is_visible_selection(self: *const Self, sel: *const Selection) bool {
|
|
const row_min = self.row;
|
|
const row_max = row_min + self.rows;
|
|
return self.is_visible(sel.begin) or is_visible(sel.end) or
|
|
(sel.begin.row < row_min and sel.end.row > row_max);
|
|
}
|
|
|
|
inline fn to_cursor_top(self: *const Self) Cursor {
|
|
return .{ .row = self.row, .col = 0 };
|
|
}
|
|
|
|
inline fn to_cursor_bottom(self: *const Self, root: Buffer.Root) Cursor {
|
|
const bottom = @min(root.lines(), self.row + self.rows + 1);
|
|
return .{ .row = bottom, .col = 0 };
|
|
}
|
|
|
|
fn clamp_row(self: *Self, cursor: *const Cursor, abs: bool) void {
|
|
const min_border_distance: usize = if (abs) scroll_cursor_min_border_distance_mouse else scroll_cursor_min_border_distance;
|
|
if (cursor.row < min_border_distance) {
|
|
self.row = 0;
|
|
return;
|
|
}
|
|
if (self.row > 0 and cursor.row >= min_border_distance) {
|
|
if (cursor.row < self.row + min_border_distance) {
|
|
self.row = cursor.row - min_border_distance;
|
|
return;
|
|
}
|
|
}
|
|
if (cursor.row < self.row) {
|
|
self.row = 0;
|
|
} else if (cursor.row > self.row + self.rows - min_border_distance) {
|
|
self.row = cursor.row + min_border_distance - self.rows;
|
|
}
|
|
}
|
|
|
|
fn clamp_col(self: *Self, cursor: *const Cursor, _: bool) void {
|
|
if (cursor.col < self.col) {
|
|
self.col = cursor.col;
|
|
} else if (cursor.col > self.col + self.cols - 1) {
|
|
self.col = cursor.col - self.cols + 1;
|
|
}
|
|
}
|
|
|
|
pub fn clamp(self: *Self, cursor: *const Cursor, abs: bool) void {
|
|
self.clamp_row(cursor, abs);
|
|
self.clamp_col(cursor, abs);
|
|
}
|
|
|
|
pub fn write(self: *const Self, writer: Buffer.MetaWriter) !void {
|
|
try cbor.writeValue(writer, .{
|
|
self.row,
|
|
self.col,
|
|
self.rows,
|
|
self.cols,
|
|
});
|
|
}
|
|
|
|
pub fn extract(self: *Self, iter: *[]const u8) !bool {
|
|
return cbor.matchValue(iter, .{
|
|
cbor.extract(&self.row),
|
|
cbor.extract(&self.col),
|
|
cbor.extract(&self.rows),
|
|
cbor.extract(&self.cols),
|
|
});
|
|
}
|