summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/look.zig26
-rw-r--r--src/pdf_view.zig10
2 files changed, 34 insertions, 2 deletions
diff --git a/src/look.zig b/src/look.zig
index 11c77760..0f5103ba 100644
--- a/src/look.zig
+++ b/src/look.zig
@@ -1260,6 +1260,20 @@ fn missedPage(p: *Pardes, id: usize, path: []const u8, page: usize) void {
missed(p, id, "{s} has no page {d}", .{ missText(path, &cut), page });
}
+/// `file.pdf:P:H` names hit H of the pane's search on page P: none there,
+/// or no search, is a miss as a page past the last is.
+fn missedHit(p: *Pardes, id: usize, path: []const u8, page: usize, hit: usize) void {
+ var cut: [miss_path_cap + "…".len]u8 = undefined;
+ missed(p, id, "{s} has no search hit {d} on page {d}", .{ missText(path, &cut), hit, page });
+}
+
+/// The open PDF pane showing `path`, if one does.
+fn pdfPaneOf(p: *Pardes, path: []const u8) ?*panes.Pdf.State {
+ if (comptime !pdf_enabled) return null;
+ for (p.panes) |slot| if (slot) |pane| if (pane.pdf) |*pv| if (std.mem.eql(u8, pv.path, path)) return pv;
+ return null;
+}
+
fn missedLine(p: *Pardes, id: usize, path: []const u8, line: anytype) void {
var cut: [miss_path_cap + "…".len]u8 = undefined;
missed(p, id, "{s} has no line {d}", .{ missText(path, &cut), line });
@@ -1505,6 +1519,7 @@ fn lookPdfPage(p: *Pardes, id: usize, target: usize, pv: anytype, expr: []const
return missed(p, id, no_text, .{missText(pv.path, &cut)}) else 0;
if (page == 0) return missedPage(p, id, pv.path, 0);
if (page > pv.page_count) return missedPage(p, id, pv.path, page);
+ if (!pv.hitExists(p.pdf_gpa, page, hit)) return missedHit(p, id, pv.path, page, hit);
const pane = p.panes[target].?;
clearNavigationSelection(p, pane);
if (pv.focusLocation(p.pdf_gpa, page, hit)) panes.Pdf.resetPageChrome(pane);
@@ -1761,8 +1776,10 @@ pub fn lookAt(p: *Pardes, id: usize, operand_raw: []const u8) void {
// A PDF's page past its last is a miss, as a line past a file's
// end is: never the last page in its place (opening one, the
// same: Pdf.openPane's .refuse).
- if (comptime pdf_enabled) if (target.pdf) |pv| if (t.at.line > pv.page_count)
- return missedPage(p, id, pv.path, t.at.line);
+ if (comptime pdf_enabled) if (target.pdf) |*pv| {
+ if (t.at.line > pv.page_count) return missedPage(p, id, pv.path, t.at.line);
+ if (!pv.hitExists(p.pdf_gpa, @max(1, t.at.line), t.at.col)) return missedHit(p, id, pv.path, @max(1, t.at.line), t.at.col);
+ };
const before = p.active;
clearNavigationSelection(p, target);
focusPaneLine(p, t.id, t.at, .center);
@@ -1791,6 +1808,11 @@ pub fn lookAt(p: *Pardes, id: usize, operand_raw: []const u8) void {
},
.file => |target| {
if (comptime pdf_enabled) if (target.kind == .pdf) {
+ // A hit of a search: one of the open pane's, checked by
+ // focusPaneByPath's pane; a PDF not open has none.
+ if (target.at.col > 0) if (pdfPaneOf(p, target.path)) |pv| {
+ if (!pv.hitExists(p.pdf_gpa, @max(1, target.at.line), target.at.col)) return missedHit(p, id, target.path, @max(1, target.at.line), target.at.col);
+ } else return missedHit(p, id, target.path, @max(1, target.at.line), target.at.col);
if (focusPaneByPath(p, target.path, target.at)) return;
const free = p.freeSlot() orelse return p.reportError(id, "look", error.NoPaneSlots);
// Said with its path and why, as an image that cannot be read
diff --git a/src/pdf_view.zig b/src/pdf_view.zig
index b307d1f3..d5769ad3 100644
--- a/src/pdf_view.zig
+++ b/src/pdf_view.zig
@@ -547,6 +547,16 @@ pub const State = if (enabled) struct {
state.search_results = results;
}
+ /// Whether page `page` (one-based) holds search hit `hit` (one-based) of
+ /// the pane's search: none asked, no hit is there.
+ pub fn hitExists(state: *@This(), gpa: std.mem.Allocator, page: usize, hit: usize) bool {
+ if (hit == 0) return true;
+ if (state.search_query.len == 0 or page == 0 or page > state.page_count) return false;
+ var results = state.document.search(gpa, page - 1, state.search_query) catch return false;
+ defer results.deinit(gpa);
+ return hit <= results.hit_count;
+ }
+
pub fn ensureOutline(state: *@This(), gpa: std.mem.Allocator) ?*const pdf.Outline {
if (!state.outline_tried) {
state.outline_tried = true;