commit 58fc5bb7a3e7f802e5309c3980344f7959f1b3e2
Author: Sam Liddicott <sliddicott@sonicwall.com>
Date:   Thu Jun 30 17:51:43 2011 +0100

    Add pdfmark support to reference

diff --git a/src/src/Graphics/Renderer/printer.cpp b/src/src/Graphics/Renderer/printer.cpp
index c1da452..946d522 100644
--- a/src/src/Graphics/Renderer/printer.cpp
+++ b/src/src/Graphics/Renderer/printer.cpp
@@ -118,6 +118,9 @@ printer_rep::~printer_rep () {
 
   generate_tex_fonts ();
   prologue << "end\n"
+
+           << "systemdict /pdfmark known{userdict /?pdfmark systemdict /exec get put}{userdict /?pdfmark systemdict /pop get put userdict /pdfmark systemdict /cleartomark get put}ifelse\n"
+
            << "%%EndProlog\n\n"
 	   << "%%BeginSetup\n"
 	   << "%%Feature: *Resolution " << as_string (dpi) << "dpi\n"
@@ -822,6 +825,40 @@ printer_rep::apply_shadow (SI x1, SI y1, SI x2, SI y2) {
   (void) x1; (void) y1; (void) x2; (void) y2;
 }
 
+void
+printer_rep::anchor(string label, SI x, SI y) {
+  string s = "(";
+  s = s << prepare_text(label) << ") cvn";
+
+  if (linelen>0) cr();
+  print("[ /Dest");
+  print(s);
+  print("/View [/XYZ");
+  print(x, y);
+  print("null] /DEST pdfmark");
+  cr();
+}
+
+void
+printer_rep::href(string label, SI x1, SI y1, SI x2, SI y2) {
+  string s = "(";
+  s = s << prepare_text(label) << ") cvn";
+
+  if (linelen>0) cr();
+
+  print("[");
+  print("/Dest");
+  print(s);
+  print("/Rect [");
+  print(x1, y1);
+  print(x2, y2);
+  print("]");
+  print("/Border [16 16 1 [3 10]] /Color [1 0 0]");
+  print("/Subtype /Link");
+  print("/ANN pdfmark");
+  cr();
+}
+
 /******************************************************************************
 * user interface
 ******************************************************************************/
diff --git a/src/src/Graphics/Renderer/printer.hpp b/src/src/Graphics/Renderer/printer.hpp
index aff9c48..486435b 100644
--- a/src/src/Graphics/Renderer/printer.hpp
+++ b/src/src/Graphics/Renderer/printer.hpp
@@ -69,6 +69,10 @@ public:
   void select_tex_font (string name);
   void generate_tex_fonts ();
 
+  /************************ subroutines hyperlinks ***************************/
+  void anchor(string label, SI x, SI y);
+  void href(string label, SI x1, SI y1, SI x2, SI y2);
+
   /********************** routines from renderer.hpp *************************/
 
   void  set_clipping (SI x1, SI y1, SI x2, SI y2, bool restore= false);
diff --git a/src/src/Graphics/Renderer/renderer.cpp b/src/src/Graphics/Renderer/renderer.cpp
index 1d458ec..5e91ab1 100644
--- a/src/src/Graphics/Renderer/renderer.cpp
+++ b/src/src/Graphics/Renderer/renderer.cpp
@@ -64,6 +64,20 @@ renderer_rep::interrupted (bool check) {
   return false;
 }
 
+void
+renderer_rep::anchor(string label, SI x, SI y) {
+  (void) label;
+  return;
+}
+
+void
+renderer_rep::href(string label, SI x1, SI y1, SI x2, SI y2) {
+  (void) label;
+  (void) x1; (void) y1; (void) x2; (void) y2;
+  return;
+}
+
+
 /******************************************************************************
 * Origin and shrinking factor
 ******************************************************************************/
diff --git a/src/src/Graphics/Renderer/renderer.hpp b/src/src/Graphics/Renderer/renderer.hpp
index f42060a..ae379c3 100644
--- a/src/src/Graphics/Renderer/renderer.hpp
+++ b/src/src/Graphics/Renderer/renderer.hpp
@@ -104,6 +104,10 @@ public:
   virtual void get_shadow (renderer ren, SI x1, SI y1, SI x2, SI y2) = 0;
   virtual void put_shadow (renderer ren, SI x1, SI y1, SI x2, SI y2) = 0;
   virtual void apply_shadow (SI x1, SI y1, SI x2, SI y2) = 0;
+
+  /* href and stuff */
+  virtual void anchor(string label, SI x, SI y);
+  virtual void href(string label, SI x1, SI y1, SI x2, SI y2);
 };
 
 void abs_round (SI& l);
