texlive[43196] Build/source/texk/web2c/luatexdir/lua: luatexdir: sync

commits+kakuto at tug.org commits+kakuto at tug.org
Sat Feb 11 23:54:15 CET 2017


Revision: 43196
          http://tug.org/svn/texlive?view=revision&revision=43196
Author:   kakuto
Date:     2017-02-11 23:54:15 +0100 (Sat, 11 Feb 2017)
Log Message:
-----------
luatexdir: sync with the upstream

Modified Paths:
--------------
    trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c	2017-02-11 22:19:29 UTC (rev 43195)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c	2017-02-11 22:54:15 UTC (rev 43196)
@@ -29,23 +29,25 @@
     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.
+    some experiments with fast access (assuming nodes), 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 don't rely on that property; treat them as abstractions. An
+    important aspect    is that one cannot mix both methods, although with
+    node.direct.tonode and node.direct.todirect one can cast 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
+    direct one when speed might be an issue. For that reason we also provide some
     get* and set* functions in the top level node namespace. There is a limited set
-    of getters and a generic getfield to complement them.
+    of getters for nodes and a generic getfield to complement them. The direct
+    namespace has a few more.
 
-    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.)
+    Keep in mind that such speed considerations only make sense when we're accessing
+    nodes 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. And with millions, we're talking of tens of millions which is not
+    that common.
 
     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
@@ -349,91 +351,50 @@
     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_get_metatablelua(luatex_node);
-    /* [given-node] [mt-given-node] [mt-node] */
-    if (!lua_rawequal(L, -1, -2)) {
-        lua_pushnil(L);
-    } else {
-        lua_pushinteger(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_pushinteger(L, type(*n));
-        return 1;
-    }
-
-*/
-
 /* node.direct.getid */
 
 static int lua_nodelib_direct_getid(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
+    if (n) {
+        lua_pushinteger(L, type(n));
+    } else {
         lua_pushnil(L);
-    } else {
-        lua_pushinteger(L, type(n));
     }
     return 1;
 }
 
-/* node.getsubtype */
+    /* node.getid */
 
-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 {
+    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_get_metatablelua(luatex_node);
-        if ( (!lua_rawequal(L, -1, -2)) || (! nodetype_has_subtype(*p))) {
+        /* [given-node] [mt-given-node] [mt-node] */
+        if (!lua_rawequal(L, -1, -2)) {
             lua_pushnil(L);
         } else {
-            lua_pushinteger(L, subtype(*p));
+            lua_pushinteger(L, type(*p));
         }
-    }
-    return 1;
-}
-
-/* node.fast.getsubtype
-
-    static int lua_nodelib_fast_getsubtype(lua_State * L)
-    {
-        halfword *n;
-        n = (halfword *) lua_touserdata(L, 1);
-        lua_pushinteger(L, subtype(*n));
         return 1;
     }
 
-*/
-
 /* node.direct.getsubtype */
+/* node.direct.setsubtype */
 
 static int lua_nodelib_direct_getsubtype(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) { /* no check, we assume sane use */
+    if (n) {
+        lua_pushinteger(L, subtype(n));
+    } else {
         lua_pushnil(L);
-    } else {
-        lua_pushinteger(L, subtype(n));
     }
     return 1;
 }
@@ -441,75 +402,96 @@
 static int lua_nodelib_direct_setsubtype(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if ((n != null) && (lua_type(L,2) == LUA_TNUMBER)) {
+    if ((n) && (lua_type(L,2) == LUA_TNUMBER)) {
         subtype(n) = (halfword) lua_tointeger(L, 2);
     }
     return 0;
 }
 
-/* node.getfont */
+    /* node.getsubtype */
 
-static int lua_nodelib_getfont(lua_State * L)
+    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_get_metatablelua(luatex_node);
+            if ( (!lua_rawequal(L, -1, -2)) || (! nodetype_has_subtype(*p))) {
+                lua_pushnil(L);
+            } else {
+                lua_pushinteger(L, subtype(*p));
+            }
+        }
+        return 1;
+    }
+
+/* node.direct.getfont */
+/* node.direct.setfont */
+
+static int lua_nodelib_direct_getfont(lua_State * L)
 {
-    halfword *n = lua_touserdata(L, 1);
-    if ( (n == NULL) || (! lua_getmetatable(L,1)) ) {
-        lua_pushnil(L);
-    } else {
-        halfword t = type(*n);
+    halfword n = lua_tointeger(L, 1);
+    if (n != null) {
+        halfword t = type(n);
         if (t == glyph_node) {
-            lua_pushinteger(L, font(*n));
+            lua_pushinteger(L, font(n));
         } else if ((t == math_char_node) || (t == math_text_char_node)) {
-            lua_pushinteger(L, fam_fnt(math_fam(*n), 0));
+            lua_pushinteger(L, fam_fnt(math_fam(n), 0));
         } else {
             lua_pushnil(L);
         }
+    } else {
+        lua_pushnil(L);
     }
     return 1;
 }
 
-/* node.fast.getfont
+static int lua_nodelib_direct_setfont(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if ((n) && type(n) == glyph_node) {
+        font(n) = (halfword) lua_tointeger(L,2);
+        /* optional char */
+        if ((lua_type(L, 3) == LUA_TNUMBER)) {
+            character(n) = (halfword) lua_tointeger(L, 3);
+        }
+    }
+    return 0;
+}
 
