beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdfaction.w
blobbb0d6e06d50a75cfca184bd439f1f146f32c7a9e
1 % pdfaction.w
3 % Copyright 2009-2011 Taco Hoekwater <taco@@luatex.org>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software; you can redistribute it and/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation; either version 2 of the License, or (at your
10 % option) any later version.
12 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
20 @ @c
22 #include "ptexlib.h"
24 @ read an action specification
26 @c halfword scan_action(PDF pdf)
28 int p = new_node(whatsit_node, pdf_action_node);
29 (void) pdf;
30 if (scan_keyword("user"))
31 set_pdf_action_type(p, pdf_action_user);
32 else if (scan_keyword("goto"))
33 set_pdf_action_type(p, pdf_action_goto);
34 else if (scan_keyword("thread"))
35 set_pdf_action_type(p, pdf_action_thread);
36 else
37 normal_error("pdf backend", "action type missing");
38 if (pdf_action_type(p) == pdf_action_user) {
39 scan_toks(false, true);
40 set_pdf_action_tokens(p, def_ref);
41 return p;
43 if (scan_keyword("file")) {
44 scan_toks(false, true);
45 set_pdf_action_file(p, def_ref);
47 if (scan_keyword("page")) {
48 if (pdf_action_type(p) != pdf_action_goto)
49 normal_error("pdf backend", "only GoTo action can be used with 'page'");
50 set_pdf_action_type(p, pdf_action_page);
51 scan_int();
52 if (cur_val <= 0)
53 normal_error("pdf backend", "page number must be positive");
54 set_pdf_action_id(p, cur_val);
55 set_pdf_action_named_id(p, 0);
56 scan_toks(false, true);
57 set_pdf_action_tokens(p, def_ref);
58 } else if (scan_keyword("name")) {
59 scan_toks(false, true);
60 set_pdf_action_named_id(p, 1);
61 set_pdf_action_id(p, def_ref);
62 } else if (scan_keyword("num")) {
63 if ((pdf_action_type(p) == pdf_action_goto) &&
64 (pdf_action_file(p) != null))
65 normal_error("pdf backend", "'goto' option cannot be used with both 'file' and 'num'");
66 scan_int();
67 if (cur_val <= 0)
68 normal_error("pdf backend", "num identifier must be positive");
69 set_pdf_action_named_id(p, 0);
70 set_pdf_action_id(p, cur_val);
71 } else {
72 normal_error("pdf backend", "identifier type missing");
74 if (scan_keyword("newwindow")) {
75 set_pdf_action_new_window(p, pdf_window_new);
76 /* Scan an optional space */
77 get_x_token();
78 if (cur_cmd != spacer_cmd)
79 back_input();
80 } else if (scan_keyword("nonewwindow")) {
81 set_pdf_action_new_window(p, pdf_window_nonew);
82 /* Scan an optional space */
83 get_x_token();
84 if (cur_cmd != spacer_cmd)
85 back_input();
86 } else {
87 set_pdf_action_new_window(p, pdf_window_notset);
89 if ((pdf_action_new_window(p) > pdf_window_notset) &&
90 (((pdf_action_type(p) != pdf_action_goto) &&
91 (pdf_action_type(p) != pdf_action_page)) ||
92 (pdf_action_file(p) == null)))
93 normal_error("pdf backend","'newwindow' or 'nonewwindow' must be used with 'goto' and 'file' option");
94 return p;
97 @ write an action specification
99 @c void write_action(PDF pdf, halfword p)
101 char *s;
102 int d = 0;
103 if (pdf_action_type(p) == pdf_action_user) {
104 pdf_out(pdf, '\n');
105 pdf_print_toks(pdf, pdf_action_tokens(p));
106 pdf_out(pdf, '\n');
107 return;
109 pdf_begin_dict(pdf);
110 if (pdf_action_file(p) != null) {
111 pdf_add_name(pdf, "F");
112 pdf_out(pdf, ' ');
113 s = tokenlist_to_cstring(pdf_action_file(p), true, NULL);
114 pdf_print_str(pdf, s);
115 xfree(s);
116 pdf_out(pdf, ' ');
117 if (pdf_action_new_window(p) > pdf_window_notset) {
118 if (pdf_action_new_window(p) == pdf_window_new)
119 pdf_dict_add_bool(pdf, "NewWindow", 1);
120 else
121 pdf_dict_add_bool(pdf, "NewWindow", 0);
124 switch (pdf_action_type(p)) {
125 case pdf_action_page:
126 pdf_dict_add_name(pdf, "S", "GoTo");
127 if (pdf_action_file(p) == null) {
128 pdf_add_name(pdf, "D");
129 pdf_begin_array(pdf);
130 pdf_add_ref(pdf, pdf_get_obj(pdf, obj_type_page, pdf_action_id(p), false));
131 } else {
132 pdf_add_name(pdf, "D");
133 pdf_begin_array(pdf);
134 pdf_print_int(pdf, pdf_action_id(p) - 1);
137 char *tokstr = tokenlist_to_cstring(pdf_action_tokens(p), true, NULL);
138 pdf_printf(pdf, " %s", tokstr);
139 pdf_end_array(pdf);
140 xfree(tokstr);
142 break;
143 case pdf_action_goto:
144 if (pdf_action_file(p) == null) {
145 pdf_dict_add_name(pdf, "S", "GoTo");
146 d = pdf_get_obj(pdf, obj_type_dest, pdf_action_id(p), pdf_action_named_id(p));
147 } else
148 pdf_dict_add_name(pdf, "S", "GoToR");
149 if (pdf_action_named_id(p) > 0) {
150 char *tokstr = tokenlist_to_cstring(pdf_action_id(p), true, NULL);
151 pdf_dict_add_string(pdf, "D", tokstr);
152 xfree(tokstr);
153 } else if (pdf_action_file(p) == null) {
154 pdf_dict_add_ref(pdf, "D", d);
155 } else {
156 normal_error("pdf backend","'goto' option cannot be used with both 'file' and 'num'");
158 break;
159 case pdf_action_thread:
160 pdf_dict_add_name(pdf, "S", "Thread");
161 if (pdf_action_file(p) == null) {
162 d = pdf_get_obj(pdf, obj_type_thread, pdf_action_id(p), pdf_action_named_id(p));
163 if (pdf_action_named_id(p) > 0) {
164 char *tokstr = tokenlist_to_cstring(pdf_action_id(p), true, NULL);
165 pdf_dict_add_string(pdf, "D", tokstr);
166 xfree(tokstr);
167 } else if (pdf_action_file(p) == null) {
168 pdf_dict_add_ref(pdf, "D", d);
169 } else {
170 pdf_dict_add_int(pdf, "D", pdf_action_id(p));
173 break;
175 pdf_end_dict(pdf);