Attached is a patch that provides hyperlink support when the file is
exported to ps and then converted to pdf using ps2pdf.
No external style sheets are needed.
After patching and re-building you WILL need to:
texmacs --delete-style-cache
once, or within texmacs click on "tools, updates, styles"
The only problem I am aware of is that the link generally moves to the
top of the target page (or bottom, if it is the last page) instead of
the correct part of the target page.
labels have a new internal definition and are implemented as a locus
containing a link of type "anchor" in which the id is written as a named
destination in postscript.
(In fact the ID is always written as a named destination even for
non-anchor links, which probably doesn't matter).
The body of the locus is the original label definition so it should all
work fine I hope.
(Let me know if labels behave badly).
best regards
Anyone want to review this, or commit this to the main project?
Sam
On 30/06/11 20:55, Sam Liddicott wrote:
I think I'm abusing locus a little too much and it's not robust.
I think I need to change the definition of reference:
env ("reference")= tree (MACRO, "Id",
tree (LOCUS, copy (ref_id), ln3, reftxt));
and replace reftxt with something like
tree(DECORATE_LINK, tree(ARG, "Id"), refrext);
And DECORATE_LINK will work something like datoms but emit the right
postscript.
This can be a general way for annotating a box with hidden postscript.
Sam
On 30/06/11 17:57, Sam Liddicott wrote:
I've decided to extend the built-in label macro to also contain a
special locus that will generate the pdfmark for a named destination
(anchor to html people).
I've already got my hackery in place for locus, so spotting a new
kind should be easy enough.
I hope to post the full patch sometime tomorrow.
(Sadly it only works for postscript -> pdf and not new pdf rendering).
Sam
On 30/06/11 12:21, Sam Liddicott wrote:
On 29/06/11 19:54, marc lalaude-labayle wrote:
I follow your posts about this feature and really hopes you'll
achieve to add this one to texmacs.
I've done it.
It's hell.
B the time a <reference> is rendered it's a locus and knowledge that
it was a reference has gone, and the actual reference value is hard
9for me) to get hold of.
However I've got the locus rendering to emit the required pdfmark,
and that's hacky but works.
Joris may have something to say.
I would rather have done this as a <specific printer> macro but I
have no knowledge of the bounding rect which is needed.
However, a <label> is not actually rendered so there is nowhere for
me to overload to add the pdfmark to the postscript.
Based on my hacking of
<specific|printer<image|<tuple|<raw-data|magic-macro>... I'm
emitting the pdfmark stuff for the label.
(It's very slow generating the post-script).
Anyway, it works - although I have to override the label macro to
emit this.
The downsides are:
1. hackyness
2. slow - I need to have the label rendered directly or find some
better means of injecting post-script
3. despite me trying to do do the label's properly (in postscript)
the link-targets just seem to be to "the page" rather that the right
part of the page, so I'll have to see what I did wrong there.
Sam
Marc
2011/6/29 Sam Liddicott <s...@liddicott.com <mailto:s...@liddicott.com>>
Wow, I'm nearly there.
Using post_display on locus_box_rep I can blot out a hyperlink!
So I'm just adding the anchor and href methods to the renderer
class.
Sam
On 28/06/11 18:15, Sam Liddicott wrote:
I'm determined to add PDF hyperlink support to texmacs.
This post-script can be inserted wherever a <label> is
rendered:
[ /Dest (LABEL-ID-HERE) cvn /View [/XYZ null null null] /DEST
pdfmark
I've found the point at which the label is rendered but
because it has no real appearance of it's own I've still got
to poke my way through to the printer_rep layer.
This post-script can be inserted wherever a reference appears,
by which I mean a certain type of LOCUS.
[
/Rect [ .. ..... .. ]
/Border [16 16 1 [3 10]]
/Color [1 0 0]
/Dest (LABEL-ID-HERE) cvn
/Subtype /Link
/ANN pdfmark
The rect coordinates are the same as used when rendering the
locus with mouse-over so that it shows a green box.
I've tested the post-script by hand-editing files and it does
work.
I'm sure that I get to do this somewhere around the final
print statement in concater_rep::typeset_locus file
concat_active.cpp but I still can't make the link between that
point and the printer_rep renderer, unless concat_active is a
subclass which I doubt.
So right now I'm trying to track down what locus_box does. I
see it in change_boxes.cpp but am no closer to finding the
point at which printer_rep's print() is invoked or where the
green rect coords are kept, but I hope to find it soon.
I'm both cases LABEL-ID-HERE has to have weird symbols in
octal with \, and \ ( ) escaped by \
This is taking me HOURS so if anyone who knows the C better
than me wants to speak out, please do.
Sam
_______________________________________________
Texmacs-dev mailing list
Texmacs-dev@gnu.org <mailto:Texmacs-dev@gnu.org>
https://lists.gnu.org/mailman/listinfo/texmacs-dev
-- [FSF Associate Member #2325]
<http://www.fsf.org/register_form?referrer=2325>
<http://www.openrightsgroup.org/>
_______________________________________________
Texmacs-dev mailing list
Texmacs-dev@gnu.org <mailto:Texmacs-dev@gnu.org>
https://lists.gnu.org/mailman/listinfo/texmacs-dev
_______________________________________________
Texmacs-dev mailing list
Texmacs-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/texmacs-dev
--
[FSF Associate Member #2325]
<http://www.fsf.org/register_form?referrer=2325>
<http://www.openrightsgroup.org/>
commit 58fc5bb7a3e7f802e5309c3980344f7959f1b3e2
Author: Sam Liddicott <sliddic...@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, "",
_______________________________________________
Texmacs-dev mailing list
Texmacs-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/texmacs-dev