-    static int lua_nodelib_fast_getfont(lua_State * L)
+    /* node.getfont */
+
+    static int lua_nodelib_getfont(lua_State * L)
     {
-        halfword *n;
-        n = (halfword *) lua_touserdata(L, 1);
-        if (type(*n) != glyph_node) {
+        halfword *n = lua_touserdata(L, 1);
+        if ((n == NULL) || (! lua_getmetatable(L,1)) ) {
             lua_pushnil(L);
         } else {
-            lua_pushinteger(L, font(*n));
+            halfword t = type(*n);
+            if (t == glyph_node) {
+                lua_pushinteger(L, font(*n));
+            } else if ((t == math_char_node) || (t == math_text_char_node)) {
+                lua_pushinteger(L, fam_fnt(math_fam(*n), 0));
+            } else {
+                lua_pushnil(L);
+            }
         }
         return 1;
     }
 
-*/
+/* node.direct.getchar */
+/* node.direct.setchar */
 
-/* node.direct.getfont */
-
-/*
-
-static int lua_nodelib_direct_getfont(lua_State * L)
+static int lua_nodelib_direct_getchar(lua_State * L)
 {
-    halfword n;
-    n = (halfword) lua_tointeger(L, 1);
-    if ((n == null) || (type(n) != glyph_node)) {
-        lua_pushnil(L);
-    } else {
-        lua_pushinteger(L, font(n));
-    }
-    return 1;
-}
-
-*/
-
-static int lua_nodelib_direct_getfont(lua_State * L) /* family_font is not yet in manual, what does arg 2 do */
-{
     halfword n = lua_tointeger(L, 1);
-    if (n != null) {
+    if (n) {
         halfword t = type(n);
         if (t == glyph_node) {
-            lua_pushinteger(L, font(n));
+            lua_pushinteger(L, character(n));
         } else if ((t == math_char_node) || (t == math_text_char_node)) {
-            lua_pushinteger(L, fam_fnt(math_fam(n), 0));
+            lua_pushinteger(L, math_character(n));
         } else {
             lua_pushnil(L);
         }
@@ -519,50 +501,44 @@
     return 1;
 }
 
-/* node.getchar */
-
-static int lua_nodelib_getcharacter(lua_State * L)
+static int lua_nodelib_direct_setchar(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_pushinteger(L, character(*n));
-    } else if ((type(*n) == math_char_node) || (type(*n) == math_text_char_node)) {
-        lua_pushinteger(L, math_character(*n));
+    halfword n = lua_tointeger(L, 1);
+    if ((n) && (lua_type(L, 2) == LUA_TNUMBER)) {
+        halfword t = type(n);
+        if (t == glyph_node) {
+            character(n) = (halfword) lua_tointeger(L, 2);
+        } else if ((t == math_char_node) || (t == math_text_char_node)) {
+            math_character(n) = (halfword) lua_tointeger(L, 2);
+        }
     }
-    return 1;
+    return 0;
 }
 
-/* node.fast.getchar
 
-    static int lua_nodelib_fast_getcharacter(lua_State * L)
+    /* node.getchar */
+
+    static int lua_nodelib_getchar(lua_State * L)
     {
-        halfword *n;
-        n = (halfword *) lua_touserdata(L, 1);
-        if (type(*n) == glyph_node) {
+        halfword *n = lua_touserdata(L, 1);
+        if ( (n == NULL) || (! lua_getmetatable(L,1)) ) {
+            lua_pushnil(L);
+        } else if (type(*n) == glyph_node) {
             lua_pushinteger(L, character(*n));
         } else if ((type(*n) == math_char_node) || (type(*n) == math_text_char_node)) {
             lua_pushinteger(L, math_character(*n));
-        } else {
-            lua_pushnil(L);
         }
         return 1;
     }
 
-*/
+/* node.direct.getcomponents */
+/* node.direct.setcomponents */
 
-/* node.direct.getchar */
-
-static int lua_nodelib_direct_getcharacter(lua_State * L)
+static int lua_nodelib_direct_getcomponents(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (type(n) == glyph_node) {
-        lua_pushinteger(L, character(n));
-    } else if ((type(n) == math_char_node) || (type(n) == math_text_char_node)) {
-        lua_pushinteger(L, math_character(n));
+    if ((n) && (type(n) == glyph_node)) {
+        lua_pushinteger(L, lig_ptr(n));
     } else {
         lua_pushnil(L);
     }
@@ -569,25 +545,26 @@
     return 1;
 }
 
-static int lua_nodelib_direct_getcomponents(lua_State * L)
+static int lua_nodelib_direct_setcomponents(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (type(n) == glyph_node) {
-        lua_pushinteger(L, lig_ptr(n));
-    } else {
-        lua_pushnil(L);
+    if ((n) && (type(n) == glyph_node)) {
+        if (lua_type(L, 2) == LUA_TNUMBER) {
+            lig_ptr(n) = (halfword) lua_tointeger(L, 2);
+        } else {
+            lig_ptr(n) = null;
+        }
     }
-    return 1;
+    return 0;
 }
 
+/* node.direct.getlang */
+/* node.direct.setlang */
+
 static int lua_nodelib_direct_getlang(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (type(n) == glyph_node) {
+    if ((n) && (type(n) == glyph_node)) {
         lua_pushinteger(L, char_lang(n));
     } else {
         lua_pushnil(L);
@@ -595,6 +572,22 @@
     return 1;
 }
 
+static int lua_nodelib_direct_setlang(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if ((n) && (type(n) == glyph_node)) {
+        if (lua_type(L, 2) == LUA_TNUMBER) {
+            set_char_lang(n,lua_tointeger(L, 2));
+        } else {
+            /* nothing */
+        }
+    }
+    return 0;
+}
+
+/* node.direct.getattributelist */
+/* node.direct.setattributelist */
+
 static int lua_nodelib_direct_getattributelist(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
@@ -606,15 +599,42 @@
     return 1;
 }
 
+static int lua_nodelib_direct_setattributelist(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if ((n) && nodetype_has_attributes(type(n))) {
+        if (lua_type(L, 2) == LUA_TNUMBER) {
+            halfword a =lua_tointeger(L, 2);
+            if (type(a) == attribute_list_node) {
+                reassign_attribute(n,a);
+            } else if (nodetype_has_attributes(type(a))) {
+                reassign_attribute(n,node_attr(a));
+            } else {
+                reassign_attribute(n,null);
+            }
+        } else {
+            reassign_attribute(n,null);
+        }
+        return 0;
+    }
+    return 0;
+}
+
+/* node.direct.getpenalty */
+/* node.direct.setpenalty */
+
 static int lua_nodelib_direct_getpenalty(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (type(n) == penalty_node) {
-        lua_pushinteger(L, penalty(n));
-    } else if (type(n) == disc_node) {
-        lua_pushinteger(L, disc_penalty(n));
+    if (n) {
+        halfword t = type(n);
+        if (t == penalty_node) {
+            lua_pushinteger(L, penalty(n));
+        } else if (t == disc_node) {
+            lua_pushinteger(L, disc_penalty(n));
+        } else {
+            lua_pushnil(L);
+        }
     } else {
         lua_pushnil(L);
     }
@@ -621,15 +641,137 @@
     return 1;
 }
 
+static int lua_nodelib_direct_setpenalty(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == penalty_node) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                penalty(n) = (halfword) lua_tointeger(L, 2);
+            } else {
+                penalty(n) = 0;
+            }
+        } else if (t == disc_node) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                disc_penalty(n) = (halfword) lua_tointeger(L, 2);
+            } else {
+                penalty(n) = 0;
+            }
+        }
+    }
+    return 0;
+}
+
+/* node.direct.getnucleus */
+/* node.direct.getsub */
+/* node.direct.getsup */
+
+static int lua_nodelib_direct_getnucleus(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == simple_noad || t == accent_noad || t == radical_noad) {
+            lua_pushinteger(L, nucleus(n));
+            return 1;
+        }
+    }
+    lua_pushnil(L);
+    return 1;
+}
+
+static int lua_nodelib_direct_setnucleus(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == simple_noad || t == accent_noad || t == radical_noad) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                nucleus(n) = lua_tointeger(L,2);
+            } else {
+                nucleus(n) = null;
+            }
+        }
+    }
+    return 0;
+}
+
+static int lua_nodelib_direct_getsub(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == simple_noad || t == accent_noad || t == radical_noad) {
+            lua_pushinteger(L, subscr(n));
+            return 1;
+        }
+    }
+    lua_pushnil(L);
+    return 1;
+}
+
+static int lua_nodelib_direct_setsub(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == simple_noad || t == accent_noad || t == radical_noad) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                subscr(n) = lua_tointeger(L,2);
+            } else {
+                subscr(n) = null;
+            }
+        }
+    }
+    return 0;
+}
+
+static int lua_nodelib_direct_getsup(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == simple_noad || t == accent_noad || t == radical_noad) {
+            lua_pushinteger(L, subscr(n));
+            return 1;
+        }
+    }
+    lua_pushnil(L);
+    return 1;
+}
+
+static int lua_nodelib_direct_setsup(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == simple_noad || t == accent_noad || t == radical_noad) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                supscr(n) = lua_tointeger(L,2);
+            } else {
+                supscr(n) = null;
+            }
+        }
+    }
+    return 0;
+}
+
+/* node.direct.getkern (overlaps with getwidth) */
+/* node.direct.setkern (overlaps with getwidth) */
+
 static int lua_nodelib_direct_getkern(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (type(n) == kern_node || type(n) == margin_kern_node) {
-        lua_pushinteger(L, width(n));
-    } else if (type(n) == math_node) {
-        lua_pushinteger(L, surround(n));
+    if (n) {
+        halfword t = type(n);
+        if (t == kern_node || t == margin_kern_node) {
+            lua_pushinteger(L, width(n));
+        } else if (t == math_node) {
+            lua_pushinteger(L, surround(n));
+        } else {
+            lua_pushnil(L);
+        }
     } else {
         lua_pushnil(L);
     }
@@ -636,19 +778,50 @@
     return 1;
 }
 
+static int lua_nodelib_direct_setkern(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n != null) {
+        halfword t = type(n);
+        if (t == kern_node || t == margin_kern_node) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                width(n) = (halfword) lua_tointeger(L, 2);
+            } else {
+                width(n) = 0;
+            }
+            if (lua_type(L, 3) == LUA_TNUMBER) {
+                subtype(n) = (halfword) lua_tointeger(L, 3);
+            }
+        } else if (t == math_node) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                surround(n) = (halfword) lua_tointeger(L, 2);
+            } else {
+                surround(n) = 0;
+            }
+        }
+    }
+    return 0;
+}
+
+/* node.direct.getdir */
+/* node.direct.setdir */
+
 static int lua_nodelib_direct_getdir(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (type(n) == dir_node) {
-        lua_push_dir_text(L, dir_dir(n));
-    } else if (type(n) == hlist_node || type(n) == vlist_node) {
-        lua_push_dir_par(L, box_dir(n));
-    } else if (type(n) == rule_node) {
-        lua_push_dir_par(L, rule_dir(n));
-    } else if (type(n) == local_par_node) {
-        lua_push_dir_par(L, local_par_dir(n));
+    if (n) {
+        halfword t = type(n);
+        if (t == dir_node) {
+            lua_push_dir_text(L, dir_dir(n));
+        } else if (t == hlist_node || t == vlist_node) {
+            lua_push_dir_par(L, box_dir(n));
+        } else if (t == rule_node) {
+            lua_push_dir_par(L, rule_dir(n));
+        } else if (t == local_par_node) {
+            lua_push_dir_par(L, local_par_dir(n));
+        } else {
+            lua_pushnil(L);
+        }
     } else {
         lua_pushnil(L);
     }
@@ -655,12 +828,31 @@
     return 1;
 }
 
+static int lua_nodelib_direct_setdir(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == dir_node) {
+            dir_dir(n) = nodelib_getdir(L, 2, 0);
+        } else if (t == hlist_node || type(n) == vlist_node) {
+            box_dir(n) = nodelib_getdir(L, 2, 1);
+        } else if (t == rule_node) {
+            rule_dir(n) = nodelib_getdir(L, 2, 1);
+        } else if (t == local_par_node) {
+            local_par_dir(n) = nodelib_getdir(L, 3, 1);
+        }
+    }
+    return 0;
+}
+
+/* node.direct.getoffsets */
+/* node.direct.setoffsets */
+
 static int lua_nodelib_direct_getoffsets(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (type(n) == glyph_node) {
+    if ((n) && (type(n) == glyph_node)) {
         lua_pushinteger(L, x_displace(n));
         lua_pushinteger(L, y_displace(n));
         return 2;
@@ -670,56 +862,98 @@
     return 1;
 }
 
-/* node.getdisc */
+static int lua_nodelib_direct_setoffsets(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if ((n) && (type(n) == glyph_node)) {
+        if ((lua_type(L, 2) == LUA_TNUMBER)) {
+            x_displace(n) = (halfword) lua_tointeger(L, 2);
+        }
+        if ((lua_type(L, 3) == LUA_TNUMBER)) {
+            y_displace(n) = (halfword) lua_tointeger(L, 3);
+        }
+    }
+    return 0;
+}
 
-static int lua_nodelib_direct_getdiscretionary(lua_State * L)
+/* node.direct.getdisc */
+/* node.direct.setdisc */
+
+static int lua_nodelib_direct_getdisc(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n != null) {
-        if (type(n) == disc_node) {
-            nodelib_pushdirect_or_nil(vlink(pre_break(n)));
-            nodelib_pushdirect_or_nil(vlink(post_break(n)));
-            nodelib_pushdirect_or_nil(vlink(no_break(n)));
-            if (lua_isboolean(L, 2)) {
-                if (lua_toboolean(L, 2)) {
-                    nodelib_pushdirect_or_nil(tlink(pre_break(n)));
-                    nodelib_pushdirect_or_nil(tlink(post_break(n)));
-                    nodelib_pushdirect_or_nil(tlink(no_break(n)));
-                    return 6;
+    if ((n) && (type(n) == disc_node)) {
+        nodelib_pushdirect_or_nil(vlink(pre_break(n)));
+        nodelib_pushdirect_or_nil(vlink(post_break(n)));
+        nodelib_pushdirect_or_nil(vlink(no_break(n)));
+        if (lua_isboolean(L, 2) && lua_toboolean(L, 2)) {
+            nodelib_pushdirect_or_nil(tlink(pre_break(n)));
+            nodelib_pushdirect_or_nil(tlink(post_break(n)));
+            nodelib_pushdirect_or_nil(tlink(no_break(n)));
+            return 6;
+        }
+        return 3;
+    } else {
+        return 0;
+    }
+}
+
+static int lua_nodelib_direct_setdisc(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (type(n) == disc_node) {
+        int t = lua_gettop(L) ;
+        if (t > 1) {
+            set_disc_field(pre_break(n), lua_tointeger(L,2));
+            if (t > 2) {
+                set_disc_field(post_break(n), lua_tointeger(L,3));
+                if (t > 3) {
+                    set_disc_field(no_break(n), lua_tointeger(L,4));
+                    if (t > 4) {
+                        subtype(n) = (quarterword) lua_tointeger(L,5);
+                        if (t > 5) {
+                            disc_penalty(n) = lua_tointeger(L,6);
+                        }
+                    }
+                } else {
+                    set_disc_field(no_break(n), null);
                 }
+            } else {
+                set_disc_field(post_break(n), null);
+                set_disc_field(no_break(n), null);
             }
-            return 3;
+        } else {
+            set_disc_field(pre_break(n), null);
+            set_disc_field(post_break(n), null);
+            set_disc_field(no_break(n), null);
         }
     }
-    lua_pushnil(L);
-    return 1;
+    return 0;
 }
 
-static int lua_nodelib_getdiscretionary(lua_State * L)
-{
-    halfword *a;
-    halfword *n = lua_touserdata(L, 1);
-    if (n != NULL) {
-        if (type(*n) == disc_node) {
+    /* node.getdisc */
+
+    static int lua_nodelib_getdisc(lua_State * L)
+    {
+        halfword *a;
+        halfword *n = lua_touserdata(L, 1);
+        if ((n != NULL) && (type(*n) == disc_node)) {
             fast_metatable_or_nil(vlink(pre_break(*n)));
             fast_metatable_or_nil(vlink(post_break(*n)));
             fast_metatable_or_nil(vlink(no_break(*n)));
-            if (lua_isboolean(L, 2)) {
-                if (lua_toboolean(L, 2)) {
-                    fast_metatable_or_nil(tlink(pre_break(*n)));
-                    fast_metatable_or_nil(tlink(post_break(*n)));
-                    fast_metatable_or_nil(tlink(no_break(*n)));
-                    return 6;
-                }
+            if (lua_isboolean(L, 2) && lua_toboolean(L, 2)) {
+                fast_metatable_or_nil(tlink(pre_break(*n)));
+                fast_metatable_or_nil(tlink(post_break(*n)));
+                fast_metatable_or_nil(tlink(no_break(*n)));
+                return 6;
             }
             return 3;
         }
+        return 0;
     }
-    lua_pushnil(L);
-    return 1;
-}
 
-/* getwhd: only core nodes */
+/* node.direct.getwhd */
+/* node.direct.setwhd */
 
 #define push_list_whd(n) \
     lua_pushinteger(L, width(n));  \
@@ -756,31 +990,6 @@
     return 0;
 }
 
-static int lua_nodelib_getwhd(lua_State * L)
-{
-    halfword *n = lua_touserdata(L, 1);
-    if (n != NULL) {
-        halfword t = type(*n);
-        if ((t == hlist_node) || (t == vlist_node) || (t == rule_node) || (t == unset_node)) {
-            push_list_whd(*n);
-            return 3;
-        } else if (t == glyph_node) {
-            push_char_whd(*n);
-            return 3;
-        } else if (t == glue_node) {
-            halfword l = leader_ptr(*n);
-            if (l != null) {
-                t = type(l) ;
-                if ((t == hlist_node) || (t == vlist_node) || (t == rule_node)) {
-                    push_list_whd(l);
-                    return 3;
-                }
-            }
-        }
-    }
-    return 0;
-}
-
 static int lua_nodelib_direct_setwhd(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
@@ -822,50 +1031,33 @@
     return 0;
 }
 
-/* node.getlist */
+    /* node.getwhd */
 
-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 if ((type(*n) == sub_box_node) || (type(*n) == sub_mlist_node)) {
-        fast_metatable_or_nil_alink(math_list(*n));
-    } else {
-        lua_pushnil(L);
-    }
-    return 1;
-}
-
-/*
-
-static int lua_nodelib_setlist(lua_State * L)
-{
-    halfword *n = lua_touserdata(L, 1);
-    if (n != null) {
-        if ((type(*n) == hlist_node) || (type(*n) == vlist_node)) {
-            if (lua_type(L,2) == LUA_TNIL) {
-                list_ptr(n) = null;
-            } else {
-                halfword *l = lua_touserdata(L, 2);
-                list_ptr(n) = l;
+    static int lua_nodelib_getwhd(lua_State * L)
+    {
+        halfword *n = lua_touserdata(L, 1);
+        if (n != NULL) {
+            halfword t = type(*n);
+            if ((t == hlist_node) || (t == vlist_node) || (t == rule_node) || (t == unset_node)) {
+                push_list_whd(*n);
+                return 3;
+            } else if (t == glyph_node) {
+                push_char_whd(*n);
+                return 3;
+            } else if (t == glue_node) {
+                halfword l = leader_ptr(*n);
+                if (l != null) {
+                    t = type(l) ;
+                    if ((t == hlist_node) || (t == vlist_node) || (t == rule_node)) {
+                        push_list_whd(l);
+                        return 3;
+                    }
+                }
             }
-        } else {
-            if (lua_type(L,2) == LUA_TNIL) {
-                math_list(n) = null;
-            } else {
-                halfword *l = lua_touserdata(L, 2);
-                math_list(n) = l;
-            }
+        }
+        return 0;
     }
-    return 0;
-}
 
-*/
-
 /* node.direct.getlist */
 
 static int lua_nodelib_direct_getlist(lua_State * L)
@@ -916,30 +1108,31 @@
     return 0;
 }
 
-/* node.getleader */
+    /* node.getlist */
 
-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);
+    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 if ((type(*n) == sub_box_node) || (type(*n) == sub_mlist_node)) {
+            fast_metatable_or_nil_alink(math_list(*n));
+        } else {
+            lua_pushnil(L);
+        }
+        return 1;
     }
-    return 1;
-}
 
 /* node.direct.getleader */
+/* node.direct.setleader */
 
 static int lua_nodelib_direct_getleader(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (type(n) == glue_node) {
+    if ((n) && (type(n) == glue_node)) {
         nodelib_pushdirect_or_nil(leader_ptr(n));
     } else {
         lua_pushnil(L);
@@ -947,10 +1140,10 @@
     return 1;
 }
 
-static int lua_nodelib_direct_setleader(lua_State * L)
+    static int lua_nodelib_direct_setleader(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if ((n != null) && (type(n) == glue_node)) {
+    if ((n) && (type(n) == glue_node)) {
         if (lua_type(L,2) == LUA_TNUMBER) {
             leader_ptr(n) = (halfword) lua_tointeger(L, 2);
         } else {
@@ -960,164 +1153,241 @@
     return 0;
 }
 
-/* node.getnext */
+    /* node.getleader */
 
-static int lua_nodelib_getnext(lua_State * L)
+    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.getnext */
+/* node.direct.setnext */
+
+static int lua_nodelib_direct_getnext(lua_State * L)
 {
-    halfword *a;
-    /* [given-node] [...]*/
-    halfword *p = lua_touserdata(L, 1);
-    if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+    halfword p = lua_tointeger(L, 1);
+    if (p == null) {
         lua_pushnil(L);
     } else {
-        /* [given-node] [mt-given-node]*/
-        lua_get_metatablelua(luatex_node);
-        /* [given-node] [mt-given-node] [mt-node]*/
-        if (!lua_rawequal(L, -1, -2)) {
-            lua_pushnil(L);
+        nodelib_pushdirect_or_nil(vlink(p));
+    }
+    return 1;
+}
+
+static int lua_nodelib_direct_setnext(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        if (lua_type(L, 2) == LUA_TNUMBER) {
+            vlink(n) = (halfword) lua_tointeger(L, 2);
         } else {
-            fast_metatable_or_nil(vlink(*p));
+            vlink(n) = null;
         }
     }
-    return 1; /* just one*/
+    return 0;
 }
 
-/* node.fast.getnext
+    /* node.getnext */
 
-    static int lua_nodelib_fast_getnext(lua_State * L)
+    static int lua_nodelib_getnext(lua_State * L)
     {
         halfword *a;
+        /* [given-node] [...]*/
         halfword *p = lua_touserdata(L, 1);
-        if ((p == NULL) || (!vlink(*p))){
+        if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
             lua_pushnil(L);
         } else {
-            lua_settop(L,1);
-            lua_getmetatable(L,1);
-            a = lua_newuserdata(L, sizeof(halfword));
-            *a = vlink(*p);
-            lua_replace(L,1);
-            lua_setmetatable(L,1);
+            /* [given-node] [mt-given-node]*/
+            lua_get_metatablelua(luatex_node);
+            /* [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;
+        return 1; /* just one*/
     }
 
-*/
+/* node.direct.getprev */
+/* node.direct.setprev */
 
-/* node.direct.getnext */
-
-static int lua_nodelib_direct_getnext(lua_State * L)
+static int lua_nodelib_direct_getprev(lua_State * L)
 {
     halfword p = lua_tointeger(L, 1);
     if (p == null) {
         lua_pushnil(L);
-    } else if ((lua_type(L, 2) == LUA_TNUMBER)) {
-        /* experiment */
-        int n = lua_tointeger(L,2);
-        while (p != null && n > 0) {
-            p = vlink(p);
-            n -= 1;
-        }
-        nodelib_pushdirect_or_nil(p);
     } else {
-        nodelib_pushdirect_or_nil(vlink(p));
+        nodelib_pushdirect_or_nil(alink(p));
     }
     return 1;
 }
 
-/* node.getprev */
-
-static int lua_nodelib_getprev(lua_State * L)
+static int lua_nodelib_direct_setprev(lua_State * L)
 {
-    halfword *a;
-    halfword *p = lua_touserdata(L, 1);
-    if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
-        lua_pushnil(L);
-    } else {
-        /* experiment */
-        lua_get_metatablelua(luatex_node);
-        if (!lua_rawequal(L, -1, -2)) {
-            lua_pushnil(L);
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        if (lua_type(L, 2) == LUA_TNUMBER) {
+            alink(n) = (halfword) lua_tointeger(L, 2);
         } else {
-            fast_metatable_or_nil(alink(*p));
+            alink(n) = null;
         }
     }
-    return 1;
+    return 0;
 }
 
-static int lua_nodelib_getboth(lua_State * L)
+    /* 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_get_metatablelua(luatex_node);
+            if (!lua_rawequal(L, -1, -2)) {
+                lua_pushnil(L);
+            } else {
+                fast_metatable_or_nil(alink(*p));
+            }
+        }
+        return 1;
+    }
+
+/* node.direct.getboth */
+/* node.direct.setboth */
+
+static int lua_nodelib_direct_getboth(lua_State * L)
 {
-    halfword *a;
-    halfword *p = lua_touserdata(L, 1);
-    if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        nodelib_pushdirect_or_nil(alink(n));
+        nodelib_pushdirect_or_nil(vlink(n));
+    } else {
         lua_pushnil(L);
         lua_pushnil(L);
-    } else {
-        lua_get_metatablelua(luatex_node);
-        if (!lua_rawequal(L, -1, -2)) {
-            lua_pushnil(L);
-            lua_pushnil(L);
+    }
+    return 2;
+}
+
+static int lua_nodelib_direct_setboth(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        if (lua_type(L, 2) == LUA_TNUMBER) {
+            alink(n) = (halfword) lua_tointeger(L, 2);
         } else {
-            fast_metatable_or_nil(alink(*p));
-            fast_metatable_or_nil(vlink(*p));
+            alink(n) = null;
         }
+        if (lua_type(L, 3) == LUA_TNUMBER) {
+            vlink(n) = (halfword) lua_tointeger(L, 3);
+        } else {
+            vlink(n) = null;
+        }
     }
-    return 2;
+    return 0;
 }
 
-/* node.fast.getprev
+    /* node.getboth */
 
-    static int lua_nodelib_fast_getprev(lua_State * L)
+    static int lua_nodelib_getboth(lua_State * L)
     {
         halfword *a;
         halfword *p = lua_touserdata(L, 1);
-        if ((p == NULL) || (!alink(*p))) {
+        if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
             lua_pushnil(L);
+            lua_pushnil(L);
         } else {
-            lua_settop(L,1);
-            lua_getmetatable(L,1);
-            a = lua_newuserdata(L, sizeof(halfword));
-            *a = alink(*p);
-            lua_replace(L,1);
-            lua_setmetatable(L,1);
+            lua_get_metatablelua(luatex_node);
+            if (lua_rawequal(L, -1, -2)) {
+                fast_metatable_or_nil(alink(*p));
+                fast_metatable_or_nil(vlink(*p));
+            } else {
+                lua_pushnil(L);
+                lua_pushnil(L);
+            }
         }
-        return 1;
+        return 2;
     }
 
+/* node.direct.setlink */
+/* node.direct.setsplit  */
+
+/*
+    a b b nil c d         : prev-a-b-c-next
+    nil a b b nil c d nil : nil-a-b-c-nil
 */
 
-/* node.direct.getprev */
-
-static int lua_nodelib_direct_getprev(lua_State * L)
+static int lua_nodelib_direct_setlink(lua_State * L)
 {
-    halfword p = lua_tointeger(L, 1);
-    if (p == null) {
+    int n = lua_gettop(L);
+    int i;
+    halfword h = null; /* head node */
+    halfword t = null; /* tail node */
+    halfword c = null; /* current node */
+    for (i=1;i<=n;i++) {
+        /*
+            we don't go for the tail of the current node because we can inject
+            between existing nodes and the nodes themselves can have old values
+            for prev and next, so ... only single nodes are looked at!
+        */
+        if (lua_type(L, i) == LUA_TNUMBER) {
+            c = lua_tointeger(L, i);
+            if (c != t) {
+                if (t != null) {
+                    vlink(t) = c;
+                    alink(c) = t;
+                } else if (i > 1) {
+                    /* we assume that the first node is a kind of head */
+                    alink(c) = null;
+                }
+                t = c;
+                if (h == null) {
+                    h = t;
+                }
+            } else {
+                /* we ignore duplicate nodes which can be tails or the previous */
+            }
+        } else if (t == null) {
+            /* we just ignore nil nodes and have no tail yet */
+        } else {
+            /* safeguard: a nil in the list can be meant as end so we nil the next of tail */
+            vlink(t) = null;
+        }
+    }
+    if (h == null) {
+        /* no head */
         lua_pushnil(L);
-    } else if ((lua_type(L, 2) == LUA_TNUMBER)) {
-        int n = lua_tointeger(L,2);
-        while (p != null && n > 0) {
-            p = alink(p);
-            n -= 1;
-        }
-        nodelib_pushdirect_or_nil(p);
     } else {
-        nodelib_pushdirect_or_nil(alink(p));
+        /* first valid head */
+        lua_pushinteger(L,h);
     }
     return 1;
 }
 
-/* node.direct.getboth */
-
-static int lua_nodelib_direct_getboth(lua_State * L)
+static int lua_nodelib_direct_setsplit(lua_State * L)
 {
-    halfword p = lua_tointeger(L, 1);
-    if (p == null) {
-        lua_pushnil(L);
-        lua_pushnil(L);
-    } else {
-        nodelib_pushdirect_or_nil(alink(p));
-        nodelib_pushdirect_or_nil(vlink(p));
+    if (lua_type(L, 1) == LUA_TNUMBER && (lua_type(L, 2) == LUA_TNUMBER)) {
+        halfword l = lua_tointeger(L, 1);
+        halfword r = lua_tointeger(L, 2);
+        if (l != r) {
+            alink(vlink(l)) = null;
+            vlink(alink(r)) = null;
+        }
+        vlink(l) = null;
+        alink(r) = null;
     }
-    return 2;
+    return 0;
 }
 
 /* node.subtype (maybe also return them for other node types now) */
@@ -2539,6 +2809,9 @@
 }
 
 /* node.direct.get_attribute */
+/* node.direct.set_attribute */
+/* node.direct.unset_attribute */
+/* node.direct.find_attribute */
 
 static int lua_nodelib_direct_get_attribute(lua_State * L)
 {
@@ -2570,6 +2843,26 @@
     return 1;
 }
 
+static int lua_nodelib_direct_set_attribute(lua_State * L)
+{
+    int i, val;
+    halfword n = lua_tointeger(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;
+}
+
 static int lua_nodelib_direct_find_attribute(lua_State * L) /* returns attr value and node */
 {
     halfword c = lua_tointeger(L, 1);
@@ -2607,36 +2900,35 @@
     return 0;
 }
 
-/* node.set_attribute */
-
-static int lua_nodelib_set_attribute(lua_State * L)
+static int lua_nodelib_direct_unset_attribute(lua_State * L)
 {
-    if (lua_gettop(L) == 3) {
-        int i = lua_tointeger(L, 2);
-        int val = lua_tointeger(L, 3);
-        halfword n = *check_isnode(L, 1);
-        if (val == UNUSED_ATTRIBUTE) {
-            (void) unset_attribute(n, i, val);
+    halfword n = lua_tointeger(L, 1);
+    if (n == null) {
+        lua_pushnil(L);
+    } else if (lua_gettop(L) <= 3) { /* a useless test, we never test for that elsewhere */
+        int i = (int)luaL_checknumber(L, 2);
+        int val = (int)luaL_optnumber(L, 3, UNUSED_ATTRIBUTE);
+        int ret = unset_attribute(n, i, val);
+        if (ret > UNUSED_ATTRIBUTE) {
+            lua_pushinteger(L, ret);
         } else {
-            set_attribute(n, i, val);
+            lua_pushnil(L);
         }
-    } else {
-        luaL_error(L, "incorrect number of arguments");
+    } else { /* can go */
+        return luaL_error(L, "incorrect number of arguments");
     }
-    return 0;
+    return 1;
 }
 
-/* node.direct.set_attribute */
+/* node.set_attribute */
+/* node.unset_attribute */
 
-static int lua_nodelib_direct_set_attribute(lua_State * L)
+static int lua_nodelib_set_attribute(lua_State * L)
 {
-    int i, val;
-    halfword n = lua_tointeger(L, 1);
-    if (n == null)
-        return 0;
     if (lua_gettop(L) == 3) {
-        i = (int) lua_tointeger(L, 2);
-        val = (int) lua_tointeger(L, 3);
+        int i = lua_tointeger(L, 2);
+        int val = lua_tointeger(L, 3);
+        halfword n = *check_isnode(L, 1);
         if (val == UNUSED_ATTRIBUTE) {
             (void) unset_attribute(n, i, val);
         } else {
@@ -2648,8 +2940,6 @@
     return 0;
 }
 
-/* node.unset_attribute */
-
 static int lua_nodelib_unset_attribute(lua_State * L)
 {
     if (lua_gettop(L) <= 3) {
@@ -2668,95 +2958,172 @@
     }
 }
 
-/* node.direct.unset_attribute */
+/* node.direct.getwidth  */
+/* node.direct.setwidth  */
+/* node.direct.getheight (for consistency) */
+/* node.direct.setheight (for consistency) */
+/* node.direct.getdepth  (for consistency) */
+/* node.direct.setdepth  (for consistency) */
 
-static int lua_nodelib_direct_unset_attribute(lua_State * L)
+/* split ifs for clearity .. compiler will optimize */
+
+static int lua_nodelib_direct_getwidth(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushnil(L);
-    } else if (lua_gettop(L) <= 3) { /* a useless test, we never test for that elsewhere */
-        int i = (int)luaL_checknumber(L, 2);
-        int val = (int)luaL_optnumber(L, 3, UNUSED_ATTRIBUTE);
-        int ret = unset_attribute(n, i, val);
-        if (ret > UNUSED_ATTRIBUTE) {
-            lua_pushinteger(L, ret);
+    if (n) {
+        halfword t = type(n);
+        if (t == hlist_node || t == vlist_node || t == rule_node) {
+            lua_pushinteger(L,width(n));
+        } else if (t == glyph_node) {
+            lua_pushinteger(L, char_width(font(n),character(n)));
+        } else if (t == glue_node || t == glue_spec_node || t == math_node || t == ins_node) {
+            lua_pushinteger(L,width(n));
+        } else if (t == kern_node || t == margin_kern_node) {
+            lua_pushinteger(L,width(n));
+        } else if (t == unset_node) {
+            lua_pushinteger(L,width(n));
         } else {
             lua_pushnil(L);
         }
-    } else { /* can go */
-        return luaL_error(L, "incorrect number of arguments");
+    } else {
+        lua_pushnil(L);
     }
     return 1;
 }
 
-/* glue */
+static int lua_nodelib_direct_setwidth(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == hlist_node || t == vlist_node || t == rule_node || t == glue_node || t == glue_spec_node || t == math_node ||
+                t == kern_node || t == margin_kern_node ||  t == ins_node || t == unset_node) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                width(n) = lua_tointeger(L,2);
+            } else {
+                width(n) = 0;
+            }
+        }
+    }
+    return 0;
+}
 
-static int lua_nodelib_set_glue(lua_State * L)
+static int lua_nodelib_direct_getheight(lua_State * L)
 {
-    halfword n = *check_isnode(L, 1);
-    int top = lua_gettop(L) ;
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
-        width(n)         = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? lua_roundnumber(L,2) : 0;
-        stretch(n)       = ((top > 2 && lua_type(L, 3) == LUA_TNUMBER)) ? lua_roundnumber(L,3) : 0;
-        shrink(n)        = ((top > 3 && lua_type(L, 4) == LUA_TNUMBER)) ? lua_roundnumber(L,4) : 0;
-        stretch_order(n) = ((top > 4 && lua_type(L, 5) == LUA_TNUMBER)) ? lua_tointeger(L,5) : 0;
-        shrink_order(n)  = ((top > 5 && lua_type(L, 6) == LUA_TNUMBER)) ? lua_tointeger(L,6) : 0;
-        return 0;
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == hlist_node || t == vlist_node || t == rule_node) {
+            lua_pushinteger(L,height(n));
+        } else if (t == glyph_node) {
+            lua_pushinteger(L, char_height(font(n),character(n)));
+        } else if (t == unset_node || t == ins_node) {
+            lua_pushinteger(L,height(n));
+        } else {
+            lua_pushnil(L);
+        }
     } else {
-        return luaL_error(L, "glue (spec) expected");
+        lua_pushnil(L);
     }
+    return 1;
 }
 
-static int lua_nodelib_direct_set_glue(lua_State * L)
+static int lua_nodelib_direct_setheight(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    int top = lua_gettop(L) ;
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
-        width(n)         = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? lua_roundnumber(L,2) : 0;
-        stretch(n)       = ((top > 2 && lua_type(L, 3) == LUA_TNUMBER)) ? lua_roundnumber(L,3) : 0;
-        shrink(n)        = ((top > 3 && lua_type(L, 4) == LUA_TNUMBER)) ? lua_roundnumber(L,4) : 0;
-        stretch_order(n) = ((top > 4 && lua_type(L, 5) == LUA_TNUMBER)) ? lua_tointeger(L,5) : 0;
-        shrink_order(n)  = ((top > 5 && lua_type(L, 6) == LUA_TNUMBER)) ? lua_tointeger(L,6) : 0;
-        return 0;
+    if (n) {
+        halfword t = type(n);
+        if (t == hlist_node || t == vlist_node || t == rule_node || t == unset_node) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                height(n) = lua_tointeger(L,2);
+            } else {
+                height(n) = 0;
+            }
+        }
+    }
+    return 0;
+}
+
+static int lua_nodelib_direct_getdepth(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == hlist_node || t == vlist_node || t == rule_node) {
+            lua_pushinteger(L,depth(n));
+        } else if (t == glyph_node) {
+            lua_pushinteger(L, char_depth(font(n),character(n)));
+        } else if (t == unset_node || t == ins_node) {
+            lua_pushinteger(L,depth(n));
+        } else {
+            lua_pushnil(L);
+        }
     } else {
-        return luaL_error(L, "glue (spec) expected");
+        lua_pushnil(L);
     }
+    return 1;
 }
 
-static int lua_nodelib_get_glue(lua_State * L)
+static int lua_nodelib_direct_setdepth(lua_State * L)
 {
-    halfword n = *check_isnode(L, 1);
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
-        int b = -1; /* false: only width, true or unset: 5 values */
-        if (lua_gettop(L) == 2) {
-            b = lua_toboolean(L, 2);
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == hlist_node || t == vlist_node || t == rule_node || t == unset_node) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                depth(n) = lua_tointeger(L,2);
+            } else {
+                depth(n) = 0;
+            }
         }
-        lua_pushinteger(L,width(n));
-        if (b == 0)
+    }
+    return 0;
+}
+
+/* node.direct.getshift */
+/* node.direct.setshift */
+
+static int lua_nodelib_direct_getshift(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == hlist_node || t == vlist_node) {
+            lua_pushinteger(L,shift_amount(n));
             return 1;
-        lua_pushinteger(L,stretch(n));
-        lua_pushinteger(L,shrink(n));
-        lua_pushinteger(L,stretch_order(n));
-        lua_pushinteger(L,shrink_order(n));
-        return 5;
-    } else {
-        return luaL_error(L, "glue (spec) expected");
+        }
     }
