summaryrefslogtreecommitdiff
path: root/src/body_layer.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/body_layer.zig')
-rw-r--r--src/body_layer.zig69
1 files changed, 34 insertions, 35 deletions
diff --git a/src/body_layer.zig b/src/body_layer.zig
index e85e10f1..2b2c8a74 100644
--- a/src/body_layer.zig
+++ b/src/body_layer.zig
@@ -135,11 +135,11 @@ fn paintTerminalSelection(p: *Pardes, pane: *Pane, r: Rect, rows: []const Pane.P
const raw = pane.body.mode == .tty;
const tx = r.x + config.GUTTER;
const width = r.w -| config.GUTTER;
- const body_y = p.bodyTop(r);
+ const body_y = p.bodyTop(pane, r);
var lines = std.mem.splitScalar(u8, body, '\n');
var visible: i32 = 0;
while (lines.next()) |line| : (visible += 1) {
- if (visible >= r.h -| BOX_H) break;
+ if (visible >= r.h -| pane.tag_rows) break;
const source_row = if (raw) panes.Terminal.gridOffset(pane) + visible else pane.wrapAt(visible).line;
for (rows) |row| {
const target = if (row.raw_terminal)
@@ -177,10 +177,10 @@ fn paintSourceSelection(p: *Pardes, pane: *Pane, r: Rect, rows: []const Pane.Poi
const terminal_lines = if (pane.file == null) panes.Terminal.cursorLines(p, pane) catch return else &.{};
const tx = r.x + config.GUTTER;
const width = r.w -| config.GUTTER;
- const body_y = p.bodyTop(r);
+ const body_y = p.bodyTop(pane, r);
const prefix: i32 = if (pane.file != null) panes.File.gutterWidth(pane) else 0;
var visible: i32 = 0;
- while (visible < @as(i32, r.h -| BOX_H)) : (visible += 1) {
+ while (visible < @as(i32, r.h -| pane.tag_rows)) : (visible += 1) {
const source = pane.wrapAt(visible);
const line = edit.pointerSourceLine(pane, terminal_lines, source.line);
const start = @min(line.len, @as(usize, @intCast(@max(0, source.at))));
@@ -224,13 +224,13 @@ pub fn paintPointerSelection(
var row: u16 = 0;
while (row < r.h) : (row += 1) {
if (@as(i32, row) < r0 or @as(i32, row) > r1) continue;
- const sy = if (row < BOX_H) tag_y else body_y + row - BOX_H;
+ const sy = if (row < pane.tag_rows) tag_y + row else body_y + row - pane.tag_rows;
// File line numbers occupy a gutter only in the body. The tag is
// row zero in Sel space and starts at its real first text cell.
- const scroll: i32 = if (row < BOX_H) pane.tag_scroll else 0;
- var col: i32 = if (pane.file != null and row >= BOX_H) @max(c0, @as(i32, panes.File.gutterWidth(pane))) else @max(0, c0 - scroll);
- const row_x = if (row < BOX_H) r.x + @min(TAG_TEXT_INSET, r.w) else tx;
- const row_width = if (row < BOX_H) r.w -| TAG_TEXT_INSET else tw;
+ const scroll: i32 = if (row < pane.tag_rows) pane.tag_scroll else 0;
+ var col: i32 = if (pane.file != null and row >= pane.tag_rows) @max(c0, @as(i32, panes.File.gutterWidth(pane))) else @max(0, c0 - scroll);
+ const row_x = if (row < pane.tag_rows) r.x + @min(TAG_TEXT_INSET, r.w) else tx;
+ const row_width = if (row < pane.tag_rows) r.w -| TAG_TEXT_INSET else tw;
while (col <= c1 - scroll and col < row_width) : (col += 1) {
const cell = s.at(row_x + @as(u16, @intCast(col)), sy);
cell.default = false;
@@ -242,8 +242,8 @@ pub fn paintPointerSelection(
pub fn renderBodyLayer(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize) !void {
if (!p.settings.tree_context_tag_style or pane.context_rows == 0 or pane.file == null or pane.collapsed) return;
- if (r.w <= config.GUTTER or r.h <= BOX_H) return;
- const viewport_rows = r.h - BOX_H;
+ if (r.w <= config.GUTTER or r.h <= pane.tag_rows) return;
+ const viewport_rows = r.h - pane.tag_rows;
if (viewport_rows == 0) return;
// The canonical fixed grid remains available to terminal clients. The
// separate body layer reserves enough rows for any compact font size.
@@ -260,24 +260,24 @@ pub fn renderBodyLayer(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rec
const layer = &p.surface.body_layers[id];
const count = logical_rows * width;
if (layer.cells.len != count) layer.cells = try p.gpa.realloc(layer.cells, count);
- const temporary_cells = try arena.alloc(Cell, @as(usize, r.w) * (logical_rows + BOX_H));
+ const temporary_cells = try arena.alloc(Cell, @as(usize, r.w) * (logical_rows + pane.tag_rows));
@memset(temporary_cells, .{});
- var temporary: Surface = .{ .cols = r.w, .rows = @intCast(logical_rows + BOX_H), .cells = temporary_cells };
+ var temporary: Surface = .{ .cols = r.w, .rows = @intCast(logical_rows + pane.tag_rows), .cells = temporary_cells };
std.mem.swap(Surface, &p.surface, &temporary);
- const synthetic: Rect = .{ .x = 0, .y = 0, .w = r.w, .h = @intCast(logical_rows + BOX_H) };
+ const synthetic: Rect = .{ .x = 0, .y = 0, .w = r.w, .h = @intCast(logical_rows + pane.tag_rows) };
renderBody(p, arena, pane, synthetic, id, id == p.active, false) catch |err| {
std.mem.swap(Surface, &p.surface, &temporary);
return err;
};
std.mem.swap(Surface, &p.surface, &temporary);
- const first_row: usize = if (p.settings.tag_bottom) 0 else BOX_H;
+ const first_row: usize = if (p.settings.tag_bottom) 0 else pane.tag_rows;
for (0..logical_rows) |row| {
const start = (row + first_row) * r.w + config.GUTTER;
@memcpy(layer.cells[row * width ..][0..width], temporary_cells[start..][0..width]);
}
layer.pane = @intCast(id);
layer.serial = pane.serial;
- layer.viewport = .{ .x = r.x + config.GUTTER, .y = p.bodyTop(r), .w = width, .h = viewport_rows };
+ layer.viewport = .{ .x = r.x + config.GUTTER, .y = p.bodyTop(pane, r), .w = width, .h = viewport_rows };
layer.cols = width;
layer.rows = @intCast(logical_rows);
layer.context_rows = pane.context_rows;
@@ -295,15 +295,15 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
const chrome = p.chromeTheme();
const tx = r.x + config.GUTTER;
const tw = r.w - config.GUTTER;
- const tag_y = if (p.settings.tag_bottom) r.y + r.h -| BOX_H else r.y;
+ const tag_y = p.tagTop(pane, r);
// Below the notice bands: they are stacked at the top of the body the
// way tree-sitter context rows are, so the body starts under them
// rather than being painted over by them.
- const body_y = p.bodyTop(r);
+ const body_y = p.bodyTop(pane, r);
const pane_bg: Color = if (th.bg) |c| .{ .rgb = c } else .default;
const page_rgb = th.bg orelse th.tag_bg;
// body: emulator rows, prompt rows hidden outside tty mode
- const body_h = r.h -| BOX_H;
+ const body_h = r.h -| pane.tag_rows;
const body_bottom = r.h;
const body_style: CellStyle = .{
.fg = if (th.fg) |c| .{ .rgb = c } else .default,
@@ -365,7 +365,7 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
if (sl.state == .done and b != 0) continue;
// A select sweep over the tag is the tag's selection, painted there
// in the tag's own selection colours.
- if (b == pardes.sel_slot and @min(sl.r0, sl.r1) < BOX_H) continue;
+ if (b == pardes.sel_slot and @min(sl.r0, sl.r1) < pane.tag_rows) continue;
paintPointerSelection(p, pane, r, tx, tw, tag_y, body_y, sl, sel_btn[b], th.sel_fg);
}
// modal line selection (helix `x`): whole body rows, normal mode only
@@ -377,13 +377,13 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
th.sel_bg;
const lo = @min(pane.body.msel.r0, pane.body.msel.r1);
const hi = @max(pane.body.msel.r0, pane.body.msel.r1);
- var row: u16 = BOX_H; // never paint the tag row
+ var row: u16 = pane.tag_rows; // never paint the tag row
while (row < body_bottom) : (row += 1) {
- const ar = pane.wrapAt(@as(i32, row) - @as(i32, BOX_H)).line;
+ const ar = pane.wrapAt(@as(i32, row) - @as(i32, pane.tag_rows)).line;
if (ar < lo or ar > hi) continue;
var col: u16 = if (pane.file != null) panes.File.gutterWidth(pane) else 0;
while (col < tw) : (col += 1) {
- const cell = s.at(tx + col, body_y + row - BOX_H);
+ const cell = s.at(tx + col, body_y + row - pane.tag_rows);
cell.default = false;
cell.style.bg = .{ .rgb = modal_bg };
if (!hover_only) cell.style.fg = .{ .rgb = th.sel_fg };
@@ -415,7 +415,7 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
else
colors.mix(th.sel_bg, page_rgb);
var vr: i32 = 0;
- while (vr + @as(i32, BOX_H) < @as(i32, body_bottom)) : (vr += 1) {
+ while (vr + @as(i32, pane.tag_rows) < @as(i32, body_bottom)) : (vr += 1) {
const w = pane.wrapAt(vr);
if (w.line < bnd.lo_row or w.line > bnd.hi_row) continue;
const visible_line = modal.lineSlice(body, @intCast(vr));
@@ -444,7 +444,7 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
if (primary and !preview and !hover_only) continue; // the hardware cursor IS the primary's
if (hover_only) continue; // quiet preview preserves the source ink
const cw = pane.wrapRow(sr.row, sr.col);
- const crow = cw.row + @as(i32, BOX_H);
+ const crow = cw.row + @as(i32, pane.tag_rows);
const ccol = (if (pane.file != null)
panes.File.displayOffset(pane, sr.row, cw.at, sr.col)
else
@@ -453,8 +453,8 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
@intCast(@max(0, cw.at)),
@intCast(@max(0, sr.col)),
)) + vpfx;
- if (crow >= BOX_H and crow < @as(i32, body_bottom) and ccol >= vpfx and ccol < tw) {
- const cell = s.at(tx + @as(u16, @intCast(ccol)), body_y + @as(u16, @intCast(crow - BOX_H)));
+ if (crow >= pane.tag_rows and crow < @as(i32, body_bottom) and ccol >= vpfx and ccol < tw) {
+ const cell = s.at(tx + @as(u16, @intCast(ccol)), body_y + @as(u16, @intCast(crow - pane.tag_rows)));
cell.default = false;
cell.style.bg = .{ .rgb = th.sel_fg };
cell.style.fg = .{ .rgb = th.sel_bg };
@@ -471,7 +471,7 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
const crow = if (pane.body.cur_pinned) pane.body.cur_row else pane.surfRow(@as(i32, @intCast(cur.y)) + goff);
const ccol = if (pane.body.cur_pinned) pane.body.cur_col else @as(i32, @intCast(cur.x));
const cwp = pane.wrapRow(crow, ccol);
- const prow = cwp.row + @as(i32, BOX_H);
+ const prow = cwp.row + @as(i32, pane.tag_rows);
// Files store source-byte columns; the Surface stores display
// cells, so account for every expanded tab before the cursor.
const cx = if (pane.file != null)
@@ -484,10 +484,10 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
)
else
ccol;
- if (prow >= BOX_H and cx >= 0 and prow < body_bottom and cx < tw)
- s.cursor = .{ .x = tx + @as(u16, @intCast(cx)), .y = body_y + @as(u16, @intCast(prow - BOX_H)), .bar = pane.body.mode == .insert };
+ if (prow >= pane.tag_rows and cx >= 0 and prow < body_bottom and cx < tw)
+ s.cursor = .{ .x = tx + @as(u16, @intCast(cx)), .y = body_y + @as(u16, @intCast(prow - pane.tag_rows)), .bar = pane.body.mode == .insert };
} else if (panes.Terminal.visibleCursor(pane)) |cur| {
- if (cur.y + BOX_H < body_bottom and cur.x < tw)
+ if (cur.y + pane.tag_rows < body_bottom and cur.x < tw)
s.cursor = .{ .x = tx + cur.x, .y = body_y + cur.y };
}
}
@@ -496,10 +496,9 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
// The rail covers the notice bands too: nothing else paints those
// two gutter columns, so a gap there keeps the frame-wide border
// fill and reads as a notch cut out of the scrollbar.
- const rail_y = if (p.settings.tag_bottom) r.y else r.y + BOX_H;
- const rail_h = r.h -| BOX_H;
- s.fill(r.x, rail_y, 1, rail_h, .{ .bg = .{ .rgb = chrome.scroll_track } });
- s.fill(r.x + 1, rail_y, 1, rail_h, .{ .bg = pane_bg });
+ const rail_h = r.h -| pane.tag_rows;
+ s.fill(r.x, body_y, 1, rail_h, .{ .bg = .{ .rgb = chrome.scroll_track } });
+ s.fill(r.x + 1, body_y, 1, rail_h, .{ .bg = pane_bg });
const sb: struct { total: usize, offset: usize, len: usize } = if (pane.file) |*f| .{
.total = panes.File.nlines(p.gpa, f),
.offset = f.scroll,