Add -dest option to jump to named destination on startup/reload
authormalc <av1474@comtv.ru>
Sun, 13 Jan 2013 06:07:41 +0000 (13 10:07 +0400)
committermalc <av1474@comtv.ru>
Sun, 13 Jan 2013 06:07:41 +0000 (13 10:07 +0400)
Only works for PDF with named destinations.

KEYS
link.c
main.ml

diff --git a/KEYS b/KEYS
index 359e7ec..9b4364b 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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),
          "<path> Set path to the trim cache file");
 
+         ("-dest", Arg.String (fun s -> state.nameddest <- s),
+         "<named destination> 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 ()));