+    lua_pushnil(L);
+    return 1;
 }
 
+static int lua_nodelib_direct_setshift(lua_State * L)
+{
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == hlist_node || t == vlist_node) {
+            if (lua_type(L, 2) == LUA_TNUMBER) {
+                shift_amount(n) = lua_tointeger(L,2);
+            } else {
+                shift_amount(n) = 0;
+            }
+        }
+    }
+    return 0;
+}
+
+/* node.direct.getglue */
+/* node.direct.setglue */
+/* node.direct.is_zero_glue */
+
 static int lua_nodelib_direct_get_glue(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
-        int b = -1;
-        if (lua_gettop(L) == 2) {
-            b = lua_toboolean(L, 2);
-        }
-        lua_pushinteger(L,width(n));
-        if (b == 0) {
-            return 1;
-        } else {
+    if (n) {
+        halfword t = type(n);
+        if (t == glue_node || t == glue_spec_node || t == math_node || t == ins_node) {
+            lua_pushinteger(L,width(n));
             lua_pushinteger(L,stretch(n));
             lua_pushinteger(L,shrink(n));
             lua_pushinteger(L,stretch_order(n));
@@ -2763,83 +3130,100 @@
             lua_pushinteger(L,shrink_order(n));
             return 5;
         }
-    } else {
-        return luaL_error(L, "glue (spec) expected");
     }
+    return 0;
 }
 
-static int lua_nodelib_is_zero_glue(lua_State * L)
+static int lua_nodelib_direct_set_glue(lua_State * L)
 {
-    halfword n = *check_isnode(L, 1);
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
-        lua_pushboolean(L,(width(n) == 0 && stretch(n) == 0 && shrink(n) == 0));
-        return 1;
-    } else {
-        return luaL_error(L, "glue (spec) expected");
+    halfword n = lua_tointeger(L, 1);
+    if (n) {
+        int top = lua_gettop(L);
+        halfword t = type(n);
+        if (t == glue_node || t == glue_spec_node || t == math_node) {
+            width(n)         = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? lua_roundnumber(L,2) : 0;
+            stretch(n)       = ((top > 2 && lua_type(L, 3) == LUA_TNUMBER)) ? lua_roundnumber(L,3) : 0;
+            shrink(n)        = ((top > 3 && lua_type(L, 4) == LUA_TNUMBER)) ? lua_roundnumber(L,4) : 0;
+            stretch_order(n) = ((top > 4 && lua_type(L, 5) == LUA_TNUMBER)) ? lua_tointeger(L,5) : 0;
+            shrink_order(n)  = ((top > 5 && lua_type(L, 6) == LUA_TNUMBER)) ? lua_tointeger(L,6) : 0;
+        }
     }
+    return 0;
 }
 
 static int lua_nodelib_direct_is_zero_glue(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
-    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node)) {
-        lua_pushboolean(L,(width(n) == 0 && stretch(n) == 0 && shrink(n) == 0));
-        return 1;
-    } else {
-        return luaL_error(L, "glue (spec) expected");
+    if (n) {
+        halfword t = type(n);
+        if (t == glue_node || t == glue_spec_node || t == math_node || t == ins_node) {
+            lua_pushboolean(L,(width(n) == 0 && stretch(n) == 0 && shrink(n) == 0));
+            return 1;
+        }
     }
+    return luaL_error(L, "glue (spec) expected");
 }
 
