1% luanode.w
2%
3% Copyright 2006-2008 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/* hh-ls: we make sure that lua never sees prev of head but also that when
21nodes are removedor inserted, temp nodes don't interfere */
22
23@ @c
24
25
26#include "ptexlib.h"
27#include "lua/luatex-api.h"
28
29/* TO BE REMOVED
30static const char *group_code_names[] = {
31    "",
32    "simple",
33    "hbox",
34    "adjusted_hbox",
35    "vbox",
36    "vtop",
37    "align",
38    "no_align",
39    "output",
40    "math",
41    "disc",
42    "insert",
43    "vcenter",
44    "math_choice",
45    "semi_simple",
46    "math_shift",
47    "math_left",
48    "local_box",
49    "split_off",
50    "split_keep",
51    "preamble",
52    "align_set",
53    "fin_row"
54};
55
56const char *pack_type_name[] = { "exactly", "additional" };
57*/
58
59@ @c
60void
61lua_node_filter_s(int filterid, int extrainfo)
62{
63    lua_State *L = Luas;
64    int callback_id = callback_defined(filterid);
65    int s_top = lua_gettop(L);
66    if (callback_id <= 0) {
67        lua_settop(L, s_top);
68        return;
69    }
70    if (!get_callback(L, callback_id)) {
71        lua_settop(L, s_top);
72        return;
73    }
74    lua_push_string_by_index(L,extrainfo); /* arg 1 */
75    if (lua_pcall(L, 1, 0, 0) != 0) {
76        fprintf(stdout, "error: %s\n", lua_tostring(L, -1));
77        lua_settop(L, s_top);
78        error();
79        return;
80    }
81    lua_settop(L, s_top);
82    return;
83}
84
85
86@ @c
87void
88lua_node_filter(int filterid, int extrainfo, halfword head_node, halfword * tail_node)
89{
90    halfword ret;
91    int a;
92    lua_State *L = Luas;
93    int s_top = lua_gettop(L);
94    int callback_id = callback_defined(filterid);
95    if (head_node == null || vlink(head_node) == null || callback_id <= 0) {
96	lua_settop(L, s_top);
97        return;
98    }
99    if (!get_callback(L, callback_id)) {
100        lua_settop(L, s_top);
101        return;
102    }
103    alink(vlink(head_node)) = null ; /* hh-ls */
104    nodelist_to_lua(L, vlink(head_node));       /* arg 1 */
105    lua_push_group_code(L,extrainfo); /* arg 2 */
106    if (lua_pcall(L, 2, 1, 0) != 0) {   /* no arg, 1 result */
107        fprintf(stdout, "error: %s\n", lua_tostring(L, -1));
108        lua_settop(L, s_top);
109        error();
110        return;
111    }
112    if (lua_isboolean(L, -1)) {
113        if (lua_toboolean(L, -1) != 1) {
114            flush_node_list(vlink(head_node));
115            vlink(head_node) = null;
116        }
117    } else {
118        a = nodelist_from_lua(L);
119        try_couple_nodes(head_node,a);
120    }
121    lua_pop(L, 2);              /* result and callback container table */
122    if (fix_node_lists)
123        fix_node_list(head_node);
124    ret = vlink(head_node);
125    if (ret != null) {
126        while (vlink(ret) != null)
127            ret = vlink(ret);
128        *tail_node = ret;
129    } else {
130        *tail_node = head_node;
131    }
132    lua_settop(L, s_top);
133    return;
134}
135
136@ @c
137int
138lua_linebreak_callback(int is_broken, halfword head_node, halfword * new_head)
139{
140    int a;
141    register halfword *p;
142    int ret = 0;                /* failure */
143    lua_State *L = Luas;
144    int s_top = lua_gettop(L);
145    int callback_id = callback_defined(linebreak_filter_callback);
146    if (head_node == null || vlink(head_node) == null || callback_id <= 0) {
147        lua_settop(L, s_top);
148        return ret;
149    }
150    if (!get_callback(L, callback_id)) {
151       lua_settop(L, s_top);
152        return ret;
153    }
154    alink(vlink(head_node)) = null ; /* hh-ls */
155    nodelist_to_lua(L, vlink(head_node));       /* arg 1 */
156    lua_pushboolean(L, is_broken);      /* arg 2 */
157    if (lua_pcall(L, 2, 1, 0) != 0) {   /* no arg, 1 result */
158        fprintf(stdout, "error: %s\n", lua_tostring(L, -1));
159        lua_settop(L, s_top);
160        error();
161        return ret;
162    }
163
164    p = lua_touserdata(L, -1);
165    if (p != NULL) {
166        a = nodelist_from_lua(L);
167        try_couple_nodes(*new_head,a);
168        ret = 1;
169    }
170    lua_settop(L, s_top);
171    return ret;
172}
173
174
175
176@ @c
177halfword
178lua_hpack_filter(halfword head_node, scaled size, int pack_type, int extrainfo,
179                 int pack_direction)
180{
181    halfword ret;
182    lua_State *L = Luas;
183    int s_top = lua_gettop(L);
184    int callback_id = callback_defined(hpack_filter_callback);
185    if (head_node == null || callback_id <= 0) {
186        lua_settop(L, s_top);
187        return head_node;
188    }
189    if (!get_callback(L, callback_id)) {
190        lua_settop(L, s_top);
191        return head_node;
192    }
193    alink(head_node) = null ; /* hh-ls */
194    nodelist_to_lua(L, head_node);
195    lua_push_group_code(L,extrainfo);
196    lua_pushnumber(L, size);
197    lua_push_pack_type(L,pack_type);
198    if (pack_direction >= 0)
199        lua_push_dir_par(L, pack_direction);
200    else
201        lua_pushnil(L);
202    if (lua_pcall(L, 5, 1, 0) != 0) {   /* no arg, 1 result */
203        fprintf(stdout, "error: %s\n", lua_tostring(L, -1));
204        lua_settop(L, s_top);
205        error();
206        return head_node;
207    }
208    ret = head_node;
209    if (lua_isboolean(L, -1)) {
210        if (lua_toboolean(L, -1) != 1) {
211            flush_node_list(head_node);
212            ret = null;
213        }
214    } else {
215        ret = nodelist_from_lua(L);
216    }
217    lua_settop(L, s_top);
218#if 0
219    lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE);
220#endif
221    if (fix_node_lists)
222        fix_node_list(ret);
223    return ret;
224}
225
226@ @c
227halfword
228lua_vpack_filter(halfword head_node, scaled size, int pack_type, scaled maxd,
229                 int extrainfo, int pack_direction)
230{
231    halfword ret;
232    int callback_id;
233    lua_State *L = Luas;
234    int s_top = lua_gettop(L);
235    if (head_node == null) {
236        lua_settop(L, s_top);
237        return head_node;
238    }
239    if  (extrainfo == 8)  { /* output */
240        callback_id = callback_defined(pre_output_filter_callback);
241    } else {
242        callback_id = callback_defined(vpack_filter_callback);
243    }
244    if (callback_id <= 0) {
245        lua_settop(L, s_top);
246        return head_node;
247    }
248    if (!get_callback(L, callback_id)) {
249        lua_settop(L, s_top);
250        return head_node;
251    }
252    alink(head_node) = null ; /* hh-ls */
253    nodelist_to_lua(L, head_node);
254    lua_push_group_code(L,extrainfo);
255    lua_pushnumber(L, size);
256    lua_push_pack_type(L,pack_type);
257    lua_pushnumber(L, maxd);
258    if (pack_direction >= 0)
259         lua_push_dir_par(L, pack_direction);
260    else
261        lua_pushnil(L);
262    if (lua_pcall(L, 6, 1, 0) != 0) {   /* no arg, 1 result */
263        fprintf(stdout, "error: %s\n", lua_tostring(L, -1));
264        lua_settop(L, s_top);
265        error();
266        return head_node;
267    }
268    ret = head_node;
269    if (lua_isboolean(L, -1)) {
270        if (lua_toboolean(L, -1) != 1) {
271            flush_node_list(head_node);
272            ret = null;
273        }
274    } else {
275        ret = nodelist_from_lua(L);
276    }
277    lua_settop(L, s_top);
278#if 0
279    lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE);
280#endif
281    if (fix_node_lists)
282        fix_node_list(ret);
283    return ret;
284}
285
286
287@ This is a quick hack to fix etex's \.{\\lastnodetype} now that
288  there are many more visible node types. TODO: check the
289  eTeX manual for the expected return values.
290
291@c
292int visible_last_node_type(int n)
293{
294    int i = type(n);
295    if (i == whatsit_node && subtype(n) == local_par_node)
296        return -1;
297    if (i == glyph_node) {
298        if (is_ligature(n))
299            return 7;           /* old ligature value */
300        else
301            return 0;           /* old character value */
302    }
303    if (i <= unset_node) {
304        return i + 1;
305    } else if (i <= delim_node) {
306        return 15;              /* so-called math nodes */
307    } else {
308        return -1;
309    }
310}
311
312@ @c
313void lua_pdf_literal(PDF pdf, int i)
314{
315    const char *s = NULL;
316    size_t l = 0;
317    lua_rawgeti(Luas, LUA_REGISTRYINDEX, i);
318    s = lua_tolstring(Luas, -1, &l);
319    pdf_out_block(pdf, s, l);
320    pdf_out(pdf, 10);           /* |pdf_print_nl| */
321    lua_pop(Luas, 1);
322}
323
324@ @c
325void copy_pdf_literal(pointer r, pointer p)
326{
327    pdf_literal_type(r) = pdf_literal_type(p);
328    pdf_literal_mode(r) = pdf_literal_mode(p);
329    if (pdf_literal_type(p) == normal) {
330        pdf_literal_data(r) = pdf_literal_data(p);
331        add_token_ref(pdf_literal_data(p));
332    } else {
333        lua_rawgeti(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p));
334        pdf_literal_data(r) = luaL_ref(Luas, LUA_REGISTRYINDEX);
335    }
336}
337
338@ @c
339void copy_late_lua(pointer r, pointer p)
340{
341    late_lua_type(r) = late_lua_type(p);
342    if (late_lua_name(p) > 0)
343        add_token_ref(late_lua_name(p));
344    if (late_lua_type(p) == normal) {
345        late_lua_data(r) = late_lua_data(p);
346        add_token_ref(late_lua_data(p));
347    } else {
348        lua_rawgeti(Luas, LUA_REGISTRYINDEX, late_lua_data(p));
349        late_lua_data(r) = luaL_ref(Luas, LUA_REGISTRYINDEX);
350    }
351}
352
353@ @c
354void copy_user_lua(pointer r, pointer p)
355{
356    if (user_node_value(p) != 0) {
357        lua_rawgeti(Luas, LUA_REGISTRYINDEX, user_node_value(p));
358        user_node_value(r) = luaL_ref(Luas, LUA_REGISTRYINDEX);
359    }
360}
361
362
363@ @c
364void free_pdf_literal(pointer p)
365{
366    if (pdf_literal_type(p) == normal) {
367        delete_token_ref(pdf_literal_data(p));
368    } else {
369        luaL_unref(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p));
370    }
371}
372
373void free_late_lua(pointer p)
374{
375    if (late_lua_name(p) > 0)
376        delete_token_ref(late_lua_name(p));
377    if (late_lua_type(p) == normal) {
378        delete_token_ref(late_lua_data(p));
379    } else {
380        luaL_unref(Luas, LUA_REGISTRYINDEX, late_lua_data(p));
381    }
382}
383
384@ @c
385void free_user_lua(pointer p)
386{
387    if (user_node_value(p) != 0) {
388        luaL_unref(Luas, LUA_REGISTRYINDEX, user_node_value(p));
389    }
390}
391
392
393@ @c
394void show_pdf_literal(pointer p)
395{
396    tprint_esc("pdfliteral");
397    switch (pdf_literal_mode(p)) {
398    case set_origin:
399        break;
400    case direct_page:
401        tprint(" page");
402        break;
403    case direct_always:
404        tprint(" direct");
405        break;
406    default:
407        confusion("literal2");
408        break;
409    }
410    if (pdf_literal_type(p) == normal) {
411        print_mark(pdf_literal_data(p));
412    } else {
413        lua_rawgeti(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p));
414        tprint("\"");
415        tprint(lua_tostring(Luas, -1));
416        tprint("\"");
417        lua_pop(Luas, 1);
418    }
419}
420
421@ @c
422void show_late_lua(pointer p)
423{
424    tprint_esc("latelua");
425    print_int(late_lua_reg(p));
426    if (late_lua_type(p) == normal) {
427        print_mark(late_lua_data(p));
428    } else {
429        tprint(" <function ");
430        print_int(late_lua_data(p));
431        tprint(">");
432    }
433}
434