]> mj.ucw.cz Git - ucwmac.git/blob - ucw-link.tex
Reformed typesetting of URLs
[ucwmac.git] / ucw-link.tex
1 % The UCW Macro Collection: Destinations and links
2 % Written by Martin Mares <mj@ucw.cz> in 2018 and placed into public domain
3 % -------------------------------------------------------------------------
4
5 \ucwdefmodule{link}
6
7 % Should clickable links be produced?
8 \newif\ifclickable
9 \ifpdf
10         \clickabletrue
11 \else
12         \clickablefalse
13 \fi
14
15 % Common style of all clickable links
16 \pdflinkmargin=1pt
17 \def\commonlinkargs{height \the\dimexpr\ht\strutbox-0.5pt\relax depth \the\dimexpr\dp\strutbox-0.5pt\relax attr {/C [0 0 0.5] /Border [0 0 2]}}
18
19 % Define a PDF destination for the current position at the page
20 \def\destpos#1{\ifclickable\pdfdest name {#1} xyz\relax\fi}
21
22 % Define a PDF destination for the current page
23 \def\destpage#1{\ifclickable\pdfdest name {#1} fit\relax\fi}
24
25 % Typeset a clickable link to the given destination
26 % \link{dest}{text}
27 \def\link#1#2{%
28         \ifclickable
29                 \pdfstartlink\commonlinkargs goto name {#1}\relax
30                 #2%
31                 \pdfendlink\relax
32         \else
33                 #2%
34         \fi
35 }
36
37 % Typeset a clickable link to the given page number
38 % (This does not use named destinations. We use it in tables of contents and indices,
39 % where absolute page numbers are known from other sources.)
40 % \linkpage{page}{text}
41 \def\linkpage#1#2{\ifclickable\pdfstartlink\commonlinkargs goto page #1 {/Fit}\relax #2\pdfendlink\else #2\fi}
42
43 % Typesetting of URLs is tricky:
44 %
45 %   - They can contain various characters considered special by TeX.
46 %   - We want to adjust appearance of "//", "_", "~" according to font.
47 %   - We want to insert a breakpoint after "/", "?", "&".
48 %   - We need the raw form of the URL for PDF links.
49 %   - We cannot rely purely on changing catcodes, as we sometimes need
50 %     to parse URLs given as arguments of macros.
51 %   - Sometimes, it is useful to insert a manual line break to the URL.
52 %
53 % Therefore:
54 %
55 %   - In our front-end macros (\url, \linkurl) we switch catcodes
56 %     to accept '%' and '#' as normal characters; if the macros are
57 %     called indirectly, these characters must be escaped as '\%' and '\#'.
58 %   - The URL is preprocessed: special characters (with their original
59 %     catcode) are replaced by calls of auxiliary macros.
60 %   - When producing PDF links, the auxiliary macros expand to ordinary
61 %     ASCII characters.
62 %   - When typesetting the URL, the auxiliary macros expand differently.
63 %     Furthermore, they can be temporarily re-defined in the \urlprefix macro.
64 %   - "\\" (which is usually called to produce a line break) disappears in PDF links.
65 %   - If you call a custom macro in the URL, you can modify its definition
66 %     for typesetting in \urlprefix and for PDF links by appending to \urlplainascii.
67
68 % Typeset a clickable URL
69 % \url{http://example.com/}
70 \def\url{\begingroup\begingroup\allowurlchars\urlaux}
71 \def\urlaux#1{\urlauxarg{#1}\linkurlauxB{\displayurl}}
72
73 % Typeset a clickable link to the given URL
74 % \linkurl{http://example.com/}{text}
75 \def\linkurl{\begingroup\begingroup\allowurlchars\linkurlaux}
76 \def\linkurlaux#1{\urlauxarg{#1}\linkurlauxB}
77 \def\linkurlauxB#1{%
78         \leavevmode
79         \ifclickable
80                 {%
81                         \urlplainascii
82                         \pdfstartlink\commonlinkargs user {/Subtype/Link /A << /Type/Action /S/URI /URI(\tmpb) >>}\relax
83                 }%
84         \fi
85         #1%
86         \ifclickable
87                 \pdfendlink
88         \fi
89         \endgroup               % opened in \url or \linkurl
90 }
91
92 % Catcode '%' and '#' to 'other'
93 \def\allowurlchars{\catcode`\%=12\catcode`\#=12\relax}
94
95 \def\urlauxarg#1{%
96         \endgroup               % opened in \url or \linkurl
97         \toks0={#1}\edef\tmpb{\the\toks0}%
98         \replacestrings{//}{\urlslashslash}%
99         \replacestrings{_}{\urlunderscore}%
100         \replacestrings{~}{\urltilde}%
101         \replacestrings{/}{\urlslash}%
102         \replacestrings{?}{\urlquestion}%
103         \replacestrings{&}{\urlamp}%
104         \replacestrings{=}{\urlequal}%
105 }
106
107 % Style switches at the beginning/end of an URL (feel free to re-define them)
108 \let\urlprefix\it
109 \let\urlsuffix\/
110
111 % Default appearance of characters special in URLs
112 \def\urlslashslash{/\kern\urlinterslashkern/}
113 \def\urlunderscore{\_}
114 \def\urltilde{{\tt\char126}}
115 \def\urlslash{/\penalty100\relax}
116 \def\urlquestion{?\penalty100\relax}
117 \def\urlamp{\&\penalty100\relax}
118 \def\urlequal{=\penalty100\relax}
119
120 % Kern to place between "//" in an URL
121 \newdimen\urlinterslashkern
122 \urlinterslashkern=-0.1em
123
124 % Switch auxiliary macros, so special characters expand to plain ASCII characters
125 % (since we need to replace them in the expand processor, we cannot use \let for that)
126 % If you want to modify expansion of your macros, extend \urlplainascii using \appendef.
127 {
128 \lccode`A=`\_
129 \lccode`B=`\~
130 \lccode`C=`\&
131 \lccode`D=`\%
132 \lccode`E=`\#
133 \lowercase{\gdef\urlplainascii{%
134         \def\urlslashslash{//}%
135         \def\urlunderscore{A}%
136         \def\urltilde{B}%
137         \def\urlslash{/}%
138         \def\urlquestion{?}%
139         \def\urlamp{C}%
140         \def\urlequal{=}%
141         \def\%{D}%
142         \def\#{E}%
143         \def\\{}%
144 }}}
145
146 % Typeset the URL stored in \tmpb. In most cases, this is used internally by \url,
147 % but you can call it explicity from the second argument of \linkurl to typeset the current URL.
148 \def\displayurl{{\urlprefix\tmpb\urlsuffix}}