/* luanode.c Copyright 2006-2008 Taco Hoekwater This file is part of LuaTeX. LuaTeX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU General Public License along with LuaTeX; if not, see . */ #include "luatex-api.h" #include #include "nodes.h" static const char _svn_version[] = "$Id: luanode.c 2448 2009-06-08 07:43:50Z taco $ $URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.3/source/texk/web2c/luatexdir/lua/luanode.c $"; #undef link /* defined by cpascal.h */ #define info(a) fixmem[(a)].hhlh #define link(a) fixmem[(a)].hhrh static char *group_code_names[] = { "", "simple", "hbox", "adjusted_hbox", "vbox", "vtop", "align", "no_align", "output", "math", "disc", "insert", "vcenter", "math_choice", "semi_simple", "math_shift", "math_left", "local_box", "split_off", "split_keep", "preamble", "align_set", "fin_row" }; char *pack_type_name[] = { "exactly", "additional" }; void lua_node_filter_s(int filterid, char *extrainfo) { lua_State *L = Luas; int s_top = lua_gettop(L); int callback_id = callback_defined(filterid); if (callback_id <= 0) return; if (!get_callback(L, callback_id)) { lua_settop(L, s_top); return; } lua_pushstring(L, extrainfo); /* arg 1 */ if (lua_pcall(L, 1, 0, 0) != 0) { fprintf(stdout, "error: %s\n", lua_tostring(L, -1)); lua_settop(L, s_top); error(); return; } lua_settop(L, s_top); return; } void lua_node_filter(int filterid, int xextrainfo, halfword head_node, halfword * tail_node) { halfword ret; int a; lua_State *L = Luas; char *extrainfo = group_code_names[xextrainfo]; int callback_id = callback_defined(filterid); if (head_node == null || vlink(head_node) == null || callback_id <= 0) return; if (!get_callback(L, callback_id)) { lua_pop(L, 2); return; } nodelist_to_lua(L, vlink(head_node)); /* arg 1 */ lua_pushstring(L, extrainfo); /* arg 2 */ if (lua_pcall(L, 2, 1, 0) != 0) { /* no arg, 1 result */ fprintf(stdout, "error: %s\n", lua_tostring(L, -1)); lua_pop(L, 2); error(); return; } if (lua_isboolean(L, -1)) { if (lua_toboolean(L, -1) != 1) { flush_node_list(vlink(head_node)); vlink(head_node) = null; } } else { a = nodelist_from_lua(L); vlink(head_node) = a; } lua_pop(L, 2); /* result and callback container table */ if (fix_node_lists) fix_node_list(head_node); ret = vlink(head_node); if (ret != null) { while (vlink(ret) != null) ret = vlink(ret); *tail_node = ret; } else { *tail_node = head_node; } return; } int lua_linebreak_callback(int is_broken, halfword head_node, halfword * new_head) { int a; register halfword *p; int ret = 0; /* failure */ lua_State *L = Luas; int callback_id = callback_defined(linebreak_filter_callback); if (head_node == null || vlink(head_node) == null || callback_id <= 0) return ret; if (!get_callback(L, callback_id)) { lua_pop(L, 2); return ret; } nodelist_to_lua(L, vlink(head_node)); /* arg 1 */ lua_pushboolean(L, is_broken); /* arg 2 */ if (lua_pcall(L, 2, 1, 0) != 0) { /* no arg, 1 result */ fprintf(stdout, "error: %s\n", lua_tostring(L, -1)); lua_pop(L, 2); error(); return ret; } p = lua_touserdata(L, -1); if (p != NULL) { a = nodelist_from_lua(L); vlink(*new_head) = a; ret = 1; } lua_pop(L, 2); /* result and callback container table */ return ret; } halfword lua_hpack_filter(halfword head_node, scaled size, int pack_type, int extrainfo) { halfword ret; lua_State *L = Luas; int callback_id = callback_defined(hpack_filter_callback); if (head_node == null || callback_id <= 0) return head_node; if (!get_callback(L, callback_id)) { lua_pop(L, 2); return head_node; } nodelist_to_lua(L, head_node); lua_pushstring(L, group_code_names[extrainfo]); lua_pushnumber(L, size); lua_pushstring(L, pack_type_name[pack_type]); if (lua_pcall(L, 4, 1, 0) != 0) { /* no arg, 1 result */ fprintf(stdout, "error: %s\n", lua_tostring(L, -1)); lua_pop(L, 2); error(); return head_node; } ret = head_node; if (lua_isboolean(L, -1)) { if (lua_toboolean(L, -1) != 1) { flush_node_list(head_node); ret = null; } } else { ret = nodelist_from_lua(L); } lua_pop(L, 2); /* result and callback container table */ /* lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE); */ if (fix_node_lists) fix_node_list(ret); return ret; } halfword lua_vpack_filter(halfword head_node, scaled size, int pack_type, scaled maxd, int extrainfo) { halfword ret; integer callback_id; lua_State *L = Luas; if (head_node == null) return head_node; if (strcmp("output", group_code_names[extrainfo]) == 0) { callback_id = callback_defined(pre_output_filter_callback); } else { callback_id = callback_defined(vpack_filter_callback); } if (callback_id <= 0) { return head_node; } if (!get_callback(L, callback_id)) { lua_pop(L, 2); return head_node; } nodelist_to_lua(L, head_node); lua_pushstring(L, group_code_names[extrainfo]); lua_pushnumber(L, size); lua_pushstring(L, pack_type_name[pack_type]); lua_pushnumber(L, maxd); if (lua_pcall(L, 5, 1, 0) != 0) { /* no arg, 1 result */ fprintf(stdout, "error: %s\n", lua_tostring(L, -1)); lua_pop(L, 2); error(); return head_node; } ret = head_node; if (lua_isboolean(L, -1)) { if (lua_toboolean(L, -1) != 1) { flush_node_list(head_node); ret = null; } } else { ret = nodelist_from_lua(L); } lua_pop(L, 2); /* result and callback container table */ /* lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE); */ if (fix_node_lists) fix_node_list(ret); return ret; } /* This is a quick hack to fix etex's \lastnodetype now that * there are many more visible node types. TODO: check the * eTeX manual for the expected return values. */ int visible_last_node_type(int n) { int i = type(n); if ((i != math_node) && (i <= unset_node)) return i + 1; if (i == glyph_node) return -1; if (i == whatsit_node && subtype(n) == local_par_node) return -1; if (i == 255) return -1; /* this is not right, probably dir nodes! */ return last_known_node + 1; } void lua_pdf_literal(int i) { char *s = NULL; size_t l = 0; lua_rawgeti(Luas, LUA_REGISTRYINDEX, i); s = (char *) lua_tolstring(Luas, -1, &l); while (l--) { pdf_room(1); pdf_buf[pdf_ptr++] = *s++; } pdf_buf[pdf_ptr++] = 10; /* pdf_print_nl */ lua_pop(Luas, 1); } void copy_pdf_literal(pointer r, pointer p) { pdf_literal_type(r) = pdf_literal_type(p); pdf_literal_mode(r) = pdf_literal_mode(p); if (pdf_literal_type(p) == normal) { pdf_literal_data(r) = pdf_literal_data(p); add_token_ref(pdf_literal_data(p)); } else { lua_rawgeti(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p)); pdf_literal_data(r) = luaL_ref(Luas, LUA_REGISTRYINDEX); } } void free_pdf_literal(pointer p) { if (pdf_literal_type(p) == normal) { delete_token_ref(pdf_literal_data(p)); } else { luaL_unref(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p)); } } void show_pdf_literal(pointer p) { tprint_esc("pdfliteral"); switch (pdf_literal_mode(p)) { case set_origin: break; case direct_page: tprint(" page"); break; case direct_always: tprint(" direct"); break; default: tconfusion("literal2"); break; } if (pdf_literal_type(p) == normal) { print_mark(pdf_literal_data(p)); } else { lua_rawgeti(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p)); tprint((char *) lua_tostring(Luas, -1)); lua_pop(Luas, 1); } }