summaryrefslogtreecommitdiff
path: root/src/panes.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/panes.zig')
-rw-r--r--src/panes.zig45
1 files changed, 35 insertions, 10 deletions
diff --git a/src/panes.zig b/src/panes.zig
index f995986b..b3424385 100644
--- a/src/panes.zig
+++ b/src/panes.zig
@@ -3324,11 +3324,28 @@ pub const Image = struct {
/// Construct an image pane from a path and optionally transferred dump bytes.
/// `raw` must be image_gpa-owned and ownership transfers only on success.
+ /// Without them the file is read here, not at the first draw: a draw
+ /// must not go out into the host (`pardes.turn`), and the path may be a
+ /// mount this editor serves. A file that cannot be read draws blank.
pub fn create(p: *pardes.Pardes, id: usize, path: []const u8, raw: []u8) !*pardes.Pane {
+ var bytes = raw;
+ var read_here = false;
+ if (bytes.len == 0) {
+ // The slot stays ours across the read: another request may
+ // make a pane meanwhile.
+ p.reserved_slots[id] = true;
+ defer p.reserved_slots[id] = false;
+ if (filesystem.read(p, path)) |from_disk| {
+ defer p.gpa.free(from_disk);
+ bytes = try p.image_gpa.dupe(u8, from_disk);
+ read_here = true;
+ } else |_| {}
+ }
+ errdefer if (read_here) p.image_gpa.free(bytes);
const path_copy = try p.image_gpa.dupe(u8, path);
errdefer p.image_gpa.free(path_copy);
const pane = try p.newDocPane(id);
- pane.image = .{ .path = path_copy, .raw = raw };
+ pane.image = .{ .path = path_copy, .raw = bytes };
return pane;
}
@@ -3427,12 +3444,8 @@ pub const Image = struct {
fn ensureDecoded(p: *pardes.Pardes, state: *State) void {
if (state.tried) return;
state.tried = true;
- const bytes: []const u8 = if (state.raw.len > 0)
- state.raw
- else
- filesystem.read(p, state.path) catch &.{};
- defer if (state.raw.len == 0) p.gpa.free(bytes);
- if (image.decode(p.image_gpa, bytes)) |decoded| {
+ if (state.raw.len == 0) return; // nothing was readable at open
+ if (image.decode(p.image_gpa, state.raw)) |decoded| {
state.rgba = decoded.rgba;
state.iw = decoded.w;
state.ih = decoded.h;
@@ -3771,9 +3784,15 @@ pub const Pdf = struct {
sections_output: ?SectionsOutput = null,
outline_reveal_pending: ?pdf.OutlineInternalDestination = null,
+ /// Read whole and opened from memory (the bridge copies), never from
+ /// the file itself: MuPDF reads a file lazily at every page, and the
+ /// path may be a mount this editor serves, which only a read that
+ /// gives the turn up can come back from (`filesystem.readFile`).
pub fn open(gpa: std.mem.Allocator, path: []const u8, page_one_based: usize) !@This() {
const local = filesystem.localPath(path) orelse return error.NonLocalPath;
- return initDocument(gpa, path, try Document.open(local), page_one_based);
+ const bytes = try filesystem.readFile(gpa, local);
+ defer gpa.free(bytes);
+ return initDocument(gpa, path, try Document.openBytes(bytes), page_one_based);
}
pub fn openBytes(gpa: std.mem.Allocator, path: []const u8, bytes: []const u8, page_one_based: usize) !@This() {
@@ -5219,6 +5238,10 @@ pub const Pdf = struct {
page_one_based: usize,
) !*pardes.Pane {
if (comptime !enabled) return error.PdfDisabled;
+ // The slot stays ours across the read: another request may make a
+ // pane meanwhile.
+ core.reserved_slots[id] = true;
+ defer core.reserved_slots[id] = false;
var state = if (filesystem.localPath(path) != null)
try State.open(core.pdf_gpa, path, page_one_based)
else virtual: {
@@ -5903,9 +5926,11 @@ pub const Pdf = struct {
null,
},
.x = text_x,
- .y = core.bodyTop(rect),
+ // Below the notice chips, like an image: a placed page is
+ // drawn after the cells and would paint a chip out.
+ .y = core.bodyTop(rect) + pane.notices.len,
.w = text_width,
- .h = rect.h -| pardes.BOX_H,
+ .h = (rect.h -| pardes.BOX_H) -| pane.notices.len,
.rgba = placed.rgba,
.iw = placed.width,
// The texture contains the retained band, not the full page.