-/* iteration */
+/* node.getglue */
+/* node.setglue */
+/* node.is_zero_glue */
 
-static int nodelib_aux_nil(lua_State * L)
+static int lua_nodelib_get_glue(lua_State * L)
 {
-    lua_pushnil(L);
-    return 1;
+    halfword n = *check_isnode(L, 1);
+    if (n) {
+        halfword t = type(n);
+        if (t == glue_node || t == glue_spec_node || t == math_node || t== ins_node) {
+            lua_pushinteger(L,width(n));
+            lua_pushinteger(L,stretch(n));
+            lua_pushinteger(L,shrink(n));
+            lua_pushinteger(L,stretch_order(n));
+            lua_pushinteger(L,shrink_order(n));
+            return 5;
+        }
+    }
+    return luaL_error(L, "glue (spec) expected");
 }
 
-/* node.traverse_id */
-
-static int nodelib_aux_next_filtered(lua_State * L)
+static int lua_nodelib_set_glue(lua_State * L)
 {
-    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);
+    halfword n = *check_isnode(L, 1);
+    int top = lua_gettop(L) ;
+    if (n) {
+        halfword t = type(n);
+        if (t == glue_node || t == glue_spec_node || t == math_node) {
+            width(n)         = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? lua_roundnumber(L,2) : 0;
+            stretch(n)       = ((top > 2 && lua_type(L, 3) == LUA_TNUMBER)) ? lua_roundnumber(L,3) : 0;
+            shrink(n)        = ((top > 3 && lua_type(L, 4) == LUA_TNUMBER)) ? lua_roundnumber(L,4) : 0;
+            stretch_order(n) = ((top > 4 && lua_type(L, 5) == LUA_TNUMBER)) ? lua_tointeger(L,5) : 0;
+            shrink_order(n)  = ((top > 5 && lua_type(L, 6) == LUA_TNUMBER)) ? lua_tointeger(L,6) : 0;
+        }
     }
