From 1bf471d902f5709f63fcd32b2f1fe0b75a27712e Mon Sep 17 00:00:00 2001 From: malc Date: Sun, 13 Jan 2013 10:07:41 +0400 Subject: [PATCH] Add -dest option to jump to named destination on startup/reload Only works for PDF with named destinations. --- KEYS | 2 +- link.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++------------------- main.ml | 39 +++++++++++++++++++++++------ 3 files changed, 95 insertions(+), 34 deletions(-) diff --git a/KEYS b/KEYS index 359e7ec..9b4364b 100644 --- a/KEYS +++ b/KEYS @@ -36,7 +36,7 @@ o - switch to outline mode ' - switch to bookmark mode h,F1 - switch to help mode i - switch to info mode -e - switch to error messages mode (if stderr was redirected) +e - view error log m - create named bookmark ~ - create quick bookmark z - crop diff --git a/link.c b/link.c index f4471e9..dd5837e 100644 --- a/link.c +++ b/link.c @@ -1155,35 +1155,45 @@ static void layout (void) } } +static struct anchor { int n; int y; int h; } desttoanchor (fz_link_dest *dest) +{ + int i; + struct anchor a; + struct pagedim *pdim = state.pagedims; + + a.n = -1; + a.y = 0; + for (i = 0; i < state.pagedimcount; ++i) { + if (state.pagedims[i].pageno > dest->ld.gotor.page) + break; + pdim = &state.pagedims[i]; + } + if (dest->ld.gotor.flags & fz_link_flag_t_valid) { + fz_point p; + p.x = 0; + p.y = dest->ld.gotor.lt.y; + p = fz_transform_point (pdim->lctm, p); + a.y = p.y; + } + if (dest->ld.gotor.page >= 0 && dest->ld.gotor.page < 1<<30) { + double y0, y1; + + y0 = MIN (pdim->bounds.y0, pdim->bounds.y1); + y1 = MAX (pdim->bounds.y0, pdim->bounds.y1); + a.h = y1 - y0; + a.n = dest->ld.gotor.page; + } + return a; +} + static void recurse_outline (fz_outline *outline, int level) { while (outline) { - fz_link_dest *dest; - int i, top = 0; - struct pagedim *pdim = state.pagedims; - - dest = &outline->dest; - for (i = 0; i < state.pagedimcount; ++i) { - if (state.pagedims[i].pageno > dest->ld.gotor.page) - break; - pdim = &state.pagedims[i]; - } - if (dest->ld.gotor.flags & fz_link_flag_t_valid) { - fz_point p; - p.x = 0; - p.y = dest->ld.gotor.lt.y; - p = fz_transform_point (pdim->lctm, p); - top = p.y; - } - if (dest->ld.gotor.page >= 0 && dest->ld.gotor.page < 1<<30) { - int h; - double y0, y1; + struct anchor a = desttoanchor (&outline->dest); - y0 = MIN (pdim->bounds.y0, pdim->bounds.y1); - y1 = MAX (pdim->bounds.y0, pdim->bounds.y1); - h = y1 - y0; + if (a.n >= 0) { printd ("o %d %d %d %d %s", - level, dest->ld.gotor.page, top, h, outline->title); + level, a.n, a.y, a.h, outline->title); } if (outline->down) { recurse_outline (outline->down, level + 1); @@ -1615,20 +1625,48 @@ static void * mainloop (void *unused) int wthack, off; char *password; char *filename; + char *nameddest; char *utf8filename; ret = sscanf (p + 5, " %d %n", &wthack, &off); if (ret != 1) { - errx (1, "malformed cs `%.*s' ret=%d", len, p, ret); + errx (1, "malformed open `%.*s' ret=%d", len, p, ret); } filename = p + 5 + off; filenamelen = strlen (filename); password = filename + filenamelen + 1; + nameddest = password + strlen (password) + 1; openxref (filename, password); pdfinfo (); initpdims (); + if (nameddest && *nameddest) { + struct anchor a; + fz_link_dest dest; + pdf_obj *needle, *obj; + + needle = pdf_new_string (state.ctx, nameddest, + strlen (nameddest)); + obj = pdf_lookup_dest (state.u.pdf, needle); + if (obj) { + dest = pdf_parse_link_dest (state.u.pdf, obj); + + a = desttoanchor (&dest); + if (a.n >= 0) { + printd ("a %d %d %d", a.n, a.y, a.h); + } + else { + printd ("emsg failed to parse destination `%s'\n", + nameddest); + } + } + else { + printd ("emsg destination `%s' not found\n", + nameddest); + } + pdf_drop_obj (needle); + } if (!wthack) { utf8filename = mbtoutf8 (filename); printd ("msg Opened %s (press h/F1 to get help)", utf8filename); diff --git a/main.ml b/main.ml index 7b5e075..7a468c3 100644 --- a/main.ml +++ b/main.ml @@ -457,6 +457,7 @@ type state = ; mutable bookmarks : outline list ; mutable path : string ; mutable password : string + ; mutable nameddest : string ; mutable geomcmds : (string * ((string * (unit -> unit)) list)) ; mutable memused : memsize ; mutable gen : gen @@ -692,6 +693,7 @@ let state = ; bookmarks = [] ; path = "" ; password = "" + ; nameddest = "" ; geomcmds = firstgeomcmds ; hists = { nav = cbnew 10 emptyanchor @@ -1863,16 +1865,17 @@ let flushpages () = Hashtbl.clear state.pagemap; ;; -let opendoc path password = +let opendoc path password nameddest = state.path <- path; state.password <- password; state.gen <- state.gen + 1; state.docinfo <- []; + state.nameddest <- nameddest; flushpages (); setaalevel conf.aalevel; Wsi.settitle ("llpp " ^ (mbtoutf8 (Filename.basename path))); - wcmd "open %d %s\000%s\000" (btod state.wthack) path password; + wcmd "open %d %s\000%s\000%s\000" (btod state.wthack) path password nameddest; invalidate "reqlayout" (fun () -> wcmd "reqlayout %d %d" conf.angle (btod conf.proportional)); @@ -1881,7 +1884,7 @@ let opendoc path password = let reload () = state.anchor <- getanchor (); state.wthack <- true; - opendoc state.path state.password; + opendoc state.path state.password state.nameddest; ;; let scalecolor c = @@ -2284,6 +2287,11 @@ let act cmds = if conf.verbose then showtext ' ' args + | "emsg" -> + Buffer.add_string state.errmsgs args; + state.newerrmsgs <- true; + G.postRedisplay "error message" + | "progress" -> let progress, text = try @@ -2498,6 +2506,18 @@ let act cmds = logcurrently currently end + | "a" -> + let (n, t, h) = + try + Scanf.sscanf args "%u %u %d" + (fun n t h -> n, t, h) + with exn -> + dolog "error processing 'a' %S: %s" + cmds (Printexc.to_string exn); + exit 1; + in + state.anchor <- (n, float t /. float h, 0.0) + | "info" -> state.docinfo <- (1, args) :: state.docinfo @@ -4420,7 +4440,7 @@ let enterinfomode = (fun v -> conf.aalevel <- bound v 0 8; state.anchor <- getanchor (); - opendoc state.path state.password; + opendoc state.path state.password state.nameddest; ); src#string "page scroll scaling factor" (fun () -> string_of_float conf.pgscale) @@ -4722,7 +4742,7 @@ let gotounder = function let ranchor = state.path, state.password, anchor in state.anchor <- (pageno, 0.0, 0.0); state.ranchors <- ranchor :: state.ranchors; - opendoc path ""; + opendoc path "" ""; ) else showtext '!' ("Could not find " ^ filename) @@ -4866,7 +4886,7 @@ let viewkeyboard key mask = | (path, password, anchor) :: rest -> state.ranchors <- rest; state.anchor <- anchor; - opendoc path password + opendoc path password "" end; end; @@ -5109,7 +5129,7 @@ let viewkeyboard key mask = | 105 -> (* i *) enterinfomode () - | 101 when conf.redirectstderr -> (* e *) + | 101 when Buffer.length state.errmsgs > 0 -> (* e *) entermsgsmode () | 109 -> (* m *) @@ -6938,6 +6958,9 @@ let () = ("-tcf", Arg.String (fun s -> trimcachepath := s), " Set path to the trim cache file"); + ("-dest", Arg.String (fun s -> state.nameddest <- s), + " Set named destination"); + ("-v", Arg.Unit (fun () -> Printf.printf "%s\nconfiguration path: %s\n" @@ -7045,7 +7068,7 @@ let () = state.sw <- sw; state.text <- "Opening " ^ (mbtoutf8 state.path); reshape winw winh; - opendoc state.path state.password; + opendoc state.path state.password state.nameddest; state.uioh <- uioh; Sys.set_signal Sys.sighup (Sys.Signal_handle (fun _ -> reload ())); -- 2.11.4.GIT