diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua/luanode.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/luanode.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/lua/luanode.c b/Build/source/texk/web2c/luatexdir/lua/luanode.c new file mode 100644 index 00000000000..3182b609773 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luanode.c @@ -0,0 +1,461 @@ +/* + +luanode.w + +Copyright 2006-2008 Taco Hoekwater <taco@@luatex.org> + +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 <http://www.gnu.org/licenses/>. + +*/ + +#include "ptexlib.h" +#include "lua/luatex-api.h" + +void lua_node_filter_s(int filterid, int extrainfo) +{ + int i; + int callback_id = callback_defined(filterid); + int s_top = lua_gettop(Luas); + if (callback_id <= 0) { + lua_settop(Luas, s_top); + return; + } + if (!get_callback(Luas, callback_id)) { + lua_settop(Luas, s_top); + return; + } + lua_push_string_by_index(Luas,extrainfo); + if ((i=lua_pcall(Luas, 1, 0, 0)) != 0) { + formatted_warning("node filter","error: %s", lua_tostring(Luas, -1)); + lua_settop(Luas, s_top); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); + return; + } + lua_settop(Luas, s_top); + return; +} + +void lua_node_filter(int filterid, int extrainfo, halfword head_node, halfword * tail_node) +{ + int i; + halfword start_node, start_done, last_node; + int s_top = lua_gettop(Luas); + int callback_id = callback_defined(filterid); + if (head_node == null || callback_id <= 0) { + lua_settop(Luas, s_top); + return; + } + /*tex We start after head. */ + start_node = vlink(head_node); + if (start_node == null || !get_callback(Luas, callback_id)) { + lua_settop(Luas, s_top); + return; + } + /*tex We make sure we have no prev */ + alink(start_node) = null ; + /*tex the action */ + nodelist_to_lua(Luas, start_node); + lua_push_group_code(Luas,extrainfo); + if ((i=lua_pcall(Luas, 2, 1, 0)) != 0) { + formatted_warning("node filter", "error: %s\n", lua_tostring(Luas, -1)); + lua_settop(Luas, s_top); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); + return; + } + /*tex the result */ + if (lua_isboolean(Luas, -1)) { + if (lua_toboolean(Luas, -1) != 1) { + /*tex discard */ + flush_node_list(start_node); + vlink(head_node) = null; + } else { + /*tex keep */ + } + } else { + /*tex append to old head */ + start_done = nodelist_from_lua(Luas,-1); + try_couple_nodes(head_node,start_done); + } + /*tex redundant as we set top anyway */ + lua_pop(Luas, 2); + /*tex find tail in order to update tail */ + start_node = vlink(head_node); + if (start_node != null) { + /*tex maybe just always slide (harmless and fast) */ + if (fix_node_lists) { + /*tex slides and returns last node */ + *tail_node = fix_node_list(start_node); + } else { + last_node = vlink(start_node); + while (last_node != null) { + start_node = last_node; + last_node = vlink(start_node); + } + /*tex we're at the end now */ + *tail_node = start_node; + } + } else { + /*tex we're already at the end */ + *tail_node = head_node; + } + /*tex clean up */ + lua_settop(Luas, s_top); + return; +} + +int lua_linebreak_callback(int is_broken, halfword head_node, halfword * new_head) +{ + int a, i; + register halfword *p; + int ret = 0; + int s_top = lua_gettop(Luas); + int callback_id = callback_defined(linebreak_filter_callback); + if (head_node == null || vlink(head_node) == null || callback_id <= 0) { + lua_settop(Luas, s_top); + return ret; + } + if (!get_callback(Luas, callback_id)) { + lua_settop(Luas, s_top); + return ret; + } + alink(vlink(head_node)) = null ; + nodelist_to_lua(Luas, vlink(head_node)); + lua_pushboolean(Luas, is_broken); + if ((i=lua_pcall(Luas, 2, 1, 0)) != 0) { + formatted_warning("linebreak", "error: %s", lua_tostring(Luas, -1)); + lua_settop(Luas, s_top); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); + return ret; + } + lua_settop(Luas, s_top); + p = lua_touserdata(Luas, -1); + if (p != NULL) { + a = nodelist_from_lua(Luas,-1); + try_couple_nodes(*new_head,a); + ret = 1; + } + return ret; +} + +int lua_appendtovlist_callback(halfword box, int location, halfword prev_depth, + boolean is_mirrored, halfword * result, int * next_depth, boolean * prev_set) +{ + register halfword *p; + int i; + int s_top = lua_gettop(Luas); + int callback_id = callback_defined(append_to_vlist_filter_callback); + if (box == null || callback_id <= 0) { + lua_settop(Luas, s_top); + return 0; + } + if (!get_callback(Luas, callback_id)) { + lua_settop(Luas, s_top); + return 0; + } + nodelist_to_lua(Luas, box); + lua_push_string_by_index(Luas,location); + lua_pushinteger(Luas, (int) prev_depth); + lua_pushboolean(Luas, is_mirrored); + if ((i=lua_pcall(Luas, 4, 2, 0)) != 0) { + formatted_warning("append to vlist","error: %s", lua_tostring(Luas, -1)); + lua_settop(Luas, s_top); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); + return 0; + } + if (lua_type(Luas,-1) == LUA_TNUMBER) { + *next_depth = lua_roundnumber(Luas,-1); + *prev_set = true; + if (lua_type(Luas, -2) != LUA_TNIL) { + p = check_isnode(Luas, -2); + *result = *p; + } + } else if (lua_type(Luas, -1) != LUA_TNIL) { + p = check_isnode(Luas, -1); + *result = *p; + } + return 1; +} + +halfword lua_hpack_filter(halfword head_node, scaled size, int pack_type, int extrainfo, + int pack_direction, halfword attr) +{ + int i; + halfword ret; + int s_top = lua_gettop(Luas); + int callback_id = callback_defined(hpack_filter_callback); + if (head_node == null || callback_id <= 0) { + lua_settop(Luas, s_top); + return head_node; + } + if (!get_callback(Luas, callback_id)) { + lua_settop(Luas, s_top); + return head_node; + } + alink(head_node) = null ; + nodelist_to_lua(Luas, head_node); + lua_push_group_code(Luas,extrainfo); + lua_pushinteger(Luas, size); + lua_push_pack_type(Luas, pack_type); + if (pack_direction >= 0) { + lua_push_dir_par(Luas, pack_direction); + } else { + lua_pushnil(Luas); + } + if (attr != null) { + nodelist_to_lua(Luas, attr); + } else { + lua_pushnil(Luas); + } + if ((i=lua_pcall(Luas, 6, 1, 0)) != 0) { + formatted_warning("hpack filter", "error: %s\n", lua_tostring(Luas, -1)); + lua_settop(Luas, s_top); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); + return head_node; + } + ret = head_node; + if (lua_isboolean(Luas, -1)) { + if (lua_toboolean(Luas, -1) != 1) { + flush_node_list(head_node); + ret = null; + } + } else { + ret = nodelist_from_lua(Luas,-1); + } + lua_settop(Luas, s_top); + 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, int pack_direction, halfword attr) +{ + halfword ret; + int i; + int callback_id; + int s_top = lua_gettop(Luas); + if (head_node == null) { + lua_settop(Luas, s_top); + return head_node; + } + if (extrainfo == 8) { + callback_id = callback_defined(pre_output_filter_callback); + } else { + callback_id = callback_defined(vpack_filter_callback); + } + if (callback_id <= 0) { + lua_settop(Luas, s_top); + return head_node; + } + if (!get_callback(Luas, callback_id)) { + lua_settop(Luas, s_top); + return head_node; + } + alink(head_node) = null ; + nodelist_to_lua(Luas, head_node); + lua_push_group_code(Luas, extrainfo); + lua_pushinteger(Luas, size); + lua_push_pack_type(Luas, pack_type); + lua_pushinteger(Luas, maxd); + if (pack_direction >= 0) { + lua_push_dir_par(Luas, pack_direction); + } else { + lua_pushnil(Luas); + } + if (attr != null) { + nodelist_to_lua(Luas, attr); + } else { + lua_pushnil(Luas); + } + if ((i=lua_pcall(Luas, 7, 1, 0)) != 0) { + formatted_warning("vpack filter", "error: %s", lua_tostring(Luas, -1)); + lua_settop(Luas, s_top); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); + return head_node; + } + ret = head_node; + if (lua_isboolean(Luas, -1)) { + if (lua_toboolean(Luas, -1) != 1) { + flush_node_list(head_node); + ret = null; + } + } else { + ret = nodelist_from_lua(Luas,-1); + } + lua_settop(Luas, s_top); + if (fix_node_lists) + fix_node_list(ret); + return ret; +} + +/*tex + + This is a quick hack to fix \ETEX's \.{\\lastnodetype} now that there are many + more visible node types. + +*/ + +int visible_last_node_type(int n) +{ + int i = type(n); + if (i != glyph_node) { + return get_etex_code(i); + } else if (is_ligature(n)) { + /*tex old ligature value */ + return 7; + } else { + /*tex old character value */ + return 0; + } +} + +void lua_pdf_literal(PDF pdf, int i, int noline) +{ + const char *s = NULL; + size_t l = 0; + lua_rawgeti(Luas, LUA_REGISTRYINDEX, i); + s = lua_tolstring(Luas, -1, &l); + if (noline) { + pdf_check_space(pdf); + pdf_out_block(pdf, s, l); + pdf_set_space(pdf); + } else { + pdf_out_block(pdf, s, l); + pdf_out(pdf, 10); + } + lua_pop(Luas, 1); +} + +void copy_pdf_literal(pointer r, pointer p) +{ + int t = pdf_literal_type(p); + pdf_literal_type(r) = t; + pdf_literal_mode(r) = pdf_literal_mode(p); + if (t == normal) { + pdf_literal_data(r) = pdf_literal_data(p); + add_token_ref(pdf_literal_data(p)); + } else if (t == lua_refid_literal) { + lua_rawgeti(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p)); + pdf_literal_data(r) = luaL_ref(Luas, LUA_REGISTRYINDEX); + } else { + /* maybe something user, we don't support a call here but best keep it sane anyway. */ + pdf_literal_data(r) = pdf_literal_data(p); + } +} + +void copy_late_lua(pointer r, pointer p) +{ + int t = late_lua_type(p); + late_lua_type(r) = t; + if (late_lua_name(p) > 0) + add_token_ref(late_lua_name(p)); + if (t == normal) { + late_lua_data(r) = late_lua_data(p); + add_token_ref(late_lua_data(p)); + } else if (t == lua_refid_literal) { + lua_rawgeti(Luas, LUA_REGISTRYINDEX, late_lua_data(p)); + late_lua_data(r) = luaL_ref(Luas, LUA_REGISTRYINDEX); + } +} + +void copy_user_lua(pointer r, pointer p) +{ + if (user_node_value(p) != 0) { + lua_rawgeti(Luas, LUA_REGISTRYINDEX, user_node_value(p)); + user_node_value(r) = luaL_ref(Luas, LUA_REGISTRYINDEX); + } +} + +void free_pdf_literal(pointer p) +{ + int t = pdf_literal_type(p); + if (t == normal) { + delete_token_ref(pdf_literal_data(p)); + } else if (t == lua_refid_literal) { + luaL_unref(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p)); + } +} + +void free_late_lua(pointer p) +{ + int t = late_lua_type(p); + if (late_lua_name(p) > 0) + delete_token_ref(late_lua_name(p)); + if (t == normal) { + delete_token_ref(late_lua_data(p)); + } else if (t == lua_refid_literal) { + luaL_unref(Luas, LUA_REGISTRYINDEX, late_lua_data(p)); + } +} + +void free_user_lua(pointer p) +{ + if (user_node_value(p) != 0) { + luaL_unref(Luas, LUA_REGISTRYINDEX, user_node_value(p)); + } +} + +void show_pdf_literal(pointer p) +{ + int t = pdf_literal_type(p); + tprint_esc("pdfliteral"); + switch (pdf_literal_mode(p)) { + case set_origin: + tprint(" origin"); + break; + case direct_page: + tprint(" page"); + break; + case direct_always: + tprint(" direct"); + break; + case direct_raw: + tprint(" raw"); + break; + default: + tprint(" <invalid mode>"); + break; + } + if (t == normal) { + print_mark(pdf_literal_data(p)); + } else if (t == lua_refid_literal) { + tprint(" <lua data reference "); + print_int(pdf_literal_data(p)); + tprint(">"); + } else { + tprint(" <invalid data>"); + } +} + +void show_late_lua(pointer p) +{ + int t = late_lua_type(p); + tprint_esc("latelua"); + print_int(late_lua_reg(p)); + if (t == normal) { + print_mark(late_lua_data(p)); + } else if (t == lua_refid_literal) { + tprint(" <function reference "); + print_int(late_lua_data(p)); + tprint(">"); + } else if (t == lua_refid_call) { + tprint(" <functioncall reference "); + print_int(late_lua_data(p)); + tprint(">"); + } else { + tprint(" <invalid data>"); + } +} |