summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
diff options
context:
space:
mode:
authorPeter Breitenlohner <peb@mppmu.mpg.de>2014-02-03 13:01:31 +0000
committerPeter Breitenlohner <peb@mppmu.mpg.de>2014-02-03 13:01:31 +0000
commit4dc568b1e2c01476f34b6c014da3bc487b71aacf (patch)
treea6a389e1a3915bdc1b618eb2aeae27fd7f21b68a /Build/source/texk/web2c/luatexdir/lua/lnodelib.c
parent4a985ab4153e6ba130b801d4cec60709b0a44e47 (diff)
Import LuaTeX snapshot 0.78.3
git-svn-id: svn://tug.org/texlive/trunk@32854 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua/lnodelib.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lnodelib.c4258
1 files changed, 3707 insertions, 551 deletions
diff --git a/Build/source/texk/web2c/luatexdir/lua/lnodelib.c b/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
index f4138f63c9c..78a468a7f1c 100644
--- a/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
+++ b/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
@@ -1,21 +1,23 @@
/* lnodelib.c
- Copyright 2006-2013 Taco Hoekwater <taco@luatex.org>
+ Copyright 2006-2013 Taco Hoekwater <taco@luatex.org>
- This file is part of LuaTeX.
+ 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 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.
+ 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/>. */
+ You should have received a copy of the GNU General Public License along
+ with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+*/
/*
@@ -24,36 +26,255 @@
supposed to be seen and set (scratch fields for the backend and par
builder).
-*/
+ After doing lots of tests with luatex and luajittex, with and without jit,
+ and with and without ffi, we came to the conclusion that userdata prevents
+ a speedup. We also found that the checking of metatables as well as assignment
+ comes with overhead that can't be neglected. This is normally not really a
+ problem but when processing fonts for more complex scripts it's quite some
+ overhead.
+
+ Because the userdata approach has some benefits, we stick to this. We did
+ some experiments with fast access (assuming nodes) and kept some of the code
+ commented here, but eventually settled for the direct approach. For code that
+ is proven to be okay, one can use the direct variants and operate on nodes
+ more directly. Currently these are numbers, but that might become light
+ userdata at one point, so *never* rely on that property. An important aspect
+ is that one cannot mix both methods, although with node.direct.tonode and
+ node.direct.todirect one can cast both representations.
+
+ So the advice is: use the indexed approach when possible and investigate the
+ direct one when speed might be an issue. For that reason we also provide the
+ get* and set* functions in the top level node namespace. There is a limited set
+ of getters.
+
+ getnext : parsing nodelist always involves this one
+ getprev : used less but is logical companion to getnext
+ getid : consulted a lot
+ getsubtype : consulted less but also a topper
+ getfont : used a lot in otf handling (glyph nodes are consulted a lot)
+ getchar : idem and also in other places
+ getlist : we often parse nested lists so this is a convenient one too (only hlist/vlist !)
+ getleader : comparable to list, seldom used in tex (but needs consulting
+ like lists)
+ getfield : generic getter, sufficient for the rest (other field names are
+ often shared so a specific getter makes no sense then)
+
+ Keep in mind that these only make sense when we're calling them millions of
+ times (which happens in font processing for instance). Setters are less important
+ as documents have not that many content related nodes (and setting many thousands
+ of properties is hardly a burden contrary to millions of consultations.)
+
+ Another change is that __index and __newindex are (as expected) exposed to
+ users but do no checking. The getfield and setfield functions do check. In
+ fact, fast mode can be simulated by fast_getfield = __index but the (measured)
+ benefit on average runs is not that large (some 5% when we also use the other
+ fast ones) which is easily nilled by inefficient coding. The direct variants
+ on the other hand can be significantly faster but with the drawback of lack
+ of userdata features. With respect to speed: keep in mind that measuring
+ a speedup on these functions is not representative for a normal run, where
+ much more happens.
+
+ maybe : setnext setprev setfont setchar (only makes sense for some scripts)
+
+ todo : check and optimize the direct function when possible
+
+ todo : once the direct ones are proven we can redefine some of the less
+ critical normal ones to call the direct ones after checking for
+ a first argument being a node (like protect/unprotect)
+
+ The code below has quite some duplicated code but this is also a prelude
+ to light userdata for diretc nodes so we prefer this method. Some userdata
+ variants could call the direct functions but not now (also because we don't
+ want to touch the originals too much). As usual: blame Luigi and Hans for
+ issues with this code. You can blame HH for weird or inaccurate comments.
+
+ Todo: as a prelude to lua 5.3 we should use integer instead of number when
+ possible. A boring job. We can use the direct variants for testing this.
+
+ Hans Hagen, Luigi Scarso (2011-2013)
+*/
static const char _svn_version[] =
- "$Id: lnodelib.c 4594 2013-03-19 14:49:13Z taco $ "
- "$URL: https://foundry.supelec.fr/svn/luatex/tags/beta-0.76.0/source/texk/web2c/luatexdir/lua/lnodelib.c $";
+ "$Id: lnodelib.c 4740 2014-01-09 17:22:45Z luigi $ "
+ "$URL: https://foundry.supelec.fr/svn/luatex/trunk/source/texk/web2c/luatexdir/lua/lnodelib.c $";
#include "ptexlib.h"
#include "lua/luatex-api.h"
-#define init_luaS_index(a) do { \
- lua_pushliteral(L,#a); \
- luaS_##a##_ptr = lua_tostring(L,-1); \
- luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
- } while (0)
+/*
-#define init_luaS_index_s(a,b) do { \
- lua_pushliteral(L,b); \
- luaS_##a##_ptr = lua_tostring(L,-1); \
- luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
- } while (0)
+ These macros create and access pointers (indices) to keys which is faster. The
+ shortcuts are created as part of the initialization.
-#define make_luaS_index(a) \
- static int luaS_##a##_index = 0; \
- static const char * luaS_##a##_ptr = NULL
+*/
-#define luaS_index(a) luaS_##a##_index
+#define init_luaS_index(a) do { \
+ lua_pushliteral(L,#a); \
+ luaS_##a##_ptr = lua_tostring(L,-1); \
+ luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
+} while (0)
+
+#define init_luaS_index_s(a,b) do { \
+ lua_pushliteral(L,b); \
+ luaS_##a##_ptr = lua_tostring(L,-1); \
+ luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
+} while (0)
+
+#define make_luaS_index(a) \
+ static int luaS_##a##_index = 0; \
+ static const char * luaS_##a##_ptr = NULL
+
+#define luaS_index(a) luaS_##a##_index
#define luaS_ptr_eq(a,b) (a==luaS_##b##_ptr)
+/*
+
+ When the first argument to an accessor is a node, we can use it's metatable
+ entry when we are returning nodes, which saves a lookup.
+
+*/
+
+#define fast_metatable(n) do { \
+ a = (halfword *) lua_newuserdata(L, sizeof(halfword)); \
+ *a = n; \
+ lua_getmetatable(L,1); \
+ lua_setmetatable(L,-2); \
+} while (0)
+
+#define fast_metatable_or_nil(n) do { \
+ if (n) { \
+ a = (halfword *) lua_newuserdata(L, sizeof(halfword)); \
+ *a = n; \
+ lua_getmetatable(L,1); \
+ lua_setmetatable(L,-2); \
+ } else { \
+ lua_pushnil(L); \
+ } \
+} while (0)
+
+#define fast_metatable_or_nil_alink(n) do { \
+ if (n) { \
+ alink(n) = null; \
+ a = (halfword *) lua_newuserdata(L, sizeof(halfword)); \
+ *a = n; \
+ lua_getmetatable(L,1); \
+ lua_setmetatable(L,-2); \
+ } else { \
+ lua_pushnil(L); \
+ } \
+} while (0)
+
+#define fast_metatable_top(n) do { \
+ a = (halfword *) lua_newuserdata(L, sizeof(halfword)); \
+ *a = n; \
+ lua_getmetatable(L,-2); \
+ lua_setmetatable(L,-2); \
+} while (0)
+
+#define lua_push_node_metatablelua do { \
+ lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node)); \
+ lua_gettable(L, LUA_REGISTRYINDEX); \
+} while (0)
+
+/*
+
+ This is a first step towards abstract direct nodes. When we have Lua 5.3 we
+ need to check all returned values for being integers. This might be another
+ level of abtraction.
+
+*/
+
+#define nodelib_pushdirect(n) lua_pushnumber(L,n)
+#define nodelib_popdirect(n) lua_tointeger(L,n)
+
+#define nodelib_pushdirect_or_nil(n) do { \
+ if (n==null) { \
+ lua_pushnil(L); \
+ } else { \
+ lua_pushnumber(L,n); \
+ } \
+} while (0)
+
+#define nodelib_pushdirect_or_nil_alink(n) do { \
+ if (n==null) { \
+ lua_pushnil(L); \
+ } else { \
+ alink(n) = null; \
+ lua_pushnumber(L,n); \
+ } \
+} while (0)
+
+/* handy sometimes: */
+
+/* static void stackDump (lua_State * L) { */
+/* int i; */
+/* int top = lua_gettop(L); */
+/* for (i = top; i >= 1; i--) { */
+/* int t = lua_type(L, i); */
+/* switch (t) { */
+/* case LUA_TSTRING: */
+/* printf("[%d] '%s'\n", i, lua_tostring(L, i)); */
+/* break; */
+/* case LUA_TBOOLEAN: */
+/* printf("[%d] %s\n",i, lua_toboolean(L, i) ? "true" : "false"); */
+/* break; */
+/* case LUA_TNUMBER: */
+/* printf("[%d] %g\n", i, lua_tonumber(L, i)); */
+/* break; */
+/* default: */
+/* printf("[%d][%d] %s &d=0x%x *d=%d\n",i-top-1, i, lua_typename(L, t), lua_touserdata(L,i), *((int *)lua_touserdata(L,i))); */
+/* break; */
+/* } */
+/* } */
+/* } */
+
+
+#define nodelib_gettoks(L,a) tokenlist_from_lua(L)
+
+#define nodelib_getspec nodelib_getlist
+#define nodelib_getaction nodelib_getlist
+
+/* a quick helper for dir nodes; there is only a small set of possible values */
+
+#define RETURN_DIR_VALUES(a) \
+if (s==luaS_##a##_ptr) { \
+ return (dir_##a); \
+} else if (!absolute_only) { \
+ if (s==luaS_p##a##_ptr) \
+ return (dir_##a); \
+ else if (s==luaS_m##a##_ptr) \
+ return ((dir_##a)-64); \
+}
+
+/* fetching a field from a node .. we can often use the reuse bot-of-stack metatable */
+
+#define nodelib_pushlist(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } /* can be: fast_metatable_or_nil(n) */
+#define nodelib_pushattr(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } /* can be: fast_metatable_or_nil(n) */
+#define nodelib_pushspec(L,n) { lua_pushnumber(L,n); lua_nodelib_push_spec(L); } /* can be: fast_metatable_or_nil(n) - different criterium? */
+#define nodelib_pushaction(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } /* can be: fast_metatable_or_nil(n) */
+#define nodelib_pushstring(L,n) { char *ss=makecstring(n); lua_pushstring(L,ss); free(ss); }
+
+/* find prev, and fix backlinks .. can be a macro instead (only used a few times) */
+
+#define set_t_to_prev(head,current) \
+t = head; \
+while (vlink(t)!=current && t != null) { \
+ if (vlink(t)!=null) \
+ alink(vlink(t)) = t; \
+ t = vlink(t); \
+}
+
+#define get_node_type_id(L,n) do_get_node_type_id(L,n,node_data)
+#define get_node_subtype_id(L,n) do_get_node_type_id(L,n,whatsit_node_data)
+
+#define box(A) eqtb[box_base+(A)].hh.rh
+#define direct_check_index_range(j,s) \
+ if (j<0 || j > 65535) { \
+ luaL_error(L, "incorrect index value %d for tex.%s()", (int)j, s); \
+ }
+
#define NODE_METATABLE "luatex_node"
#define DEBUG 0
@@ -95,8 +316,10 @@ make_luaS_index(dvi_ptr);
make_luaS_index(expansion_factor);
make_luaS_index(ext);
make_luaS_index(fam);
+make_luaS_index(fast);
make_luaS_index(file);
make_luaS_index(font);
+make_luaS_index(global);
make_luaS_index(glue_order);
make_luaS_index(glue_set);
make_luaS_index(glue_sign);
@@ -225,8 +448,10 @@ static void initialize_luaS_indexes(lua_State * L)
init_luaS_index(expansion_factor);
init_luaS_index(ext);
init_luaS_index(fam);
+ init_luaS_index(fast);
init_luaS_index(file);
init_luaS_index(font);
+ init_luaS_index(global);
init_luaS_index(glue_order);
init_luaS_index(glue_set);
init_luaS_index(glue_sign);
@@ -317,6 +542,8 @@ static void initialize_luaS_indexes(lua_State * L)
}
+/* maybe these qualify as macros, not functions */
+
static halfword *maybe_isnode(lua_State * L, int ud)
{
halfword *p = lua_touserdata(L, ud);
@@ -324,32 +551,69 @@ static halfword *maybe_isnode(lua_State * L, int ud)
if (lua_getmetatable(L, ud)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
lua_gettable(L, LUA_REGISTRYINDEX);
- if (!lua_rawequal(L, -1, -2)) {
+ if (!lua_rawequal(L, -1, -2))
p = NULL;
- }
- lua_pop(L, 2);
+ lua_pop(L, 2);
}
}
return p;
}
+/* we could make the message a function and just inline the rest (via a macro) */
+
halfword *check_isnode(lua_State * L, int ud)
{
halfword *p = maybe_isnode(L, ud);
- if (p != NULL) {
+ if (p != NULL)
return p;
- }
pdftex_fail("There should have been a lua <node> here, not an object with type %s!", luaL_typename(L, ud));
return NULL;
}
-/* This routine finds the numerical value of a string (or number) at
- lua stack index |n|. If it is not a valid node type, returns -1 */
+/*
+
+ This routine finds the numerical value of a string (or number) at
+ lua stack index |n|. If it is not a valid node type, returns -1
+
+ Todo: create a lua table instead at initialization time and then
+ use that hash, so that we don't need to loop for each lookup.
-static
-int do_get_node_type_id(lua_State * L, int n, node_info * data)
+ HH: can crash on noad 9
+
+*/
+
+static int do_get_node_type_id(lua_State * L, int n, node_info * data)
{
- register int j;
+ int j;
+ /* switch (lua_type(L, n)) { */
+ /* case LUA_TNIL: */
+ /* printf("LUA_TNIL\n"); */
+ /* break; */
+ /* case LUA_TNUMBER: */
+ /* printf("LUA_TNUMBER\n"); */
+ /* break; */
+ /* case LUA_TBOOLEAN: */
+ /* printf("LUA_TBOOLEAN\n"); */
+ /* break; */
+ /* case LUA_TSTRING: */
+ /* printf("LUA_TSTRING\n"); */
+ /* break; */
+ /* case LUA_TTABLE: */
+ /* printf("LUA_TTABLE\n"); */
+ /* break; */
+ /* case LUA_TFUNCTION: */
+ /* printf("LUA_TFUNCTION\n"); */
+ /* break; */
+ /* case LUA_TUSERDATA: */
+ /* printf("LUA_TUSERDATA\n"); */
+ /* break; */
+ /* case LUA_TTHREAD: */
+ /* printf("LUA_TTHREAD\n"); */
+ /* break; */
+ /* case LUA_TLIGHTUSERDATA: */
+ /* printf("LUA_TLIGHTUSERDATA\n"); */
+ /* break; */
+ /* } */
if (lua_type(L, n) == LUA_TSTRING) {
const char *s = lua_tostring(L, n);
for (j = 0; data[j].id != -1; j++) {
@@ -357,7 +621,7 @@ int do_get_node_type_id(lua_State * L, int n, node_info * data)
return j;
}
} else if (lua_type(L, n) == LUA_TNUMBER) {
- register int i = (int) lua_tointeger(L, n);
+ int i = (int) lua_tointeger(L, n);
for (j = 0; data[j].id != -1; j++) {
if (data[j].id == i)
return j;
@@ -366,9 +630,6 @@ int do_get_node_type_id(lua_State * L, int n, node_info * data)
return -1;
}
-#define get_node_type_id(L,n) do_get_node_type_id(L,n,node_data)
-#define get_node_subtype_id(L,n) do_get_node_type_id(L,n,whatsit_node_data)
-
static int get_valid_node_type_id(lua_State * L, int n)
{
int i = get_node_type_id(L, n);
@@ -395,18 +656,7 @@ static int get_valid_node_subtype_id(lua_State * L, int n)
return i;
}
-/* returns true is the argument is a userdata object of type node */
-
-static int lua_nodelib_isnode(lua_State * L)
-{
- if (maybe_isnode(L,1) != NULL)
- lua_pushboolean(L,1);
- else
- lua_pushboolean(L,0);
- return 1;
-}
-
-/* two simple helpers to speed up and simplify lua code: */
+/* two simple helpers to speed up and simplify lua code (replaced by getnext and getprev) */
static int lua_nodelib_next(lua_State * L)
{
@@ -430,12 +680,27 @@ static int lua_nodelib_prev(lua_State * L)
return 1;
}
+/*
+
+ static void lua_nodelib_push_simple(lua_State * L, halfword p)
+ {
+ halfword *a;
+ a = (halfword *) lua_newuserdata(L, sizeof(halfword));
+ *a = p;
+ lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_setmetatable(L, -2);
+ }
+
+*/
+
+/*
+
+ Creates a userdata object for a number found at the stack top, if it is
+ representing a node (i.e. an pointer into |varmem|). It replaces the
+ stack entry with the new userdata, or pushes |nil| if the number is |null|,
+ or if the index is definately out of range. This test could be improved.
-/* Creates a userdata object for a number found at the stack top,
- if it is representing a node (i.e. an pointer into |varmem|).
- It replaces the stack entry with the new userdata, or pushes
- |nil| if the number is |null|, or if the index is definately out of
- range. This test could be improved.
*/
void lua_nodelib_push(lua_State * L)
@@ -443,9 +708,8 @@ void lua_nodelib_push(lua_State * L)
halfword n;
halfword *a;
n = -1;
- if (lua_isnumber(L, -1)) {
+ if (lua_isnumber(L, -1))
n = (int) lua_tointeger(L, -1);
- }
lua_pop(L, 1);
if ((n == null) || (n < 0) || (n > var_mem_max)) {
lua_pushnil(L);
@@ -466,9 +730,8 @@ static void lua_nodelib_push_spec(lua_State * L)
halfword n;
halfword *a;
n = -1;
- if (lua_isnumber(L, -1)) {
+ if (lua_isnumber(L, -1))
n = (halfword) lua_tointeger(L, -1);
- }
lua_pop(L, 1);
if ((n < 0) || (n > var_mem_max)) {
lua_pushnil(L);
@@ -506,6 +769,388 @@ static int lua_nodelib_id(lua_State * L)
return 1;
}
+/* node.getid */
+
+static int lua_nodelib_getid(lua_State * L)
+{
+ /* [given-node] [...] */
+ halfword *p = lua_touserdata(L, 1);
+ if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L);
+ return 1;
+ }
+ /* [given-node] [mt-given-node] */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ /* [given-node] [mt-given-node] [mt-node] */
+ if (!lua_rawequal(L, -1, -2)) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, type(*p));
+ }
+ return 1;
+}
+
+/* node.fast.getid
+
+ static int lua_nodelib_fast_getid(lua_State * L)
+ {
+ halfword *n;
+ n = (halfword *) lua_touserdata(L, 1);
+ lua_pushnumber(L, type(*n));
+ return 1;
+ }
+
+*/
+
+/* node.direct.getid */
+
+static int lua_nodelib_direct_getid(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, type(n));
+ }
+ return 1;
+}
+
+/* node.getsubtype */
+
+static int lua_nodelib_getsubtype(lua_State * L)
+{
+ halfword *p = lua_touserdata(L, 1);
+ if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L);
+ } else {
+ lua_push_node_metatablelua;
+ if ( (!lua_rawequal(L, -1, -2)) || (! nodetype_has_subtype(*p))) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, subtype(*p));
+ }
+ }
+ return 1;
+}
+
+/* node.fast.getsubtype
+
+ static int lua_nodelib_fast_getsubtype(lua_State * L)
+ {
+ halfword *n;
+ n = (halfword *) lua_touserdata(L, 1);
+ lua_pushnumber(L, subtype(*n));
+ return 1;
+ }
+
+*/
+
+/* node.direct.getsubtype */
+
+static int lua_nodelib_direct_getsubtype(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null) { /* no check, we assume sane use */
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, subtype(n));
+ }
+ return 1;
+}
+
+/* node.getfont */
+
+static int lua_nodelib_getfont(lua_State * L)
+{
+ halfword *p = lua_touserdata(L, 1);
+ if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L);
+ } else {
+ lua_push_node_metatablelua;
+ if ( (!lua_rawequal(L, -1, -2)) || (type(*p) != glyph_node) ) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, font(*p));
+ }
+ }
+ return 1;
+}
+
+/* node.fast.getfont
+
+ static int lua_nodelib_fast_getfont(lua_State * L)
+ {
+ halfword *n;
+ n = (halfword *) lua_touserdata(L, 1);
+ if (type(*n) != glyph_node) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, font(*n));
+ }
+ return 1;
+ }
+
+*/
+
+/* node.direct.getfont */
+
+static int lua_nodelib_direct_getfont(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if ((n == null) || (type(n) != glyph_node)) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, font(n));
+ }
+ return 1;
+}
+
+/* node.getchar */
+
+static int lua_nodelib_getcharacter(lua_State * L)
+{
+ halfword *n = lua_touserdata(L, 1);
+ if ( (n == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L);
+ } else if (type(*n) == glyph_node) {
+ lua_pushnumber(L, character(*n));
+ } else if ((type(*n) == math_char_node) || (type(*n) == math_text_char_node)) {
+ lua_pushnumber(L, math_character(*n));
+ }
+ return 1;
+}
+
+/* node.fast.getchar
+
+ static int lua_nodelib_fast_getcharacter(lua_State * L)
+ {
+ halfword *n;
+ n = (halfword *) lua_touserdata(L, 1);
+ if (type(*n) == glyph_node) {
+ lua_pushnumber(L, character(*n));
+ } else if ((type(*n) == math_char_node) || (type(*n) == math_text_char_node)) {
+ lua_pushnumber(L, math_character(*n));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+ }
+
+*/
+
+/* node.direct.getchar */
+
+static int lua_nodelib_direct_getcharacter(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else if (type(n) == glyph_node) {
+ lua_pushnumber(L, character(n));
+ } else if ((type(n) == math_char_node) || (type(n) == math_text_char_node)) {
+ lua_pushnumber(L, math_character(n));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* node.getlist */
+
+static int lua_nodelib_getlist(lua_State * L)
+{
+ halfword *a;
+ halfword *n = lua_touserdata(L, 1);
+ if ( (n == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L);
+ } else if ((type(*n) == hlist_node) || (type(*n) == vlist_node)) {
+ fast_metatable_or_nil_alink(list_ptr(*n));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* node.direct.getlist */
+
+static int lua_nodelib_direct_getlist(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if ( n == null) {
+ lua_pushnil(L);
+ } else if ((type(n) == hlist_node) || (type(n) == vlist_node)) {
+ nodelib_pushdirect_or_nil_alink(list_ptr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* node.getleader */
+
+static int lua_nodelib_getleader(lua_State * L)
+{
+ halfword *a;
+ halfword *n = lua_touserdata(L, 1);
+ if ( (n == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L);
+ } else if (type(*n) == glue_node) {
+ fast_metatable_or_nil(leader_ptr(*n));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* node.direct.getleader */
+
+static int lua_nodelib_direct_getleader(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if ( n == null) {
+ lua_pushnil(L);
+ } else if (type(n) == glue_node) {
+ nodelib_pushdirect_or_nil(leader_ptr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* node.getnext */
+
+static int lua_nodelib_getnext(lua_State * L)
+{
+ halfword *a;
+ /* [given-node] [...]*/
+ halfword *p = lua_touserdata(L, 1);
+ if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L);
+ } else {
+ /* [given-node] [mt-given-node]*/
+ lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ /* [given-node] [mt-given-node] [mt-node]*/
+ if (!lua_rawequal(L, -1, -2)) {
+ lua_pushnil(L);
+ } else {
+ fast_metatable_or_nil(vlink(*p));
+ }
+ }
+ return 1; /* just one*/
+}
+
+/* node.fast.getnext
+
+ static int lua_nodelib_fast_getnext(lua_State * L)
+ {
+ halfword *a;
+ // [given-node] [...]
+ halfword *p = lua_touserdata(L, 1);
+ if ((p == NULL) || (!vlink(*p))){
+ lua_pushnil(L);
+ } else {
+ lua_settop(L,1);
+ // [given-node]
+ lua_getmetatable(L,1);
+ // [given-node] [mt-node]
+ a = lua_newuserdata(L, sizeof(halfword));
+ // [given-node] [mt-node] [next-node]
+ *a = vlink(*p);
+ lua_replace(L,1);
+ // [next-node] [mt-node]
+ lua_setmetatable(L,1);
+ // [next-node-with-mt]
+ }
+ return 1;
+ }
+
+*/
+
+/* node.direct.getnext */
+
+static int lua_nodelib_direct_getnext(lua_State * L)
+{
+ halfword p;
+ p = (halfword) lua_tonumber(L, 1);
+ if (p == null) {
+ lua_pushnil(L);
+ } else {
+ nodelib_pushdirect_or_nil(vlink(p));
+ }
+ return 1;
+}
+
+/* node.getprev */
+
+static int lua_nodelib_getprev(lua_State * L)
+{
+ halfword *a;
+ halfword *p = lua_touserdata(L, 1);
+ if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L);
+ } else {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ if (!lua_rawequal(L, -1, -2)) {
+ lua_pushnil(L);
+ } else {
+ fast_metatable_or_nil(alink(*p));
+ }
+ }
+ return 1;
+}
+
+
+/* node.fast.getprev
+
+ static int lua_nodelib_fast_getprev(lua_State * L)
+ {
+ halfword *a;
+ // [given-node] [...]
+ halfword *p = lua_touserdata(L, 1);
+ if ((p == NULL) || (!alink(*p))) {
+ lua_pushnil(L);
+ } else {
+ lua_settop(L,1);
+ // [given-node]
+ lua_getmetatable(L,1);
+ // [given-node] [mt-node]
+ a = lua_newuserdata(L, sizeof(halfword));
+ // [given-node] [mt-node] [next-node]
+ *a = alink(*p);
+ lua_replace(L,1);
+ // [next-node] [mt-node]
+ lua_setmetatable(L,1);
+ // [next-node-with-mt]
+ }
+ return 1;
+ }
+
+*/
+
+/* node.direct.getprev */
+
+static int lua_nodelib_direct_getprev(lua_State * L)
+{
+ halfword p;
+ p = (halfword) lua_tonumber(L, 1);
+ if (p == null) {
+ lua_pushnil(L);
+ } else {
+ nodelib_pushdirect_or_nil(alink(p));
+ }
+ return 1;
+}
+
+/* node.subtype */
static int lua_nodelib_subtype(lua_State * L)
{
@@ -513,12 +1158,12 @@ static int lua_nodelib_subtype(lua_State * L)
if (i >= 0) {
lua_pushnumber(L, i);
} else {
- lua_pushnil(L);
+ lua_pushnil(L); /* return 0; */
}
return 1;
}
-/* converts id numbers to type names */
+/* node.type (converts id numbers to type names) */
static int lua_nodelib_type(lua_State * L)
{
@@ -536,36 +1181,53 @@ static int lua_nodelib_type(lua_State * L)
return 1;
}
-/* allocate a new node */
+/* node.new (allocate a new node) */
static int lua_nodelib_new(lua_State * L)
{
int i, j;
halfword n = null;
i = get_valid_node_type_id(L, 1);
-
if (i == whatsit_node) {
j = -1;
- if (lua_gettop(L) > 1) {
+ if (lua_gettop(L) > 1)
j = get_valid_node_subtype_id(L, 2);
- }
- if (j < 0) {
+ if (j < 0)
luaL_error(L, "Creating a whatsit requires the subtype number as a second argument");
- }
} else {
j = 0;
- if (lua_gettop(L) > 1) {
+ if (lua_gettop(L) > 1)
j = (int) lua_tointeger(L, 2);
- }
}
n = new_node(i, j);
lua_nodelib_push_fast(L, n);
return 1;
}
+/* node.direct.new (still with checking) */
+
+static int lua_nodelib_direct_new(lua_State * L)
+{
+ int i, j;
+ halfword n ;
+ i = get_valid_node_type_id(L, 1);
+ if (i == whatsit_node) {
+ j = -1;
+ if (lua_gettop(L) > 1)
+ j = get_valid_node_subtype_id(L, 2);
+ if (j < 0)
+ luaL_error(L, "Creating a whatsit requires the subtype number as a second argument");
+ } else {
+ j = 0;
+ if (lua_gettop(L) > 1)
+ j = (int) lua_tointeger(L, 2);
+ }
+ n = new_node(i, j);
+ lua_pushnumber(L,n);
+ return 1;
+}
-/* Free a node.
- This function returns the 'next' node, because that may be helpful */
+/* node.free (this function returns the 'next' node, because that may be helpful) */
static int lua_nodelib_free(lua_State * L)
{
@@ -580,12 +1242,59 @@ static int lua_nodelib_free(lua_State * L)
n = check_isnode(L, 1);
p = vlink(*n);
flush_node(*n);
+ /* can be: lua_nodelib_push_fast(L, p); */
lua_pushnumber(L, p);
lua_nodelib_push(L);
return 1;
}
-/* Free a node list */
+/* node.direct.free */
+
+static int lua_nodelib_direct_free(lua_State * L)
+{
+ halfword n;
+ halfword p;
+ n = (halfword) lua_tonumber(L,1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else {
+ p = vlink(n);
+ flush_node(n);
+ if (p == 0) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L,p);
+ }
+ }
+ return 1;
+}
+
+/* node.flush_node (no next returned) */
+
+static int lua_nodelib_flush_node(lua_State * L)
+{
+ halfword *n;
+ if ((lua_gettop(L) < 1) || lua_isnil(L, 1))
+ return 0;
+ n = check_isnode(L, 1);
+ // no check if n?
+ flush_node(*n);
+ return 0;
+}
+
+/* node.direct.flush_node */
+
+static int lua_nodelib_direct_flush_node(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L,1);
+ if (n == null)
+ return 0;
+ flush_node(n);
+ return 0;
+}
+
+/* node.flush_list */
static int lua_nodelib_flush_list(lua_State * L)
{
@@ -597,77 +1306,127 @@ static int lua_nodelib_flush_list(lua_State * L)
return 0;
}
-/* find prev, and fix backlinks */
+/* node.direct.flush_list */
-#define set_t_to_prev(head,current) \
- t = head; \
- while (vlink(t)!=current && t != null) { \
- if (vlink(t)!=null) \
- alink(vlink(t)) = t; \
- t = vlink(t); \
- }
+static int lua_nodelib_direct_flush_list(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L,1);
+ if (n == null)
+ return 0;
+ flush_node_list(n);
+ return 0;
+}
/* remove a node from a list */
#if DEBUG
-static void show_node_links (halfword l, const char * p)
-{
- halfword t = l;
- while (t) {
- fprintf(DEBUG_OUT, "%s t = %d, prev = %d, next = %d\n", p, (int)t, (int)alink(t), (int)vlink(t));
- t = vlink(t);
+
+ static void show_node_links (halfword l, const char * p)
+ {
+ halfword t = l;
+ while (t) {
+ fprintf(DEBUG_OUT, "%s t = %d, prev = %d, next = %d\n", p, (int)t, (int)alink(t), (int)vlink(t));
+ t = vlink(t);
+ }
}
-}
+
#endif
+/* node.remove */
+
static int lua_nodelib_remove(lua_State * L)
{
halfword head, current, t;
- if (lua_gettop(L) < 2) {
+ if (lua_gettop(L) < 2)
luaL_error(L, "Not enough arguments for node.remove()");
- }
head = *(check_isnode(L, 1));
#if DEBUG
show_node_links(head, "before");
#endif
- if (lua_isnil(L, 2)) {
+ if (lua_isnil(L, 2))
return 2; /* the arguments, as they are */
- }
current = *(check_isnode(L, 2));
if (head == current) {
- if (alink(head) != null && vlink(current) != null) {
+ if (alink(head) != null && vlink(current) != null)
alink(vlink(current)) = alink(head);
- }
head = vlink(current);
current = head;
} else { /* head != current */
t = alink(current);
if (t == null || vlink(t) != current) {
set_t_to_prev(head, current);
- if (t == null) { /* error! */
- luaL_error(L,
- "Attempt to node.remove() a non-existing node");
- }
+ if (t == null) /* error! */
+ luaL_error(L,"Attempt to node.remove() a non-existing node");
}
/* t is now the previous node */
vlink(t) = vlink(current);
- if (vlink(current) != null) {
+ if (vlink(current) != null)
alink(vlink(current)) = t;
- }
current = vlink(current);
}
#if DEBUG
show_node_links(head, "after");
#endif
+ /* can be: lua_nodelib_push_fast(L, head); */
lua_pushnumber(L, head);
lua_nodelib_push(L);
+ /* can be: lua_nodelib_push_fast(L, current); */
lua_pushnumber(L, current);
lua_nodelib_push(L);
return 2;
}
-/* Insert a node in a list */
+/* node.direct.remove */
+
+static int lua_nodelib_direct_remove(lua_State * L)
+{
+ halfword head, current , t;
+ head = (halfword) lua_tonumber(L,1);
+ if (head == null) {
+ lua_pushnil(L);
+ lua_pushnil(L);
+ return 2 ;
+ }
+ current = (halfword) lua_tonumber(L,2);
+ if (current == null) {
+ lua_pushnumber(L, head);
+ lua_pushnil(L);
+ return 2 ;
+ }
+ if (head == current) {
+ if (alink(head) != null && vlink(current) != null)
+ alink(vlink(current)) = alink(head);
+ head = vlink(current);
+ current = head;
+ } else {
+ t = alink(current);
+ if (t == null || vlink(t) != current) {
+ set_t_to_prev(head, current);
+ if (t == null) {
+ luaL_error(L,"Attempt to node.direct.remove() a non-existing node");
+ }
+ }
+ vlink(t) = vlink(current);
+ if (vlink(current) != null)
+ alink(vlink(current)) = t;
+ current = vlink(current);
+ }
+ if (head == null) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, head);
+ }
+ if (current == null) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, current);
+ }
+ return 2;
+}
+
+/* node.insert_before (insert a node in a list) */
static int lua_nodelib_insert_before(lua_State * L)
{
@@ -715,6 +1474,49 @@ static int lua_nodelib_insert_before(lua_State * L)
return 2;
}
+/* node.direct.insert_before */
+
+static int lua_nodelib_direct_insert_before(lua_State * L)
+{
+ halfword head, current, n, t;
+ n = (halfword) lua_tonumber(L,3);
+ if (n == null){
+ /* no node */
+ lua_pop(L, 1);
+ return 2 ;
+ }
+ head = (halfword) lua_tonumber(L,1);
+ current = (halfword) lua_tonumber(L,2);
+ /* no head, ignore current */
+ if (head == null) {
+ vlink(n) = null;
+ alink(n) = null;
+ lua_pushnumber(L, n);
+ lua_pushvalue(L, -1);
+ /* n, n */
+ return 2;
+ }
+ /* no current */
+ if (current == null)
+ current = tail_of_list(head);
+ if (head != current) {
+ t = alink(current);
+ if (t == null || vlink(t) != current)
+ set_t_to_prev(head, current);
+ couple_nodes(t, n);
+ }
+ couple_nodes(n, current);
+ if (head == current) {
+ lua_pushnumber(L, n);
+ } else {
+ lua_pushnumber(L, head);
+ }
+ lua_pushnumber(L, n);
+ return 2;
+}
+
+/* node.insert_after */
+
static int lua_nodelib_insert_after(lua_State * L)
{
halfword head, current, n;
@@ -751,8 +1553,42 @@ static int lua_nodelib_insert_after(lua_State * L)
return 2;
}
+/* node.direct.insert_after */
+
+static int lua_nodelib_direct_insert_after(lua_State * L)
+{
+ halfword head, current, n;
+ /*[head][current][new]*/
+ n = (halfword) lua_tonumber(L,3);
+ if (n == null) {
+ /* no node */
+ return 2 ;
+ }
+ head = (halfword) lua_tonumber(L,1);
+ current = (halfword) lua_tonumber(L,2);
+ if (head == null) {
+ /* no head, ignore current */
+ vlink(n) = null;
+ alink(n) = null;
+ lua_pushnumber(L,n);
+ lua_pushvalue(L, -1);
+ /* n, n */
+ return 2;
+ }
+ if (current == null) {
+ /* no current */
+ current = head;
+ while (vlink(current) != null)
+ current = vlink(current);
+ }
+ try_couple_nodes(n, vlink(current));
+ couple_nodes(current, n);
+ lua_pop(L, 2);
+ lua_pushnumber(L, n);
+ return 2;
+}
-/* Copy a node list */
+/* node.copy_list */
static int lua_nodelib_copy_list(lua_State * L)
{
@@ -761,16 +1597,35 @@ static int lua_nodelib_copy_list(lua_State * L)
if (lua_isnil(L, 1))
return 1; /* the nil itself */
n = *check_isnode(L, 1);
- if ((lua_gettop(L) > 1) && (!lua_isnil(L,2))) {
+ if ((lua_gettop(L) > 1) && (!lua_isnil(L,2)))
s = *check_isnode(L, 2);
- }
m = do_copy_node_list(n, s);
lua_pushnumber(L, m);
lua_nodelib_push(L);
return 1;
}
-/* (Deep) copy a node */
+/* node.direct.copy_list */
+
+static int lua_nodelib_direct_copy_list(lua_State * L)
+{
+ halfword n, s, m;
+ n = (halfword) lua_tonumber(L,1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else {
+ s = (halfword) lua_tonumber(L,2);
+ if (s == null) {
+ m = do_copy_node_list(n,null);
+ } else {
+ m = do_copy_node_list(n,s);
+ }
+ lua_pushnumber(L,m);
+ }
+ return 1;
+}
+
+/* node.copy (deep copy) */
static int lua_nodelib_copy(lua_State * L)
{
@@ -784,7 +1639,23 @@ static int lua_nodelib_copy(lua_State * L)
return 1;
}
-/* output (write) a node to tex's processor */
+/* node.direct.copy (deep copy) */
+
+static int lua_nodelib_direct_copy(lua_State * L)
+{
+ halfword n;
+ halfword m;
+ if (lua_isnil(L, 1))
+ return 1; /* the nil itself */
+ /* beware, a glue node can have number 0 (zeropt) so we cannot test for null) */
+ n = (halfword) lua_tonumber(L, 1);
+ m = copy_node(n);
+ lua_pushnumber(L, m);
+ return 1;
+}
+
+
+/* node.write (output a node to tex's processor) */
static int lua_nodelib_append(lua_State * L)
{
@@ -804,16 +1675,51 @@ static int lua_nodelib_append(lua_State * L)
return 0;
}
+/* node.direct.write */
+
+static int lua_nodelib_direct_append(lua_State * L)
+{
+ halfword n;
+ halfword m;
+ int i, j;
+ j = lua_gettop(L);
+ for (i = 1; i <= j; i++) {
+ n = (halfword) lua_tonumber(L,i); /*lua_getnumber(L, i);*/
+ if (n != null) {
+ m = n ;
+ tail_append(m);
+ while (vlink(m) != null) {
+ m = vlink(m);
+ tail_append(m);
+ }
+ }
+ }
+ return 0;
+}
+
+/* node.last */
+
static int lua_nodelib_last_node(lua_State * L)
{
halfword m;
m = pop_tail();
+ /* can be: lua_nodelib_push_fast(L, m); */
lua_pushnumber(L, m);
lua_nodelib_push(L);
return 1;
}
-/* build a hbox */
+/* node.direct.last */
+
+static int lua_nodelib_direct_last_node(lua_State * L)
+{
+ halfword m;
+ m = pop_tail();
+ lua_pushnumber(L, m);
+ return 1;
+}
+
+/* node.hpack (build a hbox) */
static int lua_nodelib_hpack(lua_State * L)
{
@@ -859,6 +1765,146 @@ static int lua_nodelib_hpack(lua_State * L)
return 2;
}
+/* node.direct.hpack */
+
+static int lua_nodelib_direct_hpack(lua_State * L)
+{
+ halfword n, p;
+ const char *s;
+ int w = 0;
+ int m = 1;
+ int d = -1;
+ n = (halfword) lua_tonumber(L,1);
+ /* could be macro */
+ if (lua_gettop(L) > 1) {
+ w = (int) lua_tointeger(L, 2);
+ if (lua_gettop(L) > 2) {
+ if (lua_type(L, 3) == LUA_TSTRING) {
+ s = lua_tostring(L, 3);
+ if (luaS_ptr_eq(s, additional)) {
+ m = 1;
+ } else if (luaS_ptr_eq(s, exactly)) {
+ m = 0;
+ } else if (luaS_ptr_eq(s, cal_expand_ratio)) {
+ m = 2;
+ } else if (luaS_ptr_eq(s, subst_ex_font)) {
+ m = 3;
+ } else {
+ luaL_error(L, "3rd argument should be either additional or exactly");
+ }
+ } else if (lua_type(L, 3) == LUA_TNUMBER) {
+ m=(int)lua_tonumber(L, 3);
+ } else {
+ lua_pushstring(L, "incorrect 3rd argument");
+ }
+ if (lua_gettop(L) > 3) {
+ if (lua_type(L, 4) == LUA_TSTRING) {
+ d = nodelib_getdir(L, 4, 1);
+ } else {
+ lua_pushstring(L, "incorrect 4th argument");
+ }
+ }
+ }
+ }
+ /* till here */
+ p = hpack(n, w, m, d);
+ lua_pushnumber(L, p);
+ lua_pushnumber(L, last_badness);
+ return 2;
+}
+
+/* node.vpack (build a vbox) */
+
+static int lua_nodelib_vpack(lua_State * L)
+{
+ halfword n, p;
+ const char *s;
+ int w = 0;
+ int m = 1;
+ int d = -1;
+ n = *(check_isnode(L, 1));
+ if (lua_gettop(L) > 1) {
+ w = (int) lua_tointeger(L, 2);
+ if (lua_gettop(L) > 2) {
+ if (lua_type(L, 3) == LUA_TSTRING) {
+ s = lua_tostring(L, 3);
+ if (luaS_ptr_eq(s, additional)) {
+ m = 1;
+ } else if (luaS_ptr_eq(s, exactly)) {
+ m = 0;
+ } else {
+ luaL_error(L, "3rd argument should be either additional or exactly");
+ }
+
+ if (lua_gettop(L) > 3) {
+ if (lua_type(L, 4) == LUA_TSTRING) {
+ d = nodelib_getdir(L, 4, 1);
+ } else {
+ lua_pushstring(L, "incorrect 4th argument");
+ }
+ }
+ }
+
+ else if (lua_type(L, 3) == LUA_TNUMBER) {
+ m=(int)lua_tonumber(L, 3);
+ } else {
+ lua_pushstring(L, "incorrect 3rd argument");
+ }
+ }
+ }
+ p = vpackage(n, w, m, max_dimen, d);
+ lua_nodelib_push_fast(L, p);
+ lua_pushnumber(L, last_badness);
+ return 2;
+}
+
+/* node.direct.vpack */
+
+static int lua_nodelib_direct_vpack(lua_State * L)
+{
+ halfword n, p;
+ const char *s;
+ int w = 0;
+ int m = 1;
+ int d = -1;
+ n = (halfword) lua_tonumber(L,1);
+ if (lua_gettop(L) > 1) {
+ w = (int) lua_tointeger(L, 2);
+ if (lua_gettop(L) > 2) {
+ if (lua_type(L, 3) == LUA_TSTRING) {
+ s = lua_tostring(L, 3);
+ if (luaS_ptr_eq(s, additional)) {
+ m = 1;
+ } else if (luaS_ptr_eq(s, exactly)) {
+ m = 0;
+ } else {
+ luaL_error(L, "3rd argument should be either additional or exactly");
+ }
+
+ if (lua_gettop(L) > 3) {
+ if (lua_type(L, 4) == LUA_TSTRING) {
+ d = nodelib_getdir(L, 4, 1);
+ } else {
+ lua_pushstring(L, "incorrect 4th argument");
+ }
+ }
+ }
+
+ else if (lua_type(L, 3) == LUA_TNUMBER) {
+ m=(int)lua_tonumber(L, 3);
+ } else {
+ lua_pushstring(L, "incorrect 3rd argument");
+ }
+ }
+ }
+ p = vpackage(n, w, m, max_dimen, d);
+ lua_pushnumber(L, p);
+ lua_pushnumber(L, last_badness);
+ return 2;
+}
+
+/* node.dimensions (of a hlist or vlist) */
+
static int lua_nodelib_dimensions(lua_State * L)
{
int top;
@@ -904,52 +1950,48 @@ static int lua_nodelib_dimensions(lua_State * L)
return 0; /* not reached */
}
-/* build a vbox */
+/* node.direct.dimensions*/
-static int lua_nodelib_vpack(lua_State * L)
+static int lua_nodelib_direct_dimensions(lua_State * L)
{
- halfword n, p;
- const char *s;
- int w = 0;
- int m = 1;
- int d = -1;
- n = *(check_isnode(L, 1));
- if (lua_gettop(L) > 1) {
- w = (int) lua_tointeger(L, 2);
- if (lua_gettop(L) > 2) {
- if (lua_type(L, 3) == LUA_TSTRING) {
- s = lua_tostring(L, 3);
- if (luaS_ptr_eq(s, additional)) {
- m = 1;
- } else if (luaS_ptr_eq(s, exactly)) {
- m = 0;
- } else {
- luaL_error(L, "3rd argument should be either additional or exactly");
- }
-
- if (lua_gettop(L) > 3) {
- if (lua_type(L, 4) == LUA_TSTRING) {
- d = nodelib_getdir(L, 4, 1);
- } else {
- lua_pushstring(L, "incorrect 4th argument");
- }
- }
- }
-
- else if (lua_type(L, 3) == LUA_TNUMBER) {
- m=(int)lua_tonumber(L, 3);
+ int top;
+ top = lua_gettop(L);
+ if (top > 0) {
+ scaled_whd siz;
+ glue_ratio g_mult = 1.0;
+ int g_sign = normal;
+ int g_order = normal;
+ int i = 1;
+ int d = -1;
+ halfword n = null, p = null;
+ if (top > 3) {
+ i += 3;
+ g_mult = (glue_ratio) lua_tonumber(L, 1);
+ g_sign=(int)lua_tonumber(L, 2);
+ g_order=(int)lua_tonumber(L, 3);
+ }
+ n = (halfword) lua_tonumber(L,i);
+ if (lua_gettop(L) > i && !lua_isnil(L, (i + 1))) {
+ if (lua_type(L, (i + 1)) == LUA_TSTRING) {
+ d = nodelib_getdir(L, (i + 1), 1);
} else {
- lua_pushstring(L, "incorrect 3rd argument");
+ p = (halfword) lua_tonumber(L,i+1);
}
}
+ if (lua_gettop(L) > (i + 1) && lua_type(L, (i + 2)) == LUA_TSTRING)
+ d = nodelib_getdir(L, (i + 2), 1);
+ siz = natural_sizes(n, p, g_mult, g_sign, g_order, d);
+ lua_pushnumber(L, siz.wd);
+ lua_pushnumber(L, siz.ht);
+ lua_pushnumber(L, siz.dp);
+ return 3;
+ } else {
+ luaL_error(L, "missing argument to 'dimensions' (node expected)");
}
- p = vpackage(n, w, m, max_dimen, d);
- lua_nodelib_push_fast(L, p);
- lua_pushnumber(L, last_badness);
- return 2;
+ return 0; /* not reached */
}
-/* create a hlist from a formula */
+/* node.mlist_to_hlist (create a hlist from a formula) */
static int lua_nodelib_mlist_to_hlist(lua_State * L)
{
@@ -965,6 +2007,8 @@ static int lua_nodelib_mlist_to_hlist(lua_State * L)
return 1;
}
+/* node.family_font */
+
static int lua_nodelib_mfont(lua_State * L)
{
int f, s;
@@ -989,8 +2033,8 @@ static int lua_nodelib_mfont(lua_State * L)
static int get_node_field_id(lua_State * L, int n, int node)
{
- register int t = type(node);
- register const char *s = lua_tostring(L, n);
+ int t = type(node);
+ const char *s = lua_tostring(L, n);
if (s == NULL)
return -2;
@@ -1032,16 +2076,29 @@ static int get_node_field_id(lua_State * L, int n, int node)
return -2;
}
+/* node.has_field */
+
static int lua_nodelib_has_field(lua_State * L)
{
int i = -2;
- if (!lua_isnil(L, 1)) {
+ if (!lua_isnil(L, 1))
i = get_node_field_id(L, 2, *(check_isnode(L, 1)));
- }
lua_pushboolean(L, (i != -2));
return 1;
}
+/* node.direct.has_field */
+
+static int lua_nodelib_direct_has_field(lua_State * L)
+{
+ int i = -2;
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n != null)
+ i = get_node_field_id(L, 2, n);
+ lua_pushboolean(L, (i != -2));
+ return 1;
+}
/* fetch the list of valid node types */
@@ -1056,17 +2113,21 @@ static int do_lua_nodelib_types(lua_State * L, node_info * data)
return 1;
}
+/* node.types */
+
static int lua_nodelib_types(lua_State * L)
{
return do_lua_nodelib_types(L, node_data);
}
+/* node.whatsits */
+
static int lua_nodelib_whatsits(lua_State * L)
{
return do_lua_nodelib_types(L, whatsit_node_data);
}
-/* fetch the list of valid fields */
+/* node.fields (fetch the list of valid fields) */
static int lua_nodelib_fields(lua_State * L)
{
@@ -1104,9 +2165,9 @@ static int lua_nodelib_fields(lua_State * L)
return 1;
}
-/* find the end of a list */
+/* node.slide (find the end of a list and add prev links) */
-static int lua_nodelib_tail(lua_State * L)
+static int lua_nodelib_slide(lua_State * L)
{
halfword *n;
halfword t;
@@ -1125,7 +2186,27 @@ static int lua_nodelib_tail(lua_State * L)
return 1;
}
-static int lua_nodelib_tail_only(lua_State * L)
+/* node.direct.slide */
+
+static int lua_nodelib_direct_slide(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else {
+ while (vlink(n) != null) {
+ alink(vlink(n)) = n;
+ n = vlink(n);
+ }
+ lua_pushnumber(L, n);
+ }
+ return 1;
+}
+
+/* node.tail (find the end of a list) */
+
+static int lua_nodelib_tail(lua_State * L)
{
halfword *n;
halfword t;
@@ -1135,13 +2216,30 @@ static int lua_nodelib_tail_only(lua_State * L)
t = *n;
if (t == null)
return 1; /* the old userdata */
- while (vlink(t) != null) {
+ while (vlink(t) != null)
t = vlink(t);
- }
lua_nodelib_push_fast(L, t);
return 1;
}
+/* node.direct.tail */
+
+static int lua_nodelib_direct_tail(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else {
+ while (vlink(n) != null)
+ n = vlink(n);
+ lua_pushnumber(L, n);
+ }
+ return 1;
+}
+
+/* node.end_of_math (skip over math and return last) */
+
static int lua_nodelib_end_of_math(lua_State * L)
{
halfword *n;
@@ -1154,17 +2252,34 @@ static int lua_nodelib_end_of_math(lua_State * L)
return 1; /* the old userdata */
while (vlink(t) != null) {
t = vlink(t); /* skip first node */
- if (t && type(t)==math_node) {
- lua_nodelib_push_fast(L, t);
- return 1;
- }
+ if (t && type(t)==math_node) {
+ lua_nodelib_push_fast(L, t);
+ return 1;
+ }
}
- lua_pushnil(L);
- return 1;
+ return 0;
}
+/* node.direct.end_of_math */
-/* a few utility functions for attribute stuff */
+static int lua_nodelib_direct_end_of_math(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n != null) {
+ while (vlink(n) != null) {
+ n = vlink(n); /* skip first node */
+ if (n && type(n)==math_node) {
+ lua_pushnumber(L, n);
+ return 1;
+ }
+ }
+ }
+ lua_pushnil(L);
+ return 0;
+}
+
+/* node.has_attribute (gets attribute) */
static int lua_nodelib_has_attribute(lua_State * L)
{
@@ -1183,6 +2298,27 @@ static int lua_nodelib_has_attribute(lua_State * L)
return 1;
}
+/* node.direct.has_attribute */
+
+static int lua_nodelib_direct_has_attribute(lua_State * L)
+{
+ halfword n;
+ int i, val;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n != null) {
+ i = (int) lua_tointeger(L, 2);
+ val = (int) luaL_optinteger(L, 3, UNUSED_ATTRIBUTE);
+ if ((val = has_attribute(n, i, val)) > UNUSED_ATTRIBUTE) {
+ lua_pushnumber(L, val);
+ return 1;
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+
+/* node.set_attribute */
+
static int lua_nodelib_set_attribute(lua_State * L)
{
halfword *n;
@@ -1202,6 +2338,30 @@ static int lua_nodelib_set_attribute(lua_State * L)
return 0;
}
+/* node.direct.set_attribute */
+
+static int lua_nodelib_direct_set_attribute(lua_State * L)
+{
+ halfword n;
+ int i, val;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null)
+ return 0;
+ if (lua_gettop(L) == 3) {
+ i = (int) lua_tointeger(L, 2);
+ val = (int) lua_tointeger(L, 3);
+ if (val == UNUSED_ATTRIBUTE) {
+ (void) unset_attribute(n, i, val);
+ } else {
+ set_attribute(n, i, val);
+ }
+ } else {
+ luaL_error(L, "incorrect number of arguments");
+ }
+ return 0;
+}
+
+/* node.unset_attribute */
static int lua_nodelib_unset_attribute(lua_State * L)
{
@@ -1223,6 +2383,30 @@ static int lua_nodelib_unset_attribute(lua_State * L)
}
}
+/* node.direct.unset_attribute */
+
+static int lua_nodelib_direct_unset_attribute(lua_State * L)
+{
+ halfword n;
+ int i, val, ret;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else if (lua_gettop(L) <= 3) { /* a useless test, we never test for that elsewhere */
+ i=(int)luaL_checknumber(L, 2);
+ val=(int)luaL_optnumber(L, 3, UNUSED_ATTRIBUTE);
+ ret = unset_attribute(n, i, val);
+ if (ret > UNUSED_ATTRIBUTE) {
+ lua_pushnumber(L, ret);
+ } else {
+ lua_pushnil(L);
+ }
+ } else { /* can go */
+ return luaL_error(L, "incorrect number of arguments");
+ }
+ return 1;
+}
+
/* iteration */
static int nodelib_aux_nil(lua_State * L)
@@ -1231,15 +2415,20 @@ static int nodelib_aux_nil(lua_State * L)
return 1;
}
+/* node.traverse_id */
+
static int nodelib_aux_next_filtered(lua_State * L)
{
- register halfword t; /* traverser */
- register int i = (int) lua_tointeger(L, lua_upvalueindex(1));
+ halfword t; /* traverser */
+ halfword *a;
+ int i = (int) lua_tointeger(L, lua_upvalueindex(1));
if (lua_isnil(L, 2)) { /* first call */
t = *check_isnode(L, 1);
+ lua_settop(L,1);
} else {
t = *check_isnode(L, 2);
t = vlink(t);
+ lua_settop(L,2);
}
while (t != null && type(t) != i) {
t = vlink(t);
@@ -1247,12 +2436,11 @@ static int nodelib_aux_next_filtered(lua_State * L)
if (t == null) {
lua_pushnil(L);
} else {
- lua_nodelib_push_fast(L, t);
+ fast_metatable_top(t);
}
return 1;
}
-
static int lua_nodelib_traverse_filtered(lua_State * L)
{
halfword n;
@@ -1268,19 +2456,67 @@ static int lua_nodelib_traverse_filtered(lua_State * L)
return 3;
}
+/* node.direct.traverse_id */
+
+static int nodelib_direct_aux_next_filtered(lua_State * L)
+{
+ halfword t; /* traverser */
+ int i = (int) lua_tointeger(L, lua_upvalueindex(1));
+ if (lua_isnil(L, 2)) { /* first call */
+ t = lua_tonumber(L,1) ;
+ lua_settop(L,1);
+ } else {
+ t = lua_tonumber(L,2) ;
+ t = vlink(t);
+ lua_settop(L,2);
+ }
+ while (t != null && type(t) != i) {
+ t = vlink(t);
+ }
+ if (t == null) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L,t);
+ }
+ return 1;
+}
+
+static int lua_nodelib_direct_traverse_filtered(lua_State * L)
+{
+ halfword n;
+ if (lua_isnil(L, 2)) {
+ lua_pushcclosure(L, nodelib_aux_nil, 0);
+ return 1;
+ }
+ n = (halfword) lua_tonumber(L, 2);
+ if (n == null)
+ return 0;
+ n = (halfword) lua_tonumber(L, 2);
+ lua_pop(L, 1);
+ lua_pushcclosure(L, nodelib_direct_aux_next_filtered, 1);
+ lua_pushnumber(L,n);
+ lua_pushnil(L);
+ return 3;
+}
+
+/* node.traverse */
+
static int nodelib_aux_next(lua_State * L)
{
- register halfword t; /* traverser */
+ halfword t; /* traverser */
+ halfword *a; /* a or *a */
if (lua_isnil(L, 2)) { /* first call */
t = *check_isnode(L, 1);
+ lua_settop(L,1);
} else {
t = *check_isnode(L, 2);
t = vlink(t);
+ lua_settop(L,2);
}
if (t == null) {
lua_pushnil(L);
} else {
- lua_nodelib_push_fast(L, t);
+ fast_metatable_top(t);
}
return 1;
}
@@ -1297,23 +2533,66 @@ static int lua_nodelib_traverse(lua_State * L)
lua_nodelib_push_fast(L, n);
lua_pushnil(L);
return 3;
- ;
}
+/* node.direct.traverse */
+
+static int nodelib_direct_aux_next(lua_State * L)
+{
+ halfword t; /* traverser */
+ /*int i = (int) lua_tointeger(L, lua_upvalueindex(1));*/
+ if (lua_isnil(L, 2)) { /* first call */
+ t = lua_tonumber(L,1) ;
+ lua_settop(L,1);
+ } else {
+ t = lua_tonumber(L,2) ;
+ t = vlink(t);
+ lua_settop(L,2);
+ }
+ if (t == null) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L,t);
+ }
+ return 1;
+}
+
+static int lua_nodelib_direct_traverse(lua_State * L)
+{
+ halfword n;
+ if (lua_isnil(L, 1)) {
+ lua_pushcclosure(L, nodelib_aux_nil, 0);
+ return 1;
+ }
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null) {
+ lua_pushcclosure(L, nodelib_aux_nil, 0);
+ return 1;
+ }
+ lua_pushcclosure(L, nodelib_direct_aux_next, 0);
+ lua_pushnumber(L,n);
+ lua_pushnil(L);
+ return 3;
+}
+
+
+/* counting */
+
static int do_lua_nodelib_count(lua_State * L, halfword match, int i, halfword first1)
{
int count = 0;
int t = first1;
while (t != match) {
- if (i < 0 || type(t) == i) {
+ if (i < 0 || type(t) == i)
count++;
- }
t = vlink(t);
}
lua_pushnumber(L, count);
return 1;
}
+/* node.length */
+
static int lua_nodelib_length(lua_State * L)
{
halfword n;
@@ -1323,12 +2602,26 @@ static int lua_nodelib_length(lua_State * L)
return 1;
}
n = *(check_isnode(L, 1));
- if (lua_gettop(L) == 2) {
+ if (lua_gettop(L) == 2)
m = *(check_isnode(L, 2));
+ return do_lua_nodelib_count(L, m, -1, n);
+}
+
+/* node.direct.length */
+
+static int lua_nodelib_direct_length(lua_State * L)
+{
+ halfword n, m;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == 0) {
+ lua_pushnumber(L, 0);
+ return 1;
}
+ m = (halfword) lua_tonumber(L, 2);
return do_lua_nodelib_count(L, m, -1, n);
}
+/* node.count */
static int lua_nodelib_count(lua_State * L)
{
@@ -1346,13 +2639,18 @@ static int lua_nodelib_count(lua_State * L)
return do_lua_nodelib_count(L, m, i, n);
}
-/* fetching a field from a node */
+/* node.direct.count */
-#define nodelib_pushlist(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); }
-#define nodelib_pushattr(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); }
-#define nodelib_pushspec(L,n) { lua_pushnumber(L,n); lua_nodelib_push_spec(L); }
-#define nodelib_pushaction(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); }
-#define nodelib_pushstring(L,n) { char *ss=makecstring(n); lua_pushstring(L,ss); free(ss); }
+static int lua_nodelib_direct_count(lua_State * L)
+{
+ return do_lua_nodelib_count(L,
+ (halfword) lua_tonumber(L, 3), /* m */
+ (int) lua_tointeger(L, 1), /* i */
+ (halfword) lua_tonumber(L, 2) /* n */
+ );
+}
+
+/* directions (could be a macro) */
static void nodelib_pushdir(lua_State * L, int n, boolean dirnode)
{
@@ -1363,9 +2661,65 @@ static void nodelib_pushdir(lua_State * L, int n, boolean dirnode)
}
}
+/* getting and setting fields (helpers) */
+
+static int nodelib_getlist(lua_State * L, int n)
+{
+ halfword *m;
+ if (lua_isuserdata(L, n)) {
+ m = check_isnode(L, n);
+ return *m;
+ } else {
+ return null;
+ }
+}
+
+int nodelib_getdir(lua_State * L, int n, int absolute_only)
+{
+ if (lua_type(L, n) == LUA_TSTRING) {
+ const char *s = lua_tostring(L, n);
+ RETURN_DIR_VALUES(TRT);
+ RETURN_DIR_VALUES(TLT);
+ RETURN_DIR_VALUES(LTL);
+ RETURN_DIR_VALUES(RTT);
+ luaL_error(L, "Bad direction specifier %s", s);
+ } else {
+ luaL_error(L, "Direction specifiers have to be strings");
+ }
+ return 0;
+}
+
+static str_number nodelib_getstring(lua_State * L, int a)
+{
+ size_t k;
+ const char *s = lua_tolstring(L, a, &k);
+ return maketexlstring(s, k);
+}
+
+static void nodelib_setattr(lua_State * L, int stackindex, halfword n)
+{
+ halfword p;
+ p = nodelib_getlist(L, stackindex);
+ if (node_attr(n) != p) {
+ if (node_attr(n) != null)
+ delete_attribute_ref(node_attr(n));
+ node_attr(n) = p;
+ if (p != null)
+ attr_list_ref(p)++;
+ }
+}
+
+static int nodelib_cantset(lua_State * L, int n, const char *s)
+{
+ luaL_error(L,"You cannot set field %s in a node of type %s",s,node_data[type(n)].name);
+ return 0;
+}
+
+/* node.direct.getfield */
+
static void lua_nodelib_getfield_whatsit(lua_State * L, int n, const char *s)
{
- register int t ;
+ int t ;
t = subtype(n);
if (t == dir_node) {
@@ -1388,12 +2742,14 @@ static void lua_nodelib_getfield_whatsit(lua_State * L, int n, const char *s)
} else if (luaS_ptr_eq(s, value)) {
switch (user_node_type(n)) {
case 'a':
+ /* fast_metatable(n) */
nodelib_pushlist(L, user_node_value(n));
break;
case 'd':
lua_pushnumber(L, user_node_value(n));
break;
case 'n':
+ /* fast_metatable(n) */
nodelib_pushlist(L, user_node_value(n));
break;
case 's':
@@ -1417,10 +2773,12 @@ static void lua_nodelib_getfield_whatsit(lua_State * L, int n, const char *s)
} else if (luaS_ptr_eq(s, dir)) {
nodelib_pushdir(L, local_par_dir(n), false);
} else if (luaS_ptr_eq(s, box_left)) {
+ /* can be: fast_metatable_or_nil(local_box_left(n)) */
nodelib_pushlist(L, local_box_left(n));
} else if (luaS_ptr_eq(s, box_left_width)) {
lua_pushnumber(L, local_box_left_width(n));
} else if (luaS_ptr_eq(s, box_right)) {
+ /* can be: fast_metatable_or_nil(local_box_right(n)) */
nodelib_pushlist(L, local_box_right(n));
} else if (luaS_ptr_eq(s, box_right_width)) {
lua_pushnumber(L, local_box_right_width(n));
@@ -1609,22 +2967,20 @@ static void lua_nodelib_getfield_whatsit(lua_State * L, int n, const char *s)
}
}
- /* experiment */
-
-
-static int lua_nodelib_getfield(lua_State * L)
+static int lua_nodelib_fast_getfield(lua_State * L)
{
/*
the order is somewhat determined by the occurance of nodes and
importance of fields
*/
- register halfword n;
- register const char *s;
- register int t ;
+ halfword n;
+ halfword *a;
+ const char *s;
+ int t ;
- n = *((halfword *) lua_touserdata(L, 1));
- t = type(n);
+ n = *((halfword *) lua_touserdata(L, 1));
+ t = type(n);
/*
@@ -1637,8 +2993,8 @@ static int lua_nodelib_getfield(lua_State * L)
if (lua_type(L, 2) == LUA_TNUMBER) {
- register halfword p;
- register int i;
+ halfword p;
+ int i;
if (! nodetype_has_attributes(t)) {
lua_pushnil(L);
@@ -1650,7 +3006,6 @@ static int lua_nodelib_getfield(lua_State * L)
lua_pushnil(L);
return 1;
}
-
i = (int) lua_tointeger(L, 2);
p = vlink(p);
while (p != null) {
@@ -1663,34 +3018,26 @@ static int lua_nodelib_getfield(lua_State * L)
}
p = vlink(p);
}
-
lua_pushnil(L);
return 1;
-
}
s = lua_tostring(L, 2);
if (luaS_ptr_eq(s, id)) {
lua_pushnumber(L, t);
- return 1;
} else if (luaS_ptr_eq(s, next)) {
- lua_pushnumber(L, vlink(n));
- lua_nodelib_push(L);
- return 1;
+ fast_metatable_or_nil(vlink(n));
} else if (luaS_ptr_eq(s, prev)) {
- lua_pushnumber(L, alink(n));
- lua_nodelib_push(L);
- return 1;
+ fast_metatable_or_nil(alink(n));
} else if (luaS_ptr_eq(s, attr)) {
- if (nodetype_has_attributes(t)) {
- nodelib_pushattr(L, node_attr(n));
- } else {
+ if (! nodetype_has_attributes(t)) {
lua_pushnil(L);
+ } else {
+ nodelib_pushattr(L, node_attr(n));
}
- return 1;
} else if (t == glyph_node) {
- /* candidates: fontchar (font,char) whd (width,height,depth) */
+ /* candidates: fontchar (font,char) whd (width,height,depth) */
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, font)) {
@@ -1710,7 +3057,7 @@ static int lua_nodelib_getfield(lua_State * L)
} else if (luaS_ptr_eq(s, expansion_factor)) {
lua_pushnumber(L, ex_glyph(n));
} else if (luaS_ptr_eq(s, components)) {
- nodelib_pushlist(L, lig_ptr(n));
+ fast_metatable_or_nil(lig_ptr(n));
} else if (luaS_ptr_eq(s, lang)) {
lua_pushnumber(L, char_lang(n));
} else if (luaS_ptr_eq(s, left)) {
@@ -1722,16 +3069,12 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if ((t == hlist_node) || (t == vlist_node)) {
- /* candidates: whd (width,height,depth) */
+ /* candidates: whd (width,height,depth) */
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, list) || luaS_ptr_eq(s, head)) {
- if (list_ptr(n)) {
- alink(list_ptr(n)) = null;
- }
- nodelib_pushlist(L, list_ptr(n));
+ fast_metatable_or_nil_alink(list_ptr(n));
} else if (luaS_ptr_eq(s, width)) {
lua_pushnumber(L, width(n));
} else if (luaS_ptr_eq(s, height)) {
@@ -1751,31 +3094,28 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == disc_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, pre)) {
- nodelib_pushlist(L, vlink(pre_break(n)));
+ fast_metatable_or_nil(vlink(pre_break(n)));
} else if (luaS_ptr_eq(s, post)) {
- nodelib_pushlist(L, vlink(post_break(n)));
+ fast_metatable_or_nil(vlink(post_break(n)));
} else if (luaS_ptr_eq(s, replace)) {
- nodelib_pushlist(L, vlink(no_break(n)));
+ fast_metatable_or_nil(vlink(no_break(n)));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == glue_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, spec)) {
nodelib_pushspec(L, glue_ptr(n));
} else if (luaS_ptr_eq(s, leader)) {
- nodelib_pushlist(L, leader_ptr(n));
+ fast_metatable_or_nil(leader_ptr(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == glue_spec_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, 0); /* dummy, the only one that prevents move up */
@@ -1796,7 +3136,6 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == kern_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -1807,7 +3146,6 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == penalty_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -1816,7 +3154,6 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == rule_node) {
/* candidates: whd (width,height,depth) */
if (luaS_ptr_eq(s, subtype)) {
@@ -1832,27 +3169,24 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == whatsit_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else {
- lua_nodelib_getfield_whatsit(L, n, s);
+ lua_nodelib_getfield_whatsit(L, n, s);
}
- return 1;
} else if (t == simple_noad) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, nucleus)) {
- nodelib_pushlist(L, nucleus(n));
+ fast_metatable_or_nil(nucleus(n));
} else if (luaS_ptr_eq(s, sub)) {
- nodelib_pushlist(L, subscr(n));
+ fast_metatable_or_nil(subscr(n));
} else if (luaS_ptr_eq(s, sup)) {
- nodelib_pushlist(L, supscr(n));
+ fast_metatable_or_nil(supscr(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if ((t == math_char_node) || (t == math_text_char_node)) {
/* candidates: famchar (fam,char) */
if (luaS_ptr_eq(s, subtype)) {
@@ -1864,7 +3198,6 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == mark_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -1875,7 +3208,6 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == ins_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -1888,14 +3220,10 @@ static int lua_nodelib_getfield(lua_State * L)
} else if (luaS_ptr_eq(s, spec)) {
nodelib_pushspec(L, split_top_ptr(n));
} else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))) {
- if (ins_ptr(n)) {
- alink(ins_ptr(n)) = null;
- }
- nodelib_pushlist(L, ins_ptr(n));
+ fast_metatable_or_nil_alink(ins_ptr(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == math_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -1904,24 +3232,22 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == fraction_noad) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, width)) {
lua_pushnumber(L, thickness(n));
} else if (luaS_ptr_eq(s, num)) {
- nodelib_pushlist(L, numerator(n));
+ fast_metatable_or_nil(numerator(n));
} else if (luaS_ptr_eq(s, denom)) {
- nodelib_pushlist(L, denominator(n));
+ fast_metatable_or_nil(denominator(n));
} else if (luaS_ptr_eq(s, left)) {
- nodelib_pushlist(L, left_delimiter(n));
+ fast_metatable_or_nil(left_delimiter(n));
} else if (luaS_ptr_eq(s, right)) {
- nodelib_pushlist(L, right_delimiter(n));
+ fast_metatable_or_nil(right_delimiter(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == style_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -1930,33 +3256,30 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == accent_noad) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, nucleus)) {
- nodelib_pushlist(L, nucleus(n));
+ fast_metatable_or_nil(nucleus(n));
} else if (luaS_ptr_eq(s, sub)) {
- nodelib_pushlist(L, subscr(n));
+ fast_metatable_or_nil(subscr(n));
} else if (luaS_ptr_eq(s, sup)) {
- nodelib_pushlist(L, supscr(n));
+ fast_metatable_or_nil(supscr(n));
} else if (luaS_ptr_eq(s, accent)) {
- nodelib_pushlist(L, accent_chr(n));
+ fast_metatable_or_nil(accent_chr(n));
} else if (luaS_ptr_eq(s, bot_accent)) {
- nodelib_pushlist(L, bot_accent_chr(n));
+ fast_metatable_or_nil(bot_accent_chr(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == fence_noad) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, delim)) {
- nodelib_pushlist(L, delimiter(n));
+ fast_metatable_or_nil(delimiter(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == delim_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -1971,88 +3294,78 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if ((t == sub_box_node) || (t == sub_mlist_node)) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))){
- if (math_list(n)) {
- alink(math_list(n)) = null;
- }
- nodelib_pushlist(L, math_list(n));
+ fast_metatable_or_nil_alink(math_list(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == radical_noad) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, nucleus)) {
- nodelib_pushlist(L, nucleus(n));
+ fast_metatable_or_nil(nucleus(n));
} else if (luaS_ptr_eq(s, sub)) {
- nodelib_pushlist(L, subscr(n));
+ fast_metatable_or_nil(subscr(n));
} else if (luaS_ptr_eq(s, sup)) {
- nodelib_pushlist(L, supscr(n));
+ fast_metatable_or_nil(supscr(n));
} else if (luaS_ptr_eq(s, left)) {
- nodelib_pushlist(L, left_delimiter(n));
+ fast_metatable_or_nil(left_delimiter(n));
} else if (luaS_ptr_eq(s, degree)) {
- nodelib_pushlist(L, degree(n));
+ fast_metatable_or_nil(degree(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == margin_kern_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, width)) {
lua_pushnumber(L, width(n));
} else if (luaS_ptr_eq(s, glyph)) {
- nodelib_pushlist(L, margin_char(n));
+ fast_metatable_or_nil(margin_char(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == split_up_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, last_ins_ptr)) {
- nodelib_pushlist(L, last_ins_ptr(n));
+ fast_metatable_or_nil(last_ins_ptr(n));
} else if (luaS_ptr_eq(s, best_ins_ptr)) {
- nodelib_pushlist(L, best_ins_ptr(n));
+ fast_metatable_or_nil(best_ins_ptr(n));
} else if (luaS_ptr_eq(s, broken_ptr)) {
- nodelib_pushlist(L, broken_ptr(n));
+ fast_metatable_or_nil(broken_ptr(n));
} else if (luaS_ptr_eq(s, broken_ins)) {
- nodelib_pushlist(L, broken_ins(n));
+ fast_metatable_or_nil(broken_ins(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == choice_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, display)) {
- nodelib_pushlist(L, display_mlist(n));
+ fast_metatable_or_nil(display_mlist(n));
} else if (luaS_ptr_eq(s, text)) {
- nodelib_pushlist(L, text_mlist(n));
+ fast_metatable_or_nil(text_mlist(n));
} else if (luaS_ptr_eq(s, script)) {
- nodelib_pushlist(L, script_mlist(n));
+ fast_metatable_or_nil(script_mlist(n));
} else if (luaS_ptr_eq(s, scriptscript)) {
- nodelib_pushlist(L, script_script_mlist(n));
+ fast_metatable_or_nil(script_script_mlist(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == inserting_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if (luaS_ptr_eq(s, last_ins_ptr)) {
- nodelib_pushlist(L, last_ins_ptr(n));
+ fast_metatable_or_nil(last_ins_ptr(n));
} else if (luaS_ptr_eq(s, best_ins_ptr)) {
- nodelib_pushlist(L, best_ins_ptr(n));
+ fast_metatable_or_nil(best_ins_ptr(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == attribute_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -2063,19 +3376,14 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == adjust_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))) {
- if (adjust_ptr(n)) {
- alink(adjust_ptr(n)) = null;
- }
- nodelib_pushlist(L, adjust_ptr(n));
+ fast_metatable_or_nil_alink(adjust_ptr(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == action_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));/* dummy subtype */
@@ -2100,7 +3408,6 @@ static int lua_nodelib_getfield(lua_State * L)
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == unset_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
@@ -2123,104 +3430,1197 @@ static int lua_nodelib_getfield(lua_State * L)
} else if (luaS_ptr_eq(s, count)) {
lua_pushnumber(L, span_count(n));
} else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))){
- if (list_ptr(n)) {
- alink(list_ptr(n)) = null;
- }
- nodelib_pushlist(L, list_ptr(n));
+ fast_metatable_or_nil_alink(list_ptr(n));
} else {
lua_pushnil(L);
}
- return 1;
} else if (t == attribute_list_node) {
if (luaS_ptr_eq(s, subtype)) {
lua_pushnumber(L, subtype(n));
} else {
lua_pushnil(L);
}
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int lua_nodelib_getfield(lua_State * L)
+{
+ /* [given-node] [...]*/
+ halfword *p = lua_touserdata(L, 1);
+ if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+ lua_pushnil(L) ;
+ return 1;
+ }
+ /* [given-node] [mt-given-node]*/
+ lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ /* [given-node] [mt-given-node] [mt-node]*/
+ if (!lua_rawequal(L, -1, -2)) {
+ lua_pushnil(L) ;
return 1;
+ }
+ /* prune stack and call getfield */
+ lua_settop(L,2);
+ return lua_nodelib_fast_getfield(L);
+}
+
+/* node.direct.getfield */
+
+static void lua_nodelib_direct_getfield_whatsit(lua_State * L, int n, const char *s)
+{
+ int t ;
+ t = subtype(n);
+
+ if (t == dir_node) {
+ if (luaS_ptr_eq(s, dir)) {
+ nodelib_pushdir(L, dir_dir(n), true);
+ } else if (luaS_ptr_eq(s, level)) {
+ lua_pushnumber(L, dir_level(n));
+ } else if (luaS_ptr_eq(s, dvi_ptr)) {
+ lua_pushnumber(L, dir_dvi_ptr(n));
+ } else if (luaS_ptr_eq(s, dir_h)) {
+ lua_pushnumber(L, dir_dvi_h(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == user_defined_node) {
+ if (luaS_ptr_eq(s, user_id)) {
+ lua_pushnumber(L, user_node_id(n));
+ } else if (luaS_ptr_eq(s, type)) {
+ lua_pushnumber(L, user_node_type(n));
+ } else if (luaS_ptr_eq(s, value)) {
+ switch (user_node_type(n)) {
+ case 'a':
+ nodelib_pushdirect(user_node_value(n));
+ break;
+ case 'd':
+ lua_pushnumber(L, user_node_value(n));
+ break;
+ case 'n':
+ nodelib_pushdirect(user_node_value(n));
+ break;
+ case 's':
+ nodelib_pushstring(L, user_node_value(n));
+ break;
+ case 't':
+ tokenlist_to_lua(L, user_node_value(n));
+ break;
+ default:
+ lua_pushnumber(L, user_node_value(n));
+ break;
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == local_par_node) {
+ if (luaS_ptr_eq(s, pen_inter)) {
+ lua_pushnumber(L, local_pen_inter(n));
+ } else if (luaS_ptr_eq(s, pen_broken)) {
+ lua_pushnumber(L, local_pen_broken(n));
+ } else if (luaS_ptr_eq(s, dir)) {
+ nodelib_pushdir(L, local_par_dir(n), false);
+ } else if (luaS_ptr_eq(s, box_left)) {
+ nodelib_pushdirect_or_nil(local_box_left(n));
+ } else if (luaS_ptr_eq(s, box_left_width)) {
+ lua_pushnumber(L, local_box_left_width(n));
+ } else if (luaS_ptr_eq(s, box_right)) {
+ nodelib_pushdirect_or_nil(local_box_right(n));
+ } else if (luaS_ptr_eq(s, box_right_width)) {
+ lua_pushnumber(L, local_box_right_width(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_literal_node) {
+ if (luaS_ptr_eq(s, mode)) {
+ lua_pushnumber(L, pdf_literal_mode(n));
+ } else if (luaS_ptr_eq(s, data)) {
+ if (pdf_literal_type(n) == lua_refid_literal) {
+ lua_rawgeti(Luas, LUA_REGISTRYINDEX, pdf_literal_data(n));
+ } else {
+ tokenlist_to_luastring(L, pdf_literal_data(n));
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == late_lua_node) {
+ if (luaS_ptr_eq(s, name)) {
+ tokenlist_to_luastring(L, late_lua_name(n));
+ } else if (luaS_ptr_eq(s, data) || luaS_ptr_eq(s, string)) {
+ if (late_lua_type(n) == lua_refid_literal) {
+ lua_rawgeti(Luas, LUA_REGISTRYINDEX, late_lua_data(n));
+ } else {
+ tokenlist_to_luastring(L, late_lua_data(n));
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_annot_node) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, objnum)) {
+ lua_pushnumber(L, pdf_annot_objnum(n));
+ } else if (luaS_ptr_eq(s, data)) {
+ tokenlist_to_luastring(L, pdf_annot_data(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_dest_node) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, named_id)) {
+ lua_pushnumber(L, pdf_dest_named_id(n));
+ } else if (luaS_ptr_eq(s, dest_id)) {
+ if (pdf_dest_named_id(n) == 1)
+ tokenlist_to_luastring(L, pdf_dest_id(n));
+ else
+ lua_pushnumber(L, pdf_dest_id(n));
+ } else if (luaS_ptr_eq(s, dest_type)) {
+ lua_pushnumber(L, pdf_dest_type(n));
+ } else if (luaS_ptr_eq(s, xyz_zoom)) {
+ lua_pushnumber(L, pdf_dest_xyz_zoom(n));
+ } else if (luaS_ptr_eq(s, objnum)) {
+ lua_pushnumber(L, pdf_dest_objnum(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_setmatrix_node) {
+ if (luaS_ptr_eq(s, data)) {
+ tokenlist_to_luastring(L, pdf_setmatrix_data(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_colorstack_node) {
+ if (luaS_ptr_eq(s, stack)) {
+ lua_pushnumber(L, pdf_colorstack_stack(n));
+ } else if (luaS_ptr_eq(s, command)) {
+ lua_pushnumber(L, pdf_colorstack_cmd(n));
+ } else if (luaS_ptr_eq(s, data)) {
+ tokenlist_to_luastring(L, pdf_colorstack_data(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_refobj_node) {
+ if (luaS_ptr_eq(s, objnum)) {
+ lua_pushnumber(L, pdf_obj_objnum(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_refxform_node) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, objnum)) {
+ lua_pushnumber(L, pdf_xform_objnum(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_refximage_node) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, transform)) {
+ lua_pushnumber(L, pdf_ximage_transform(n));
+ } else if (luaS_ptr_eq(s, index)) {
+ lua_pushnumber(L, pdf_ximage_index(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == write_node) {
+ if (luaS_ptr_eq(s, stream)) {
+ lua_pushnumber(L, write_stream(n));
+ } else if (luaS_ptr_eq(s, data)) {
+ tokenlist_to_lua(L, write_tokens(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == special_node) {
+ if (luaS_ptr_eq(s, data)) {
+ tokenlist_to_luastring(L, write_tokens(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == pdf_start_link_node) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, objnum)) {
+ lua_pushnumber(L, pdf_link_objnum(n));
+ } else if (luaS_ptr_eq(s, link_attr)) {
+ tokenlist_to_luastring(L, pdf_link_attr(n));
+ } else if (luaS_ptr_eq(s, action)) {
+ nodelib_pushaction(L, pdf_link_action(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if ((t == pdf_thread_node) || (t == pdf_start_thread_node)) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, named_id)) {
+ lua_pushnumber(L, pdf_thread_named_id(n));
+ } else if (luaS_ptr_eq(s, thread_id)) {
+ if (pdf_thread_named_id(n) == 1) {
+ tokenlist_to_luastring(L, pdf_thread_id(n));
+ } else {
+ lua_pushnumber(L, pdf_thread_id(n));
+ }
+ } else if (luaS_ptr_eq(s, thread_attr)) {
+ tokenlist_to_luastring(L, pdf_thread_attr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == open_node) {
+ if (luaS_ptr_eq(s, stream)) {
+ lua_pushnumber(L, write_stream(n));
+ } else if (luaS_ptr_eq(s, name)) {
+ nodelib_pushstring(L, open_name(n));
+ } else if (luaS_ptr_eq(s, area)) {
+ nodelib_pushstring(L, open_area(n));
+ } else if (luaS_ptr_eq(s, ext)) {
+ nodelib_pushstring(L, open_ext(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == close_node) {
+ if (luaS_ptr_eq(s, stream)) {
+ lua_pushnumber(L, write_stream(n));
+ } else {
+ lua_pushnil(L);
+ }
} else {
- return 0;
+ lua_pushnil(L);
}
}
-static int nodelib_getlist(lua_State * L, int n)
+static int lua_nodelib_direct_getfield(lua_State * L)
{
- halfword *m;
- if (lua_isuserdata(L, n)) {
- m = check_isnode(L, n);
- return *m;
+
+ halfword n;
+ const char *s;
+ int t ;
+
+ n = (halfword) lua_tonumber(L, 1);
+
+ t = type(n);
+
+ if (lua_type(L, 2) == LUA_TNUMBER) {
+
+ halfword p;
+ int i;
+
+ if (! nodetype_has_attributes(t)) {
+ lua_pushnil(L) ;
+ return 1;
+ }
+
+ p = node_attr(n);
+ if (p == null || vlink(p) == null) {
+ lua_pushnil(L) ;
+ return 1;
+ }
+ i = (int) lua_tointeger(L, 2);
+ p = vlink(p);
+ while (p != null) {
+ if (attribute_id(p) == i) {
+ lua_pushnumber(L, (int) attribute_value(p));
+ return 1;
+ } else if (attribute_id(p) > i) {
+ lua_pushnil(L) ;
+ return 1;
+ }
+ p = vlink(p);
+ }
+ lua_pushnil(L) ;
+ return 1;
+ }
+
+ s = lua_tostring(L, 2);
+
+ if (luaS_ptr_eq(s, id)) {
+ lua_pushnumber(L, t);
+ } else if (luaS_ptr_eq(s, next)) {
+ nodelib_pushdirect_or_nil(vlink(n));
+ } else if (luaS_ptr_eq(s, prev)) {
+ nodelib_pushdirect_or_nil(alink(n));
+ } else if (luaS_ptr_eq(s, attr)) {
+ if (! nodetype_has_attributes(t)) {
+ lua_pushnil(L);
+ } else {
+ nodelib_pushattr(L, node_attr(n));
+ }
+ } else if (luaS_ptr_eq(s, subtype)) {
+ if (t == glue_spec_node) {
+ lua_pushnumber(L, 0); /* dummy, the only one */
+ } else {
+ lua_pushnumber(L, subtype(n));
+ }
+ } else if (t == glyph_node) {
+ if (luaS_ptr_eq(s, font)) {
+ lua_pushnumber(L, font(n));
+ } else if (luaS_ptr_eq(s, char)) {
+ lua_pushnumber(L, character(n));
+ } else if (luaS_ptr_eq(s, xoffset)) {
+ lua_pushnumber(L, x_displace(n));
+ } else if (luaS_ptr_eq(s, yoffset)) {
+ lua_pushnumber(L, y_displace(n));
+ } else if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, char_width(font(n),character(n)));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, char_height(font(n),character(n)));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, char_depth(font(n),character(n)));
+ } else if (luaS_ptr_eq(s, expansion_factor)) {
+ lua_pushnumber(L, ex_glyph(n));
+ } else if (luaS_ptr_eq(s, components)) {
+ nodelib_pushdirect_or_nil(lig_ptr(n));
+ } else if (luaS_ptr_eq(s, lang)) {
+ lua_pushnumber(L, char_lang(n));
+ } else if (luaS_ptr_eq(s, left)) {
+ lua_pushnumber(L, char_lhmin(n));
+ } else if (luaS_ptr_eq(s, right)) {
+ lua_pushnumber(L, char_rhmin(n));
+ } else if (luaS_ptr_eq(s, uchyph)) {
+ lua_pushnumber(L, char_uchyph(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if ((t == hlist_node) || (t == vlist_node)) {
+ /* candidates: whd (width,height,depth) */
+ if (luaS_ptr_eq(s, list) || luaS_ptr_eq(s, head)) {
+ nodelib_pushdirect_or_nil_alink(list_ptr(n));
+ } else if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, dir)) {
+ nodelib_pushdir(L, box_dir(n), false);
+ } else if (luaS_ptr_eq(s, shift)) {
+ lua_pushnumber(L, shift_amount(n));
+ } else if (luaS_ptr_eq(s, glue_order)) {
+ lua_pushnumber(L, glue_order(n));
+ } else if (luaS_ptr_eq(s, glue_sign)) {
+ lua_pushnumber(L, glue_sign(n));
+ } else if (luaS_ptr_eq(s, glue_set)) {
+ lua_pushnumber(L, (double) glue_set(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == disc_node) {
+ if (luaS_ptr_eq(s, pre)) {
+ nodelib_pushdirect_or_nil(vlink(pre_break(n)));
+ } else if (luaS_ptr_eq(s, post)) {
+ nodelib_pushdirect_or_nil(vlink(post_break(n)));
+ } else if (luaS_ptr_eq(s, replace)) {
+ nodelib_pushdirect_or_nil(vlink(no_break(n)));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == glue_node) {
+ if (luaS_ptr_eq(s, spec)) {
+ nodelib_pushdirect(glue_ptr(n));
+ } else if (luaS_ptr_eq(s, leader)) {
+ nodelib_pushdirect_or_nil(leader_ptr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == glue_spec_node) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, stretch)) {
+ lua_pushnumber(L, stretch(n));
+ } else if (luaS_ptr_eq(s, shrink)) {
+ lua_pushnumber(L, shrink(n));
+ } else if (luaS_ptr_eq(s, stretch_order)) {
+ lua_pushnumber(L, stretch_order(n));
+ } else if (luaS_ptr_eq(s, shrink_order)) {
+ lua_pushnumber(L, shrink_order(n));
+ } else if (luaS_ptr_eq(s, ref_count)) {
+ lua_pushnumber(L, glue_ref_count(n));
+ } else if (luaS_ptr_eq(s, writable)) {
+ lua_pushboolean(L, valid_node(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == kern_node) {
+ if (luaS_ptr_eq(s, kern)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, expansion_factor)) {
+ lua_pushnumber(L, ex_kern(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == penalty_node) {
+ if (luaS_ptr_eq(s, penalty)) {
+ lua_pushnumber(L, penalty(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == rule_node) {
+ /* candidates: whd (width,height,depth) */
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, dir)) {
+ nodelib_pushdir(L, rule_dir(n), false);
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == whatsit_node) {
+ lua_nodelib_direct_getfield_whatsit(L, n, s);
+ } else if (t == simple_noad) {
+ if (luaS_ptr_eq(s, nucleus)) {
+ nodelib_pushdirect_or_nil(nucleus(n));
+ } else if (luaS_ptr_eq(s, sub)) {
+ nodelib_pushdirect_or_nil(subscr(n));
+ } else if (luaS_ptr_eq(s, sup)) {
+ nodelib_pushdirect_or_nil(supscr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if ((t == math_char_node) || (t == math_text_char_node)) {
+ if (luaS_ptr_eq(s, fam)) {
+ lua_pushnumber(L, math_fam(n));
+ } else if (luaS_ptr_eq(s, char)) {
+ lua_pushnumber(L, math_character(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == mark_node) {
+ if (luaS_ptr_eq(s, class)) {
+ lua_pushnumber(L, mark_class(n));
+ } else if (luaS_ptr_eq(s, mark)) {
+ tokenlist_to_lua(L, mark_ptr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == ins_node) {
+ if (luaS_ptr_eq(s, cost)) {
+ lua_pushnumber(L, float_cost(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, spec)) {
+ nodelib_pushdirect_or_nil(split_top_ptr(n));
+ } else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))) {
+ nodelib_pushdirect_or_nil_alink(ins_ptr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == math_node) {
+ if (luaS_ptr_eq(s, surround)) {
+ lua_pushnumber(L, surround(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == fraction_noad) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, thickness(n));
+ } else if (luaS_ptr_eq(s, num)) {
+ nodelib_pushdirect_or_nil(numerator(n));
+ } else if (luaS_ptr_eq(s, denom)) {
+ nodelib_pushdirect_or_nil(denominator(n));
+ } else if (luaS_ptr_eq(s, left)) {
+ nodelib_pushdirect_or_nil(left_delimiter(n));
+ } else if (luaS_ptr_eq(s, right)) {
+ nodelib_pushdirect_or_nil(right_delimiter(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == style_node) {
+ if (luaS_ptr_eq(s, style)) {
+ lua_pushstring(L, math_style_names[subtype(n)]);
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == accent_noad) {
+ if (luaS_ptr_eq(s, nucleus)) {
+ nodelib_pushdirect_or_nil(nucleus(n));
+ } else if (luaS_ptr_eq(s, sub)) {
+ nodelib_pushdirect_or_nil(subscr(n));
+ } else if (luaS_ptr_eq(s, sup)) {
+ nodelib_pushdirect_or_nil(supscr(n));
+ } else if (luaS_ptr_eq(s, accent)) {
+ nodelib_pushdirect_or_nil(accent_chr(n));
+ } else if (luaS_ptr_eq(s, bot_accent)) {
+ nodelib_pushdirect_or_nil(bot_accent_chr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == fence_noad) {
+ if (luaS_ptr_eq(s, delim)) {
+ nodelib_pushdirect_or_nil(delimiter(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == delim_node) {
+ if (luaS_ptr_eq(s, small_fam)) {
+ lua_pushnumber(L, small_fam(n));
+ } else if (luaS_ptr_eq(s, small_char)) {
+ lua_pushnumber(L, small_char(n));
+ } else if (luaS_ptr_eq(s, large_fam)) {
+ lua_pushnumber(L, large_fam(n));
+ } else if (luaS_ptr_eq(s, large_char)) {
+ lua_pushnumber(L, large_char(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if ((t == sub_box_node) || (t == sub_mlist_node)) {
+ if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))){
+ nodelib_pushdirect_or_nil_alink(math_list(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == radical_noad) {
+ if (luaS_ptr_eq(s, nucleus)) {
+ nodelib_pushdirect_or_nil(nucleus(n));
+ } else if (luaS_ptr_eq(s, sub)) {
+ nodelib_pushdirect_or_nil(subscr(n));
+ } else if (luaS_ptr_eq(s, sup)) {
+ nodelib_pushdirect_or_nil(supscr(n));
+ } else if (luaS_ptr_eq(s, left)) {
+ nodelib_pushdirect_or_nil(left_delimiter(n));
+ } else if (luaS_ptr_eq(s, degree)) {
+ nodelib_pushdirect_or_nil(degree(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == margin_kern_node) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, glyph)) {
+ nodelib_pushdirect_or_nil(margin_char(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == split_up_node) {
+ if (luaS_ptr_eq(s, last_ins_ptr)) {
+ nodelib_pushdirect_or_nil(last_ins_ptr(n));
+ } else if (luaS_ptr_eq(s, best_ins_ptr)) {
+ nodelib_pushdirect_or_nil(best_ins_ptr(n));
+ } else if (luaS_ptr_eq(s, broken_ptr)) {
+ nodelib_pushdirect_or_nil(broken_ptr(n));
+ } else if (luaS_ptr_eq(s, broken_ins)) {
+ nodelib_pushdirect_or_nil(broken_ins(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == choice_node) {
+ if (luaS_ptr_eq(s, display)) {
+ nodelib_pushdirect_or_nil(display_mlist(n));
+ } else if (luaS_ptr_eq(s, text)) {
+ nodelib_pushdirect_or_nil(text_mlist(n));
+ } else if (luaS_ptr_eq(s, script)) {
+ nodelib_pushdirect_or_nil(script_mlist(n));
+ } else if (luaS_ptr_eq(s, scriptscript)) {
+ nodelib_pushdirect_or_nil(script_script_mlist(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == inserting_node) {
+ if (luaS_ptr_eq(s, last_ins_ptr)) {
+ nodelib_pushdirect_or_nil(last_ins_ptr(n));
+ } else if (luaS_ptr_eq(s, best_ins_ptr)) {
+ nodelib_pushdirect_or_nil(best_ins_ptr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == attribute_node) {
+ if (luaS_ptr_eq(s, number)) {
+ lua_pushnumber(L, attribute_id(n));
+ } else if (luaS_ptr_eq(s, value)) {
+ lua_pushnumber(L, attribute_value(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == adjust_node) {
+ if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))) {
+ nodelib_pushdirect_or_nil_alink(adjust_ptr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == action_node) {
+ if (luaS_ptr_eq(s, action_type)) {
+ lua_pushnumber(L, pdf_action_type(n));
+ } else if (luaS_ptr_eq(s, named_id)) {
+ lua_pushnumber(L, pdf_action_named_id(n));
+ } else if (luaS_ptr_eq(s, action_id)) {
+ if (pdf_action_named_id(n) == 1) {
+ tokenlist_to_luastring(L, pdf_action_id(n));
+ } else {
+ lua_pushnumber(L, pdf_action_id(n));
+ }
+ } else if (luaS_ptr_eq(s, file)) {
+ tokenlist_to_luastring(L, pdf_action_file(n));
+ } else if (luaS_ptr_eq(s, new_window)) {
+ lua_pushnumber(L, pdf_action_new_window(n));
+ } else if (luaS_ptr_eq(s, data)) {
+ tokenlist_to_luastring(L, pdf_action_tokens(n));
+ } else if (luaS_ptr_eq(s, ref_count)) {
+ lua_pushnumber(L, pdf_action_refcount(n));
+ } else {
+ lua_pushnil(L);
+ }
+ } else if (t == unset_node) {
+ if (luaS_ptr_eq(s, width)) {
+ lua_pushnumber(L, width(n));
+ } else if (luaS_ptr_eq(s, height)) {
+ lua_pushnumber(L, height(n));
+ } else if (luaS_ptr_eq(s, depth)) {
+ lua_pushnumber(L, depth(n));
+ } else if (luaS_ptr_eq(s, dir)) {
+ nodelib_pushdir(L, box_dir(n), false);
+ } else if (luaS_ptr_eq(s, shrink)) {
+ lua_pushnumber(L, glue_shrink(n));
+ } else if (luaS_ptr_eq(s, glue_order)) {
+ lua_pushnumber(L, glue_order(n));
+ } else if (luaS_ptr_eq(s, glue_sign)) {
+ lua_pushnumber(L, glue_sign(n));
+ } else if (luaS_ptr_eq(s, stretch)) {
+ lua_pushnumber(L, glue_stretch(n));
+ } else if (luaS_ptr_eq(s, count)) {
+ lua_pushnumber(L, span_count(n));
+ } else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))){
+ nodelib_pushdirect_or_nil_alink(list_ptr(n));
+ } else {
+ lua_pushnil(L);
+ }
+ /* } else if (t == attribute_list_node) { */
+ /* lua_pushnil(L); */
} else {
- return null;
+ lua_pushnil(L);
}
+ return 1;
}
-/* a quick helper because I am too lazy to type this out: */
+/* msg could be preallocated and shared */
+
+static void lua_nodelib_do_tostring(lua_State * L, halfword n, const char *tag)
+{
+ char *msg;
+ char a[7] = { ' ', ' ', ' ', 'n', 'i', 'l', 0 };
+ char v[7] = { ' ', ' ', ' ', 'n', 'i', 'l', 0 };
+ msg = xmalloc(256);
+ if (alink(n) != null)
+ snprintf(a, 7, "%6d", (int) alink(n));
+ if (vlink(n) != null)
+ snprintf(v, 7, "%6d", (int) vlink(n));
+ snprintf(msg, 255, "<%s %s < %6d > %s : %s %d>", tag, a, (int) n, v, node_data[type(n)].name, subtype(n));
+ lua_pushstring(L, msg);
+ free(msg);
+ return ;
+}
+
+/* __tostring node.tostring */
+
+static int lua_nodelib_tostring(lua_State * L)
+{
+ halfword *n;
+ n = check_isnode(L, 1);
+ lua_nodelib_do_tostring(L, *n, "node");
+ return 1;
+}
-#define RETURN_DIR_VALUES(a) \
- if (s==luaS_##a##_ptr) { \
- return (dir_##a); \
- } else if (!absolute_only) { \
- if (s==luaS_p##a##_ptr) \
- return (dir_##a); \
- else if (s==luaS_m##a##_ptr) \
- return ((dir_##a)-64); \
+/* node.direct.tostring */
+
+static int lua_nodelib_direct_tostring(lua_State * L)
+{
+ halfword n = (halfword) lua_tonumber(L,1);
+ if (n==0) {
+ lua_pushnil(L);
+ } else {
+ lua_nodelib_do_tostring(L, n, "direct");
}
+ return 1;
+}
+/* __eq */
-int nodelib_getdir(lua_State * L, int n, int absolute_only)
+static int lua_nodelib_equal(lua_State * L)
{
- if (lua_type(L, n) == LUA_TSTRING) {
- const char *s = lua_tostring(L, n);
- RETURN_DIR_VALUES(TRT);
- RETURN_DIR_VALUES(TLT);
- RETURN_DIR_VALUES(LTL);
- RETURN_DIR_VALUES(RTT);
- /* still here? that's an error */
- luaL_error(L, "Bad direction specifier %s", s);
+ halfword n, m;
+ n = *((halfword *) lua_touserdata(L, 1));
+ m = *((halfword *) lua_touserdata(L, 2));
+ lua_pushboolean(L, (n == m));
+ return 1;
+}
+
+/* node.ligaturing */
+
+static int font_tex_ligaturing(lua_State * L)
+{
+ /* on the stack are two nodes and a direction */
+ halfword tmp_head;
+ halfword *h;
+ halfword t = null;
+ if (lua_gettop(L) < 1) {
+ lua_pushnil(L);
+ lua_pushboolean(L, 0);
+ return 2;
+ }
+ h = check_isnode(L, 1);
+ if (lua_gettop(L) > 1) {
+ t = *(check_isnode(L, 2));
+ }
+ tmp_head = new_node(nesting_node, 1);
+ couple_nodes(tmp_head, *h);
+ tlink(tmp_head) = t;
+ t = handle_ligaturing(tmp_head, t);
+ lua_pushnumber(L, vlink(tmp_head));
+ /* can be: lua_nodelib_push_fast(L, head); */
+ flush_node(tmp_head);
+ lua_nodelib_push(L);
+ /* can be: lua_nodelib_push_fast(L, t); */
+ lua_pushnumber(L, t);
+ lua_nodelib_push(L);
+ lua_pushboolean(L, 1);
+ return 3;
+}
+
+/* node.kerning */
+
+static int font_tex_kerning(lua_State * L)
+{
+ /* on the stack are two nodes and a direction */
+
+ halfword tmp_head;
+ halfword *h;
+ halfword t = null;
+ if (lua_gettop(L) < 1) {
+ lua_pushnil(L);
+ lua_pushboolean(L, 0);
+ return 2;
+ }
+ h = check_isnode(L, 1);
+ if (lua_gettop(L) > 1) {
+ t = *(check_isnode(L, 2));
+ }
+ tmp_head = new_node(nesting_node, 1);
+ couple_nodes(tmp_head, *h);
+ tlink(tmp_head) = t;
+ t = handle_kerning(tmp_head, t);
+ lua_pushnumber(L, vlink(tmp_head));
+ /* can be: lua_nodelib_push_fast(L, head); */
+ flush_node(tmp_head);
+ lua_nodelib_push(L);
+ /* can be: lua_nodelib_push_fast(L, t); */
+ lua_pushnumber(L, t);
+ lua_nodelib_push(L);
+ lua_pushboolean(L, 1);
+ return 3;
+}
+
+/* node.protect_glyphs (returns also boolean because that signals callback) */
+
+static int lua_nodelib_protect_glyphs(lua_State * L)
+{
+ int t = 0;
+ halfword head = *(check_isnode(L, 1));
+ while (head != null) {
+ if (type(head) == glyph_node) {
+ int s = subtype(head);
+ if (s <= 256) {
+ t = 1;
+ subtype(head) = (quarterword) (s == 1 ? 256 : 256 + s);
+ }
+ }
+ head = vlink(head);
+ }
+ lua_pushboolean(L, t);
+ lua_pushvalue(L, 1);
+ return 2;
+}
+
+/* node.direct.protect_glyphs */
+
+static int lua_nodelib_direct_protect_glyphs(lua_State * L)
+{
+ int t = 0;
+ halfword head = (halfword) lua_tonumber(L,1);
+ while (head != null) {
+ if (type(head) == glyph_node) {
+ int s = subtype(head);
+ if (s <= 256) {
+ t = 1;
+ subtype(head) = (quarterword) (s == 1 ? 256 : 256 + s);
+ }
+ }
+ head = vlink(head);
+ }
+ lua_pushboolean(L, t);
+ lua_pushvalue(L, 1);
+ return 2;
+}
+
+/* node.unprotect_glyphs (returns also boolean because that signals callback) */
+
+static int lua_nodelib_unprotect_glyphs(lua_State * L)
+{
+ int t = 0;
+ halfword head = *(check_isnode(L, 1));
+ while (head != null) {
+ if (type(head) == glyph_node) {
+ int s = subtype(head);
+ if (s > 256) {
+ t = 1;
+ subtype(head) = (quarterword) (s - 256);
+ }
+ }
+ head = vlink(head);
+ }
+ lua_pushboolean(L, t);
+ lua_pushvalue(L, 1);
+ return 2;
+}
+
+/* node.direct.unprotect_glyphs */
+
+static int lua_nodelib_direct_unprotect_glyphs(lua_State * L)
+{
+ int t = 0;
+ halfword head = (halfword) lua_tonumber(L,1);
+ while (head != null) {
+ if (type(head) == glyph_node) {
+ int s = subtype(head);
+ if (s > 256) {
+ t = 1;
+ subtype(head) = (quarterword) (s - 256);
+ }
+ }
+ head = vlink(head);
+ }
+ lua_pushboolean(L, t);
+ lua_pushvalue(L, 1);
+ return 2;
+}
+
+/* node.first_glyph */
+
+static int lua_nodelib_first_glyph(lua_State * L)
+{
+ /* on the stack are two nodes and a direction */
+ halfword h, savetail = null, t = null;
+ if (lua_gettop(L) < 1) {
+ lua_pushnil(L);
+ lua_pushboolean(L, 0);
+ return 2;
+ }
+ h = *(check_isnode(L, 1));
+ if (lua_gettop(L) > 1) {
+ t = *(check_isnode(L, 2));
+ savetail = vlink(t);
+ vlink(t) = null;
+ }
+ while (h != null && (type(h) != glyph_node || !is_simple_character(h))) {
+ h = vlink(h);
+ }
+ if (savetail != null) {
+ vlink(t) = savetail;
+ }
+ lua_pushnumber(L, h);
+ lua_nodelib_push(L);
+ lua_pushboolean(L, (h == null ? 0 : 1));
+ return 2;
+}
+
+/* node.direct.first_glyph */
+
+static int lua_nodelib_direct_first_glyph(lua_State * L)
+{
+ halfword h,savetail,t;
+ savetail = null;
+ t = null;
+ h = (halfword) lua_tonumber(L,1);
+ if (h == null) {
+ lua_pushnil(L);
+ return 1;
+ }
+ t = (halfword) lua_tonumber(L,2);
+ if (t != null) {
+ savetail = vlink(t);
+ vlink(t) = null;
+ }
+ while (h != null && (type(h) != glyph_node || !is_simple_character(h)))
+ h = vlink(h);
+ if (savetail != null)
+ vlink(t) = savetail;
+ lua_pushnumber(L, h);
+ return 1; /* no need to also push a boolean if we have nil */
+}
+
+/* new, fast and dumb ones: only signals that something needs to be processed */
+
+/* #define do_has_glyph(h) do { \ */
+/* while (h != null) { \ */
+/* if (type(h) == glyph_node) { \ */
+/* return h; \ */
+/* } else { \ */
+/* h = vlink(h); \ */
+/* } \ */
+/* } \ */
+/* return null; \ */
+/* } while (0) */
+
+
+
+
+/* node.has_glyph */
+
+static int lua_nodelib_has_glyph(lua_State * L)
+{
+ halfword *a;
+ halfword h = (halfword) *(check_isnode(L,1)) ;
+ while (h != null) {
+ if (type(h) == glyph_node) {
+ fast_metatable(h);
+ return 1;
+ } else {
+ h = vlink(h);
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+
+/* node.direct.has_glyph */
+
+static int lua_nodelib_direct_has_glyph(lua_State * L)
+{
+ halfword h = (halfword) lua_tonumber(L,1) ;
+ while (h != null) {
+ if (type(h) == glyph_node) {
+ nodelib_pushdirect(h);
+ return 1;
+ } else {
+ h = vlink(h);
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+
+
+/* depricated */
+
+static int lua_nodelib_first_character(lua_State * L)
+{
+ pdftex_warn("node.first_character() is deprecated, please update to node.first_glyph()");
+ return lua_nodelib_first_glyph(L);
+}
+
+/* this is too simplistic, but it helps Hans to get going */
+
+static halfword do_ligature_n(halfword prev, halfword stop, halfword lig)
+{
+ vlink(lig) = vlink(stop);
+ vlink(stop) = null;
+ lig_ptr(lig) = vlink(prev);
+ vlink(prev) = lig;
+ return lig;
+}
+
+/* node.do_ligature_n(node prev, node last, node lig) */
+
+static int lua_nodelib_do_ligature_n(lua_State * L)
+{
+ halfword n, m, o, p, tmp_head;
+ n = *(check_isnode(L, 1));
+ m = *(check_isnode(L, 2));
+ o = *(check_isnode(L, 3));
+ if (alink(n) == null || vlink(alink(n)) != n) {
+ tmp_head = new_node(temp_node, 0);
+ couple_nodes(tmp_head, n);
+ p = do_ligature_n(tmp_head, m, o);
+ flush_node(tmp_head);
} else {
- luaL_error(L, "Direction specifiers have to be strings");
+ p = do_ligature_n(alink(n), m, o);
}
- return 0;
+ lua_pushnumber(L, p);
+ lua_nodelib_push(L);
+ return 1;
}
-#define nodelib_getspec nodelib_getlist
-#define nodelib_getaction nodelib_getlist
+/* node.direct.do_ligature_n(node prev, node last, node lig) */
-static str_number nodelib_getstring(lua_State * L, int a)
+static int lua_nodelib_direct_do_ligature_n(lua_State * L)
{
- size_t k;
- const char *s = lua_tolstring(L, a, &k);
- return maketexlstring(s, k);
+ halfword n, m, o, p, tmp_head;
+ n = (halfword) lua_tonumber(L, 1);
+ m = (halfword) lua_tonumber(L, 2);
+ o = (halfword) lua_tonumber(L, 3);
+ if ((n == null) || (m == null) || (o == null)) {
+ lua_pushnil(L);
+ } else {
+ if (alink(n) == null || vlink(alink(n)) != n) {
+ tmp_head = new_node(temp_node, 0);
+ couple_nodes(tmp_head, n);
+ p = do_ligature_n(tmp_head, m, o);
+ flush_node(tmp_head);
+ } else {
+ p = do_ligature_n(alink(n), m, o);
+ }
+ lua_pushnumber(L, p);
+ }
+ return 1;
}
-#define nodelib_gettoks(L,a) tokenlist_from_lua(L)
+/* node.usedlist */
-static void nodelib_setattr(lua_State * L, int stackindex, halfword n)
+static int lua_nodelib_usedlist(lua_State * L)
{
- halfword p;
- p = nodelib_getlist(L, stackindex);
- if (node_attr(n) != p) {
- if (node_attr(n) != null)
- delete_attribute_ref(node_attr(n));
- node_attr(n) = p;
- if (p != null)
- attr_list_ref(p)++;
+ lua_pushnumber(L, list_node_mem_usage());
+ lua_nodelib_push(L);
+ return 1;
+}
+
+/* node.direct.usedlist */
+
+static int lua_nodelib_direct_usedlist(lua_State * L)
+{
+ lua_pushnumber(L, list_node_mem_usage());
+ return 1;
+}
+
+/* node.protrusion_skipable(node m) */
+
+static int lua_nodelib_cp_skipable(lua_State * L)
+{
+ halfword n;
+ n = *(check_isnode(L, 1));
+ lua_pushboolean(L, cp_skipable(n));
+ return 1;
+}
+
+/* node.direct.protrusion_skipable(node m) */
+
+static int lua_nodelib_direct_cp_skipable(lua_State * L)
+{
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else {
+ lua_pushboolean(L, cp_skipable(n));
}
+ return 1;
}
-static int nodelib_cantset(lua_State * L, int n, const char *s)
+/* node.currentattr(node m) */
+
+static int lua_nodelib_currentattr(lua_State * L)
{
- luaL_error(L,
- "You cannot set field %s in a node of type %s",
- s,
- node_data[type(n)].name);
+ int n = lua_gettop(L);
+ if (n == null) {
+ /* query */
+ if (max_used_attr >= 0) {
+ if (attr_list_cache == cache_disabled) {
+ update_attribute_cache();
+ if (attr_list_cache == null) {
+ lua_pushnil (L);
+ return 1;
+ }
+ }
+ attr_list_ref(attr_list_cache)++;
+ lua_pushnumber(L, attr_list_cache);
+ lua_nodelib_push(L);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+ } else {
+ /* assign */
+ pdftex_warn("Assignment via node.current_attr(<list>) is not supported (yet)");
+ return 0;
+ }
+}
- return 0;
+/* node.direct.currentattr(node m) */
+
+static int lua_nodelib_direct_currentattr(lua_State * L)
+{
+ if (max_used_attr >= 0) {
+ if (attr_list_cache == cache_disabled) {
+ update_attribute_cache();
+ if (attr_list_cache == null) {
+ lua_pushnil (L);
+ return 1;
+ }
+ }
+ attr_list_ref(attr_list_cache)++;
+ lua_pushnumber(L, attr_list_cache);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
}
+/* node.direct.todirect */
+
+static int lua_nodelib_direct_todirect(lua_State * L)
+{
+ if (lua_type(L,1) != LUA_TNUMBER) {
+ /* assume node, no further testing, used in known situations */
+ void *n ;
+ n = lua_touserdata(L, 1);
+ if (n == null) {
+ lua_pushnil(L);
+ } else {
+ lua_pushnumber(L, *((halfword *)n) );
+ }
+ } /* else assume direct and returns argument */
+ return 1;
+}
+
+
+/* node.direct.tonode */
+
+static int lua_nodelib_direct_tonode(lua_State * L)
+{
+ halfword *a;
+ halfword n;
+ n = (halfword) lua_tonumber(L, 1);
+ if (n != null) {
+ a = (halfword *) lua_newuserdata(L, sizeof(halfword));
+ *a=n;
+ lua_push_node_metatablelua;
+ lua_setmetatable(L,-2);
+ } /* else assume node and return argument */
+ return 1;
+}
+
+/* node.setfield */
+
static int lua_nodelib_setfield_whatsit(lua_State * L, int n, const char *s)
{
- register int t ;
+ int t ;
t = subtype(n);
if (t == dir_node) {
@@ -2477,18 +4877,18 @@ static int lua_nodelib_setfield_whatsit(lua_State * L, int n, const char *s)
return 0;
}
-static int lua_nodelib_setfield(lua_State * L)
+static int lua_nodelib_fast_setfield(lua_State * L)
{
- register halfword n;
- register const char *s;
- register int t ;
+ halfword n;
+ const char *s;
+ int t ;
n = *((halfword *) lua_touserdata(L, 1));
t = type(n);
if (lua_type(L, 2) == LUA_TNUMBER) {
- register int i, val;
+ int i, val;
if (lua_gettop(L) == 3) {
i = (int) lua_tointeger(L, 2);
@@ -2615,10 +5015,10 @@ static int lua_nodelib_setfield(lua_State * L)
stretch_order(n) = (quarterword) lua_tointeger(L, 3);
} else if (luaS_ptr_eq(s, shrink_order)) {
lua_pushnumber(L, shrink_order(n));
- /* } else if (luaS_ptr_eq(s, ref_count)) {
+ /* } else if (luaS_ptr_eq(s, ref_count)) {
glue_ref_count(n) = (halfword) lua_tointeger(L, 3);
} else if (luaS_ptr_eq(s, writable)) {
- */
+ */
/* can't be set */
} else {
return nodelib_cantset(L, n, s);
@@ -2740,7 +5140,7 @@ static int lua_nodelib_setfield(lua_State * L)
lua_pushstring(L, math_style_names[subtype(n)]);
} else {
/* return nodelib_cantset(L, n, s); */
- subtype(n) = (quarterword) luaL_checkoption(L, 3, "text", math_style_names);
+ subtype(n) = (quarterword) luaL_checkoption(L, 3, "text", math_style_names); /* not 2? */
}
} else if (t == accent_noad) {
if (luaS_ptr_eq(s, subtype)) {
@@ -2889,8 +5289,8 @@ static int lua_nodelib_setfield(lua_State * L)
pdf_action_new_window(n) = (halfword) lua_tointeger(L, 3);
} else if (luaS_ptr_eq(s, data)) {
pdf_action_tokens(n) = nodelib_gettoks(L, 3);
- /* } else if (luaS_ptr_eq(s, ref_count)) {
- pdf_action_refcount(n) = (halfword) lua_tointeger(L, 3); */
+ /* } else if (luaS_ptr_eq(s, ref_count)) {
+ pdf_action_refcount(n) = (halfword) lua_tointeger(L, 3); */
} else {
return nodelib_cantset(L, n, s);
}
@@ -2932,238 +5332,965 @@ static int lua_nodelib_setfield(lua_State * L)
return 0;
}
-static int lua_nodelib_print(lua_State * L)
-{
- char *msg;
- char a[7] = { ' ', ' ', ' ', 'n', 'i', 'l', 0 };
- char v[7] = { ' ', ' ', ' ', 'n', 'i', 'l', 0 };
- halfword *n;
- n = check_isnode(L, 1);
- msg = xmalloc(256);
- if (alink(*n) != null)
- snprintf(a, 7, "%6d", (int) alink(*n));
- if (vlink(*n) != null)
- snprintf(v, 7, "%6d", (int) vlink(*n));
- snprintf(msg, 255, "<node %s < %6d > %s : %s %d>", a, (int) *n, v,
- node_data[type(*n)].name, subtype(*n));
- lua_pushstring(L, msg);
- free(msg);
- return 1;
-}
-
-static int lua_nodelib_equal(lua_State * L)
-{
- register halfword n, m;
- n = *((halfword *) lua_touserdata(L, 1));
- m = *((halfword *) lua_touserdata(L, 2));
- lua_pushboolean(L, (n == m));
- return 1;
-}
-
-static int font_tex_ligaturing(lua_State * L)
+static int lua_nodelib_setfield(lua_State * L)
{
- /* on the stack are two nodes and a direction */
- halfword tmp_head;
- halfword *h;
- halfword t = null;
- if (lua_gettop(L) < 1) {
- lua_pushnil(L);
- lua_pushboolean(L, 0);
- return 2;
+ /* [given-node] [...]*/
+ halfword *p = lua_touserdata(L, 1);
+ if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+ return 0;
}
- h = check_isnode(L, 1);
- if (lua_gettop(L) > 1) {
- t = *(check_isnode(L, 2));
+ /* [given-node] [mt-given-node]*/
+ lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ /* [given-node] [mt-given-node] [mt-node]*/
+ if ( (!lua_rawequal(L, -1, -2)) ) {
+ return 0;
}
- tmp_head = new_node(nesting_node, 1);
- couple_nodes(tmp_head, *h);
- tlink(tmp_head) = t;
- t = handle_ligaturing(tmp_head, t);
- lua_pushnumber(L, vlink(tmp_head));
- flush_node(tmp_head);
- lua_nodelib_push(L);
- lua_pushnumber(L, t);
- lua_nodelib_push(L);
- lua_pushboolean(L, 1);
- return 3;
+ /* prune stack and call getfield */
+ lua_settop(L,3);
+ return lua_nodelib_fast_setfield(L);
}
-static int font_tex_kerning(lua_State * L)
+/* node.direct.setfield */
+
+static int lua_nodelib_direct_setfield_whatsit(lua_State * L, int n, const char *s)
{
- /* on the stack are two nodes and a direction */
+ int t ;
+ t = subtype(n);
- halfword tmp_head;
- halfword *h;
- halfword t = null;
- if (lua_gettop(L) < 1) {
- lua_pushnil(L);
- lua_pushboolean(L, 0);
- return 2;
- }
- h = check_isnode(L, 1);
- if (lua_gettop(L) > 1) {
- t = *(check_isnode(L, 2));
+ if (t == dir_node) {
+ if (luaS_ptr_eq(s, dir)) {
+ dir_dir(n) = nodelib_getdir(L, 3, 0);
+ } else if (luaS_ptr_eq(s, level)) {
+ dir_level(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, dvi_ptr)) {
+ dir_dvi_ptr(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, dir_h)) {
+ dir_dvi_h(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_literal_node) {
+ if (luaS_ptr_eq(s, mode)) {
+ pdf_literal_mode(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, data)) {
+ if (ini_version) {
+ pdf_literal_data(n) = nodelib_gettoks(L, 3);
+ } else {
+ lua_pushvalue(L, 3);
+ pdf_literal_data(n) = luaL_ref(L, LUA_REGISTRYINDEX);
+ pdf_literal_type(n) = lua_refid_literal;
+ }
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == late_lua_node) {
+ if (luaS_ptr_eq(s, data)) {
+ late_lua_data(n) = nodelib_gettoks(L, 3);
+ late_lua_type(n) = normal;
+ } else if (luaS_ptr_eq(s, name)) {
+ late_lua_name(n) = nodelib_gettoks(L, 3);
+ } else if (luaS_ptr_eq(s, string)) {
+ if (ini_version) {
+ late_lua_data(n) = nodelib_gettoks(L, 3);
+ late_lua_type(n) = normal;
+ } else {
+ lua_pushvalue(L, 3);
+ late_lua_data(n) = luaL_ref(L, LUA_REGISTRYINDEX);
+ late_lua_type(n) = lua_refid_literal;
+ }
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == user_defined_node) {
+ if (luaS_ptr_eq(s, user_id)) {
+ user_node_id(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, type)) {
+ user_node_type(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, value)) {
+ switch (user_node_type(n)) {
+ case 'a':
+ user_node_value(n) = nodelib_getlist(L, 3);
+ break;
+ case 'd':
+ user_node_value(n) = (halfword) lua_tointeger(L, 3);
+ break;
+ case 'n':
+ user_node_value(n) = nodelib_getlist(L, 3);
+ break;
+ case 's':
+ user_node_value(n) = nodelib_getstring(L, 3);
+ break;
+ case 't':
+ user_node_value(n) = nodelib_gettoks(L, 3);
+ break;
+ default:
+ user_node_value(n) = (halfword) lua_tointeger(L, 3);
+ break;
+ }
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_annot_node) {
+ if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, objnum)) {
+ pdf_annot_objnum(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, data)) {
+ pdf_annot_data(n) = nodelib_gettoks(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_dest_node) {
+ if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, named_id)) {
+ pdf_dest_named_id(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, dest_id)) {
+ if (pdf_dest_named_id(n) == 1) {
+ pdf_dest_id(n) = nodelib_gettoks(L, 3);
+ } else {
+ pdf_dest_id(n) = (halfword) lua_tointeger(L, 3);
+ }
+ } else if (luaS_ptr_eq(s, dest_type)) {
+ pdf_dest_type(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, xyz_zoom)) {
+ pdf_dest_xyz_zoom(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, objnum)) {
+ pdf_dest_objnum(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_setmatrix_node) {
+ if (luaS_ptr_eq(s, data)) {
+ pdf_setmatrix_data(n) = nodelib_gettoks(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_refobj_node) {
+ if (luaS_ptr_eq(s, objnum)) {
+ pdf_obj_objnum(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_refxform_node) {
+ if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, objnum)) {
+ pdf_xform_objnum(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_refximage_node) {
+ if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, transform)) {
+ pdf_ximage_transform(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, index)) {
+ pdf_ximage_index(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == local_par_node) {
+ if (luaS_ptr_eq(s, pen_inter)) {
+ local_pen_inter(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, pen_broken)) {
+ local_pen_broken(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, dir)) {
+ local_par_dir(n) = nodelib_getdir(L, 3, 1);
+ } else if (luaS_ptr_eq(s, box_left)) {
+ local_box_left(n) = nodelib_getlist(L, 3);
+ } else if (luaS_ptr_eq(s, box_left_width)) {
+ local_box_left_width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, box_right)) {
+ local_box_right(n) = nodelib_getlist(L, 3);
+ } else if (luaS_ptr_eq(s, box_right_width)) {
+ local_box_right_width(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_start_link_node) {
+ if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, objnum)) {
+ pdf_link_objnum(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, link_attr)) {
+ pdf_link_attr(n) = nodelib_gettoks(L, 3);
+ } else if (luaS_ptr_eq(s, action)) {
+ pdf_link_action(n) = nodelib_popdirect(n); /*nodelib_getaction(L, 3);*/
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == write_node) {
+ if (luaS_ptr_eq(s, stream)) {
+ write_stream(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, data)) {
+ write_tokens(n) = nodelib_gettoks(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == pdf_colorstack_node) {
+ if (luaS_ptr_eq(s, stack)) {
+ pdf_colorstack_stack(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, command)) {
+ pdf_colorstack_cmd(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, data)) {
+ pdf_colorstack_data(n) = nodelib_gettoks(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if ((t == pdf_thread_node) || (t == pdf_start_thread_node)) {
+ if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, named_id)) {
+ pdf_thread_named_id(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, thread_id)) {
+ if (pdf_thread_named_id(n) == 1) {
+ pdf_thread_id(n) = nodelib_gettoks(L, 3);
+ } else {
+ pdf_thread_id(n) = (halfword) lua_tointeger(L, 3);
+ }
+ } else if (luaS_ptr_eq(s, thread_attr)) {
+ pdf_thread_attr(n) = nodelib_gettoks(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == special_node) {
+ if (luaS_ptr_eq(s, data)) {
+ write_tokens(n) = nodelib_gettoks(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == open_node) {
+ if (luaS_ptr_eq(s, stream)) {
+ write_stream(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, name)) {
+ open_name(n) = nodelib_getstring(L, 3);
+ } else if (luaS_ptr_eq(s, area)) {
+ open_area(n) = nodelib_getstring(L, 3);
+ } else if (luaS_ptr_eq(s, ext)) {
+ open_ext(n) = nodelib_getstring(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == close_node) {
+ if (luaS_ptr_eq(s, stream)) {
+ write_stream(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if ((t == pdf_end_link_node) || (t == pdf_end_thread_node) || (t == pdf_save_pos_node) ||
+ (t == pdf_save_node) || (t == pdf_restore_node) || (t == cancel_boundary_node)) {
+ return nodelib_cantset(L, n, s);
+ } else {
+ /* do nothing */
}
- tmp_head = new_node(nesting_node, 1);
- couple_nodes(tmp_head, *h);
- tlink(tmp_head) = t;
- t = handle_kerning(tmp_head, t);
- lua_pushnumber(L, vlink(tmp_head));
- flush_node(tmp_head);
- lua_nodelib_push(L);
- lua_pushnumber(L, t);
- lua_nodelib_push(L);
- lua_pushboolean(L, 1);
- return 3;
+ return 0;
}
-static int lua_nodelib_protect_glyphs(lua_State * L)
+static int lua_nodelib_direct_setfield(lua_State * L)
{
- int t = 0;
- halfword head = *(check_isnode(L, 1));
- while (head != null) {
- if (type(head) == glyph_node) {
- register int s = subtype(head);
- if (s <= 256) {
- t = 1;
- subtype(head) = (quarterword) (s == 1 ? 256 : 256 + s);
+ halfword n;
+ const char *s;
+ int t ;
+
+ n = (halfword ) lua_tonumber(L, 1);
+ t = type(n);
+
+ if (lua_type(L, 2) == LUA_TNUMBER) {
+
+ int i, val;
+
+ if (lua_gettop(L) == 3) {
+ i = (int) lua_tointeger(L, 2);
+ val = (int) lua_tointeger(L, 3);
+ if (val == UNUSED_ATTRIBUTE) {
+ (void) unset_attribute(n, i, val);
+ } else {
+ set_attribute(n, i, val);
}
+ } else {
+ luaL_error(L, "incorrect number of arguments");
}
- head = vlink(head);
+ return 0;
}
- lua_pushboolean(L, t);
- lua_pushvalue(L, 1);
- return 2;
-}
-static int lua_nodelib_unprotect_glyphs(lua_State * L)
-{
- int t = 0;
- halfword head = *(check_isnode(L, 1));
- while (head != null) {
- if (type(head) == glyph_node) {
- register int s = subtype(head);
- if (s > 256) {
- t = 1;
- subtype(head) = (quarterword) (s - 256);
+ s = lua_tostring(L, 2);
+
+ if (luaS_ptr_eq(s, id)) {
+ lua_pushnumber(L, t);
+ } else if (luaS_ptr_eq(s, next)) {
+ halfword x = nodelib_popdirect(3);
+ if (x>0 && type(x) == glue_spec_node) {
+ return luaL_error(L, "You can't assign a %s node to a next field\n", node_data[type(x)].name);
+ }
+ vlink(n) = x;
+ } else if (luaS_ptr_eq(s, prev)) {
+ halfword x = nodelib_popdirect(3);
+ if (x>0 && type(x) == glue_spec_node) {
+ return luaL_error(L, "You can't assign a %s node to a prev field\n", node_data[type(x)].name);
+ }
+ alink(n) = x;
+ } else if (luaS_ptr_eq(s, attr)) {
+ if (nodetype_has_attributes(type(n))) {
+ nodelib_setattr(L, 3, n);
+ }
+ } else if (t == glyph_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, font)) {
+ font(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, char)) {
+ character(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, xoffset)) {
+ x_displace(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, yoffset)) {
+ y_displace(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, width)) {
+ /* not yet */
+ } else if (luaS_ptr_eq(s, height)) {
+ /* not yet */
+ } else if (luaS_ptr_eq(s, depth)) {
+ /* not yet */
+ } else if (luaS_ptr_eq(s, expansion_factor)) {
+ ex_glyph(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, components)) {
+ lig_ptr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, lang)) {
+ set_char_lang(n, (halfword) lua_tointeger(L, 3));
+ } else if (luaS_ptr_eq(s, left)) {
+ set_char_lhmin(n, (halfword) lua_tointeger(L, 3));
+ } else if (luaS_ptr_eq(s, right)) {
+ set_char_rhmin(n, (halfword) lua_tointeger(L, 3));
+ } else if (luaS_ptr_eq(s, uchyph)) {
+ set_char_uchyph(n, (halfword) lua_tointeger(L, 3));
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if ((t == hlist_node) || (t == vlist_node)) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, list) || luaS_ptr_eq(s, head)) {
+ list_ptr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, dir)) {
+ box_dir(n) = nodelib_getdir(L, 3, 1);
+ } else if (luaS_ptr_eq(s, shift)) {
+ shift_amount(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, glue_order)) {
+ glue_order(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, glue_sign)) {
+ glue_sign(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, glue_set)) {
+ glue_set(n) = (glue_ratio) lua_tonumber(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == disc_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, pre)) {
+ set_disc_field(pre_break(n), nodelib_popdirect(3));
+ } else if (luaS_ptr_eq(s, post)) {
+ set_disc_field(post_break(n), nodelib_popdirect(3));
+ } else if (luaS_ptr_eq(s, replace)) {
+ set_disc_field(no_break(n), nodelib_popdirect(3));
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == glue_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, spec)) {
+ glue_ptr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, leader)) {
+ leader_ptr(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == glue_spec_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3); /* dummy, the only one that prevents move up */
+ } else if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, stretch)) {
+ stretch(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, shrink)) {
+ shrink(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, stretch_order)) {
+ stretch_order(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, shrink_order)) {
+ lua_pushnumber(L, shrink_order(n));
+ /* } else if (luaS_ptr_eq(s, ref_count)) {
+ glue_ref_count(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, writable)) {
+ */
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == kern_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, kern)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, expansion_factor)) {
+ ex_kern(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == penalty_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ /* dummy subtype */
+ } else if (luaS_ptr_eq(s, penalty)) {
+ penalty(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == rule_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, dir)) {
+ rule_dir(n) = nodelib_getdir(L, 3, 1);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == whatsit_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else {
+ lua_nodelib_direct_setfield_whatsit(L, n, s);
+ }
+ } else if (t == simple_noad) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, nucleus)) {
+ nucleus(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, sub)) {
+ subscr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, sup)) {
+ supscr(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if ((t == math_char_node) || (t == math_text_char_node)) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, fam)) {
+ math_fam(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, char)) {
+ math_character(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == mark_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, class)) {
+ mark_class(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, mark)) {
+ mark_ptr(n) = nodelib_gettoks(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == ins_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, cost)) {
+ float_cost(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, spec)) {
+ split_top_ptr(n) = nodelib_popdirect(3);
+ } else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))) {
+ ins_ptr(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == math_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, surround)) {
+ surround(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == fraction_noad) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, width)) {
+ thickness(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, num)) {
+ numerator(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, denom)) {
+ denominator(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, left)) {
+ left_delimiter(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, right)) {
+ right_delimiter(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == style_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ /* dummy subtype */
+ } else if (luaS_ptr_eq(s, style)) {
+ lua_pushstring(L, math_style_names[subtype(n)]);
+ } else {
+ /* return nodelib_cantset(L, n, s); */
+ subtype(n) = (quarterword) luaL_checkoption(L, 2, "text", math_style_names); /* was 3 */
+ }
+ } else if (t == accent_noad) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, nucleus)) {
+ nucleus(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, sub)) {
+ subscr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, sup)) {
+ supscr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, accent)) {
+ accent_chr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, bot_accent)) {
+ bot_accent_chr(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == fence_noad) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, delim)) {
+ delimiter(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == delim_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, small_fam)) {
+ small_fam(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, small_char)) {
+ small_char(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, large_fam)) {
+ large_fam(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, large_char)) {
+ large_char(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if ((t == sub_box_node) || (t == sub_mlist_node)) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))){
+ math_list(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == radical_noad) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, nucleus)) {
+ nucleus(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, sub)) {
+ subscr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, sup)) {
+ supscr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, left)) {
+ left_delimiter(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, degree)) {
+ degree(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == margin_kern_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, glyph)) {
+ margin_char(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == split_up_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, last_ins_ptr)) {
+ last_ins_ptr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, best_ins_ptr)) {
+ best_ins_ptr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, broken_ptr)) {
+ broken_ptr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, broken_ins)) {
+ broken_ins(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == choice_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, display)) {
+ display_mlist(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, text)) {
+ text_mlist(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, script)) {
+ script_mlist(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, scriptscript)) {
+ script_script_mlist(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == inserting_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, last_ins_ptr)) {
+ last_ins_ptr(n) = nodelib_popdirect(3);
+ } else if (luaS_ptr_eq(s, best_ins_ptr)) {
+ best_ins_ptr(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == attribute_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ /* dummy subtype */
+ } else if (luaS_ptr_eq(s, number)) {
+ attribute_id(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, value)) {
+ attribute_value(n) = (halfword) lua_tointeger(L, 3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == adjust_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ subtype(n) = (quarterword) lua_tointeger(L, 3);
+ } else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))) {
+ adjust_ptr(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == action_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ /* dummy subtype */
+ } else if (luaS_ptr_eq(s, action_type)) {
+ pdf_action_type(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, named_id)) {
+ pdf_action_named_id(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, action_id)) {
+ if (pdf_action_named_id(n) == 1) {
+ pdf_action_id(n) = nodelib_gettoks(L, 3);
+ } else {
+ pdf_action_id(n) = (halfword) lua_tointeger(L, 3);
}
+ } else if (luaS_ptr_eq(s, file)) {
+ pdf_action_file(n) = nodelib_gettoks(L, 3);
+ } else if (luaS_ptr_eq(s, new_window)) {
+ pdf_action_new_window(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, data)) {
+ pdf_action_tokens(n) = nodelib_gettoks(L, 3);
+ /* } else if (luaS_ptr_eq(s, ref_count)) {
+ pdf_action_refcount(n) = (halfword) lua_tointeger(L, 3); */
+ } else {
+ return nodelib_cantset(L, n, s);
}
- head = vlink(head);
+ } else if (t == unset_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ /* dummy subtype */
+ } else if (luaS_ptr_eq(s, width)) {
+ width(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, height)) {
+ height(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, depth)) {
+ depth(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, dir)) {
+ box_dir(n) = nodelib_getdir(L, 3, 1);
+ } else if (luaS_ptr_eq(s, shrink)) {
+ glue_shrink(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, glue_order)) {
+ glue_order(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, glue_sign)) {
+ glue_sign(n) = (quarterword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, stretch)) {
+ glue_stretch(n) = (halfword) lua_tointeger(L, 3);
+ } else if (luaS_ptr_eq(s, count)) {
+ span_count(n) = (quarterword) lua_tointeger(L, 3);
+ } else if ((luaS_ptr_eq(s, list)) || (luaS_ptr_eq(s, head))){
+ list_ptr(n) = nodelib_popdirect(3);
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else if (t == attribute_list_node) {
+ if (luaS_ptr_eq(s, subtype)) {
+ /* dummy subtype */
+ } else {
+ return nodelib_cantset(L, n, s);
+ }
+ } else {
+ return luaL_error(L, "You can't assign to this %s node (%d)\n", node_data[t].name, n);
}
- lua_pushboolean(L, t);
- lua_pushvalue(L, 1);
- return 2;
+ return 0;
}
-static int lua_nodelib_first_glyph(lua_State * L)
+/* boxes */
+
+static int direct_get_box_id(lua_State * L, int i)
{
- /* on the stack are two nodes and a direction */
- halfword h, savetail = null, t = null;
- if (lua_gettop(L) < 1) {
- lua_pushnil(L);
- lua_pushboolean(L, 0);
- return 2;
- }
- h = *(check_isnode(L, 1));
- if (lua_gettop(L) > 1) {
- t = *(check_isnode(L, 2));
- savetail = vlink(t);
- vlink(t) = null;
- }
- while (h != null && (type(h) != glyph_node || !is_simple_character(h))) {
- h = vlink(h);
- }
- if (savetail != null) {
- vlink(t) = savetail;
+ const char *s;
+ int cur_cs1, cur_cmd1;
+ size_t k = 0;
+ int j = -1;
+ switch (lua_type(L, i)) {
+ case LUA_TSTRING:
+ s = lua_tolstring(L, i, &k);
+ cur_cs1 = string_lookup(s, k);
+ cur_cmd1 = eq_type(cur_cs1);
+ if (cur_cmd1 == char_given_cmd ||
+ cur_cmd1 == math_given_cmd) {
+ j = equiv(cur_cs1);
+ }
+ break;
+ case LUA_TNUMBER:
+ j=(int)lua_tonumber(L, (i));
+ break;
+ default:
+ luaL_error(L, "argument must be a string or a number");
+ j = -1; /* not a valid box id */
}
- lua_pushnumber(L, h);
- lua_nodelib_push(L);
- lua_pushboolean(L, (h == null ? 0 : 1));
- return 2;
+ return j;
}
-static int lua_nodelib_first_character(lua_State * L)
+/* node.getbox = tex.getbox */
+
+/* node.direct.getbox */
+
+static int lua_nodelib_direct_getbox(lua_State * L)
{
- pdftex_warn("node.first_character() is deprecated, please update to node.first_glyph()");
- return lua_nodelib_first_glyph(L);
+ int k, t;
+ k = direct_get_box_id(L, -1);
+ direct_check_index_range(k, "getbox");
+ t = get_tex_box_register(k);
+ lua_pushnumber(L, t);
+ return 1;
}
-/* this is too simplistic, but it helps Hans to get going */
-
-static halfword do_ligature_n(halfword prev, halfword stop, halfword lig)
+static int direct_vsetbox(lua_State * L, int is_global)
{
- vlink(lig) = vlink(stop);
- vlink(stop) = null;
- lig_ptr(lig) = vlink(prev);
- vlink(prev) = lig;
- return lig;
+ int j, k, err;
+ int save_global_defs = int_par(global_defs_code);
+ if (is_global)
+ int_par(global_defs_code) = 1;
+ k = direct_get_box_id(L, -2);
+ direct_check_index_range(k, "setbox");
+ if (lua_isboolean(L, -1)) {
+ j = lua_toboolean(L, -1);
+ if (j == 0)
+ j = null;
+ else
+ return 0;
+ } else {
+ j=nodelib_popdirect(-1);
+ if (j != null && type(j) != hlist_node && type(j) != vlist_node) {
+ luaL_error(L, "setbox: incompatible node type (%s)\n",get_node_name(type(j), subtype(j)));
+ return 0;
+ }
+
+ }
+ err = set_tex_box_register(k, j);
+ int_par(global_defs_code) = save_global_defs;
+ if (err) {
+ luaL_error(L, "incorrect value");
+ }
+ return 0;
}
-/* node.do_ligature_n(node prev, node last, node lig) */
+/* node.setbox = tex.setbox */
+/* node.setbox */
-static int lua_nodelib_do_ligature_n(lua_State * L)
+static int lua_nodelib_direct_setbox(lua_State * L)
{
- halfword n, m, o, p, tmp_head;
- n = *(check_isnode(L, 1));
- m = *(check_isnode(L, 2));
- o = *(check_isnode(L, 3));
- if (alink(n) == null || vlink(alink(n)) != n) {
- tmp_head = new_node(temp_node, 0);
- couple_nodes(tmp_head, n);
- p = do_ligature_n(tmp_head, m, o);
- flush_node(tmp_head);
- } else {
- p = do_ligature_n(alink(n), m, o);
+ int isglobal = 0;
+ int n = lua_gettop(L);
+ if (n == 3 && lua_isstring(L, 1)) {
+ const char *s = lua_tostring(L, 1);
+ if (luaS_ptr_eq(s, global))
+ isglobal = 1;
}
- lua_pushnumber(L, p);
- lua_nodelib_push(L);
- return 1;
+ return direct_vsetbox(L, isglobal);
}
-static int lua_nodelib_usedlist(lua_State * L)
+/* node.is_node(n) */
+
+static int lua_nodelib_is_node(lua_State * L)
{
- lua_pushnumber(L, list_node_mem_usage());
- lua_nodelib_push(L);
+ if (maybe_isnode(L,1) == NULL)
+ lua_pushboolean(L,0);
+ else
+ lua_pushboolean(L,1);
return 1;
}
-/* node.protrusion_skipable(node m) */
+/* node.direct.is_direct(n) (handy for mixed usage testing) */
-static int lua_nodelib_cp_skipable(lua_State * L)
-{
- halfword n;
- n = *(check_isnode(L, 1));
- lua_pushboolean(L, cp_skipable(n));
+static int lua_nodelib_direct_is_direct(lua_State * L)
+{ /*
+ quick and dirty and faster than not node.is_node, this helper
+ returns false or <direct>
+ */
+ /*
+ if (lua_type(L,1) == LUA_TNUMBER)
+ lua_pushboolean(L,1);
+ else
+ lua_pushboolean(L,0);
+ */
+ if (lua_type(L,1) != LUA_TNUMBER)
+ lua_pushboolean(L,0);
+ /* else return direct */
return 1;
}
-static int lua_nodelib_currentattr(lua_State * L)
-{
- int n = lua_gettop(L);
- if (n == 0) {
- /* query */
- if (max_used_attr >= 0) {
- if (attr_list_cache == cache_disabled) {
- update_attribute_cache();
- if (attr_list_cache == null) {
- lua_pushnil (L);
- return 1;
- }
- }
- attr_list_ref(attr_list_cache)++;
- lua_pushnumber(L, attr_list_cache);
- lua_nodelib_push(L);
- } else {
- lua_pushnil (L);
- }
- return 1;
- } else {
- /* assign */
- pdftex_warn("Assignment via node.current_attr(<list>) is not supported (yet)");
- return 0;
- }
+/* node.direct.is_node(n) (handy for mixed usage testing) */
+
+static int lua_nodelib_direct_is_node(lua_State * L)
+{ /*
+ quick and dirty, only checks userdata, node.is_node is slower but
+ more exact, this helper returns false or <node>
+ */
+ /*
+ halfword *n = lua_touserdata(L, 1);
+ if (n != NULL) {
+ lua_pushboolean(L,1);
+ } else {
+ lua_pushboolean(L,0);
+ }
+ */
+ if (maybe_isnode(L,1) == NULL)
+ lua_pushboolean(L,0);
+ /* else assume and return node */
+ return 1;
}
+/* node.fast.*
+
+ static const struct luaL_Reg fast_nodelib_f[] = {
+ {"getid", lua_nodelib_fast_getid},
+ {"getsubtype", lua_nodelib_fast_getsubtype},
+ {"getfont", lua_nodelib_fast_getfont},
+ {"getchar", lua_nodelib_fast_getcharacter},
+ {"getnext", lua_nodelib_fast_getnext},
+ {"getprev", lua_nodelib_fast_getprev},
+ {"getfield", lua_nodelib_fast_getfield},
+ {"setfield", lua_nodelib_fast_setfield},
+ {NULL, NULL}
+ };
+
+*/
+
+/* node.direct.* */
+
+static const struct luaL_Reg direct_nodelib_f[] = {
+ {"copy", lua_nodelib_direct_copy},
+ {"copy_list", lua_nodelib_direct_copy_list},
+ {"count", lua_nodelib_direct_count},
+ {"current_attr", lua_nodelib_direct_currentattr},
+ {"dimensions", lua_nodelib_direct_dimensions},
+ {"do_ligature_n", lua_nodelib_direct_do_ligature_n},
+ {"end_of_math", lua_nodelib_direct_end_of_math},
+ /* {"family_font", lua_nodelib_mfont}, */ /* no node argument */
+ /* {"fields", lua_nodelib_fields}, */ /* no node argument */
+ /* {"first_character", lua_nodelib_first_character}, */ /* obsolete */
+ {"first_glyph", lua_nodelib_direct_first_glyph},
+ {"flush_list", lua_nodelib_direct_flush_list},
+ {"flush_node", lua_nodelib_direct_flush_node},
+ {"free", lua_nodelib_direct_free},
+ {"getbox", lua_nodelib_direct_getbox},
+ {"getchar", lua_nodelib_direct_getcharacter},
+ {"getfield", lua_nodelib_direct_getfield},
+ {"getfont", lua_nodelib_direct_getfont},
+ {"getid", lua_nodelib_direct_getid},
+ {"getnext", lua_nodelib_direct_getnext},
+ {"getprev", lua_nodelib_direct_getprev},
+ {"getlist", lua_nodelib_direct_getlist},
+ {"getleader", lua_nodelib_direct_getleader},
+ {"getsubtype", lua_nodelib_direct_getsubtype},
+ {"has_glyph", lua_nodelib_direct_has_glyph},
+ {"has_attribute", lua_nodelib_direct_has_attribute},
+ {"has_field", lua_nodelib_direct_has_field},
+ {"hpack", lua_nodelib_direct_hpack},
+ /* {"id", lua_nodelib_id}, */ /* no node argument */
+ {"insert_after", lua_nodelib_direct_insert_after},
+ {"insert_before", lua_nodelib_direct_insert_before},
+ {"is_direct", lua_nodelib_direct_is_direct},
+ {"is_node", lua_nodelib_direct_is_node},
+ /* {"kerning", font_tex_kerning}, */ /* maybe direct too (rather basic callback exposure) */
+ {"last_node", lua_nodelib_direct_last_node},
+ {"length", lua_nodelib_direct_length},
+ /* {"ligaturing", font_tex_ligaturing}, */ /* maybe direct too (rather basic callback exposure) */
+ /* {"mlist_to_hlist", lua_nodelib_mlist_to_hlist}, */ /* maybe direct too (rather basic callback exposure) */
+ {"new", lua_nodelib_direct_new},
+ /* {"next", lua_nodelib_next}, */ /* replaced by getnext */
+ /* {"prev", lua_nodelib_prev}, */ /* replaced by getprev */
+ {"tostring", lua_nodelib_direct_tostring},
+ {"protect_glyphs", lua_nodelib_direct_protect_glyphs},
+ {"protrusion_skippable", lua_nodelib_direct_cp_skipable},
+ {"remove", lua_nodelib_direct_remove},
+ {"set_attribute", lua_nodelib_direct_set_attribute},
+ {"setbox", lua_nodelib_direct_setbox},
+ {"setfield", lua_nodelib_direct_setfield},
+ {"slide", lua_nodelib_direct_slide},
+ /* {"subtype", lua_nodelib_subtype}, */ /* no node argument */
+ {"tail", lua_nodelib_direct_tail},
+ {"todirect", lua_nodelib_direct_todirect}, /* not in node.* */
+ {"tonode", lua_nodelib_direct_tonode}, /* similar to node.* */
+ {"traverse", lua_nodelib_direct_traverse},
+ {"traverse_id", lua_nodelib_direct_traverse_filtered},
+ /* {"type", lua_nodelib_type}, */ /* no node argument */
+ /* {"types", lua_nodelib_types}, */ /* no node argument */
+ {"unprotect_glyphs", lua_nodelib_direct_unprotect_glyphs},
+ {"unset_attribute", lua_nodelib_direct_unset_attribute},
+ {"usedlist", lua_nodelib_direct_usedlist},
+ {"vpack", lua_nodelib_direct_vpack},
+ /* {"whatsits", lua_nodelib_whatsits}, */ /* no node argument */
+ {"write", lua_nodelib_direct_append},
+ {NULL, NULL} /* sentinel */
+};
+
+/* node.* */
+
static const struct luaL_Reg nodelib_f[] = {
{"copy", lua_nodelib_copy},
{"copy_list", lua_nodelib_copy_list},
@@ -3177,29 +6304,44 @@ static const struct luaL_Reg nodelib_f[] = {
{"first_character", lua_nodelib_first_character},
{"first_glyph", lua_nodelib_first_glyph},
{"flush_list", lua_nodelib_flush_list},
+ {"flush_node", lua_nodelib_flush_node},
{"free", lua_nodelib_free},
+ /* {"getbox", lua_nodelib_getbox}, */ /* tex.getbox */
+ {"getnext", lua_nodelib_getnext},
+ {"getprev", lua_nodelib_getprev},
+ {"getlist", lua_nodelib_getlist},
+ {"getleader", lua_nodelib_getleader},
+ {"getid", lua_nodelib_getid},
+ {"getfield", lua_nodelib_getfield},
+ {"setfield", lua_nodelib_setfield},
+ {"getsubtype", lua_nodelib_getsubtype},
+ {"getfont", lua_nodelib_getfont},
+ {"getchar", lua_nodelib_getcharacter},
+ {"has_glyph", lua_nodelib_has_glyph},
{"has_attribute", lua_nodelib_has_attribute},
{"has_field", lua_nodelib_has_field},
{"hpack", lua_nodelib_hpack},
{"id", lua_nodelib_id},
{"insert_after", lua_nodelib_insert_after},
{"insert_before", lua_nodelib_insert_before},
- {"is_node", lua_nodelib_isnode},
+ {"is_node", lua_nodelib_is_node},
{"kerning", font_tex_kerning},
{"last_node", lua_nodelib_last_node},
{"length", lua_nodelib_length},
{"ligaturing", font_tex_ligaturing},
{"mlist_to_hlist", lua_nodelib_mlist_to_hlist},
{"new", lua_nodelib_new},
- {"next", lua_nodelib_next},
- {"prev", lua_nodelib_prev},
+ {"next", lua_nodelib_next}, /* getnext is somewhat more efficient, and get* fits better in direct compatibility */
+ {"prev", lua_nodelib_prev}, /* getprev is somewhat more efficient, and get* fits better in direct compatibility */
+ {"tostring", lua_nodelib_tostring},
{"protect_glyphs", lua_nodelib_protect_glyphs},
{"protrusion_skippable", lua_nodelib_cp_skipable},
{"remove", lua_nodelib_remove},
+ /* {"setbox", lua_nodelib_setbox}, */ /* tex.setbox */
{"set_attribute", lua_nodelib_set_attribute},
- {"slide", lua_nodelib_tail},
+ {"slide", lua_nodelib_slide},
{"subtype", lua_nodelib_subtype},
- {"tail", lua_nodelib_tail_only},
+ {"tail", lua_nodelib_tail},
{"traverse", lua_nodelib_traverse},
{"traverse_id", lua_nodelib_traverse_filtered},
{"type", lua_nodelib_type},
@@ -3210,22 +6352,36 @@ static const struct luaL_Reg nodelib_f[] = {
{"vpack", lua_nodelib_vpack},
{"whatsits", lua_nodelib_whatsits},
{"write", lua_nodelib_append},
- {NULL, NULL} /* sentinel */
+ {NULL, NULL} /* sentinel */
};
static const struct luaL_Reg nodelib_m[] = {
- {"__index", lua_nodelib_getfield},
- {"__newindex", lua_nodelib_setfield},
- {"__tostring", lua_nodelib_print},
+ {"__index", lua_nodelib_fast_getfield},
+ {"__newindex", lua_nodelib_fast_setfield},
+ {"__tostring", lua_nodelib_tostring},
{"__eq", lua_nodelib_equal},
- {NULL, NULL} /* sentinel */
+ {NULL, NULL} /* sentinel */
};
int luaopen_node(lua_State * L)
{
+ /* the main metatable of node userdata */
luaL_newmetatable(L, NODE_METATABLE);
+ /* node.* */
luaL_register(L, NULL, nodelib_m);
luaL_register(L, "node", nodelib_f);
+ /* node.fast (experimental code)
+ lua_pushstring(L,"fast");
+ lua_newtable(L);
+ luaL_register(L, NULL, fast_nodelib_f);
+ lua_rawset(L,-3);
+ */
+ /* node.direct */
+ lua_pushstring(L,"direct");
+ lua_newtable(L);
+ luaL_register(L, NULL, direct_nodelib_f);
+ lua_rawset(L,-3);
+ /* initialization of keywords */
initialize_luaS_indexes(L);
return 1;
}