diff --git a/src/src/Typeset/Boxes/Modifier/change_boxes.cpp b/src/src/Typeset/Boxes/Modifier/change_boxes.cpp
index 3b4ab4d..d656d8e 100644
--- a/src/src/Typeset/Boxes/Modifier/change_boxes.cpp
+++ b/src/src/Typeset/Boxes/Modifier/change_boxes.cpp
@@ -469,20 +469,39 @@ action_box_rep::action (tree t, SI x, SI y, SI delta) {
 struct locus_box_rep: public change_box_rep {
   list<string> ids;
   SI pixel;
+  string ref;
+  string anchor;
   locus_box_rep (path ip, box b, list<string> ids, SI pixel);
+  locus_box_rep (path ip, box b, list<string> ids, SI pixel, string _rep, string _anchor);
   operator tree () { return tree (TUPLE, "locus"); }
   void loci (SI x, SI y, SI delta, list<string>& ids2, rectangles& rs);
+  void post_display (renderer &ren);
+
 };
 
 locus_box_rep::locus_box_rep (path ip, box b, list<string> ids2, SI pixel2):
   change_box_rep (ip, true), ids (ids2), pixel (pixel2)
 {
+  ref = "";
+  anchor = "";
   insert (b, 0, 0);
   position ();
   left_justify ();
   finalize ();
 }
 
+locus_box_rep::locus_box_rep (path ip, box b, list<string> ids2, SI pixel2, string _ref, string _anchor):
+  change_box_rep (ip, true), ids (ids2), pixel (pixel2)
+{
+  ref = _ref;
+  anchor = _anchor;
+  insert (b, 0, 0);
+  position ();
+  left_justify ();
+  finalize ();
+}
+
+
 void
 locus_box_rep::loci (SI x, SI y, SI delta, list<string>& l, rectangles& rs) {
   bs[0]->loci (x, y, delta, l, rs);
@@ -490,6 +509,12 @@ locus_box_rep::loci (SI x, SI y, SI delta, list<string>& l, rectangles& rs) {
   rs= rs * outline (rectangles (rectangle (x1, y1, x2, y2)), pixel);
 }
 
+void
+locus_box_rep::post_display (renderer &ren) {
+  if (ref!="") ren->href(ref, x1, y1, x2, y2);
+  if (anchor!="") ren->anchor(anchor, x1, y1);
+}
+
 /******************************************************************************
 * tag boxes
 ******************************************************************************/
@@ -630,6 +655,11 @@ locus_box (path ip, box b, list<string> ids, SI pixel) {
 }
 
 box
+locus_box (path ip, box b, list<string> ids, SI pixel, string ref, string anchor) {
+  return tm_new<locus_box_rep> (ip, b, ids, pixel, ref, anchor);
+}
+
+box
 tag_box (path ip, box b, tree keys) {
   return tm_new<tag_box_rep> (ip, b, keys);
 }
diff --git a/src/src/Typeset/Boxes/construct.hpp b/src/src/Typeset/Boxes/construct.hpp
index bd4eaf0..f146dd8 100644
--- a/src/src/Typeset/Boxes/construct.hpp
+++ b/src/src/Typeset/Boxes/construct.hpp
@@ -93,6 +93,7 @@ box page_box (path ip, tree page, SI w, SI h,
 box action_box (path ip, box b, tree filter, command cmd, bool child_flag);
 box action_box (path ip, box b, tree f, command c, bool ch, path vip);
 box locus_box (path ip, box b, list<string> ids, SI pixel);
+box locus_box (path ip, box b, list<string> ids, SI pixel, string ref, string anchor);
 box macro_box (path ip, box b, font big_fn= font ());
 box tag_box (path ip, box b, tree keys);
 
diff --git a/src/src/Typeset/Concat/concat_active.cpp b/src/src/Typeset/Concat/concat_active.cpp
index 86ed5eb..390f8ef 100644
--- a/src/src/Typeset/Concat/concat_active.cpp
+++ b/src/src/Typeset/Concat/concat_active.cpp
@@ -81,13 +81,16 @@ concater_rep::typeset_case (tree t, path ip) {
 ******************************************************************************/
 
 bool
-build_locus (edit_env env, tree t, list<string>& ids, string& col) {
+build_locus (edit_env env, tree t, list<string>& ids, string& col, string &ref, string &anchor) {
   //cout << "Typeset " << t << "\n";
   int last= N(t)-1;
   tree body= env->expand (t[last], true);
   //cout << "Typeset " << body << "\n";
   bool accessible= is_accessible (obtain_ip (body));
   bool visited= false;
+  ref="";
+  anchor="";
+
   if (!is_nil (env->link_env)) {
     int i, j;
     for (i=0; i<last; i++) {
@@ -110,10 +113,14 @@ build_locus (edit_env env, tree t, list<string>& ids, string& col) {
 	       << (env->secure? tree ("true"): tree ("false"));
 	env->link_env->insert_link (arg);
 	for (j=2; j<N(arg); j++) {
-	  if (is_compound (arg[j], "id", 1) && is_atomic (arg[j][0]))
+	  if (is_compound (arg[j], "id", 1) && is_atomic (arg[j][0])) {
 	    visited= visited || has_been_visited ("id:" * arg[j][0]->label);
-	  if (is_compound (arg[j], "url", 1) && is_atomic (arg[j][0]))
+	    anchor = arg[j][0]->label;
+	  }
+	  if (is_compound (arg[j], "url", 1) && is_atomic (arg[j][0])) {
 	    visited= visited || has_been_visited ("url:" * arg[j][0]->label);
+	    ref = arg[j][0]->label;
+	  }
 	}
       }
     }
@@ -132,13 +139,23 @@ build_locus (edit_env env, tree t, list<string>& ids, string& col) {
   return accessible;
 }
 
+bool
+build_locus (edit_env env, tree t, list<string>& ids, string& col) {
+  string ref;
+  string anchor;
+  return build_locus(env, t, ids, col, ref, anchor);
+}
+
 void
 concater_rep::typeset_locus (tree t, path ip) {
+  string ref;
+  string anchor;
+
   if (N(t) == 0) { typeset_error (t, ip); return; }
   int last= N(t)-1;
   list<string> ids;
   string col;
-  if (build_locus (env, t, ids, col)) {
+  if (build_locus (env, t, ids, col, ref, anchor)) {
     marker (descend (ip, 0));
     tree old= env->local_begin (COLOR, col);
     typeset (t[last], descend (ip, last));
@@ -149,7 +166,7 @@ concater_rep::typeset_locus (tree t, path ip) {
     tree old= env->local_begin (COLOR, col);
     box b= typeset_as_concat (env, t[last], descend (ip, last));
     env->local_end (COLOR, old);
-    print (locus_box (ip, b, ids, env->get_int (SFACTOR) * PIXEL));
+    print (locus_box (ip, b, ids, env->get_int (SFACTOR) * PIXEL, ref, anchor));
   }
 }
 
diff --git a/src/src/Typeset/Env/env_default.cpp b/src/src/Typeset/Env/env_default.cpp
index ff41d06..7245129 100644
--- a/src/src/Typeset/Env/env_default.cpp
+++ b/src/src/Typeset/Env/env_default.cpp
@@ -252,9 +252,11 @@ initialize_default_env () {
   tree dest_url (URL, tree (ARG, "destination"));
   tree dest_script (SCRIPT, tree (ARG, "destination"), tree (ARG, "where"));
   tree dest_ref (URL, tree (MERGE, "#", tree (ARG, "Id")));
+  tree anchor (ID, tree (MERGE, "#", tree (ARG, "Id")));
   tree ln1 (LINK, "hyperlink", copy (src_id), copy (dest_url));
   tree ln2 (LINK, "action", copy (src_id), copy (dest_script));
   tree ln3 (LINK, "hyperlink", copy (ref_id), copy (dest_ref));
+  tree ln4 (LINK, "anchor", anchor);
   tree labflag (FLAG, tree (ARG, "Id"), "blue", "Id");
   tree labtxt (SET_BINDING, tree (ARG, "Id"), tree (VALUE, THE_LABEL));
   tree merged (MERGE, tree (VALUE, THE_TAGS), tuple (tree (ARG, "Id")));
@@ -267,7 +269,8 @@ initialize_default_env () {
   env ("action")= tree (MACRO, "body", "destination", "where",
 			tree (LOCUS, copy (src_id), ln2,
                               tree (ARG, "body")));
-  env ("label")= tree (MACRO, "Id", tree (CONCAT, labflag, labtxt));
+  env ("label")= tree (MACRO, "Id", 
+		       tree (LOCUS, copy (ref_id), ln4, tree (CONCAT, labflag, labtxt)));
   env ("tag")= tree (MACRO, "Id", "body",
 		     tree (WITH, "the-tags", merged,
 			   tree (SURROUND, tagflag, "",
