summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/File.zig13
-rw-r--r--src/Terminal.zig4
-rw-r--r--src/body_layer.zig38
-rw-r--r--src/draw.zig32
-rw-r--r--src/image.zig5
-rw-r--r--src/pdf_view.zig7
6 files changed, 44 insertions, 55 deletions
diff --git a/src/File.zig b/src/File.zig
index af538385..26585f77 100644
--- a/src/File.zig
+++ b/src/File.zig
@@ -6,6 +6,7 @@ const vaxis = @import("vaxis");
const pardes = @import("pardes.zig");
const config = @import("config.zig");
const Pardes = pardes.Pardes;
+const Surface = pardes.Surface;
const modal = @import("modal.zig");
const filesystem = @import("fs.zig");
const syntax = @import("syntax.zig");
@@ -1124,8 +1125,7 @@ fn fillBody(dst: ?[]u8, pane: *Pane, f: *State, width: usize, record_wrap: bool)
return written;
}
-pub fn drawGutter(p: *Pardes, pane: *Pane, r: pardes.Rect, tx: u16, tw: u16, body_h: u16, active: bool) void {
- const s = &p.surface;
+pub fn drawGutter(p: *Pardes, s: *Surface, pane: *Pane, r: pardes.Rect, tx: u16, tw: u16, body_h: u16, active: bool) void {
const prefix_width = gutterWidth(pane);
const goff = pane.scroll();
const gcur = Terminal.gridCursor(pane);
@@ -1176,11 +1176,10 @@ fn synStyle(p: *Pardes, sy: syntax.Syn) ?SynStyle {
/// syntax colors: recolor each content cell from its tree-sitter style byte;
/// content starts after the lineno gutter
-pub fn recolorSyntax(p: *Pardes, pane: *Pane, f: *State, r: pardes.Rect, tx: u16, tw: u16, body_h: u16) void {
+pub fn recolorSyntax(p: *Pardes, s: *Surface, pane: *Pane, f: *State, r: pardes.Rect, tx: u16, tw: u16, body_h: u16) void {
const highlights = if (f.mini) |mini| mini.colors else f.highlights;
const highlight_start = if (f.mini != null) 0 else f.highlight_start;
if (highlights.len == 0 and f.output == null) return;
- const s = &p.surface;
const prefix_width = gutterWidth(pane);
const tz_recolor = tracy.zone(@src(), "synRecolor");
defer tz_recolor.end();
@@ -1255,6 +1254,7 @@ pub fn recolorSyntax(p: *Pardes, pane: *Pane, f: *State, r: pardes.Rect, tx: u16
pub fn drawWrapMarkers(
p: *Pardes,
+ s: *Surface,
pane: *const Pane,
r: pardes.Rect,
tx: u16,
@@ -1268,7 +1268,7 @@ pub fn drawWrapMarkers(
var row: u16 = 0;
while (row + 1 < pane.wrap_n and row + 1 < body_h) : (row += 1) {
if (pane.wrap_line[row + 1] != pane.wrap_line[row]) continue;
- p.surface.set(tx + tw - 1, body_y + row, config.wrap_marker, .{
+ s.set(tx + tw - 1, body_y + row, config.wrap_marker, .{
.fg = .{ .rgb = marker_fg },
.bg = pane_bg,
});
@@ -1277,6 +1277,7 @@ pub fn drawWrapMarkers(
pub fn paintWordSelection(
p: *Pardes,
+ s: *Surface,
pane: *Pane,
r: pardes.Rect,
row: i32,
@@ -1301,7 +1302,7 @@ pub fn paintWordSelection(
const c1 = @as(i32, prefix_width) + displayEndOffset(pane, row, here.at, hi - 1);
var col = @max(@as(i32, prefix_width), c0);
while (col <= c1 and col < @as(i32, tw)) : (col += 1) {
- const cell = p.surface.at(tx + @as(u16, @intCast(col)), body_y + @as(u16, @intCast(vr)));
+ const cell = s.at(tx + @as(u16, @intCast(col)), body_y + @as(u16, @intCast(vr)));
cell.default = false;
cell.style.bg = .{ .rgb = bg };
}
diff --git a/src/Terminal.zig b/src/Terminal.zig
index cd292e5f..62a77ca8 100644
--- a/src/Terminal.zig
+++ b/src/Terminal.zig
@@ -5,6 +5,7 @@ const std = @import("std");
const pardes = @import("pardes.zig");
const config = @import("config.zig");
const Pardes = pardes.Pardes;
+const Surface = pardes.Surface;
const modal = @import("modal.zig");
const tracy = @import("tracy.zig");
const dump = @import("dump.zig");
@@ -1756,11 +1757,10 @@ const Anchor = struct {
}
};
-pub fn recolorAnsi(p: *Pardes, pane: *Pane, r: pardes.Rect, tx: u16, tw: u16, body_h: u16, body: []const u8) void {
+pub fn recolorAnsi(p: *Pardes, s: *Surface, pane: *Pane, r: pardes.Rect, tx: u16, tw: u16, body_h: u16, body: []const u8) void {
// No emulator, no ANSI cells: the whole pass — and the 256-colour theme
// projection behind it — is compiled out.
if (comptime !enabled) return;
- const s = &p.surface;
if (pane.terminal == null) return;
const body_y = p.bodyTop(pane, r);
var filtered_storage: FilteredColors = undefined;
diff --git a/src/body_layer.zig b/src/body_layer.zig
index aa52957c..db4d9524 100644
--- a/src/body_layer.zig
+++ b/src/body_layer.zig
@@ -145,7 +145,7 @@ test "compact context borders separate source gaps and preserve multiline header
// ---- drawing a pane body into the surface ----
-fn paintTerminalSelection(p: *Pardes, pane: *Pane, r: Rect, rows: []const Pane.PointerRow, bg: [3]u8, fg: ?[3]u8) void {
+fn paintTerminalSelection(p: *Pardes, s: *Surface, pane: *Pane, r: Rect, rows: []const Pane.PointerRow, bg: [3]u8, fg: ?[3]u8) void {
const body = bodyText(p, p.scratch.allocator(), pane) catch return;
const raw = pane.body.mode == .tty;
const tx = r.x + config.GUTTER;
@@ -178,7 +178,7 @@ fn paintTerminalSelection(p: *Pardes, pane: *Pane, r: Rect, rows: []const Pane.P
var col = panes.File.rawDisplayCol(line, lo);
const end = panes.File.rawDisplayCol(line, hi);
while (col < end and col < width) : (col += 1) {
- const cell = p.surface.at(tx + @as(u16, @intCast(col)), body_y + @as(u16, @intCast(visible)));
+ const cell = s.at(tx + @as(u16, @intCast(col)), body_y + @as(u16, @intCast(visible)));
cell.default = false;
cell.style.bg = .{ .rgb = bg };
if (fg) |ink| cell.style.fg = .{ .rgb = ink };
@@ -187,8 +187,8 @@ fn paintTerminalSelection(p: *Pardes, pane: *Pane, r: Rect, rows: []const Pane.P
}
}
-fn paintSourceSelection(p: *Pardes, pane: *Pane, r: Rect, rows: []const Pane.PointerRow, bg: [3]u8, fg: ?[3]u8) void {
- if (pane.isTerminal()) return paintTerminalSelection(p, pane, r, rows, bg, fg);
+fn paintSourceSelection(p: *Pardes, s: *Surface, pane: *Pane, r: Rect, rows: []const Pane.PointerRow, bg: [3]u8, fg: ?[3]u8) void {
+ if (pane.isTerminal()) return paintTerminalSelection(p, s, pane, r, rows, bg, fg);
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;
@@ -209,7 +209,7 @@ fn paintSourceSelection(p: *Pardes, pane: *Pane, r: Rect, rows: []const Pane.Poi
var col = prefix + @as(i32, @intCast(panes.File.rawDisplayCol(line[start..], lo - start)));
const last = prefix + @as(i32, @intCast(panes.File.rawDisplayCol(line[start..], hi - start)));
while (col < last and col < width) : (col += 1) {
- const cell = p.surface.at(tx + @as(u16, @intCast(col)), body_y + @as(u16, @intCast(visible)));
+ const cell = s.at(tx + @as(u16, @intCast(col)), body_y + @as(u16, @intCast(visible)));
cell.default = false;
cell.style.bg = .{ .rgb = bg };
if (fg) |ink| cell.style.fg = .{ .rgb = ink };
@@ -220,6 +220,7 @@ fn paintSourceSelection(p: *Pardes, pane: *Pane, r: Rect, rows: []const Pane.Poi
pub fn paintPointerSelection(
p: *Pardes,
+ s: *Surface,
pane: *Pane,
r: Rect,
tx: u16,
@@ -230,8 +231,7 @@ pub fn paintPointerSelection(
bg: [3]u8,
fg: ?[3]u8,
) void {
- if (pane.pointerSelection(sl)) |rows| return paintSourceSelection(p, pane, r, rows, bg, fg);
- const s = &p.surface;
+ if (pane.pointerSelection(sl)) |rows| return paintSourceSelection(p, s, pane, r, rows, bg, fg);
const r0 = @min(sl.r0, sl.r1);
const r1 = @max(sl.r0, sl.r1);
const c0 = @max(0, @min(sl.c0, sl.c1));
@@ -278,13 +278,8 @@ pub fn renderBodyLayer(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rec
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 + 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 + 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);
+ try renderBody(p, &temporary, arena, pane, synthetic, id, id == p.active, false);
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;
@@ -304,8 +299,7 @@ pub fn renderBodyLayer(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rec
}
}
-pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize, active: bool, scrollbar: bool) !void {
- const s = &p.surface;
+pub fn renderBody(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize, active: bool, scrollbar: bool) !void {
const th = p.theme();
const chrome = p.chromeTheme();
const tx = r.x + config.GUTTER;
@@ -343,12 +337,12 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
const tz_color = tracy.zone(@src(), "paneRecolor");
// File layout is independent of whether its producer requests colors.
if (pane.file) |*f| {
- panes.File.drawGutter(p, pane, r, tx, tw, body_h, active);
+ panes.File.drawGutter(p, s, pane, r, tx, tw, body_h, active);
if (p.settings.colors and pane.colorAlgo() != .none)
- panes.File.recolorSyntax(p, pane, f, r, tx, tw, body_h);
- panes.File.drawWrapMarkers(p, pane, r, tx, tw, body_h, pane_bg);
+ panes.File.recolorSyntax(p, s, pane, f, r, tx, tw, body_h);
+ panes.File.drawWrapMarkers(p, s, pane, r, tx, tw, body_h, pane_bg);
} else if (pane.isTerminal() and p.settings.colors) {
- panes.Terminal.recolorAnsi(p, pane, r, tx, tw, body_h, body);
+ panes.Terminal.recolorAnsi(p, s, pane, r, tx, tw, body_h, body);
}
tz_color.end();
@@ -366,9 +360,9 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
// macOS composes its glass overlay over exactly these.
const preview_bg = colors.mix(page_rgb, colors.mix(page_rgb, th.sel_bg));
if (preview.file_word) |word|
- panes.File.paintWordSelection(p, pane, r, word.row, word.lo, word.hi, preview_bg)
+ panes.File.paintWordSelection(p, s, pane, r, word.row, word.lo, word.hi, preview_bg)
else if (preview.sel) |sel|
- paintPointerSelection(p, pane, r, tx, tw, tag_y, body_y, sel, preview_bg, null);
+ paintPointerSelection(p, s, pane, r, tx, tw, tag_y, body_y, sel, preview_bg, null);
}
}
const modal_hover = if (p.look_hover_preview) |preview|
@@ -381,7 +375,7 @@ pub fn renderBody(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id
// 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) < pane.tag_rows) continue;
- paintPointerSelection(p, pane, r, tx, tw, tag_y, body_y, sl, sel_btn[b], th.sel_fg);
+ paintPointerSelection(p, s, 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
if ((pane.body.mode == .normal or modal_hover) and pane.body.msel.active) {
diff --git a/src/draw.zig b/src/draw.zig
index 5db6da30..d84f2033 100644
--- a/src/draw.zig
+++ b/src/draw.zig
@@ -90,7 +90,7 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface {
pane.context_row_limit = null;
s.body_layers[id].rows = 0;
Messages.collectNotices(p, pane, p.rects[id], id);
- try renderPane(p, arena, pane, p.rects[id], id, id == p.active);
+ try renderPane(p, s, arena, pane, p.rects[id], id, id == p.active);
try body_layer.renderBodyLayer(p, arena, pane, p.rects[id], id);
}
for (&p.panes, 0..) |*slot, id| {
@@ -156,7 +156,7 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface {
}
}
- try paintHeaders(p);
+ try paintHeaders(p, s);
try renderTagLayers(p, arena);
switch (p.drag) {
@@ -397,11 +397,10 @@ fn hasGlyph(cell: *const Cell) bool {
return !cell.default and !(cell.len == 1 and cell.text[0] == ' ');
}
-fn renderPane(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize, active: bool) !void {
+fn renderPane(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize, active: bool) !void {
const tz = tracy.zone(@src(), "renderPane");
defer tz.end();
if (r.w <= config.GUTTER or r.h == 0) return;
- const s = &p.surface;
const th = p.theme();
const chrome = p.chromeTheme();
const tx = r.x + config.GUTTER; // text area (tag + body), right of the gutter
@@ -436,14 +435,14 @@ fn renderPane(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: us
.tty => config.tag_tty,
}, box_style);
- try paintPaneTag(p, arena, pane, r, id, active, p.tagCapacity(r.w -| TAG_TEXT_INSET));
+ try paintPaneTag(p, s, arena, pane, r, id, active, p.tagCapacity(r.w -| TAG_TEXT_INSET));
// Folded panes retain their body state, but neither body pixels nor
// its cursor belong outside the one-row tag rectangle.
if (pane.collapsed) return;
if (comptime pdf_enabled)
- if (pane.hasPdf() and panes.Pdf.draw(p, pane, r, id, tx, tw)) return;
+ if (pane.hasPdf() and panes.Pdf.draw(p, s, pane, r, id, tx, tw)) return;
if (pane.image) |*iv| {
// Below the notice chips: a picture is drawn after the cells (the
@@ -451,7 +450,7 @@ fn renderPane(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: us
// painted out. Text gets the overlay; a picture gives up the rows.
const shown = pane.notices.span();
const image_h = (r.h -| pane.tag_rows) -| shown;
- panes.Image.draw(p, iv, @intCast(id), pane.serial, tx, body_y + shown, tw, image_h);
+ panes.Image.draw(p, s, iv, @intCast(id), pane.serial, tx, body_y + shown, tw, image_h);
// thumbless, but the same one column as the real scrollbar below —
// that is the whole point of drawing it, and like that one it runs
// past the notice bands so the gutter has no notch in it
@@ -460,14 +459,13 @@ fn renderPane(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: us
return;
}
- try body_layer.renderBody(p, arena, pane, r, id, active, true);
+ try body_layer.renderBody(p, s, arena, pane, r, id, active, true);
}
/// The workspace and column tags as the grid shows them: their text, the
/// word under the pointer and, in the one being edited, its selection and
/// caret. Their tag layers are drawn by renderTagLayers.
-pub fn paintHeaders(p: *Pardes) !void {
- const s = &p.surface;
+pub fn paintHeaders(p: *Pardes, s: *Surface) !void {
const chrome = p.chromeTheme();
const th = p.theme();
// global tagbar: full width, top rows — unless a native shell has
@@ -623,12 +621,7 @@ pub fn renderTagLayers(p: *Pardes, arena: std.mem.Allocator) !void {
const storage = try arena.alloc(Cell, pitch * rows);
@memset(storage, .{});
var temporary: Surface = .{ .cols = columns + TAG_TEXT_INSET, .rows = rows, .cells = storage };
- std.mem.swap(Surface, &p.surface, &temporary);
- paintPaneTag(p, arena, pane, .{ .x = 0, .y = 0, .w = columns + TAG_TEXT_INSET, .h = rows }, id, id == p.active, p.tagCapacity(r.w - TAG_TEXT_INSET)) catch |err| {
- std.mem.swap(Surface, &p.surface, &temporary);
- return err;
- };
- std.mem.swap(Surface, &p.surface, &temporary);
+ try paintPaneTag(p, &temporary, arena, pane, .{ .x = 0, .y = 0, .w = columns + TAG_TEXT_INSET, .h = rows }, id, id == p.active, p.tagCapacity(r.w - TAG_TEXT_INSET));
// A layer to a line: the first in the pane's own slot, the rest
// in the slots kept for the lines of taller tags.
for (0..rows) |line| {
@@ -791,8 +784,7 @@ fn renderHeaderLayer(p: *Pardes, arena: std.mem.Allocator, index: usize, kind: T
}
}
-pub fn paintPaneTag(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize, active: bool, capacity: u16) !void {
- const s = &p.surface;
+pub fn paintPaneTag(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize, active: bool, capacity: u16) !void {
const th = p.theme();
const chrome = p.chromeTheme();
const tx = r.x + @min(TAG_TEXT_INSET, r.w);
@@ -867,7 +859,7 @@ pub fn paintPaneTag(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect,
if (p.look_hover_preview) |preview| {
if (preview.pane == id and preview.serial == pane.serial) if (preview.sel) |sel| if (@min(sel.r0, sel.r1) < rows) {
const preview_bg = colors.mix(page_rgb, colors.mix(page_rgb, th.sel_bg));
- body_layer.paintPointerSelection(p, pane, r, tx, tw, tag_y, body_y, sel, preview_bg, null);
+ body_layer.paintPointerSelection(p, s, pane, r, tx, tw, tag_y, body_y, sel, preview_bg, null);
};
}
// The tag's own selections, while it has the keyboard, a line at a
@@ -908,6 +900,6 @@ pub fn paintPaneTag(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect,
for (pane.sel, 0..) |selection, button| {
if (selection.state == .none or (selection.state == .done and button != 0)) continue;
if (@min(selection.r0, selection.r1) >= rows) continue;
- body_layer.paintPointerSelection(p, pane, r, tx, tw, tag_y, body_y, selection, th.sel_bg, th.sel_fg);
+ body_layer.paintPointerSelection(p, s, pane, r, tx, tw, tag_y, body_y, selection, th.sel_bg, th.sel_fg);
}
}
diff --git a/src/image.zig b/src/image.zig
index 09f049ca..071a2e2a 100644
--- a/src/image.zig
+++ b/src/image.zig
@@ -941,6 +941,7 @@ fn ensureGrid(p: *pardes.Pardes, state: *State, cols: u16, rows: u16) void {
pub fn draw(
p: *pardes.Pardes,
+ s: *pardes.Surface,
state: *State,
pane_id: u8,
serial: u32,
@@ -982,7 +983,7 @@ pub fn draw(
};
const sx = x + @as(u16, @intCast(offx + cx));
const sy = y + @as(u16, @intCast(offy + cy));
- if (sx < p.surface.cols and sy < p.surface.rows)
- p.surface.set(sx, sy, cell.glyph[0..cell.glyph_len], .{ .fg = fg, .bg = bg });
+ if (sx < s.cols and sy < s.rows)
+ s.set(sx, sy, cell.glyph[0..cell.glyph_len], .{ .fg = fg, .bg = bg });
};
}
diff --git a/src/pdf_view.zig b/src/pdf_view.zig
index b2fd5866..78d3de27 100644
--- a/src/pdf_view.zig
+++ b/src/pdf_view.zig
@@ -2542,6 +2542,7 @@ pub fn horizontalWheel(core: *pardes.Pardes, pane: *pardes.Pane, direction: i8)
pub fn draw(
core: *pardes.Pardes,
+ s: *pardes.Surface,
pane: *pardes.Pane,
rect: pardes.Rect,
pane_id: usize,
@@ -2622,8 +2623,8 @@ pub fn draw(
const theme = core.theme();
const pane_bg: pardes.Color = if (theme.bg) |color| .{ .rgb = color } else .default;
// The rail runs past the notice bands; only the thumb tracks the text.
- core.surface.fill(rect.x, body_y, 1, body_h, .{ .bg = .{ .rgb = chrome.scroll_track } });
- core.surface.fill(rect.x + 1, body_y, 1, body_h, .{ .bg = pane_bg });
+ s.fill(rect.x, body_y, 1, body_h, .{ .bg = .{ .rgb = chrome.scroll_track } });
+ s.fill(rect.x + 1, body_y, 1, body_h, .{ .bg = pane_bg });
const track_h: usize = body_h;
const total = @max(@as(u64, 1), state.document_height);
@@ -2641,7 +2642,7 @@ pub fn draw(
));
var y = pos;
while (y < track_h and y < pos + len) : (y += 1)
- core.surface.fill(
+ s.fill(
rect.x,
body_y + @as(u16, @intCast(y)),
1,