1% pdfliteral.w
2%
3% Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org>
4%
5% This file is part of LuaTeX.
6%
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.
11%
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.
16%
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/>.
19
20@ @c
21
22
23#include "ptexlib.h"
24
25@ @c
26void pdf_special(PDF pdf, halfword p)
27{
28    int old_setting;            /* holds print |selector| */
29    str_number s;
30    old_setting = selector;
31    selector = new_string;
32    show_token_list(token_link(write_tokens(p)), null, -1);
33    selector = old_setting;
34    s = make_string();
35    pdf_literal(pdf, s, scan_special, true);
36    flush_str(s);
37}
38
39
40@ To ship out a \TeX\ box to PDF page description we need to implement
41|hlist_out|, |vlist_out| and |ship_out|, which are equivalent to
42the \TeX' original |hlist_out|, |vlist_out| and |ship_out| resp. But first we
43need to declare some procedures needed in |hlist_out| and |vlist_out|.
44
45@c
46void pdf_out_literal(PDF pdf, halfword p)
47{
48    int old_setting;            /* holds print |selector| */
49    str_number s;
50    pdfstructure *ps = pdf->pstruct;
51    if (pdf_literal_type(p) == normal) {
52        old_setting = selector;
53        selector = new_string;
54        show_token_list(token_link(pdf_literal_data(p)), null, -1);
55        selector = old_setting;
56        s = make_string();
57        pdf_literal(pdf, s, pdf_literal_mode(p), false);
58        flush_str(s);
59    } else {
60        assert(pdf_literal_mode(p) != scan_special);
61        switch (pdf_literal_mode(p)) {
62        case set_origin:
63            pdf_goto_pagemode(pdf);
64            pdf_set_pos(pdf, pdf->posstruct->pos);
65            break;
66        case direct_page:
67            pdf_goto_pagemode(pdf);
68            break;
69        case direct_always:
70            pdf_end_string_nl(pdf);
71            ps->need_tm = true;
72            break;
73        default:
74            confusion("literal1");
75            break;
76        }
77        lua_pdf_literal(pdf, pdf_literal_data(p));
78    }
79}
80
81@ test equality of start of strings
82@c
83static boolean str_in_cstr(str_number s, const char *r, unsigned i)
84{
85    const unsigned char *k, *l;
86    if ((unsigned) str_length(s) < i + strlen(r))
87        return false;
88    k = (const unsigned char *) r;
89    l = str_string(s) + i;
90    while ((*l) && (*k)) {
91        if (*l++ != *k++)
92            return false;
93    }
94    return true;
95}
96
97@ @c
98void pdf_literal(PDF pdf, str_number s, int literal_mode, boolean warn)
99{
100    unsigned char *ss;
101    size_t l;
102    pool_pointer j = 0;         /* current character code position, initialized to make the compiler happy */
103    pdfstructure *p = pdf->pstruct;
104    if (s >= STRING_OFFSET) {   /* needed for |out_save| */
105        j = 0;
106        if (literal_mode == scan_special) {
107            if (!(str_in_cstr(s, "PDF:", 0) || str_in_cstr(s, "pdf:", 0))) {
108                if (warn
109                    &&
110                    ((!(str_in_cstr(s, "SRC:", 0) || str_in_cstr(s, "src:", 0)))
111                     || (str_length(s) == 0)))
112                    tprint_nl("Non-PDF special ignored!");
113                return;
114            }
115            j = j + (pool_pointer) strlen("PDF:");
116            if (str_in_cstr(s, "direct:", strlen("PDF:"))) {
117                j = j + (pool_pointer) strlen("direct:");
118                literal_mode = direct_always;
119            } else if (str_in_cstr(s, "page:", strlen("PDF:"))) {
120                j = j + (pool_pointer) strlen("page:");
121                literal_mode = direct_page;
122            } else {
123                literal_mode = set_origin;
124            }
125        }
126    }
127    switch (literal_mode) {
128    case set_origin:
129        pdf_goto_pagemode(pdf);
130        pdf_set_pos(pdf, pdf->posstruct->pos);
131        break;
132    case direct_page:
133        pdf_goto_pagemode(pdf);
134        break;
135    case direct_always:
136        pdf_end_string_nl(pdf);
137        p->need_tm = true;
138        break;
139    default:
140        confusion("literal1");
141        break;
142    }
143    if (s >= STRING_OFFSET) {
144        ss = str_string(s);
145        l = str_length(s) - (size_t) j;
146        pdf_out_block(pdf, (const char *) (ss + j), l);
147    } else {
148        assert(s < 256);
149        pdf_out(pdf, s);
150    }
151    pdf_out(pdf, '\n');
152}
153