-    while (t != null && type(t) != i) {
-        t = vlink(t);
-    }
-    if (t == null) {
-        lua_pushnil(L);
-    } else {
-        fast_metatable_top(t);
-    }
-    return 1;
+    return luaL_error(L, "glue (spec) expected");
+    return 0;
 }
 
-static int lua_nodelib_traverse_filtered(lua_State * L)
+static int lua_nodelib_is_zero_glue(lua_State * L)
 {
-    halfword n;
-    if (lua_isnil(L, 2)) {
-        lua_pushcclosure(L, nodelib_aux_nil, 0);
+    halfword n = *check_isnode(L, 1);
+    if ((n != null) && (type(n) == glue_node || type(n) == glue_spec_node || type(n) == math_node || type(n) == ins_node)) {
+        lua_pushboolean(L,(width(n) == 0 && stretch(n) == 0 && shrink(n) == 0));
         return 1;
     }
-    n = *check_isnode(L, 2);
-    lua_pop(L, 1);              /* the node, integer remains */
-    lua_pushcclosure(L, nodelib_aux_next_filtered, 1);
-    lua_nodelib_push_fast(L, n);
+    return luaL_error(L, "glue (spec) expected");
+}
+
+/* iteration */
+
+static int nodelib_aux_nil(lua_State * L)
+{
     lua_pushnil(L);
-    return 3;
+    return 1;
 }
 
 /* node.direct.traverse_id */
+/* node.direct.traverse */
+/* node.direct.traverse_char */
 
 static int nodelib_direct_aux_next_filtered(lua_State * L)
 {
@@ -2884,8 +3268,43 @@
     return 3;
 }
 
-/* node.direct.traverse_char */
+static int nodelib_direct_aux_next(lua_State * L)
+{
+    halfword t;            /* traverser */
+    if (lua_isnil(L, 2)) { /* first call */
+        t = lua_tointeger(L,1) ;
+        lua_settop(L,1);
+    } else {
+        t = lua_tointeger(L,2) ;
+        t = vlink(t);
+        lua_settop(L,2);
+    }
+    if (t == null) {
+        lua_pushnil(L);
+    } else {
+        lua_pushinteger(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_tointeger(L, 1);
+    if (n == null) {
+        lua_pushcclosure(L, nodelib_aux_nil, 0);
+        return 1;
+    }
+    lua_pushcclosure(L, nodelib_direct_aux_next, 0);
+    lua_pushinteger(L,n);
+    lua_pushnil(L);
+    return 3;
+}
+
 static int nodelib_direct_aux_next_char(lua_State * L)
 {
     halfword t;            /* traverser */
@@ -2929,13 +3348,16 @@
     return 3;
 }
 
+/* node.traverse_id */
 /* node.traverse */
+/* node.traverse_char */
 
-static int nodelib_aux_next(lua_State * L)
+static int nodelib_aux_next_filtered(lua_State * L)
 {
-    halfword t;            /* traverser */
-    halfword *a;           /* a or *a */
-    if (lua_isnil(L, 2)) { /* first call */
+    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 {
@@ -2943,6 +3365,9 @@
         t = vlink(t);
         lua_settop(L,2);
     }
+    while (t != null && type(t) != i) {
+        t = vlink(t);
+    }
     if (t == null) {
         lua_pushnil(L);
     } else {
@@ -2951,26 +3376,25 @@
     return 1;
 }
 
-static int lua_nodelib_traverse(lua_State * L)
+static int lua_nodelib_traverse_filtered(lua_State * L)
 {
     halfword n;
-    if (lua_isnil(L, 1)) {
+    if (lua_isnil(L, 2)) {
         lua_pushcclosure(L, nodelib_aux_nil, 0);
         return 1;
     }
-    n = *check_isnode(L, 1);
-    lua_pushcclosure(L, nodelib_aux_next, 0);
+    n = *check_isnode(L, 2);
+    lua_pop(L, 1);              /* the node, integer remains */
+    lua_pushcclosure(L, nodelib_aux_next_filtered, 1);
     lua_nodelib_push_fast(L, n);
     lua_pushnil(L);
     return 3;
 }
 
-/* node.traverse_char */
-
-static int nodelib_aux_next_char(lua_State * L)
+static int nodelib_aux_next(lua_State * L)
 {
     halfword t;            /* traverser */
-    halfword *a;
+    halfword *a;           /* a or *a */
     if (lua_isnil(L, 2)) { /* first call */
         t = *check_isnode(L, 1);
         lua_settop(L,1);
@@ -2979,20 +3403,15 @@
         t = vlink(t);
         lua_settop(L,2);
     }
-    while (1) {
-        if (t == null) {
-            break;
-        } else if ((type(t) == glyph_node) && (subtype(t) < 256)){
-            fast_metatable_top(t);
-            return 1;
-        } else {
-            t = vlink(t);
-        }
+    if (t == null) {
+        lua_pushnil(L);
+    } else {
+        fast_metatable_top(t);
     }
     return 1;
 }
 
-static int lua_nodelib_traverse_char(lua_State * L)
+static int lua_nodelib_traverse(lua_State * L)
 {
     halfword n;
     if (lua_isnil(L, 1)) {
@@ -3000,34 +3419,38 @@
         return 1;
     }
     n = *check_isnode(L, 1);
-    lua_pushcclosure(L, nodelib_aux_next_char, 0);
+    lua_pushcclosure(L, nodelib_aux_next, 0);
     lua_nodelib_push_fast(L, n);
     lua_pushnil(L);
     return 3;
 }
 
-/* node.direct.traverse */
-
-static int nodelib_direct_aux_next(lua_State * L)
+static int nodelib_aux_next_char(lua_State * L)
 {
     halfword t;            /* traverser */
+    halfword *a;
     if (lua_isnil(L, 2)) { /* first call */
-        t = lua_tointeger(L,1) ;
+        t = *check_isnode(L, 1);
         lua_settop(L,1);
     } else {
-        t = lua_tointeger(L,2) ;
+        t = *check_isnode(L, 2);
         t = vlink(t);
         lua_settop(L,2);
     }
-    if (t == null) {
-        lua_pushnil(L);
-    } else {
-        lua_pushinteger(L,t);
+    while (1) {
+        if (t == null) {
+            break;
+        } else if ((type(t) == glyph_node) && (subtype(t) < 256)){
+            fast_metatable_top(t);
+            return 1;
+        } else {
+            t = vlink(t);
+        }
     }
     return 1;
 }
 
-static int lua_nodelib_direct_traverse(lua_State * L)
+static int lua_nodelib_traverse_char(lua_State * L)
 {
     halfword n;
     if (lua_isnil(L, 1)) {
@@ -3034,13 +3457,9 @@
         lua_pushcclosure(L, nodelib_aux_nil, 0);
         return 1;
     }
-    n = (halfword) lua_tointeger(L, 1);
-    if (n == null) {
-        lua_pushcclosure(L, nodelib_aux_nil, 0);
-        return 1;
-    }
-    lua_pushcclosure(L, nodelib_direct_aux_next, 0);
-    lua_pushinteger(L,n);
+    n = *check_isnode(L, 1);
+    lua_pushcclosure(L, nodelib_aux_next_char, 0);
+    lua_nodelib_push_fast(L, n);
     lua_pushnil(L);
     return 3;
 }
@@ -3060,7 +3479,32 @@
     return 1;
 }
 
+/* node.direct.length */
+/* node.direct.count */
+
+static int lua_nodelib_direct_length(lua_State * L)
+{
+    halfword m;
+    halfword n = lua_tointeger(L, 1);
+    if (n == 0) {
+        lua_pushinteger(L, 0);
+        return 1;
+    }
+    m = (halfword) lua_tointeger(L, 2);
+    return do_lua_nodelib_count(L, m, -1, n);
+}
+
+static int lua_nodelib_direct_count(lua_State * L)
+{
+    return do_lua_nodelib_count(L,
+        (halfword) lua_tointeger(L, 3), /* m */
+        (int) lua_tointeger(L, 1),      /* i */
+        (halfword) lua_tointeger(L, 2)  /* n */
+    );
+}
+
 /* node.length */
+/* node.count */
 
 static int lua_nodelib_length(lua_State * L)
 {
@@ -3076,22 +3520,6 @@
     return do_lua_nodelib_count(L, m, -1, n);
 }
 
-/* node.direct.length */
-
-static int lua_nodelib_direct_length(lua_State * L)
-{
-    halfword m;
-    halfword n = lua_tointeger(L, 1);
-    if (n == 0) {
-        lua_pushinteger(L, 0);
-        return 1;
-    }
-    m = (halfword) lua_tointeger(L, 2);
-    return do_lua_nodelib_count(L, m, -1, n);
-}
-
-/* node.count */
-
 static int lua_nodelib_count(lua_State * L)
 {
     halfword n;
@@ -3107,17 +3535,6 @@
     return do_lua_nodelib_count(L, m, i, n);
 }
 
-/* node.direct.count */
-
-static int lua_nodelib_direct_count(lua_State * L)
-{
-    return do_lua_nodelib_count(L,
-        (halfword) lua_tointeger(L, 3), /* m */
-        (int) lua_tointeger(L, 1),      /* i */
-        (halfword) lua_tointeger(L, 2)  /* n */
-    );
-}
-
 /* getting and setting fields (helpers) */
 
 int nodelib_getlist(lua_State * L, int n)
@@ -4527,7 +4944,7 @@
             lua_pushnil(L);
         }
     } else if (t == margin_kern_node) {
-        if (lua_key_eq(s, width)) {
+        if (lua_key_eq(s, kern) ||lua_key_eq(s, width)) {
             lua_pushinteger(L, width(n));
         } else if (lua_key_eq(s, glyph)) {
             nodelib_pushdirect_or_nil(margin_char(n));
@@ -5861,7 +6278,7 @@
     } else if (t == margin_kern_node) {
         if (lua_key_eq(s, subtype)) {
             subtype(n) = (quarterword) lua_tointeger(L, 3);
-        } else if (lua_key_eq(s, width)) {
+        } else if (lua_key_eq(s, width) || lua_key_eq(s, kern)) {
             width(n) = (halfword) lua_roundnumber(L, 3);
         } else if (lua_key_eq(s, glyph)) {
             margin_char(n) = nodelib_getlist(L, 3);
@@ -6235,272 +6652,9 @@
     return 0;
 }
 
-static int lua_nodelib_direct_setcharacter(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if ((n) && (lua_type(L, 2) == LUA_TNUMBER)) {
-        if (type(n) == glyph_node) {
-            character(n) = (halfword) lua_tointeger(L, 2);
-        } else if ((type(n) == math_char_node) || (type(n) == math_text_char_node)) {
-            math_character(n) = (halfword) lua_tointeger(L, 2);
-        }
-    }
-    return 0;
-}
+/* direct.is_char  */
+/* direct.is_glyph */
 
-static int lua_nodelib_direct_setfont(lua_State * L) /* family_font is not yet in manual, what does arg 2 do */
-{
-    halfword n = lua_tointeger(L, 1);
-    if (n != null) {
-        halfword t = type(n);
-        /* mandate font */
-        if (t == glyph_node) {
-            font(n) = (halfword) lua_tointeger(L,2);
-            /* optional char */
-            if ((lua_type(L, 3) == LUA_TNUMBER)) {
-                character(n) = (halfword) lua_tointeger(L, 3);
-            }
-        }
-    }
-    return 0;
-}
-
-
-static int lua_nodelib_direct_setcomponents(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if ((n) && (lua_type(L, 2) == LUA_TNUMBER)) {
-        if (type(n) == glyph_node) {
-            lig_ptr(n) = (halfword) lua_tointeger(L, 2);
-        }
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setattributelist(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if ((n) && nodetype_has_attributes(type(n))) {
-        if (lua_type(L, 2) == LUA_TNUMBER) {
-            halfword a =lua_tointeger(L, 2);
-            if (type(a) == attribute_list_node) {
-                reassign_attribute(n,a);
-            } else if (nodetype_has_attributes(type(a))) {
-                reassign_attribute(n,node_attr(a));
-            } else {
-                reassign_attribute(n,null);
-            }
-        } else {
-            reassign_attribute(n,null);
-        }
-        return 0;
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setlang(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if ((n) && (lua_type(L, 2) == LUA_TNUMBER)) {
-        if (type(n) == glyph_node) {
-            set_char_lang(n,lua_tointeger(L, 2));
-        }
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setpenalty(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if (n == null) {
-        if (type(n) == penalty_node) {
-            if (lua_type(L, 2) == LUA_TNUMBER) {
-                penalty(n) = (halfword) lua_tointeger(L, 2);
-            } else {
-                penalty(n) = 0;
-            }
-        } else if (type(n) == disc_node) {
-            if (lua_type(L, 2) == LUA_TNUMBER) {
-                disc_penalty(n) = (halfword) lua_tointeger(L, 2);
-            } else {
-                penalty(n) = 0;
-            }
-        }
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setkern(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if (n != null) {
-        if (type(n) == kern_node || type(n) == margin_kern_node) {
-            if (lua_type(L, 2) == LUA_TNUMBER) {
-                width(n) = (halfword) lua_tointeger(L, 2);
-            } else {
-                width(n) = 0;
-            }
-            if (lua_type(L, 3) == LUA_TNUMBER) {
-                subtype(n) = (halfword) lua_tointeger(L, 3);
-            }
-        } else if (type(n) == math_node) {
-            if (lua_type(L, 2) == LUA_TNUMBER) {
-                surround(n) = (halfword) lua_tointeger(L, 2);
-            } else {
-                surround(n) = 0;
-            }
-        }
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setdir(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if (n != null) {
-        if (type(n) == dir_node) {
-            dir_dir(n) = nodelib_getdir(L, 2, 0);
-        } else if (type(n) == hlist_node || type(n) == vlist_node) {
-            box_dir(n) = nodelib_getdir(L, 2, 1);
-        } else if (type(n) == rule_node) {
-            rule_dir(n) = nodelib_getdir(L, 2, 1);
-        } else if (type(n) == local_par_node) {
-            local_par_dir(n) = nodelib_getdir(L, 3, 1);
-        }
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setoffsets(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if ((n) && (type(n) == glyph_node)) {
-        if ((lua_type(L, 2) == LUA_TNUMBER)) {
-            x_displace(n) = (halfword) lua_tointeger(L, 2);
-        }
-        if ((lua_type(L, 3) == LUA_TNUMBER)) {
-            y_displace(n) = (halfword) lua_tointeger(L, 3);
-        }
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setnext(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if (n) {
-        if (lua_type(L, 2) == LUA_TNUMBER) {
-            vlink(n) = (halfword) lua_tointeger(L, 2);
-        } else {
-            vlink(n) = null;
-        }
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setprev(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if (n) {
-        if (lua_type(L, 2) == LUA_TNUMBER) {
-            alink(n) = (halfword) lua_tointeger(L, 2);
-        } else {
-            alink(n) = null;
-        }
-    }
-    return 0;
-}
-
-static int lua_nodelib_direct_setboth(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if (n) {
-        if (lua_type(L, 2) == LUA_TNUMBER) {
-            alink(n) = (halfword) lua_tointeger(L, 2);
-        } else {
-            alink(n) = null;
-        }
-        if (lua_type(L, 3) == LUA_TNUMBER) {
-            vlink(n) = (halfword) lua_tointeger(L, 3);
-        } else {
-            vlink(n) = null;
-        }
-    }
-    return 0;
-}
-
-/*
-static int lua_nodelib_direct_setlink(lua_State * L)
-{
-    if (lua_type(L, 1) == LUA_TNUMBER) {
-        halfword a = lua_tointeger(L, 1);
-        if (lua_type(L, 2) == LUA_TNUMBER) {
-            halfword b = lua_tointeger(L, 2);
-            vlink(a) = b;
-            alink(b) = a;
-        } else {
-            vlink(a) = null;
-        }
-    } else if (lua_type(L, 2) == LUA_TNUMBER) {
-        halfword b = lua_tointeger(L, 2);
-        alink(b) = null;
-    }
-    return 0;
-}
-*/
-
-/*
-    a b b nil c d         : prev-a-b-c-next
-    nil a b b nil c d nil : nil-a-b-c-nil
-*/
-
-static int lua_nodelib_direct_setlink(lua_State * L)
-{
-    int n = lua_gettop(L);
-    int i;
-    halfword h = null; /* head node */
-    halfword t = null; /* tail node */
-    halfword c = null; /* current node */
-    for (i=1;i<=n;i++) {
-        /*
-            we don't go for the tail of the current node because we can inject
-            between existing nodes and the nodes themselves can have old values
-            for prev and next, so ... only single nodes are looked at!
-        */
-        if (lua_type(L, i) == LUA_TNUMBER) {
-            c = lua_tointeger(L, i);
-            if (c != t) {
-                if (t != null) {
-                    vlink(t) = c;
-                    alink(c) = t;
-                } else if (i > 1) {
-                    /* we assume that the first node is a kind of head */
-                    alink(c) = null;
-                }
-                t = c;
-                if (h == null) {
-                    h = t;
-                }
-            } else {
-                /* we ignore duplicate nodes which can be tails or the previous */
-            }
-        } else if (t == null) {
-            /* we just ignore nil nodes and have no tail yet */
-        } else {
-            /* safeguard: a nil in the list can be meant as end so we nil the next of tail */
-            vlink(t) = null;
-        }
-    }
-    if (h == null) {
-        /* no head */
-        lua_pushnil(L);
-    } else {
-        /* first valid head */
-        lua_pushinteger(L,h);
-    }
-    return 1;
-}
-
 static int lua_nodelib_direct_is_char(lua_State * L)
 {
     halfword n = lua_tointeger(L, 1);
@@ -6536,38 +6690,7 @@
     return 2;
 }
 
-static int lua_nodelib_direct_setdiscretionary(lua_State * L)
-{
-    halfword n = lua_tointeger(L, 1);
-    if (type(n) == disc_node) {
-        int t = lua_gettop(L) ;
-        if (t > 1) {
-            set_disc_field(pre_break(n), lua_tointeger(L,2));
-            if (t > 2) {
-                set_disc_field(post_break(n), lua_tointeger(L,3));
-                if (t > 3) {
-                    set_disc_field(no_break(n), lua_tointeger(L,4));
-                    if (t > 4) {
-                        subtype(n) = (quarterword) lua_tointeger(L,5);
-                        if (t > 5) {
-                            disc_penalty(n) = lua_tointeger(L,6);
-                        }
-                    }
-                } else {
-                    set_disc_field(no_break(n), null);
-                }
-            } else {
-                set_disc_field(post_break(n), null);
-                set_disc_field(no_break(n), null);
-            }
-        } else {
-            set_disc_field(pre_break(n), null);
-            set_disc_field(post_break(n), null);
-            set_disc_field(no_break(n), null);
-        }
-    }
-    return 0;
-}
+/* direct.setfield */
 
 static int lua_nodelib_direct_setfield(lua_State * L)
 {
@@ -6960,7 +7083,7 @@
     } else if (t == margin_kern_node) {
         if (lua_key_eq(s, subtype)) {
             subtype(n) = (quarterword) lua_tointeger(L, 3);
-        } else if (lua_key_eq(s, width)) {
+        } else if (lua_key_eq(s, width) || lua_key_eq(s, width)) {
             width(n) = (halfword) lua_roundnumber(L, 3);
         } else if (lua_key_eq(s, glyph)) {
             margin_char(n) = nodelib_popdirect(3);
@@ -7112,8 +7235,10 @@
 }
 
 /* node.getbox = tex.getbox */
+/* node.setbox = tex.setbox */
 
 /* node.direct.getbox */
+/* node.direct.setbox */
 
 static int lua_nodelib_direct_getbox(lua_State * L)
 {
@@ -7129,9 +7254,6 @@
     return 1;
 }
 
-/* node.setbox = tex.setbox */
-/* node.setbox */
-
 static int lua_nodelib_direct_setbox(lua_State * L)
 {
     int isglobal = 0;
@@ -7504,7 +7626,7 @@
     {"flush_node", lua_nodelib_direct_flush_node},
     {"free", lua_nodelib_direct_free},
     {"getbox", lua_nodelib_direct_getbox},
-    {"getchar", lua_nodelib_direct_getcharacter},
+    {"getchar", lua_nodelib_direct_getchar},
     {"getcomponents", lua_nodelib_direct_getcomponents},
     {"getlang", lua_nodelib_direct_getlang},
     {"getkern", lua_nodelib_direct_getkern},
@@ -7511,8 +7633,12 @@
     {"getpenalty", lua_nodelib_direct_getpenalty},
     {"getdir", lua_nodelib_direct_getdir},
     {"getoffsets", lua_nodelib_direct_getoffsets},
-    {"getdisc", lua_nodelib_direct_getdiscretionary},
+    {"getdisc", lua_nodelib_direct_getdisc},
     {"getwhd", lua_nodelib_direct_getwhd},
+    {"getwidth", lua_nodelib_direct_getwidth},
+    {"getheight", lua_nodelib_direct_getheight},
+    {"getdepth", lua_nodelib_direct_getdepth},
+    {"getshift", lua_nodelib_direct_getshift},
     {"getfield", lua_nodelib_direct_getfield},
     {"getfont", lua_nodelib_direct_getfont},
     {"getid", lua_nodelib_direct_getid},
@@ -7523,6 +7649,9 @@
     {"getleader", lua_nodelib_direct_getleader},
     {"getsubtype", lua_nodelib_direct_getsubtype},
     {"getattributelist", lua_nodelib_direct_getattributelist},
+    {"getnucleus", lua_nodelib_direct_getnucleus},
+    {"getsub", lua_nodelib_direct_getsub},
+    {"getsup", lua_nodelib_direct_getsup},
     {"has_glyph", lua_nodelib_direct_has_glyph},
     {"has_attribute", lua_nodelib_direct_has_attribute},
     {"get_attribute", lua_nodelib_direct_get_attribute},
@@ -7550,7 +7679,7 @@
     {"set_attribute", lua_nodelib_direct_set_attribute},
     {"setbox", lua_nodelib_direct_setbox},
     {"setfield", lua_nodelib_direct_setfield},
-    {"setchar", lua_nodelib_direct_setcharacter},
+    {"setchar", lua_nodelib_direct_setchar},
     {"setfont", lua_nodelib_direct_setfont},
     {"setcomponents", lua_nodelib_direct_setcomponents},
     {"setlang", lua_nodelib_direct_setlang},
@@ -7558,16 +7687,24 @@
     {"setpenalty", lua_nodelib_direct_setpenalty},
     {"setdir", lua_nodelib_direct_setdir},
     {"setoffsets", lua_nodelib_direct_setoffsets},
-    {"setdisc", lua_nodelib_direct_setdiscretionary},
+    {"setdisc", lua_nodelib_direct_setdisc},
     {"setwhd", lua_nodelib_direct_setwhd},
+    {"setwidth", lua_nodelib_direct_setwidth},
+    {"setheight", lua_nodelib_direct_setheight},
+    {"setdepth", lua_nodelib_direct_setdepth},
+    {"setshift", lua_nodelib_direct_setshift},
     {"setnext", lua_nodelib_direct_setnext},
     {"setprev", lua_nodelib_direct_setprev},
     {"setboth", lua_nodelib_direct_setboth},
     {"setlink", lua_nodelib_direct_setlink},
+    {"setsplit", lua_nodelib_direct_setsplit},
     {"setlist", lua_nodelib_direct_setlist},
     {"setleader", lua_nodelib_direct_setleader},
     {"setsubtype", lua_nodelib_direct_setsubtype},
     {"setattributelist", lua_nodelib_direct_setattributelist},
+    {"setnucleus", lua_nodelib_direct_setnucleus},
+    {"setsub", lua_nodelib_direct_setsub},
+    {"setsup", lua_nodelib_direct_setsup},
     {"slide", lua_nodelib_direct_slide},
  /* {"subtype", lua_nodelib_subtype}, */ /* no node argument */
     {"tail", lua_nodelib_direct_tail},
@@ -7621,7 +7758,7 @@
     {"getnext", lua_nodelib_getnext},
     {"getprev", lua_nodelib_getprev},
     {"getboth", lua_nodelib_getboth},
-    {"getdisc", lua_nodelib_getdiscretionary},
+    {"getdisc", lua_nodelib_getdisc},
     {"getwhd", lua_nodelib_getwhd},
     {"getlist", lua_nodelib_getlist},
     {"getleader", lua_nodelib_getleader},
@@ -7628,7 +7765,7 @@
     {"getid", lua_nodelib_getid},
     {"getsubtype", lua_nodelib_getsubtype},
     {"getfont", lua_nodelib_getfont},
-    {"getchar", lua_nodelib_getcharacter},
+    {"getchar", lua_nodelib_getchar},
     {"getfield", lua_nodelib_getfield},
     {"setfield", lua_nodelib_setfield},
     {"has_glyph", lua_nodelib_has_glyph},

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c	2017-02-11 22:19:29 UTC (rev 43195)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c	2017-02-11 22:54:15 UTC (rev 43196)
@@ -898,21 +898,11 @@
         top -= 1;
     }
     /* [global] slot [width] [stretch] [shrink] [stretch_order] [shrink_order] */
-    if (top > 1) {
-        width(value) = lua_roundnumber(L,index+1);
-    }
-    if (top > 2) {
-        stretch(value) = lua_roundnumber(L,index+2);
-    }
-    if (top > 3) {
-        shrink(value) = lua_roundnumber(L,index+3);
-    }
-    if (top > 4) {
-        stretch_order(value) = lua_tointeger(L,index+4);
-    }
-    if (top > 5) {
-        shrink_order(value) = lua_tointeger(L,index+5);
-    }
+    if (top > 1) { width(value) = lua_roundnumber(L,index+1); }
+    if (top > 2) { stretch(value) = lua_roundnumber(L,index+2); }
+    if (top > 3) { shrink(value) = lua_roundnumber(L,index+3); }
+    if (top > 4) { stretch_order(value) = lua_tointeger(L,index+4); }
+    if (top > 5) { shrink_order(value) = lua_tointeger(L,index+5); }
     set_item_index_plus(L, index, skip_base, "skip", value, isglobal, is_glue_assign, set_tex_skip_register, true);
     return 0;
 }
@@ -921,16 +911,9 @@
 {
     int value = 0;
     int top = lua_gettop(L);
-    int b = -1; /* false: only width, true or unset: 5 values */
-    if (lua_type(L, top) == LUA_TBOOLEAN) {
-        b = lua_toboolean(L, top);
-        top -= 1 ;
-    }
     get_item_index_plus(L, top, skip_base, "skip", value, is_glue_assign, get_tex_skip_register, true);
     if (value == null) {
         lua_pushinteger(L,0);
-        if (b == 0)
-            return 1;
         lua_pushinteger(L,0);
         lua_pushinteger(L,0);
         lua_pushinteger(L,0);
@@ -937,8 +920,6 @@
         lua_pushinteger(L,0);
     } else {
         lua_pushinteger(L,width(value));
-        if (b == 0)
-            return 1;
         lua_pushinteger(L,stretch(value));
         lua_pushinteger(L,shrink(value));
         lua_pushinteger(L,stretch_order(value));
@@ -983,21 +964,11 @@
         top -= 1;
     }
     /* [global] slot [width] [stretch] [shrink] [stretch_order] [shrink_order] */
-    if (top > 1) {
-        width(value) = lua_roundnumber(L,index+1);
-    }
-    if (top > 2) {
-        stretch(value) = lua_roundnumber(L,index+2);
-    }
-    if (top > 3) {
-        shrink(value) = lua_roundnumber(L,index+3);
-    }
-    if (top > 4) {
-        stretch_order(value) = lua_tointeger(L,index+4);
-    }
-    if (top > 5) {
-        shrink_order(value) = lua_tointeger(L,index+5);
-    }
+    if (top > 1) { width(value) = lua_roundnumber(L,index+1); }
+    if (top > 2) { stretch(value) = lua_roundnumber(L,index+2); }
+    if (top > 3) { shrink(value) = lua_roundnumber(L,index+3); }
+    if (top > 4) { stretch_order(value) = lua_tointeger(L,index+4); }
+    if (top > 5) { shrink_order(value) = lua_tointeger(L,index+5); }
     set_item_index_plus(L, index, mu_skip_base, "muskip", value, isglobal, is_mu_glue_assign, set_tex_mu_skip_register, true);
     return 0;
 }
@@ -1709,26 +1680,18 @@
                 assign_internal_value((isglobal ? 4 : 0), equiv(cur_cs1), j);
             } else if (is_glue_assign(cur_cmd1)) {
                 int a = isglobal;
-if (lua_type(L, i) == LUA_TNUMBER) {
-                halfword value = copy_node(zero_glue);
-                width(value) = lua_roundnumber(L,i);
-                if (i > 1) {
-                    stretch(value) = lua_roundnumber(L,i+1);
+                if (lua_type(L, i) == LUA_TNUMBER) {
+                    halfword value = copy_node(zero_glue);
+                    width(value) = lua_roundnumber(L,i);
+                    if (i > 1) { stretch(value) = lua_roundnumber(L,i+1); }
+                    if (i > 3) { shrink(value) = lua_roundnumber(L,i+2); }
+                    if (i > 4) { stretch_order(value) = lua_tointeger(L,i+3); }
+                    if (i > 5) { shrink_order(value) = lua_tointeger(L,i+4); }
+                    define(equiv(cur_cs1), assign_glue_cmd, value);
+                } else {
+                    halfword *j1 = check_isnode(L, i);     /* the value */
+                    define(equiv(cur_cs1), assign_glue_cmd, *j1);
                 }
-                if (i > 3) {
-                    shrink(value) = lua_roundnumber(L,i+2);
-                }
-                if (i > 4) {
-                    stretch_order(value) = lua_tointeger(L,i+3);
-                }
-                if (i > 5) {
-                    shrink_order(value) = lua_tointeger(L,i+4);
-                }
-                define(equiv(cur_cs1), assign_glue_cmd, value);
-} else {
-                halfword *j1 = check_isnode(L, i);     /* the value */
-                define(equiv(cur_cs1), assign_glue_cmd, *j1);
-}
             } else if (is_toks_assign(cur_cmd1)) {
                 if (lua_type(L,i) == LUA_TSTRING) {
                     j = tokenlist_from_lua(L);  /* uses stack -1 */



More information about the tex-live-commits mailing list