Hi, Taco: In TeX's Packaging algorithm, TeX wraps lists into boxes. Knuth create two functions, hpack (p,w,m) and vpack (p,w,m)= vpackage(p,w,m,max_dimen) to solve this problem. In the LuaTeX manual, (4.1.3.13), only node.hpack is given. maybe we should also write something called node.vpack? I wrote one for LuaTeX since I need it in my document project. I think it will be useful to others too. The code is easy to write by following yours and here is the patch: yue@localhost ~/luatex $ svn diff Index: src/texk/web2c/luatexdir/lua/lnodelib.c =================================================================== --- src/texk/web2c/luatexdir/lua/lnodelib.c (revision 1985) +++ src/texk/web2c/luatexdir/lua/lnodelib.c (working copy) @@ -496,6 +496,32 @@ return 1; } +/* build a vbox */ + +static int lua_nodelib_vpack(lua_State * L) +{ + halfword n, p; + char *s; + integer w = 0; + int m = 1; + n = *(check_isnode(L, 1)); + if (lua_gettop(L) > 1) { + w = lua_tointeger(L, 2); + if (lua_gettop(L) > 2 && lua_type(L, 3) == LUA_TSTRING) { + s = (char *) lua_tostring(L, 3); + if (strcmp(s, "additional") == 0) { + m = 1; + } else { + m = lua_tonumber(L, 3); + } + } + } + p = vpackage(n, w, m, max_dimen); + lua_nodelib_push_fast(L, p); + return 1; +} + + /* create a hlist from a formula */ static int lua_nodelib_mlist_to_hlist(lua_State * L) @@ -3202,6 +3228,7 @@ {"copy", lua_nodelib_copy}, {"copy_list", lua_nodelib_copy_list}, {"hpack", lua_nodelib_hpack}, + {"vpack", lua_nodelib_vpack}, {"mlist_to_hlist", lua_nodelib_mlist_to_hlist}, {"family_font", lua_nodelib_mfont}, {"has_attribute", lua_nodelib_has_attribute}, btw, I think the original code buggy, shouldn't it be something like this? yue@localhost ~/luatex $ svn diff Index: src/texk/web2c/luatexdir/lua/lnodelib.c =================================================================== --- src/texk/web2c/luatexdir/lua/lnodelib.c (revision 1985) +++ src/texk/web2c/luatexdir/lua/lnodelib.c (working copy) @@ -482,13 +482,24 @@ n = *(check_isnode(L, 1)); if (lua_gettop(L) > 1) { w = lua_tointeger(L, 2); - if (lua_gettop(L) > 2 && lua_type(L, 3) == LUA_TSTRING) { - s = (char *) lua_tostring(L, 3); - if (strcmp(s, "additional") == 0) { - m = 1; - } else { + if (lua_gettop(L) > 2){ + if (lua_type(L, 3) == LUA_TSTRING) { + s = (char *) lua_tostring(L, 3); + if (strcmp(s, "additional") == 0) + m = 1; + else if (strcmp(s,"exactly") == 0) + m = 0; + else { + lua_pushstring(L, "3rd argument should be either additional or exactly"); + lua_error(L); + } + } + + else if (lua_type(L, 3) == LUA_TNUMBER) { m = lua_tonumber(L, 3); - } + }else{ + lua_pushstring(L, "incorrect 3rd argument"); + } } } p = hpack(n, w, m); @@ -496,6 +507,42 @@ return 1; } +/* build a vbox */ +static int lua_nodelib_vpack(lua_State * L) +{ + halfword n, p; + char *s; + integer w = 0; + int m = 1; + n = *(check_isnode(L, 1)); + if (lua_gettop(L) > 1) { + w = lua_tointeger(L, 2); + if (lua_gettop(L) > 2){ + if (lua_type(L, 3) == LUA_TSTRING) { + s = (char *) lua_tostring(L, 3); + if (strcmp(s, "additional") == 0) + m = 1; + else if (strcmp(s,"exactly") == 0) + m = 0; + else { + lua_pushstring(L, "3rd argument should be either additional or exactly"); + lua_error(L); + } + } + + else if (lua_type(L, 3) == LUA_TNUMBER) { + m = lua_tonumber(L, 3); + }else{ + lua_pushstring(L, "incorrect 3rd argument"); + } + } + } + p = vpackage(n, w, m, max_dimen); + lua_nodelib_push_fast(L, p); + return 1; +} + + /* create a hlist from a formula */ static int lua_nodelib_mlist_to_hlist(lua_State * L) @@ -3202,6 +3249,7 @@ {"copy", lua_nodelib_copy}, {"copy_list", lua_nodelib_copy_list}, {"hpack", lua_nodelib_hpack}, + {"vpack", lua_nodelib_vpack}, {"mlist_to_hlist", lua_nodelib_mlist_to_hlist}, {"family_font", lua_nodelib_mfont}, {"has_attribute", lua_nodelib_has_attribute}, yue@localhost ~/luatex $ Yue Wang