1 /* lnodelib.c
2
3 Copyright 2006-2013 Taco Hoekwater <taco@luatex.org>
4
5 This file is part of LuaTeX.
6
7 LuaTeX is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
11
12 LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
19
20 */
21
22 /*
23
24 The node getter and setter are adapted a bit by Hans and Luigi so blame
25 them! On the agenda: check all keys, maybe hide some fields that are not
26 supposed to be seen and set (scratch fields for the backend and par
27 builder).
28
29 After doing lots of tests with luatex and luajittex, with and without jit,
30 and with and without ffi, we came to the conclusion that userdata prevents
31 a speedup. We also found that the checking of metatables as well as assignment
32 comes with overhead that can't be neglected. This is normally not really a
33 problem but when processing fonts for more complex scripts it's quite some
34 overhead.
35
36 Because the userdata approach has some benefits, we stick to this. We did
37 some experiments with fast access (assuming nodes) and kept some of the code
38 commented here, but eventually settled for the direct approach. For code that
39 is proven to be okay, one can use the direct variants and operate on nodes
40 more directly. Currently these are numbers, but that might become light
41 userdata at one point, so *never* rely on that property. An important aspect
42 is that one cannot mix both methods, although with node.direct.tonode and
43 node.direct.todirect one can cast both representations.
44
45 So the advice is: use the indexed approach when possible and investigate the
46 direct one when speed might be an issue. For that reason we also provide the
47 get* and set* functions in the top level node namespace. There is a limited set
48 of getters.
49
50 getnext : parsing nodelist always involves this one
51 getprev : used less but is logical companion to getnext
52 getid : consulted a lot
53 getsubtype : consulted less but also a topper
54 getfont : used a lot in otf handling (glyph nodes are consulted a lot)
55 getchar : idem and also in other places
56 getlist : we often parse nested lists so this is a convenient one too (only hlist/vlist !)
57 getleader : comparable to list, seldom used in tex (but needs consulting
58 like lists)
59 getfield : generic getter, sufficient for the rest (other field names are
60 often shared so a specific getter makes no sense then)
61
62 Keep in mind that these only make sense when we're calling them millions of
63 times (which happens in font processing for instance). Setters are less important
64 as documents have not that many content related nodes (and setting many thousands
65 of properties is hardly a burden contrary to millions of consultations.)
66
67 Another change is that __index and __newindex are (as expected) exposed to
68 users but do no checking. The getfield and setfield functions do check. In
69 fact, fast mode can be simulated by fast_getfield = __index but the (measured)
70 benefit on average runs is not that large (some 5% when we also use the other
71 fast ones) which is easily nilled by inefficient coding. The direct variants
72 on the other hand can be significantly faster but with the drawback of lack
73 of userdata features. With respect to speed: keep in mind that measuring
74 a speedup on these functions is not representative for a normal run, where
75 much more happens.
76
77 maybe : setnext setprev setfont setchar (only makes sense for some scripts)
78
79 todo : check and optimize the direct function when possible
80
81 todo : once the direct ones are proven we can redefine some of the less
82 critical normal ones to call the direct ones after checking for
83 a first argument being a node (like protect/unprotect)
84
85 The code below has quite some duplicated code but this is also a prelude
86 to light userdata for diretc nodes so we prefer this method. Some userdata
87 variants could call the direct functions but not now (also because we don't
88 want to touch the originals too much). As usual: blame Luigi and Hans for
89 issues with this code. You can blame HH for weird or inaccurate comments.
90
91 Todo: as a prelude to lua 5.3 we should use integer instead of number when
92 possible. A boring job. We can use the direct variants for testing this.
93
94 Hans Hagen, Luigi Scarso (2011-2013)
95
96 */
97
98
99 #include "ptexlib.h"
100 #include "lua/luatex-api.h"
101 #ifdef LuajitTeX
102 #include "lua/lauxlib_bridge.h"
103 #else
104 #include "lauxlib.h"
105 #endif
106
107 /*
108
109 These macros create and access pointers (indices) to keys which is faster. The
110 shortcuts are created as part of the initialization.
111
112 */
113
114
115 /*
116
117 When the first argument to an accessor is a node, we can use it's metatable
118 entry when we are returning nodes, which saves a lookup.
119
120 */
121
122 #define fast_metatable(n) do { \
123 a = (halfword *) lua_newuserdata(L, sizeof(halfword)); \
124 *a = n; \
125 lua_getmetatable(L,1); \
126 lua_setmetatable(L,-2); \
127 } while (0)
128
129 #define fast_metatable_or_nil(n) do { \
130 if (n) { \
131 a = (halfword *) lua_newuserdata(L, sizeof(halfword)); \
132 *a = n; \
133 lua_getmetatable(L,1); \
134 lua_setmetatable(L,-2); \
135 } else { \
136 lua_pushnil(L); \
137 } \
138 } while (0)
139
140 #define fast_metatable_or_nil_alink(n) do { \
141 if (n) { \
142 alink(n) = null; \
143 a = (halfword *) lua_newuserdata(L, sizeof(halfword)); \
144 *a = n; \
145 lua_getmetatable(L,1); \
146 lua_setmetatable(L,-2); \
147 } else { \
148 lua_pushnil(L); \
149 } \
150 } while (0)
151
152 #define fast_metatable_top(n) do { \
153 a = (halfword *) lua_newuserdata(L, sizeof(halfword)); \
154 *a = n; \
155 lua_getmetatable(L,-2); \
156 lua_setmetatable(L,-2); \
157 } while (0)
158
159 #define lua_push_node_metatablelua do { \
160 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node)); \
161 lua_gettable(L, LUA_REGISTRYINDEX); \
162 } while (0)
163
164 /*
165
166 This is a first step towards abstract direct nodes. When we have Lua 5.3 we
167 need to check all returned values for being integers. This might be another
168 level of abtraction.
169
170 */
171
172 #define nodelib_pushdirect(n) lua_pushnumber(L,n)
173 #define nodelib_popdirect(n) lua_tointeger(L,n)
174
175 #define nodelib_pushdirect_or_nil(n) do { \
176 if (n==null) { \
177 lua_pushnil(L); \
178 } else { \
179 lua_pushnumber(L,n); \
180 } \
181 } while (0)
182
183 #define nodelib_pushdirect_or_nil_alink(n) do { \
184 if (n==null) { \
185 lua_pushnil(L); \
186 } else { \
187 alink(n) = null; \
188 lua_pushnumber(L,n); \
189 } \
190 } while (0)
191
192 /* handy sometimes: */
193
194 /* static void stackDump (lua_State * L) { */
195 /* int i; */
196 /* int top = lua_gettop(L); */
197 /* for (i = top; i >= 1; i--) { */
198 /* int t = lua_type(L, i); */
199 /* switch (t) { */
200 /* case LUA_TSTRING: */
201 /* printf("[%d] '%s'\n", i, lua_tostring(L, i)); */
202 /* break; */
203 /* case LUA_TBOOLEAN: */
204 /* printf("[%d] %s\n",i, lua_toboolean(L, i) ? "true" : "false"); */
205 /* break; */
206 /* case LUA_TNUMBER: */
207 /* printf("[%d] %g\n", i, lua_tonumber(L, i)); */
208 /* break; */
209 /* default: */
210 /* 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))); */
211 /* break; */
212 /* } */
213 /* } */
214 /* } */
215
216
217 #define nodelib_setattr(L, s, n) reassign_attribute(n,nodelib_getlist(L,s))
218
219 #define nodelib_gettoks(L,a) tokenlist_from_lua(L)
220
221 #define nodelib_getspec nodelib_getlist
222 #define nodelib_getaction nodelib_getlist
223
224 /* a quick helper for dir nodes; there is only a small set of possible values */
225
226 #define RETURN_DIR_VALUES(a) \
227 if (s==luaS_##a##_ptr) { \
228 return (dir_##a); \
229 } else if (!absolute_only) { \
230 if (s==luaS_p##a##_ptr) \
231 return (dir_##a); \
232 else if (s==luaS_m##a##_ptr) \
233 return ((dir_##a)-64); \
234 }
235
236 /* fetching a field from a node .. we can often use the reuse bot-of-stack metatable */
237
238 #define nodelib_pushlist(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } /* can be: fast_metatable_or_nil(n) */
239 #define nodelib_pushattr(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } /* can be: fast_metatable_or_nil(n) */
240 #define nodelib_pushspec(L,n) { lua_pushnumber(L,n); lua_nodelib_push_spec(L); } /* can be: fast_metatable_or_nil(n) - different criterium? */
241 #define nodelib_pushaction(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } /* can be: fast_metatable_or_nil(n) */
242 #define nodelib_pushstring(L,n) { char *ss=makecstring(n); lua_pushstring(L,ss); free(ss); }
243
244 /* find prev, and fix backlinks .. can be a macro instead (only used a few times) */
245
246 #define set_t_to_prev(head,current) \
247 t = head; \
248 while (vlink(t)!=current && t != null) { \
249 if (vlink(t)!=null) \
250 alink(vlink(t)) = t; \
251 t = vlink(t); \
252 }
253
254 #define get_node_type_id(L,n) do_get_node_type_id(L,n,node_data)
255 #define get_node_subtype_id(L,n) do_get_node_type_id(L,n,whatsit_node_data)
256
257 #define box(A) eqtb[box_base+(A)].hh.rh
258 #define direct_check_index_range(j,s) \
259 if (j<0 || j > 65535) { \
260 luaL_error(L, "incorrect index value %d for tex.%s()", (int)j, s); \
261 }
262
263 #define NODE_METATABLE "luatex.node"
264
265 #define DEBUG 0
266 #define DEBUG_OUT stdout
267
268 /* maybe these qualify as macros, not functions */
269
maybe_isnode(lua_State * L,int ud)270 static halfword *maybe_isnode(lua_State * L, int ud)
271 {
272 halfword *p = lua_touserdata(L, ud);
273 if (p != NULL) {
274 if (lua_getmetatable(L, ud)) {
275 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
276 lua_gettable(L, LUA_REGISTRYINDEX);
277 if (!lua_rawequal(L, -1, -2))
278 p = NULL;
279 lua_pop(L, 2);
280 }
281 }
282 return p;
283 }
284
285 /* we could make the message a function and just inline the rest (via a macro) */
286
check_isnode(lua_State * L,int ud)287 halfword *check_isnode(lua_State * L, int ud)
288 {
289 halfword *p = maybe_isnode(L, ud);
290 if (p != NULL)
291 return p;
292 luatex_fail("There should have been a lua <node> here, not an object with type %s!", luaL_typename(L, ud));
293 return NULL;
294 }
295
296 /*
297
298 This routine finds the numerical value of a string (or number) at
299 lua stack index |n|. If it is not a valid node type, returns -1
300
301 Todo: create a lua table instead at initialization time and then
302 use that hash, so that we don't need to loop for each lookup.
303
304 HH: can crash on noad 9
305
306 */
307
do_get_node_type_id(lua_State * L,int n,node_info * data)308 static int do_get_node_type_id(lua_State * L, int n, node_info * data)
309 {
310 int j;
311 /* switch (lua_type(L, n)) { */
312 /* case LUA_TNIL: */
313 /* printf("LUA_TNIL\n"); */
314 /* break; */
315 /* case LUA_TNUMBER: */
316 /* printf("LUA_TNUMBER\n"); */
317 /* break; */
318 /* case LUA_TBOOLEAN: */
319 /* printf("LUA_TBOOLEAN\n"); */
320 /* break; */
321 /* case LUA_TSTRING: */
322 /* printf("LUA_TSTRING\n"); */
323 /* break; */
324 /* case LUA_TTABLE: */
325 /* printf("LUA_TTABLE\n"); */
326 /* break; */
327 /* case LUA_TFUNCTION: */
328 /* printf("LUA_TFUNCTION\n"); */
329 /* break; */
330 /* case LUA_TUSERDATA: */
331 /* printf("LUA_TUSERDATA\n"); */
332 /* break; */
333 /* case LUA_TTHREAD: */
334 /* printf("LUA_TTHREAD\n"); */
335 /* break; */
336 /* case LUA_TLIGHTUSERDATA: */
337 /* printf("LUA_TLIGHTUSERDATA\n"); */
338 /* break; */
339 /* } */
340 if (lua_type(L, n) == LUA_TSTRING) {
341 const char *s = lua_tostring(L, n);
342 for (j = 0; data[j].id != -1; j++) {
343 if (strcmp(s, data[j].name) == 0)
344 return j;
345 }
346 } else if (lua_type(L, n) == LUA_TNUMBER) {
347 int i = (int) lua_tointeger(L, n);
348 for (j = 0; data[j].id != -1; j++) {
349 if (data[j].id == i)
350 return j;
351 }
352 }
353 return -1;
354 }
355
get_valid_node_type_id(lua_State * L,int n)356 static int get_valid_node_type_id(lua_State * L, int n)
357 {
358 int i = get_node_type_id(L, n);
359 if (i == -1) {
360 if (lua_type(L, n) == LUA_TSTRING) {
361 luaL_error(L, "Invalid node type id: %s", lua_tostring(L, n));
362 } else {
363 luaL_error(L, "Invalid node type id: %d", lua_tonumber(L, n));
364 }
365 }
366 return i;
367 }
368
get_valid_node_subtype_id(lua_State * L,int n)369 static int get_valid_node_subtype_id(lua_State * L, int n)
370 {
371 int i = get_node_subtype_id(L, n);
372 if (i == -1) {
373 if (lua_type(L, n) == LUA_TSTRING) {
374 luaL_error(L, "Invalid whatsit node id: %s", lua_tostring(L, n));
375 } else {
376 luaL_error(L, "Invalid whatsit node id: %d", lua_tonumber(L, n));
377 }
378 }
379 return i;
380 }
381
382 /* two simple helpers to speed up and simplify lua code (replaced by getnext and getprev) */
383
lua_nodelib_next(lua_State * L)384 static int lua_nodelib_next(lua_State * L)
385 {
386 halfword *p = maybe_isnode(L,1);
387 if (p != NULL && *p && vlink(*p)) {
388 lua_nodelib_push_fast(L,vlink(*p));
389 } else {
390 lua_pushnil(L);
391 }
392 return 1;
393 }
394
lua_nodelib_prev(lua_State * L)395 static int lua_nodelib_prev(lua_State * L)
396 {
397 halfword *p = maybe_isnode(L,1);
398 if (p != NULL && *p && alink(*p)) {
399 lua_nodelib_push_fast(L,alink(*p));
400 } else {
401 lua_pushnil(L);
402 }
403 return 1;
404 }
405
406 /*
407
408 static void lua_nodelib_push_simple(lua_State * L, halfword p)
409 {
410 halfword *a;
411 a = (halfword *) lua_newuserdata(L, sizeof(halfword));
412 *a = p;
413 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
414 lua_gettable(L, LUA_REGISTRYINDEX);
415 lua_setmetatable(L, -2);
416 }
417
418 */
419
420 /*
421
422 Creates a userdata object for a number found at the stack top, if it is
423 representing a node (i.e. an pointer into |varmem|). It replaces the
424 stack entry with the new userdata, or pushes |nil| if the number is |null|,
425 or if the index is definately out of range. This test could be improved.
426
427 */
428
lua_nodelib_push(lua_State * L)429 void lua_nodelib_push(lua_State * L)
430 {
431 halfword n;
432 halfword *a;
433 n = -1;
434 if (lua_isnumber(L, -1))
435 n = (int) lua_tointeger(L, -1);
436 lua_pop(L, 1);
437 if ((n == null) || (n < 0) || (n > var_mem_max)) {
438 lua_pushnil(L);
439 } else {
440 a = lua_newuserdata(L, sizeof(halfword));
441 *a = n;
442 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
443 lua_gettable(L, LUA_REGISTRYINDEX);
444 lua_setmetatable(L, -2);
445 }
446 return;
447 }
448
449 /* |spec_ptr| fields can legally be zero, which is why there is a special function. */
450
lua_nodelib_push_spec(lua_State * L)451 static void lua_nodelib_push_spec(lua_State * L)
452 {
453 halfword n;
454 halfword *a;
455 n = -1;
456 if (lua_isnumber(L, -1))
457 n = (halfword) lua_tointeger(L, -1);
458 lua_pop(L, 1);
459 if ((n < 0) || (n > var_mem_max)) {
460 lua_pushnil(L);
461 } else {
462 a = lua_newuserdata(L, sizeof(halfword));
463 *a = n;
464 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
465 lua_gettable(L, LUA_REGISTRYINDEX);
466 lua_setmetatable(L, -2);
467 }
468 return;
469 }
470
lua_nodelib_push_fast(lua_State * L,halfword n)471 void lua_nodelib_push_fast(lua_State * L, halfword n)
472 {
473 halfword *a;
474 a = lua_newuserdata(L, sizeof(halfword));
475 *a = n;
476 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
477 lua_gettable(L, LUA_REGISTRYINDEX);
478 lua_setmetatable(L, -2);
479 return;
480 }
481
482 /* converts type strings to type ids */
483
lua_nodelib_id(lua_State * L)484 static int lua_nodelib_id(lua_State * L)
485 {
486 int i = get_node_type_id(L, 1);
487 if (i >= 0) {
488 lua_pushnumber(L, i);
489 } else {
490 lua_pushnil(L);
491 }
492 return 1;
493 }
494
495 /* node.getid */
496
lua_nodelib_getid(lua_State * L)497 static int lua_nodelib_getid(lua_State * L)
498 {
499 /* [given-node] [...] */
500 halfword *p = lua_touserdata(L, 1);
501 if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
502 lua_pushnil(L);
503 return 1;
504 }
505 /* [given-node] [mt-given-node] */
506 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
507 lua_gettable(L, LUA_REGISTRYINDEX);
508 /* [given-node] [mt-given-node] [mt-node] */
509 if (!lua_rawequal(L, -1, -2)) {
510 lua_pushnil(L);
511 } else {
512 lua_pushnumber(L, type(*p));
513 }
514 return 1;
515 }
516
517 /* node.fast.getid
518
519 static int lua_nodelib_fast_getid(lua_State * L)
520 {
521 halfword *n;
522 n = (halfword *) lua_touserdata(L, 1);
523 lua_pushnumber(L, type(*n));
524 return 1;
525 }
526
527 */
528
529 /* node.direct.getid */
530
lua_nodelib_direct_getid(lua_State * L)531 static int lua_nodelib_direct_getid(lua_State * L)
532 {
533 halfword n;
534 n = (halfword) lua_tonumber(L, 1);
535 if (n == null) {
536 lua_pushnil(L);
537 } else {
538 lua_pushnumber(L, type(n));
539 }
540 return 1;
541 }
542
543 /* node.getsubtype */
544
lua_nodelib_getsubtype(lua_State * L)545 static int lua_nodelib_getsubtype(lua_State * L)
546 {
547 halfword *p = lua_touserdata(L, 1);
548 if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
549 lua_pushnil(L);
550 } else {
551 lua_push_node_metatablelua;
552 if ( (!lua_rawequal(L, -1, -2)) || (! nodetype_has_subtype(*p))) {
553 lua_pushnil(L);
554 } else {
555 lua_pushnumber(L, subtype(*p));
556 }
557 }
558 return 1;
559 }
560
561 /* node.fast.getsubtype
562
563 static int lua_nodelib_fast_getsubtype(lua_State * L)
564 {
565 halfword *n;
566 n = (halfword *) lua_touserdata(L, 1);
567 lua_pushnumber(L, subtype(*n));
568 return 1;
569 }
570
571 */
572
573 /* node.direct.getsubtype */
574
lua_nodelib_direct_getsubtype(lua_State * L)575 static int lua_nodelib_direct_getsubtype(lua_State * L)
576 {
577 halfword n;
578 n = (halfword) lua_tonumber(L, 1);
579 if (n == null) { /* no check, we assume sane use */
580 lua_pushnil(L);
581 } else {
582 lua_pushnumber(L, subtype(n));
583 }
584 return 1;
585 }
586
587 /* node.getfont */
588
lua_nodelib_getfont(lua_State * L)589 static int lua_nodelib_getfont(lua_State * L)
590 {
591 halfword *p = lua_touserdata(L, 1);
592 if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
593 lua_pushnil(L);
594 } else {
595 lua_push_node_metatablelua;
596 if ( (!lua_rawequal(L, -1, -2)) || (type(*p) != glyph_node) ) {
597 lua_pushnil(L);
598 } else {
599 lua_pushnumber(L, font(*p));
600 }
601 }
602 return 1;
603 }
604
605 /* node.fast.getfont
606
607 static int lua_nodelib_fast_getfont(lua_State * L)
608 {
609 halfword *n;
610 n = (halfword *) lua_touserdata(L, 1);
611 if (type(*n) != glyph_node) {
612 lua_pushnil(L);
613 } else {
614 lua_pushnumber(L, font(*n));
615 }
616 return 1;
617 }
618
619 */
620
621 /* node.direct.getfont */
622
lua_nodelib_direct_getfont(lua_State * L)623 static int lua_nodelib_direct_getfont(lua_State * L)
624 {
625 halfword n;
626 n = (halfword) lua_tonumber(L, 1);
627 if ((n == null) || (type(n) != glyph_node)) {
628 lua_pushnil(L);
629 } else {
630 lua_pushnumber(L, font(n));
631 }
632 return 1;
633 }
634
635 /* node.getchar */
636
lua_nodelib_getcharacter(lua_State * L)637 static int lua_nodelib_getcharacter(lua_State * L)
638 {
639 halfword *n = lua_touserdata(L, 1);
640 if ( (n == NULL) || (! lua_getmetatable(L,1)) ) {
641 lua_pushnil(L);
642 } else if (type(*n) == glyph_node) {
643 lua_pushnumber(L, character(*n));
644 } else if ((type(*n) == math_char_node) || (type(*n) == math_text_char_node)) {
645 lua_pushnumber(L, math_character(*n));
646 }
647 return 1;
648 }
649
650 /* node.fast.getchar
651
652 static int lua_nodelib_fast_getcharacter(lua_State * L)
653 {
654 halfword *n;
655 n = (halfword *) lua_touserdata(L, 1);
656 if (type(*n) == glyph_node) {
657 lua_pushnumber(L, character(*n));
658 } else if ((type(*n) == math_char_node) || (type(*n) == math_text_char_node)) {
659 lua_pushnumber(L, math_character(*n));
660 } else {
661 lua_pushnil(L);
662 }
663 return 1;
664 }
665
666 */
667
668 /* node.direct.getchar */
669
lua_nodelib_direct_getcharacter(lua_State * L)670 static int lua_nodelib_direct_getcharacter(lua_State * L)
671 {
672 halfword n;
673 n = (halfword) lua_tonumber(L, 1);
674 if (n == null) {
675 lua_pushnil(L);
676 } else if (type(n) == glyph_node) {
677 lua_pushnumber(L, character(n));
678 } else if ((type(n) == math_char_node) || (type(n) == math_text_char_node)) {
679 lua_pushnumber(L, math_character(n));
680 } else {
681 lua_pushnil(L);
682 }
683 return 1;
684 }
685
686 /* node.getlist */
687
lua_nodelib_getlist(lua_State * L)688 static int lua_nodelib_getlist(lua_State * L)
689 {
690 halfword *a;
691 halfword *n = lua_touserdata(L, 1);
692 if ( (n == NULL) || (! lua_getmetatable(L,1)) ) {
693 lua_pushnil(L);
694 } else if ((type(*n) == hlist_node) || (type(*n) == vlist_node)) {
695 fast_metatable_or_nil_alink(list_ptr(*n));
696 } else {
697 lua_pushnil(L);
698 }
699 return 1;
700 }
701
702 /* node.direct.getlist */
703
lua_nodelib_direct_getlist(lua_State * L)704 static int lua_nodelib_direct_getlist(lua_State * L)
705 {
706 halfword n;
707 n = (halfword) lua_tonumber(L, 1);
708 if ( n == null) {
709 lua_pushnil(L);
710 } else if ((type(n) == hlist_node) || (type(n) == vlist_node)) {
711 nodelib_pushdirect_or_nil_alink(list_ptr(n));
712 } else {
713 lua_pushnil(L);
714 }
715 return 1;
716 }
717
718 /* node.getleader */
719
lua_nodelib_getleader(lua_State * L)720 static int lua_nodelib_getleader(lua_State * L)
721 {
722 halfword *a;
723 halfword *n = lua_touserdata(L, 1);
724 if ( (n == NULL) || (! lua_getmetatable(L,1)) ) {
725 lua_pushnil(L);
726 } else if (type(*n) == glue_node) {
727 fast_metatable_or_nil(leader_ptr(*n));
728 } else {
729 lua_pushnil(L);
730 }
731 return 1;
732 }
733
734 /* node.direct.getleader */
735
lua_nodelib_direct_getleader(lua_State * L)736 static int lua_nodelib_direct_getleader(lua_State * L)
737 {
738 halfword n;
739 n = (halfword) lua_tonumber(L, 1);
740 if ( n == null) {
741 lua_pushnil(L);
742 } else if (type(n) == glue_node) {
743 nodelib_pushdirect_or_nil(leader_ptr(n));
744 } else {
745 lua_pushnil(L);
746 }
747 return 1;
748 }
749
750 /* node.getnext */
751
lua_nodelib_getnext(lua_State * L)752 static int lua_nodelib_getnext(lua_State * L)
753 {
754 halfword *a;
755 /* [given-node] [...]*/
756 halfword *p = lua_touserdata(L, 1);
757 if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
758 lua_pushnil(L);
759 } else {
760 /* [given-node] [mt-given-node]*/
761 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
762 lua_gettable(L, LUA_REGISTRYINDEX);
763 /* [given-node] [mt-given-node] [mt-node]*/
764 if (!lua_rawequal(L, -1, -2)) {
765 lua_pushnil(L);
766 } else {
767 fast_metatable_or_nil(vlink(*p));
768 }
769 }
770 return 1; /* just one*/
771 }
772
773 /* node.fast.getnext
774
775 static int lua_nodelib_fast_getnext(lua_State * L)
776 {
777 halfword *a;
778 // [given-node] [...]
779 halfword *p = lua_touserdata(L, 1);
780 if ((p == NULL) || (!vlink(*p))){
781 lua_pushnil(L);
782 } else {
783 lua_settop(L,1);
784 // [given-node]
785 lua_getmetatable(L,1);
786 // [given-node] [mt-node]
787 a = lua_newuserdata(L, sizeof(halfword));
788 // [given-node] [mt-node] [next-node]
789 *a = vlink(*p);
790 lua_replace(L,1);
791 // [next-node] [mt-node]
792 lua_setmetatable(L,1);
793 // [next-node-with-mt]
794 }
795 return 1;
796 }
797
798 */
799
800 /* node.direct.getnext */
801
lua_nodelib_direct_getnext(lua_State * L)802 static int lua_nodelib_direct_getnext(lua_State * L)
803 {
804 halfword p;
805 p = (halfword) lua_tonumber(L, 1);
806 if (p == null) {
807 lua_pushnil(L);
808 } else {
809 nodelib_pushdirect_or_nil(vlink(p));
810 }
811 return 1;
812 }
813
814 /* node.getprev */
815
lua_nodelib_getprev(lua_State * L)816 static int lua_nodelib_getprev(lua_State * L)
817 {
818 halfword *a;
819 halfword *p = lua_touserdata(L, 1);
820 if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
821 lua_pushnil(L);
822 } else {
823 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
824 lua_gettable(L, LUA_REGISTRYINDEX);
825 if (!lua_rawequal(L, -1, -2)) {
826 lua_pushnil(L);
827 } else {
828 fast_metatable_or_nil(alink(*p));
829 }
830 }
831 return 1;
832 }
833
834
835 /* node.fast.getprev
836
837 static int lua_nodelib_fast_getprev(lua_State * L)
838 {
839 halfword *a;
840 // [given-node] [...]
841 halfword *p = lua_touserdata(L, 1);
842 if ((p == NULL) || (!alink(*p))) {
843 lua_pushnil(L);
844 } else {
845 lua_settop(L,1);
846 // [given-node]
847 lua_getmetatable(L,1);
848 // [given-node] [mt-node]
849 a = lua_newuserdata(L, sizeof(halfword));
850 // [given-node] [mt-node] [next-node]
851 *a = alink(*p);
852 lua_replace(L,1);
853 // [next-node] [mt-node]
854 lua_setmetatable(L,1);
855 // [next-node-with-mt]
856 }
857 return 1;
858 }
859
860 */
861
862 /* node.direct.getprev */
863
lua_nodelib_direct_getprev(lua_State * L)864 static int lua_nodelib_direct_getprev(lua_State * L)
865 {
866 halfword p;
867 p = (halfword) lua_tonumber(L, 1);
868 if (p == null) {
869 lua_pushnil(L);
870 } else {
871 nodelib_pushdirect_or_nil(alink(p));
872 }
873 return 1;
874 }
875
876 /* node.subtype */
877
lua_nodelib_subtype(lua_State * L)878 static int lua_nodelib_subtype(lua_State * L)
879 {
880 int i = get_node_subtype_id(L, 1);
881 if (i >= 0) {
882 lua_pushnumber(L, i);
883 } else {
884 lua_pushnil(L); /* return 0; */
885 }
886 return 1;
887 }
888
889 /* node.type (converts id numbers to type names) */
890
lua_nodelib_type(lua_State * L)891 static int lua_nodelib_type(lua_State * L)
892 {
893 if (lua_type(L,1) == LUA_TNUMBER) {
894 int i = get_node_type_id(L, 1);
895 if (i >= 0) {
896 lua_pushstring(L, node_data[i].name);
897 return 1;
898 }
899 } else if (maybe_isnode(L, 1) != NULL) {
900 lua_pushstring(L,"node");
901 return 1;
902 }
903 lua_pushnil(L);
904 return 1;
905 }
906
907 /* node.new (allocate a new node) */
908
lua_nodelib_new(lua_State * L)909 static int lua_nodelib_new(lua_State * L)
910 {
911 int i, j;
912 halfword n = null;
913 i = get_valid_node_type_id(L, 1);
914 if (i == whatsit_node) {
915 j = -1;
916 if (lua_gettop(L) > 1)
917 j = get_valid_node_subtype_id(L, 2);
918 if (j < 0)
919 luaL_error(L, "Creating a whatsit requires the subtype number as a second argument");
920 } else {
921 j = 0;
922 if (lua_gettop(L) > 1)
923 j = (int) lua_tointeger(L, 2);
924 }
925 n = new_node(i, j);
926 lua_nodelib_push_fast(L, n);
927 return 1;
928 }
929
930 /* node.direct.new (still with checking) */
931
lua_nodelib_direct_new(lua_State * L)932 static int lua_nodelib_direct_new(lua_State * L)
933 {
934 int i, j;
935 halfword n ;
936 i = get_valid_node_type_id(L, 1);
937 if (i == whatsit_node) {
938 j = -1;
939 if (lua_gettop(L) > 1)
940 j = get_valid_node_subtype_id(L, 2);
941 if (j < 0)
942 luaL_error(L, "Creating a whatsit requires the subtype number as a second argument");
943 } else {
944 j = 0;
945 if (lua_gettop(L) > 1)
946 j = (int) lua_tointeger(L, 2);
947 }
948 n = new_node(i, j);
949 lua_pushnumber(L,n);
950 return 1;
951 }
952
953 /* node.free (this function returns the 'next' node, because that may be helpful) */
954
lua_nodelib_free(lua_State * L)955 static int lua_nodelib_free(lua_State * L)
956 {
957 halfword *n;
958 halfword p;
959 if (lua_gettop(L) < 1) {
960 lua_pushnil(L);
961 return 1;
962 } else if (lua_isnil(L, 1)) {
963 return 1; /* the nil itself */
964 }
965 n = check_isnode(L, 1);
966 p = vlink(*n);
967 flush_node(*n);
968 /* can be: lua_nodelib_push_fast(L, p); */
969 lua_pushnumber(L, p);
970 lua_nodelib_push(L);
971 return 1;
972 }
973
974 /* node.direct.free */
975
lua_nodelib_direct_free(lua_State * L)976 static int lua_nodelib_direct_free(lua_State * L)
977 {
978 halfword n;
979 halfword p;
980 n = (halfword) lua_tonumber(L,1);
981 if (n == null) {
982 lua_pushnil(L);
983 } else {
984 p = vlink(n);
985 flush_node(n);
986 if (p == 0) {
987 lua_pushnil(L);
988 } else {
989 lua_pushnumber(L,p);
990 }
991 }
992 return 1;
993 }
994
995 /* node.flush_node (no next returned) */
996
lua_nodelib_flush_node(lua_State * L)997 static int lua_nodelib_flush_node(lua_State * L)
998 {
999 halfword *n;
1000 if ((lua_gettop(L) < 1) || lua_isnil(L, 1))
1001 return 0;
1002 n = check_isnode(L, 1);
1003 // no check if n?
1004 flush_node(*n);
1005 return 0;
1006 }
1007
1008 /* node.direct.flush_node */
1009
lua_nodelib_direct_flush_node(lua_State * L)1010 static int lua_nodelib_direct_flush_node(lua_State * L)
1011 {
1012 halfword n;
1013 n = (halfword) lua_tonumber(L,1);
1014 if (n == null)
1015 return 0;
1016 flush_node(n);
1017 return 0;
1018 }
1019
1020 /* node.flush_list */
1021
lua_nodelib_flush_list(lua_State * L)1022 static int lua_nodelib_flush_list(lua_State * L)
1023 {
1024 halfword *n_ptr;
1025 if ((lua_gettop(L) < 1) || lua_isnil(L, 1))
1026 return 0;
1027 n_ptr = check_isnode(L, 1);
1028 flush_node_list(*n_ptr);
1029 return 0;
1030 }
1031
1032 /* node.direct.flush_list */
1033
lua_nodelib_direct_flush_list(lua_State * L)1034 static int lua_nodelib_direct_flush_list(lua_State * L)
1035 {
1036 halfword n;
1037 n = (halfword) lua_tonumber(L,1);
1038 if (n == null)
1039 return 0;
1040 flush_node_list(n);
1041 return 0;
1042 }
1043
1044 /* remove a node from a list */
1045
1046 #if DEBUG
1047
show_node_links(halfword l,const char * p)1048 static void show_node_links (halfword l, const char * p)
1049 {
1050 halfword t = l;
1051 while (t) {
1052 fprintf(DEBUG_OUT, "%s t = %d, prev = %d, next = %d\n", p, (int)t, (int)alink(t), (int)vlink(t));
1053 t = vlink(t);
1054 }
1055 }
1056
1057 #endif
1058
1059 /* node.remove */
1060
lua_nodelib_remove(lua_State * L)1061 static int lua_nodelib_remove(lua_State * L)
1062 {
1063 halfword head, current, t;
1064 if (lua_gettop(L) < 2)
1065 luaL_error(L, "Not enough arguments for node.remove()");
1066 head = *(check_isnode(L, 1));
1067 #if DEBUG
1068 show_node_links(head, "before");
1069 #endif
1070 if (lua_isnil(L, 2))
1071 return 2; /* the arguments, as they are */
1072 current = *(check_isnode(L, 2));
1073 if (head == current) {
1074 if (alink(current)){
1075 vlink(alink(current)) = vlink(current); // vlink(prev) = next
1076 }
1077 if (vlink(current)){
1078 alink( vlink(current)) = alink(current); // alink(next) = prev
1079 }
1080
1081 head = vlink(current); //head = next
1082 current = vlink(current); //current = next
1083 } else { /* head != current */
1084 t = alink(current);
1085 if (t == null || vlink(t) != current) {
1086 set_t_to_prev(head, current);
1087 if (t == null) /* error! */
1088 luaL_error(L,"Attempt to node.remove() a non-existing node");
1089 }
1090 /* t is now the previous node */
1091 vlink(t) = vlink(current);
1092 if (vlink(current) != null)
1093 alink(vlink(current)) = t;
1094 current = vlink(current);
1095 }
1096 #if DEBUG
1097 show_node_links(head, "after");
1098 #endif
1099 /* can be: lua_nodelib_push_fast(L, head); */
1100 lua_pushnumber(L, head);
1101 lua_nodelib_push(L);
1102 /* can be: lua_nodelib_push_fast(L, current); */
1103 lua_pushnumber(L, current);
1104 lua_nodelib_push(L);
1105 return 2;
1106 }
1107
1108 /* node.direct.remove */
1109
lua_nodelib_direct_remove(lua_State * L)1110 static int lua_nodelib_direct_remove(lua_State * L)
1111 {
1112 halfword head, current , t;
1113 head = (halfword) lua_tonumber(L,1);
1114 if (head == null) {
1115 lua_pushnil(L);
1116 lua_pushnil(L);
1117 return 2 ;
1118 }
1119 current = (halfword) lua_tonumber(L,2);
1120 if (current == null) {
1121 lua_pushnumber(L, head);
1122 lua_pushnil(L);
1123 return 2 ;
1124 }
1125 if (head == current) {
1126 if (alink(current)){
1127 vlink( alink(current) ) = vlink(current); // vlink(prev) = next
1128 }
1129 if (vlink(current)){
1130 alink( vlink(current) ) = alink(current); // alink(next) = prev
1131 }
1132 head = vlink(current); //head = next
1133 current = vlink(current); //current = next
1134 } else {
1135 t = alink(current);
1136 if (t == null || vlink(t) != current) {
1137 set_t_to_prev(head, current);
1138 if (t == null) {
1139 luaL_error(L,"Attempt to node.direct.remove() a non-existing node");
1140 }
1141 }
1142 vlink(t) = vlink(current);
1143 if (vlink(current) != null)
1144 alink(vlink(current)) = t;
1145 current = vlink(current);
1146 }
1147 if (head == null) {
1148 lua_pushnil(L);
1149 } else {
1150 lua_pushnumber(L, head);
1151 }
1152 if (current == null) {
1153 lua_pushnil(L);
1154 } else {
1155 lua_pushnumber(L, current);
1156 }
1157 return 2;
1158 }
1159
1160 /* node.insert_before (insert a node in a list) */
1161
lua_nodelib_insert_before(lua_State * L)1162 static int lua_nodelib_insert_before(lua_State * L)
1163 {
1164 halfword head, current, n, t;
1165 if (lua_gettop(L) < 3) {
1166 luaL_error(L, "Not enough arguments for node.insert_before()");
1167 }
1168 if (lua_isnil(L, 3)) {
1169 lua_pop(L, 1);
1170 return 2;
1171 } else {
1172 n = *(check_isnode(L, 3));
1173 }
1174 if (lua_isnil(L, 1)) { /* no head */
1175 vlink(n) = null;
1176 alink(n) = null;
1177 lua_nodelib_push_fast(L, n);
1178 lua_pushvalue(L, -1);
1179 return 2;
1180 } else {
1181 head = *(check_isnode(L, 1));
1182 }
1183 if (lua_isnil(L, 2)) {
1184 current = tail_of_list(head);
1185 } else {
1186 current = *(check_isnode(L, 2));
1187 }
1188 if (head != current) {
1189 t = alink(current);
1190 if (t == null || vlink(t) != current) {
1191 set_t_to_prev(head, current);
1192 if (t == null) { /* error! */
1193 luaL_error(L, "Attempt to node.insert_before() a non-existing node");
1194 }
1195 }
1196 couple_nodes(t, n);
1197 }
1198 couple_nodes(n, current);
1199 if (head == current) {
1200 lua_nodelib_push_fast(L, n);
1201 } else {
1202 lua_nodelib_push_fast(L, head);
1203 }
1204 lua_nodelib_push_fast(L, n);
1205 return 2;
1206 }
1207
1208 /* node.direct.insert_before */
1209
lua_nodelib_direct_insert_before(lua_State * L)1210 static int lua_nodelib_direct_insert_before(lua_State * L)
1211 {
1212 halfword head, current, n, t;
1213 n = (halfword) lua_tonumber(L,3);
1214 if (n == null){
1215 /* no node */
1216 lua_pop(L, 1);
1217 return 2 ;
1218 }
1219 head = (halfword) lua_tonumber(L,1);
1220 current = (halfword) lua_tonumber(L,2);
1221 /* no head, ignore current */
1222 if (head == null) {
1223 vlink(n) = null;
1224 alink(n) = null;
1225 lua_pushnumber(L, n);
1226 lua_pushvalue(L, -1);
1227 /* n, n */
1228 return 2;
1229 }
1230 /* no current */
1231 if (current == null)
1232 current = tail_of_list(head);
1233 if (head != current) {
1234 t = alink(current);
1235 if (t == null || vlink(t) != current)
1236 set_t_to_prev(head, current);
1237 couple_nodes(t, n);
1238 }
1239 couple_nodes(n, current);
1240 if (head == current) {
1241 lua_pushnumber(L, n);
1242 } else {
1243 lua_pushnumber(L, head);
1244 }
1245 lua_pushnumber(L, n);
1246 return 2;
1247 }
1248
1249 /* node.insert_after */
1250
lua_nodelib_insert_after(lua_State * L)1251 static int lua_nodelib_insert_after(lua_State * L)
1252 {
1253 halfword head, current, n;
1254 if (lua_gettop(L) < 3) {
1255 luaL_error(L, "Not enough arguments for node.insert_after()");
1256 }
1257 if (lua_isnil(L, 3)) {
1258 lua_pop(L, 1);
1259 return 2;
1260 } else {
1261 n = *(check_isnode(L, 3));
1262 }
1263 if (lua_isnil(L, 1)) { /* no head */
1264 vlink(n) = null;
1265 alink(n) = null;
1266 lua_nodelib_push_fast(L, n);
1267 lua_pushvalue(L, -1);
1268 return 2;
1269 } else {
1270 head = *(check_isnode(L, 1));
1271 }
1272 if (lua_isnil(L, 2)) {
1273 current = head;
1274 while (vlink(current) != null)
1275 current = vlink(current);
1276 } else {
1277 current = *(check_isnode(L, 2));
1278 }
1279 try_couple_nodes(n, vlink(current));
1280 couple_nodes(current, n);
1281
1282 lua_pop(L, 2);
1283 lua_nodelib_push_fast(L, n);
1284 return 2;
1285 }
1286
1287 /* node.direct.insert_after */
1288
lua_nodelib_direct_insert_after(lua_State * L)1289 static int lua_nodelib_direct_insert_after(lua_State * L)
1290 {
1291 halfword head, current, n;
1292 /*[head][current][new]*/
1293 n = (halfword) lua_tonumber(L,3);
1294 if (n == null) {
1295 /* no node */
1296 return 2 ;
1297 }
1298 head = (halfword) lua_tonumber(L,1);
1299 current = (halfword) lua_tonumber(L,2);
1300 if (head == null) {
1301 /* no head, ignore current */
1302 vlink(n) = null;
1303 alink(n) = null;
1304 lua_pushnumber(L,n);
1305 lua_pushvalue(L, -1);
1306 /* n, n */
1307 return 2;
1308 }
1309 if (current == null) {
1310 /* no current */
1311 current = head;
1312 while (vlink(current) != null)
1313 current = vlink(current);
1314 }
1315 try_couple_nodes(n, vlink(current));
1316 couple_nodes(current, n);
1317 lua_pop(L, 2);
1318 lua_pushnumber(L, n);
1319 return 2;
1320 }
1321
1322 /* node.copy_list */
1323 /* hh-ls: we need to use an intermediate variable as otherwise target is used in the loop
1324 and subfields get overwritten (or something like that) which results in crashes and
1325 unexpected side effects */
lua_nodelib_copy_list(lua_State * L)1326 static int lua_nodelib_copy_list(lua_State * L)
1327 {
1328 halfword n, s = null;
1329 halfword m;
1330 if (lua_isnil(L, 1))
1331 return 1; /* the nil itself */
1332 n = *check_isnode(L, 1);
1333 if ((lua_gettop(L) > 1) && (!lua_isnil(L,2)))
1334 s = *check_isnode(L, 2);
1335 m = do_copy_node_list(n, s);
1336 // lua_pushnumber(L, m);
1337 // lua_nodelib_push(L);
1338 lua_nodelib_push_fast(L,m);
1339 return 1;
1340
1341 }
1342
1343
1344 /* node.direct.copy_list */
1345
lua_nodelib_direct_copy_list(lua_State * L)1346 static int lua_nodelib_direct_copy_list(lua_State * L)
1347 {
1348 halfword n, s, m;
1349 n = (halfword) lua_tonumber(L,1);
1350 if (n == null) {
1351 lua_pushnil(L);
1352 } else {
1353 s = (halfword) lua_tonumber(L,2);
1354 if (s == null) {
1355 m = do_copy_node_list(n,null);
1356 } else {
1357 m = do_copy_node_list(n,s);
1358 }
1359 lua_pushnumber(L,m);
1360 }
1361 return 1;
1362 }
1363
1364 /* node.copy (deep copy) */
1365
lua_nodelib_copy(lua_State * L)1366 static int lua_nodelib_copy(lua_State * L)
1367 {
1368 halfword *n;
1369 halfword m;
1370 if (lua_isnil(L, 1))
1371 return 1; /* the nil itself */
1372 n = check_isnode(L, 1);
1373 m = copy_node(*n);
1374 lua_nodelib_push_fast(L, m);
1375 return 1;
1376 }
1377
1378 /* node.direct.copy (deep copy) */
1379
lua_nodelib_direct_copy(lua_State * L)1380 static int lua_nodelib_direct_copy(lua_State * L)
1381 {
1382 halfword n;
1383 halfword m;
1384 if (lua_isnil(L, 1))
1385 return 1; /* the nil itself */
1386 /* beware, a glue node can have number 0 (zeropt) so we cannot test for null) */
1387 n = (halfword) lua_tonumber(L, 1);
1388 m = copy_node(n);
1389 lua_pushnumber(L, m);
1390 return 1;
1391 }
1392
1393
1394 /* node.write (output a node to tex's processor) */
1395
lua_nodelib_append(lua_State * L)1396 static int lua_nodelib_append(lua_State * L)
1397 {
1398 halfword *n;
1399 halfword m;
1400 int i, j;
1401 j = lua_gettop(L);
1402 for (i = 1; i <= j; i++) {
1403 n = check_isnode(L, i);
1404 m = *n;
1405 tail_append(m);
1406 while (vlink(m) != null) {
1407 m = vlink(m);
1408 tail_append(m);
1409 }
1410 }
1411 return 0;
1412 }
1413
1414 /* node.direct.write */
1415
lua_nodelib_direct_append(lua_State * L)1416 static int lua_nodelib_direct_append(lua_State * L)
1417 {
1418 halfword n;
1419 halfword m;
1420 int i, j;
1421 j = lua_gettop(L);
1422 for (i = 1; i <= j; i++) {
1423 n = (halfword) lua_tonumber(L,i); /*lua_getnumber(L, i);*/
1424 if (n != null) {
1425 m = n ;
1426 tail_append(m);
1427 while (vlink(m) != null) {
1428 m = vlink(m);
1429 tail_append(m);
1430 }
1431 }
1432 }
1433 return 0;
1434 }
1435
1436 /* node.last */
1437
lua_nodelib_last_node(lua_State * L)1438 static int lua_nodelib_last_node(lua_State * L)
1439 {
1440 halfword m;
1441 m = pop_tail();
1442 /* can be: lua_nodelib_push_fast(L, m); */
1443 lua_pushnumber(L, m);
1444 lua_nodelib_push(L);
1445 return 1;
1446 }
1447
1448 /* node.direct.last */
1449
lua_nodelib_direct_last_node(lua_State * L)1450 static int lua_nodelib_direct_last_node(lua_State * L)
1451 {
1452 halfword m;
1453 m = pop_tail();
1454 lua_pushnumber(L, m);
1455 return 1;
1456 }
1457
1458 /* node.hpack (build a hbox) */
1459
lua_nodelib_hpack(lua_State * L)1460 static int lua_nodelib_hpack(lua_State * L)
1461 {
1462 halfword n, p;
1463 const char *s;
1464 int w = 0;
1465 int m = 1;
1466 int d = -1;
1467 n = *(check_isnode(L, 1));
1468 if (lua_gettop(L) > 1) {
1469 w = (int) lua_tointeger(L, 2);
1470 if (lua_gettop(L) > 2) {
1471 if (lua_type(L, 3) == LUA_TSTRING) {
1472 s = lua_tostring(L, 3);
1473 if (lua_key_eq(s, exactly)) {
1474 m = 0;
1475 } else if (lua_key_eq(s, additional)) {
1476 m = 1;
1477 } else if (lua_key_eq(s, cal_expand_ratio)) {
1478 m = 2;
1479 } else if (lua_key_eq(s, subst_ex_font)) {
1480 m = 3;
1481 } else {
1482 luaL_error(L, "3rd argument should be either additional or exactly");
1483 }
1484 } else if (lua_type(L, 3) == LUA_TNUMBER) {
1485 m=(int)lua_tonumber(L, 3);
1486 } else {
1487 lua_pushstring(L, "incorrect 3rd argument");
1488 }
1489 if (lua_gettop(L) > 3) {
1490 if (lua_type(L, 4) == LUA_TSTRING) {
1491 d = nodelib_getdir(L, 4, 1);
1492 } else {
1493 lua_pushstring(L, "incorrect 4th argument");
1494 }
1495 }
1496 }
1497 }
1498 p = hpack(n, w, m, d);
1499 lua_nodelib_push_fast(L, p);
1500 lua_pushnumber(L, last_badness);
1501 return 2;
1502 }
1503
1504 /* node.direct.hpack */
1505
lua_nodelib_direct_hpack(lua_State * L)1506 static int lua_nodelib_direct_hpack(lua_State * L)
1507 {
1508 halfword n, p;
1509 const char *s;
1510 int w = 0;
1511 int m = 1;
1512 int d = -1;
1513 n = (halfword) lua_tonumber(L,1);
1514 /* could be macro */
1515 if (lua_gettop(L) > 1) {
1516 w = (int) lua_tointeger(L, 2);
1517 if (lua_gettop(L) > 2) {
1518 if (lua_type(L, 3) == LUA_TSTRING) {
1519 s = lua_tostring(L, 3);
1520 if (lua_key_eq(s, additional)) {
1521 m = 1;
1522 } else if (lua_key_eq(s, exactly)) {
1523 m = 0;
1524 } else if (lua_key_eq(s, cal_expand_ratio)) {
1525 m = 2;
1526 } else if (lua_key_eq(s, subst_ex_font)) {
1527 m = 3;
1528 } else {
1529 luaL_error(L, "3rd argument should be either additional or exactly");
1530 }
1531 } else if (lua_type(L, 3) == LUA_TNUMBER) {
1532 m=(int)lua_tonumber(L, 3);
1533 } else {
1534 lua_pushstring(L, "incorrect 3rd argument");
1535 }
1536 if (lua_gettop(L) > 3) {
1537 if (lua_type(L, 4) == LUA_TSTRING) {
1538 d = nodelib_getdir(L, 4, 1);
1539 } else {
1540 lua_pushstring(L, "incorrect 4th argument");
1541 }
1542 }
1543 }
1544 }
1545 /* till here */
1546 p = hpack(n, w, m, d);
1547 lua_pushnumber(L, p);
1548 lua_pushnumber(L, last_badness);
1549 return 2;
1550 }
1551
1552 /* node.vpack (build a vbox) */
1553
lua_nodelib_vpack(lua_State * L)1554 static int lua_nodelib_vpack(lua_State * L)
1555 {
1556 halfword n, p;
1557 const char *s;
1558 int w = 0;
1559 int m = 1;
1560 int d = -1;
1561 n = *(check_isnode(L, 1));
1562 if (lua_gettop(L) > 1) {
1563 w = (int) lua_tointeger(L, 2);
1564 if (lua_gettop(L) > 2) {
1565 if (lua_type(L, 3) == LUA_TSTRING) {
1566 s = lua_tostring(L, 3);
1567 if (lua_key_eq(s, additional)) {
1568 m = 1;
1569 } else if (lua_key_eq(s, exactly)) {
1570 m = 0;
1571 } else {
1572 luaL_error(L, "3rd argument should be either additional or exactly");
1573 }
1574
1575 if (lua_gettop(L) > 3) {
1576 if (lua_type(L, 4) == LUA_TSTRING) {
1577 d = nodelib_getdir(L, 4, 1);
1578 } else {
1579 lua_pushstring(L, "incorrect 4th argument");
1580 }
1581 }
1582 }
1583
1584 else if (lua_type(L, 3) == LUA_TNUMBER) {
1585 m=(int)lua_tonumber(L, 3);
1586 } else {
1587 lua_pushstring(L, "incorrect 3rd argument");
1588 }
1589 }
1590 }
1591 p = vpackage(n, w, m, max_dimen, d);
1592 lua_nodelib_push_fast(L, p);
1593 lua_pushnumber(L, last_badness);
1594 return 2;
1595 }
1596
1597 /* node.direct.vpack */
1598
lua_nodelib_direct_vpack(lua_State * L)1599 static int lua_nodelib_direct_vpack(lua_State * L)
1600 {
1601 halfword n, p;
1602 const char *s;
1603 int w = 0;
1604 int m = 1;
1605 int d = -1;
1606 n = (halfword) lua_tonumber(L,1);
1607 if (lua_gettop(L) > 1) {
1608 w = (int) lua_tointeger(L, 2);
1609 if (lua_gettop(L) > 2) {
1610 if (lua_type(L, 3) == LUA_TSTRING) {
1611 s = lua_tostring(L, 3);
1612 if (lua_key_eq(s, additional)) {
1613 m = 1;
1614 } else if (lua_key_eq(s, exactly)) {
1615 m = 0;
1616 } else {
1617 luaL_error(L, "3rd argument should be either additional or exactly");
1618 }
1619
1620 if (lua_gettop(L) > 3) {
1621 if (lua_type(L, 4) == LUA_TSTRING) {
1622 d = nodelib_getdir(L, 4, 1);
1623 } else {
1624 lua_pushstring(L, "incorrect 4th argument");
1625 }
1626 }
1627 }
1628
1629 else if (lua_type(L, 3) == LUA_TNUMBER) {
1630 m=(int)lua_tonumber(L, 3);
1631 } else {
1632 lua_pushstring(L, "incorrect 3rd argument");
1633 }
1634 }
1635 }
1636 p = vpackage(n, w, m, max_dimen, d);
1637 lua_pushnumber(L, p);
1638 lua_pushnumber(L, last_badness);
1639 return 2;
1640 }
1641
1642 /* node.dimensions (of a hlist or vlist) */
1643
lua_nodelib_dimensions(lua_State * L)1644 static int lua_nodelib_dimensions(lua_State * L)
1645 {
1646 int top;
1647 top = lua_gettop(L);
1648 if (top > 0) {
1649 scaled_whd siz;
1650 glue_ratio g_mult = 1.0;
1651 int g_sign = normal;
1652 int g_order = normal;
1653 int i = 1;
1654 int d = -1;
1655 halfword n = null, p = null;
1656 /* maybe be more restrictive: LUA_TNUMBER i.e. it's not good to mix numbers and strings with digits */
1657 if (lua_isnumber(L, 1)) {
1658 if (top < 4) {
1659 lua_pushnil(L);
1660 return 1;
1661 }
1662 i += 3;
1663 g_mult = (glue_ratio) lua_tonumber(L, 1);
1664 g_sign=(int)lua_tonumber(L, 2);
1665 g_order=(int)lua_tonumber(L, 3);
1666 }
1667 n = *(check_isnode(L, i));
1668 if (lua_gettop(L) > i && !lua_isnil(L, (i + 1))) {
1669 if (lua_type(L, (i + 1)) == LUA_TSTRING) {
1670 d = nodelib_getdir(L, (i + 1), 1);
1671 } else {
1672 p = *(check_isnode(L, (i + 1)));
1673 }
1674 }
1675 if (lua_gettop(L) > (i + 1) && lua_type(L, (i + 2)) == LUA_TSTRING) {
1676 d = nodelib_getdir(L, (i + 2), 1);
1677 }
1678 siz = natural_sizes(n, p, g_mult, g_sign, g_order, d);
1679 lua_pushnumber(L, siz.wd);
1680 lua_pushnumber(L, siz.ht);
1681 lua_pushnumber(L, siz.dp);
1682 return 3;
1683 } else {
1684 luaL_error(L, "missing argument to 'dimensions' (node expected)");
1685 }
1686 return 0; /* not reached */
1687 }
1688
1689 /* node.direct.dimensions*/
1690
lua_nodelib_direct_dimensions(lua_State * L)1691 static int lua_nodelib_direct_dimensions(lua_State * L)
1692 {
1693 int top;
1694 top = lua_gettop(L);
1695 if (top > 0) {
1696 scaled_whd siz;
1697 glue_ratio g_mult = 1.0;
1698 int g_sign = normal;
1699 int g_order = normal;
1700 int i = 1;
1701 int d = -1;
1702 halfword n = null, p = null;
1703 if (top > 3) {
1704 i += 3;
1705 g_mult = (glue_ratio) lua_tonumber(L, 1);
1706 g_sign=(int)lua_tonumber(L, 2);
1707 g_order=(int)lua_tonumber(L, 3);
1708 }
1709 n = (halfword) lua_tonumber(L,i);
1710 if (lua_gettop(L) > i && !lua_isnil(L, (i + 1))) {
1711 if (lua_type(L, (i + 1)) == LUA_TSTRING) {
1712 d = nodelib_getdir(L, (i + 1), 1);
1713 } else {
1714 p = (halfword) lua_tonumber(L,i+1);
1715 }
1716 }
1717 if (lua_gettop(L) > (i + 1) && lua_type(L, (i + 2)) == LUA_TSTRING)
1718 d = nodelib_getdir(L, (i + 2), 1);
1719 siz = natural_sizes(n, p, g_mult, g_sign, g_order, d);
1720 lua_pushnumber(L, siz.wd);
1721 lua_pushnumber(L, siz.ht);
1722 lua_pushnumber(L, siz.dp);
1723 return 3;
1724 } else {
1725 luaL_error(L, "missing argument to 'dimensions' (node expected)");
1726 }
1727 return 0; /* not reached */
1728 }
1729
1730 /* node.mlist_to_hlist (create a hlist from a formula) */
1731
lua_nodelib_mlist_to_hlist(lua_State * L)1732 static int lua_nodelib_mlist_to_hlist(lua_State * L)
1733 {
1734 halfword n;
1735 int w;
1736 boolean m;
1737 n = *(check_isnode(L, 1));
1738 //w = luaL_checkoption(L, 2, "text", math_style_names);
1739 assign_math_style(L,2,w);
1740 luaL_checkany(L, 3);
1741 m = lua_toboolean(L, 3);
1742 mlist_to_hlist_args(n, w, m);
1743 alink(vlink(temp_head)) = null; /*hh-ls */
1744 lua_nodelib_push_fast(L, vlink(temp_head));
1745 return 1;
1746 }
1747
1748 /* node.family_font */
1749
lua_nodelib_mfont(lua_State * L)1750 static int lua_nodelib_mfont(lua_State * L)
1751 {
1752 int f, s;
1753 f = (int) luaL_checkinteger(L, 1);
1754 if (lua_gettop(L) == 2)
1755 s = (int) lua_tointeger(L, 2); /* this should be a multiple of 256 ! */
1756 else
1757 s = 0;
1758 lua_pushnumber(L, fam_fnt(f, s));
1759 return 1;
1760 }
1761
1762 /*
1763 This function is similar to |get_node_type_id|, for field
1764 identifiers. It has to do some more work, because not all
1765 identifiers are valid for all types of nodes.
1766
1767 If really needed we can optimize this one using a big if ..
1768 .. else like with the getter and setter.
1769
1770 */
1771
get_node_field_id(lua_State * L,int n,int node)1772 static int get_node_field_id(lua_State * L, int n, int node)
1773 {
1774 int t = type(node);
1775 const char *s = lua_tostring(L, n);
1776
1777 if (s == NULL)
1778 return -2;
1779
1780 if (lua_key_eq(s, next)) {
1781 return 0;
1782 } else if (lua_key_eq(s, id)) {
1783 return 1;
1784 } else if (lua_key_eq(s, subtype)) {
1785 if (nodetype_has_subtype(t)) {
1786 return 2;
1787 }
1788 } else if (lua_key_eq(s, attr)) {
1789 if (nodetype_has_attributes(t)) {
1790 return 3;
1791 }
1792 } else if (lua_key_eq(s, prev)) {
1793 if (nodetype_has_prev(t)) {
1794 return -1;
1795 }
1796 } else {
1797 int j;
1798 const char **fields = node_data[t].fields;
1799 if (t == whatsit_node) {
1800 fields = whatsit_node_data[subtype(node)].fields;
1801 }
1802 if (lua_key_eq(s, list)) {
1803 /* head and list are equivalent; we don't catch extra virtual fields */
1804 s = luaS_head_ptr;
1805 }
1806 if (fields != NULL) {
1807 for (j = 0; fields[j] != NULL; j++) {
1808 if (strcmp(s, fields[j]) == 0) {
1809 return j + 3;
1810 }
1811 }
1812 }
1813 }
1814 return -2;
1815 }
1816
1817 /* node.has_field */
1818
lua_nodelib_has_field(lua_State * L)1819 static int lua_nodelib_has_field(lua_State * L)
1820 {
1821 int i = -2;
1822 if (!lua_isnil(L, 1))
1823 i = get_node_field_id(L, 2, *(check_isnode(L, 1)));
1824 lua_pushboolean(L, (i != -2));
1825 return 1;
1826 }
1827
1828 /* node.direct.has_field */
1829
lua_nodelib_direct_has_field(lua_State * L)1830 static int lua_nodelib_direct_has_field(lua_State * L)
1831 {
1832 int i = -2;
1833 halfword n;
1834 n = (halfword) lua_tonumber(L, 1);
1835 if (n != null)
1836 i = get_node_field_id(L, 2, n);
1837 lua_pushboolean(L, (i != -2));
1838 return 1;
1839 }
1840
1841 /* fetch the list of valid node types */
1842
do_lua_nodelib_types(lua_State * L,node_info * data)1843 static int do_lua_nodelib_types(lua_State * L, node_info * data)
1844 {
1845 int i;
1846 lua_newtable(L);
1847 for (i = 0; data[i].id != -1; i++) {
1848 lua_pushstring(L, data[i].name);
1849 lua_rawseti(L, -2, data[i].id);
1850 }
1851 return 1;
1852 }
1853
1854 /* node.types */
1855
lua_nodelib_types(lua_State * L)1856 static int lua_nodelib_types(lua_State * L)
1857 {
1858 return do_lua_nodelib_types(L, node_data);
1859 }
1860
1861 /* node.whatsits */
1862
lua_nodelib_whatsits(lua_State * L)1863 static int lua_nodelib_whatsits(lua_State * L)
1864 {
1865 return do_lua_nodelib_types(L, whatsit_node_data);
1866 }
1867
1868 /* node.fields (fetch the list of valid fields) */
1869
lua_nodelib_fields(lua_State * L)1870 static int lua_nodelib_fields(lua_State * L)
1871 {
1872 int i = -1;
1873 int offset = 2;
1874 const char **fields;
1875 int t = get_valid_node_type_id(L, 1);
1876 if (t == whatsit_node) {
1877 t = get_valid_node_subtype_id(L, 2);
1878 fields = whatsit_node_data[t].fields;
1879 } else {
1880 fields = node_data[t].fields;
1881 }
1882 lua_checkstack(L, 2);
1883 lua_newtable(L);
1884 // lua_pushstring(L, "next");
1885 lua_push_string_by_name(L,next);
1886 lua_rawseti(L, -2, 0);
1887 // lua_pushstring(L, "id");
1888 lua_push_string_by_name(L,id);
1889 lua_rawseti(L, -2, 1);
1890 if (nodetype_has_subtype(t)) {
1891 // lua_pushstring(L, "subtype");
1892 lua_push_string_by_name(L,subtype);
1893 lua_rawseti(L, -2, 2);
1894 offset++;
1895 }
1896 if (fields != NULL) {
1897 if (nodetype_has_prev(t)) {
1898 // lua_pushstring(L, "prev");
1899 lua_push_string_by_name(L,prev);
1900 lua_rawseti(L, -2, -1);
1901 }
1902 for (i = 0; fields[i] != NULL; i++) {
1903 lua_pushstring(L, fields[i]); /* todo */
1904 lua_rawseti(L, -2, (i + offset));
1905 }
1906 }
1907 return 1;
1908 }
1909
1910 /* node.slide (find the end of a list and add prev links) */
1911
lua_nodelib_slide(lua_State * L)1912 static int lua_nodelib_slide(lua_State * L)
1913 {
1914 halfword *n;
1915 halfword t;
1916 if (lua_isnil(L, 1))
1917 return 1; /* the nil itself */
1918 n = check_isnode(L, 1);
1919 t = *n;
1920 if (t == null)
1921 return 1; /* the old userdata */
1922 /* alink(t) = null; */ /* don't do this, |t|'s |alink| may be a valid pointer */
1923 while (vlink(t) != null) {
1924 alink(vlink(t)) = t;
1925 t = vlink(t);
1926 }
1927 lua_nodelib_push_fast(L, t);
1928 return 1;
1929 }
1930
1931 /* node.direct.slide */
1932
lua_nodelib_direct_slide(lua_State * L)1933 static int lua_nodelib_direct_slide(lua_State * L)
1934 {
1935 halfword n;
1936 n = (halfword) lua_tonumber(L, 1);
1937 if (n == null) {
1938 lua_pushnil(L);
1939 } else {
1940 while (vlink(n) != null) {
1941 alink(vlink(n)) = n;
1942 n = vlink(n);
1943 }
1944 lua_pushnumber(L, n);
1945 }
1946 return 1;
1947 }
1948
1949 /* node.tail (find the end of a list) */
1950
lua_nodelib_tail(lua_State * L)1951 static int lua_nodelib_tail(lua_State * L)
1952 {
1953 halfword *n;
1954 halfword t;
1955 if (lua_isnil(L, 1))
1956 return 1; /* the nil itself */
1957 n = check_isnode(L, 1);
1958 t = *n;
1959 if (t == null)
1960 return 1; /* the old userdata */
1961 while (vlink(t) != null)
1962 t = vlink(t);
1963 lua_nodelib_push_fast(L, t);
1964 return 1;
1965 }
1966
1967 /* node.direct.tail */
1968
lua_nodelib_direct_tail(lua_State * L)1969 static int lua_nodelib_direct_tail(lua_State * L)
1970 {
1971 halfword n;
1972 n = (halfword) lua_tonumber(L, 1);
1973 if (n == null) {
1974 lua_pushnil(L);
1975 } else {
1976 while (vlink(n) != null)
1977 n = vlink(n);
1978 lua_pushnumber(L, n);
1979 }
1980 return 1;
1981 }
1982
1983 /* node.end_of_math (skip over math and return last) */
1984
lua_nodelib_end_of_math(lua_State * L)1985 static int lua_nodelib_end_of_math(lua_State * L)
1986 {
1987 halfword *n;
1988 halfword t;
1989 if (lua_isnil(L, 1))
1990 return 0;
1991 n = check_isnode(L, 1);
1992 t = *n;
1993 if (t == null)
1994 return 0;
1995 if (type(t)==math_node && (subtype(t)==1)) {
1996 lua_nodelib_push_fast(L, t);
1997 return 1;
1998 }
1999 while (vlink(t) != null) {
2000 t = vlink(t);
2001 if (t && (type(t)==math_node) && (subtype(t)==1)) {
2002 lua_nodelib_push_fast(L, t);
2003 return 1;
2004 }
2005 }
2006 return 0;
2007 }
2008
2009 /* node.direct.end_of_math */
2010
lua_nodelib_direct_end_of_math(lua_State * L)2011 static int lua_nodelib_direct_end_of_math(lua_State * L)
2012 {
2013 halfword n;
2014 n = (halfword) lua_tonumber(L, 1);
2015 if (n == null)
2016 return 0;
2017 if ((type(n)==math_node && (subtype(n)==1))) {
2018 lua_pushnumber(L, n);
2019 return 1;
2020 }
2021 while (vlink(n) != null) {
2022 n = vlink(n);
2023 if (n && (type(n)==math_node) && (subtype(n)==1)) {
2024 lua_pushnumber(L, n);
2025 return 1;
2026 }
2027 }
2028 return 0;
2029 }
2030
2031
2032 /* node.has_attribute (gets attribute) */
2033
lua_nodelib_has_attribute(lua_State * L)2034 static int lua_nodelib_has_attribute(lua_State * L)
2035 {
2036 halfword *n;
2037 int i, val;
2038 n = check_isnode(L, 1);
2039 if (n != NULL) {
2040 i = (int) lua_tointeger(L, 2);
2041 val = (int) luaL_optinteger(L, 3, UNUSED_ATTRIBUTE);
2042 if ((val = has_attribute(*n, i, val)) > UNUSED_ATTRIBUTE) {
2043 lua_pushnumber(L, val);
2044 return 1;
2045 }
2046 }
2047 lua_pushnil(L);
2048 return 1;
2049 }
2050
2051 /* node.direct.has_attribute */
2052
lua_nodelib_direct_has_attribute(lua_State * L)2053 static int lua_nodelib_direct_has_attribute(lua_State * L)
2054 {
2055 halfword n;
2056 int i, val;
2057 n = (halfword) lua_tonumber(L, 1);
2058 if (n != null) {
2059 i = (int) lua_tointeger(L, 2);
2060 val = (int) luaL_optinteger(L, 3, UNUSED_ATTRIBUTE);
2061 if ((val = has_attribute(n, i, val)) > UNUSED_ATTRIBUTE) {
2062 lua_pushnumber(L, val);
2063 return 1;
2064 }
2065 }
2066 lua_pushnil(L);
2067 return 1;
2068 }
2069
2070 /* node.set_attribute */
2071
lua_nodelib_set_attribute(lua_State * L)2072 static int lua_nodelib_set_attribute(lua_State * L)
2073 {
2074 halfword *n;
2075 int i, val;
2076 if (lua_gettop(L) == 3) {
2077 i = (int) lua_tointeger(L, 2);
2078 val = (int) lua_tointeger(L, 3);
2079 n = check_isnode(L, 1);
2080 if (val == UNUSED_ATTRIBUTE) {
2081 (void) unset_attribute(*n, i, val);
2082 } else {
2083 set_attribute(*n, i, val);
2084 }
2085 } else {
2086 luaL_error(L, "incorrect number of arguments");
2087 }
2088 return 0;
2089 }
2090
2091 /* node.direct.set_attribute */
2092
lua_nodelib_direct_set_attribute(lua_State * L)2093 static int lua_nodelib_direct_set_attribute(lua_State * L)
2094 {
2095 halfword n;
2096 int i, val;
2097 n = (halfword) lua_tonumber(L, 1);
2098 if (n == null)
2099 return 0;
2100 if (lua_gettop(L) == 3) {
2101 i = (int) lua_tointeger(L, 2);
2102 val = (int) lua_tointeger(L, 3);
2103 if (val == UNUSED_ATTRIBUTE) {
2104 (void) unset_attribute(n, i, val);
2105 } else {
2106 set_attribute(n, i, val);
2107 }
2108 } else {
2109 luaL_error(L, "incorrect number of arguments");
2110 }
2111 return 0;
2112 }
2113
2114 /* node.unset_attribute */
2115
lua_nodelib_unset_attribute(lua_State * L)2116 static int lua_nodelib_unset_attribute(lua_State * L)
2117 {
2118 halfword *n;
2119 int i, val, ret;
2120 if (lua_gettop(L) <= 3) {
2121 i=(int)luaL_checknumber(L, 2);
2122 val=(int)luaL_optnumber(L, 3, UNUSED_ATTRIBUTE);
2123 n = check_isnode(L, 1);
2124 ret = unset_attribute(*n, i, val);
2125 if (ret > UNUSED_ATTRIBUTE) {
2126 lua_pushnumber(L, ret);
2127 } else {
2128 lua_pushnil(L);
2129 }
2130 return 1;
2131 } else {
2132 return luaL_error(L, "incorrect number of arguments");
2133 }
2134 }
2135
2136 /* node.direct.unset_attribute */
2137
lua_nodelib_direct_unset_attribute(lua_State * L)2138 static int lua_nodelib_direct_unset_attribute(lua_State * L)
2139 {
2140 halfword n;
2141 int i, val, ret;
2142 n = (halfword) lua_tonumber(L, 1);
2143 if (n == null) {
2144 lua_pushnil(L);
2145 } else if (lua_gettop(L) <= 3) { /* a useless test, we never test for that elsewhere */
2146 i=(int)luaL_checknumber(L, 2);
2147 val=(int)luaL_optnumber(L, 3, UNUSED_ATTRIBUTE);
2148 ret = unset_attribute(n, i, val);
2149 if (ret > UNUSED_ATTRIBUTE) {
2150 lua_pushnumber(L, ret);
2151 } else {
2152 lua_pushnil(L);
2153 }
2154 } else { /* can go */
2155 return luaL_error(L, "incorrect number of arguments");
2156 }
2157 return 1;
2158 }
2159
2160 /* iteration */
2161
nodelib_aux_nil(lua_State * L)2162 static int nodelib_aux_nil(lua_State * L)
2163 {
2164 lua_pushnil(L);
2165 return 1;
2166 }
2167
2168 /* node.traverse_id */
2169
nodelib_aux_next_filtered(lua_State * L)2170 static int nodelib_aux_next_filtered(lua_State * L)
2171 {
2172 halfword t; /* traverser */
2173 halfword *a;
2174 int i = (int) lua_tointeger(L, lua_upvalueindex(1));
2175 if (lua_isnil(L, 2)) { /* first call */
2176 t = *check_isnode(L, 1);
2177 lua_settop(L,1);
2178 } else {
2179 t = *check_isnode(L, 2);
2180 t = vlink(t);
2181 lua_settop(L,2);
2182 }
2183 while (t != null && type(t) != i) {
2184 t = vlink(t);
2185 }
2186 if (t == null) {
2187 lua_pushnil(L);
2188 } else {
2189 fast_metatable_top(t);
2190 }
2191 return 1;
2192 }
2193
lua_nodelib_traverse_filtered(lua_State * L)2194 static int lua_nodelib_traverse_filtered(lua_State * L)
2195 {
2196 halfword n;
2197 if (lua_isnil(L, 2)) {
2198 lua_pushcclosure(L, nodelib_aux_nil, 0);
2199 return 1;
2200 }
2201 n = *(check_isnode(L, 2));
2202 lua_pop(L, 1); /* the node, integer remains */
2203 lua_pushcclosure(L, nodelib_aux_next_filtered, 1);
2204 lua_nodelib_push_fast(L, n);
2205 lua_pushnil(L);
2206 return 3;
2207 }
2208
2209 /* node.direct.traverse_id */
2210
nodelib_direct_aux_next_filtered(lua_State * L)2211 static int nodelib_direct_aux_next_filtered(lua_State * L)
2212 {
2213 halfword t; /* traverser */
2214 int i = (int) lua_tointeger(L, lua_upvalueindex(1));
2215 if (lua_isnil(L, 2)) { /* first call */
2216 t = lua_tonumber(L,1) ;
2217 lua_settop(L,1);
2218 } else {
2219 t = lua_tonumber(L,2) ;
2220 t = vlink(t);
2221 lua_settop(L,2);
2222 }
2223 while (t != null && type(t) != i) {
2224 t = vlink(t);
2225 }
2226 if (t == null) {
2227 lua_pushnil(L);
2228 } else {
2229 lua_pushnumber(L,t);
2230 }
2231 return 1;
2232 }
2233
lua_nodelib_direct_traverse_filtered(lua_State * L)2234 static int lua_nodelib_direct_traverse_filtered(lua_State * L)
2235 {
2236 halfword n;
2237 if (lua_isnil(L, 2)) {
2238 lua_pushcclosure(L, nodelib_aux_nil, 0);
2239 return 1;
2240 }
2241 n = (halfword) lua_tonumber(L, 2);
2242 if (n == null)
2243 return 0;
2244 n = (halfword) lua_tonumber(L, 2);
2245 lua_pop(L, 1);
2246 lua_pushcclosure(L, nodelib_direct_aux_next_filtered, 1);
2247 lua_pushnumber(L,n);
2248 lua_pushnil(L);
2249 return 3;
2250 }
2251
2252 /* node.traverse */
2253
nodelib_aux_next(lua_State * L)2254 static int nodelib_aux_next(lua_State * L)
2255 {
2256 halfword t; /* traverser */
2257 halfword *a; /* a or *a */
2258 if (lua_isnil(L, 2)) { /* first call */
2259 t = *check_isnode(L, 1);
2260 lua_settop(L,1);
2261 } else {
2262 t = *check_isnode(L, 2);
2263 t = vlink(t);
2264 lua_settop(L,2);
2265 }
2266 if (t == null) {
2267 lua_pushnil(L);
2268 } else {
2269 fast_metatable_top(t);
2270 }
2271 return 1;
2272 }
2273
lua_nodelib_traverse(lua_State * L)2274 static int lua_nodelib_traverse(lua_State * L)
2275 {
2276 halfword n;
2277 if (lua_isnil(L, 1)) {
2278 lua_pushcclosure(L, nodelib_aux_nil, 0);
2279 return 1;
2280 }
2281 n = *(check_isnode(L, 1));
2282 lua_pushcclosure(L, nodelib_aux_next, 0);
2283 lua_nodelib_push_fast(L, n);
2284 lua_pushnil(L);
2285 return 3;
2286 }
2287
2288 /* node.direct.traverse */
2289
nodelib_direct_aux_next(lua_State * L)2290 static int nodelib_direct_aux_next(lua_State * L)
2291 {
2292 halfword t; /* traverser */
2293 /*int i = (int) lua_tointeger(L, lua_upvalueindex(1));*/
2294 if (lua_isnil(L, 2)) { /* first call */
2295 t = lua_tonumber(L,1) ;
2296 lua_settop(L,1);
2297 } else {
2298 t = lua_tonumber(L,2) ;
2299 t = vlink(t);
2300 lua_settop(L,2);
2301 }
2302 if (t == null) {
2303 lua_pushnil(L);
2304 } else {
2305 lua_pushnumber(L,t);
2306 }
2307 return 1;
2308 }
2309
lua_nodelib_direct_traverse(lua_State * L)2310 static int lua_nodelib_direct_traverse(lua_State * L)
2311 {
2312 halfword n;
2313 if (lua_isnil(L, 1)) {
2314 lua_pushcclosure(L, nodelib_aux_nil, 0);
2315 return 1;
2316 }
2317 n = (halfword) lua_tonumber(L, 1);
2318 if (n == null) {
2319 lua_pushcclosure(L, nodelib_aux_nil, 0);
2320 return 1;
2321 }
2322 lua_pushcclosure(L, nodelib_direct_aux_next, 0);
2323 lua_pushnumber(L,n);
2324 lua_pushnil(L);
2325 return 3;
2326 }
2327
2328
2329 /* counting */
2330
do_lua_nodelib_count(lua_State * L,halfword match,int i,halfword first1)2331 static int do_lua_nodelib_count(lua_State * L, halfword match, int i, halfword first1)
2332 {
2333 int count = 0;
2334 int t = first1;
2335 while (t != match) {
2336 if (i < 0 || type(t) == i)
2337 count++;
2338 t = vlink(t);
2339 }
2340 lua_pushnumber(L, count);
2341 return 1;
2342 }
2343
2344 /* node.length */
2345
lua_nodelib_length(lua_State * L)2346 static int lua_nodelib_length(lua_State * L)
2347 {
2348 halfword n;
2349 halfword m = null;
2350 if (lua_isnil(L, 1)) {
2351 lua_pushnumber(L, 0);
2352 return 1;
2353 }
2354 n = *(check_isnode(L, 1));
2355 if (lua_gettop(L) == 2)
2356 m = *(check_isnode(L, 2));
2357 return do_lua_nodelib_count(L, m, -1, n);
2358 }
2359
2360 /* node.direct.length */
2361
lua_nodelib_direct_length(lua_State * L)2362 static int lua_nodelib_direct_length(lua_State * L)
2363 {
2364 halfword n, m;
2365 n = (halfword) lua_tonumber(L, 1);
2366 if (n == 0) {
2367 lua_pushnumber(L, 0);
2368 return 1;
2369 }
2370 m = (halfword) lua_tonumber(L, 2);
2371 return do_lua_nodelib_count(L, m, -1, n);
2372 }
2373
2374 /* node.count */
2375
lua_nodelib_count(lua_State * L)2376 static int lua_nodelib_count(lua_State * L)
2377 {
2378 halfword n;
2379 halfword m = null;
2380 int i = -1;
2381 i = (int) lua_tointeger(L, 1);
2382 if (lua_isnil(L, 2)) {
2383 lua_pushnumber(L, 0);
2384 return 1;
2385 }
2386 n = *(check_isnode(L, 2));
2387 if (lua_gettop(L) == 3)
2388 m = *(check_isnode(L, 3));
2389 return do_lua_nodelib_count(L, m, i, n);
2390 }
2391
2392 /* node.direct.count */
2393
lua_nodelib_direct_count(lua_State * L)2394 static int lua_nodelib_direct_count(lua_State * L)
2395 {
2396 return do_lua_nodelib_count(L,
2397 (halfword) lua_tonumber(L, 3), /* m */
2398 (int) lua_tointeger(L, 1), /* i */
2399 (halfword) lua_tonumber(L, 2) /* n */
2400 );
2401 }
2402
2403 /* directions (could be a macro) */
2404
2405 // static void nodelib_pushdir(lua_State * L, int n, boolean dirnode)
2406 // {
2407 // if (dirnode) {
2408 // lua_pushstring(L, dir_strings[n+64]);
2409 // } else {
2410 // lua_pushstring(L, dir_strings[n+64]+1);
2411 // }
2412 // }
2413
2414 /* getting and setting fields (helpers) */
2415
nodelib_getlist(lua_State * L,int n)2416 static int nodelib_getlist(lua_State * L, int n)
2417 {
2418 halfword *m;
2419 if (lua_isuserdata(L, n)) {
2420 m = check_isnode(L, n);
2421 return *m;
2422 } else {
2423 return null;
2424 }
2425 }
2426
nodelib_getdir(lua_State * L,int n,int absolute_only)2427 int nodelib_getdir(lua_State * L, int n, int absolute_only)
2428 {
2429 if (lua_type(L, n) == LUA_TSTRING) {
2430 const char *s = lua_tostring(L, n);
2431 RETURN_DIR_VALUES(TLT);
2432 RETURN_DIR_VALUES(TRT);
2433 RETURN_DIR_VALUES(LTL);
2434 RETURN_DIR_VALUES(RTT);
2435 luaL_error(L, "Bad direction specifier %s", s);
2436 } else {
2437 luaL_error(L, "Direction specifiers have to be strings");
2438 }
2439 return 0;
2440 }
2441
nodelib_getstring(lua_State * L,int a)2442 static str_number nodelib_getstring(lua_State * L, int a)
2443 {
2444 size_t k;
2445 const char *s = lua_tolstring(L, a, &k);
2446 return maketexlstring(s, k);
2447 }
2448
2449
nodelib_cantset(lua_State * L,int n,const char * s)2450 static int nodelib_cantset(lua_State * L, int n, const char *s)
2451 {
2452 luaL_error(L,"You cannot set field %s in a node of type %s",s,node_data[type(n)].name);
2453 return 0;
2454 }
2455
2456 /* node.direct.getfield */
2457
lua_nodelib_getfield_whatsit(lua_State * L,int n,const char * s)2458 static void lua_nodelib_getfield_whatsit(lua_State * L, int n, const char *s)
2459 {
2460 int t ;
2461 t = subtype(n);
2462
2463 if (t == dir_node) {
2464 if (lua_key_eq(s, dir)) {
2465 // nodelib_pushdir(L, dir_dir(n), true);
2466 lua_push_dir_text(L, dir_dir(n));
2467 } else if (lua_key_eq(s, level)) {
2468 lua_pushnumber(L, dir_level(n));
2469 } else if (lua_key_eq(s, dvi_ptr)) {
2470 lua_pushnumber(L, dir_dvi_ptr(n));
2471 } else if (lua_key_eq(s, dir_h)) {
2472 lua_pushnumber(L, dir_dvi_h(n));
2473 } else {
2474 lua_pushnil(L);
2475 }
2476 } else if (t == user_defined_node) {
2477 if (lua_key_eq(s, user_id)) {
2478 lua_pushnumber(L, user_node_id(n));
2479 } else if (lua_key_eq(s, type)) {
2480 lua_pushnumber(L, user_node_type(n));
2481 } else if (lua_key_eq(s, value)) {
2482 switch (user_node_type(n)) {
2483 case 'a':
2484 nodelib_pushlist(L, user_node_value(n));
2485 break;
2486 case 'd':
2487 lua_pushnumber(L, user_node_value(n));
2488 break;
2489 case 'l':
2490 if (user_node_value(n) != 0) {
2491 lua_rawgeti(L, LUA_REGISTRYINDEX, user_node_value(n));
2492 } else {
2493 lua_pushnil(L);
2494 }
2495 break;
2496 case 'n':
2497 nodelib_pushlist(L, user_node_value(n));
2498 break;
2499 case 's':
2500 nodelib_pushstring(L, user_node_value(n));
2501 break;
2502 case 't':
2503 tokenlist_to_lua(L, user_node_value(n));
2504 break;
2505 default:
2506 lua_pushnumber(L, user_node_value(n));
2507 break;
2508 }
2509 } else {
2510 lua_pushnil(L);
2511 }
2512 } else if (t == local_par_node) {
2513 if (lua_key_eq(s, pen_inter)) {
2514 lua_pushnumber(L, local_pen_inter(n));
2515 } else if (lua_key_eq(s, pen_broken)) {
2516 lua_pushnumber(L, local_pen_broken(n));
2517 } else if (lua_key_eq(s, dir)) {
2518 // nodelib_pushdir(L, local_par_dir(n), false);
2519 lua_push_dir_par(L, local_par_dir(n));
2520 } else if (lua_key_eq(s, box_left)) {
2521 /* can be: fast_metatable_or_nil(local_box_left(n)) */
2522 nodelib_pushlist(L, local_box_left(n));
2523 } else if (lua_key_eq(s, box_left_width)) {
2524 lua_pushnumber(L, local_box_left_width(n));
2525 } else if (lua_key_eq(s, box_right)) {
2526 /* can be: fast_metatable_or_nil(local_box_right(n)) */
2527 nodelib_pushlist(L, local_box_right(n));
2528 } else if (lua_key_eq(s, box_right_width)) {
2529 lua_pushnumber(L, local_box_right_width(n));
2530 } else {
2531 lua_pushnil(L);
2532 }
2533 } else if (t == pdf_literal_node) {
2534 if (lua_key_eq(s, mode)) {
2535 lua_pushnumber(L, pdf_literal_mode(n));
2536 } else if (lua_key_eq(s, data)) {
2537 if (pdf_literal_type(n) == lua_refid_literal) {
2538 lua_rawgeti(L, LUA_REGISTRYINDEX, pdf_literal_data(n));
2539 } else {
2540 tokenlist_to_luastring(L, pdf_literal_data(n));
2541 }
2542 } else {
2543 lua_pushnil(L);
2544 }
2545 } else if (t == late_lua_node) {
2546 if (lua_key_eq(s, string) || lua_key_eq(s, data)) {
2547 if (late_lua_type(n) == lua_refid_literal) {
2548 lua_rawgeti(L, LUA_REGISTRYINDEX, late_lua_data(n));
2549 } else {
2550 tokenlist_to_luastring(L, late_lua_data(n));
2551 }
2552 } else if (lua_key_eq(s, name)) {
2553 tokenlist_to_luastring(L, late_lua_name(n));
2554 } else {
2555 lua_pushnil(L);
2556 }
2557 } else if (t == pdf_annot_node) {
2558 if (lua_key_eq(s, width)) {
2559 lua_pushnumber(L, width(n));
2560 } else if (lua_key_eq(s, depth)) {
2561 lua_pushnumber(L, depth(n));
2562 } else if (lua_key_eq(s, height)) {
2563 lua_pushnumber(L, height(n));
2564 } else if (lua_key_eq(s, objnum)) {
2565 lua_pushnumber(L, pdf_annot_objnum(n));
2566 } else if (lua_key_eq(s, data)) {
2567 tokenlist_to_luastring(L, pdf_annot_data(n));
2568 } else {
2569 lua_pushnil(L);
2570 }
2571 } else if (t == pdf_dest_node) {
2572 if (lua_key_eq(s, width)) {
2573 lua_pushnumber(L, width(n));
2574 } else if (lua_key_eq(s, depth)) {
2575 lua_pushnumber(L, depth(n));
2576 } else if (lua_key_eq(s, height)) {
2577 lua_pushnumber(L, height(n));
2578 } else if (lua_key_eq(s, named_id)) {
2579 lua_pushnumber(L, pdf_dest_named_id(n));
2580 } else if (lua_key_eq(s, dest_id)) {
2581 if (pdf_dest_named_id(n) == 1)
2582 tokenlist_to_luastring(L, pdf_dest_id(n));
2583 else
2584 lua_pushnumber(L, pdf_dest_id(n));
2585 } else if (lua_key_eq(s, dest_type)) {
2586 lua_pushnumber(L, pdf_dest_type(n));
2587 } else if (lua_key_eq(s, xyz_zoom)) {
2588 lua_pushnumber(L, pdf_dest_xyz_zoom(n));
2589 } else if (lua_key_eq(s, objnum)) {
2590 lua_pushnumber(L, pdf_dest_objnum(n));
2591 } else {
2592 lua_pushnil(L);
2593 }
2594 } else if (t == pdf_setmatrix_node) {
2595 if (lua_key_eq(s, data)) {
2596 tokenlist_to_luastring(L, pdf_setmatrix_data(n));
2597 } else {
2598 lua_pushnil(L);
2599 }
2600 } else if (t == pdf_colorstack_node) {
2601 if (lua_key_eq(s, stack)) {
2602 lua_pushnumber(L, pdf_colorstack_stack(n));
2603 } else if (lua_key_eq(s, command)) {
2604 lua_pushnumber(L, pdf_colorstack_cmd(n));
2605 } else if (lua_key_eq(s, data)) {
2606 tokenlist_to_luastring(L, pdf_colorstack_data(n));
2607 } else {
2608 lua_pushnil(L);
2609 }
2610 } else if (t == pdf_refobj_node) {
2611 if (lua_key_eq(s, objnum)) {
2612 lua_pushnumber(L, pdf_obj_objnum(n));
2613 } else {
2614 lua_pushnil(L);
2615 }
2616 } else if (t == pdf_refxform_node) {
2617 if (lua_key_eq(s, width)) {
2618 lua_pushnumber(L, width(n));
2619 } else if (lua_key_eq(s, depth)) {
2620 lua_pushnumber(L, depth(n));
2621 } else if (lua_key_eq(s, height)) {
2622 lua_pushnumber(L, height(n));
2623 } else if (lua_key_eq(s, objnum)) {
2624 lua_pushnumber(L, pdf_xform_objnum(n));
2625 } else {
2626 lua_pushnil(L);
2627 }
2628 } else if (t == pdf_refximage_node) {
2629 if (lua_key_eq(s, width)) {
2630 lua_pushnumber(L, width(n));
2631 } else if (lua_key_eq(s, depth)) {
2632 lua_pushnumber(L, depth(n));
2633 } else if (lua_key_eq(s, height)) {
2634 lua_pushnumber(L, height(n));
2635 } else if (lua_key_eq(s, transform)) {
2636 lua_pushnumber(L, pdf_ximage_transform(n));
2637 } else if (lua_key_eq(s, index)) {
2638 lua_pushnumber(L, pdf_ximage_index(n));
2639 } else {
2640 lua_pushnil(L);
2641 }
2642 } else if (t == write_node) {
2643 if (lua_key_eq(s, stream)) {
2644 lua_pushnumber(L, write_stream(n));
2645 } else if (lua_key_eq(s, data)) {
2646 tokenlist_to_lua(L, write_tokens(n));
2647 } else {
2648 lua_pushnil(L);
2649 }
2650 } else if (t == special_node) {
2651 if (lua_key_eq(s, data)) {
2652 tokenlist_to_luastring(L, write_tokens(n));
2653 } else {
2654 lua_pushnil(L);
2655 }
2656 } else if (t == pdf_start_link_node) {
2657 if (lua_key_eq(s, width)) {
2658 lua_pushnumber(L, width(n));
2659 } else if (lua_key_eq(s, depth)) {
2660 lua_pushnumber(L, depth(n));
2661 } else if (lua_key_eq(s, height)) {
2662 lua_pushnumber(L, height(n));
2663 } else if (lua_key_eq(s, objnum)) {
2664 lua_pushnumber(L, pdf_link_objnum(n));
2665 } else if (lua_key_eq(s, link_attr)) {
2666 tokenlist_to_luastring(L, pdf_link_attr(n));
2667 } else if (lua_key_eq(s, action)) {
2668 nodelib_pushaction(L, pdf_link_action(n));
2669 } else {
2670 lua_pushnil(L);
2671 }
2672 } else if ((t == pdf_thread_node) || (t == pdf_start_thread_node)) {
2673 if (lua_key_eq(s, width)) {
2674 lua_pushnumber(L, width(n));
2675 } else if (lua_key_eq(s, depth)) {
2676 lua_pushnumber(L, depth(n));
2677 } else if (lua_key_eq(s, height)) {
2678 lua_pushnumber(L, height(n));
2679 } else if (lua_key_eq(s, named_id)) {
2680 lua_pushnumber(L, pdf_thread_named_id(n));
2681 } else if (lua_key_eq(s, thread_id)) {
2682 if (pdf_thread_named_id(n) == 1) {
2683 tokenlist_to_luastring(L, pdf_thread_id(n));
2684 } else {
2685 lua_pushnumber(L, pdf_thread_id(n));
2686 }
2687 } else if (lua_key_eq(s, thread_attr)) {
2688 tokenlist_to_luastring(L, pdf_thread_attr(n));
2689 } else {
2690 lua_pushnil(L);
2691 }
2692 } else if (t == open_node) {
2693 if (lua_key_eq(s, stream)) {
2694 lua_pushnumber(L, write_stream(n));
2695 } else if (lua_key_eq(s, name)) {
2696 nodelib_pushstring(L, open_name(n));
2697 } else if (lua_key_eq(s, area)) {
2698 nodelib_pushstring(L, open_area(n));
2699 } else if (lua_key_eq(s, ext)) {
2700 nodelib_pushstring(L, open_ext(n));
2701 } else {
2702 lua_pushnil(L);
2703 }
2704 } else if (t == close_node) {
2705 if (lua_key_eq(s, stream)) {
2706 lua_pushnumber(L, write_stream(n));
2707 } else {
2708 lua_pushnil(L);
2709 }
2710 } else {
2711 lua_pushnil(L);
2712 }
2713 }
2714
lua_nodelib_fast_getfield(lua_State * L)2715 static int lua_nodelib_fast_getfield(lua_State * L)
2716 {
2717 /*
2718 the order is somewhat determined by the occurance of nodes and
2719 importance of fields
2720 */
2721
2722 halfword n;
2723 halfword *a;
2724 const char *s;
2725 int t ;
2726
2727 n = *((halfword *) lua_touserdata(L, 1));
2728 t = type(n);
2729
2730 /*
2731
2732 somenode[9] as interface to attributes ... 30% faster than has_attribute
2733 (1) because there is no lua function overhead, and (2) because we already
2734 know that we deal with a node so no checking is needed. The fast typecheck
2735 is needed (lua_check... is a slow down actually).
2736
2737 */
2738
2739 if (lua_type(L, 2) == LUA_TNUMBER) {
2740
2741 halfword p;
2742 int i;
2743
2744 if (! nodetype_has_attributes(t)) {
2745 lua_pushnil(L);
2746 return 1;
2747 }
2748
2749 p = node_attr(n);
2750 if (p == null || vlink(p) == null) {
2751 lua_pushnil(L);
2752 return 1;
2753 }
2754 i = (int) lua_tointeger(L, 2);
2755 p = vlink(p);
2756 while (p != null) {
2757 if (attribute_id(p) == i) {
2758 if ((int) attribute_value(p) > UNUSED_ATTRIBUTE) {
2759 lua_pushnumber(L, (int) attribute_value(p));
2760 } else {
2761 lua_pushnil(L);
2762 }
2763 return 1;
2764 } else if (attribute_id(p) > i) {
2765 lua_pushnil(L);
2766 return 1;
2767 }
2768 p = vlink(p);
2769 }
2770 lua_pushnil(L);
2771 return 1;
2772 }
2773
2774 s = lua_tostring(L, 2);
2775
2776 if (lua_key_eq(s, id)) {
2777 lua_pushnumber(L, t);
2778 } else if (lua_key_eq(s, next)) {
2779 fast_metatable_or_nil(vlink(n));
2780 } else if (lua_key_eq(s, prev)) {
2781 fast_metatable_or_nil(alink(n));
2782 } else if (lua_key_eq(s, attr)) {
2783 if (! nodetype_has_attributes(t)) {
2784 lua_pushnil(L);
2785 } else {
2786 nodelib_pushattr(L, node_attr(n));
2787 }
2788 } else if (t == glyph_node) {
2789 /* candidates: fontchar (font,char) whd (width,height,depth) */
2790 if (lua_key_eq(s, subtype)) {
2791 lua_pushnumber(L, subtype(n));
2792 } else if (lua_key_eq(s, font)) {
2793 lua_pushnumber(L, font(n));
2794 } else if (lua_key_eq(s, char)) {
2795 lua_pushnumber(L, character(n));
2796 } else if (lua_key_eq(s, xoffset)) {
2797 lua_pushnumber(L, x_displace(n));
2798 } else if (lua_key_eq(s, yoffset)) {
2799 lua_pushnumber(L, y_displace(n));
2800 } else if (lua_key_eq(s, width)) {
2801 lua_pushnumber(L, char_width(font(n),character(n)));
2802 } else if (lua_key_eq(s, height)) {
2803 lua_pushnumber(L, char_height(font(n),character(n)));
2804 } else if (lua_key_eq(s, depth)) {
2805 lua_pushnumber(L, char_depth(font(n),character(n)));
2806 } else if (lua_key_eq(s, expansion_factor)) {
2807 lua_pushnumber(L, ex_glyph(n));
2808 } else if (lua_key_eq(s, components)) {
2809 fast_metatable_or_nil(lig_ptr(n));
2810 } else if (lua_key_eq(s, lang)) {
2811 lua_pushnumber(L, char_lang(n));
2812 } else if (lua_key_eq(s, left)) {
2813 lua_pushnumber(L, char_lhmin(n));
2814 } else if (lua_key_eq(s, right)) {
2815 lua_pushnumber(L, char_rhmin(n));
2816 } else if (lua_key_eq(s, uchyph)) {
2817 lua_pushnumber(L, char_uchyph(n));
2818 } else {
2819 lua_pushnil(L);
2820 }
2821 } else if ((t == hlist_node) || (t == vlist_node)) {
2822 /* candidates: whd (width,height,depth) */
2823 if (lua_key_eq(s, subtype)) {
2824 lua_pushnumber(L, subtype(n));
2825 } else if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
2826 fast_metatable_or_nil_alink(list_ptr(n));
2827 } else if (lua_key_eq(s, width)) {
2828 lua_pushnumber(L, width(n));
2829 } else if (lua_key_eq(s, height)) {
2830 lua_pushnumber(L, height(n));
2831 } else if (lua_key_eq(s, depth)) {
2832 lua_pushnumber(L, depth(n));
2833 } else if (lua_key_eq(s, dir)) {
2834 // nodelib_pushdir(L, box_dir(n), false);
2835 lua_push_dir_par(L, box_dir(n));
2836 } else if (lua_key_eq(s, shift)) {
2837 lua_pushnumber(L, shift_amount(n));
2838 } else if (lua_key_eq(s, glue_order)) {
2839 lua_pushnumber(L, glue_order(n));
2840 } else if (lua_key_eq(s, glue_sign)) {
2841 lua_pushnumber(L, glue_sign(n));
2842 } else if (lua_key_eq(s, glue_set)) {
2843 lua_pushnumber(L, (double) glue_set(n));
2844 } else {
2845 lua_pushnil(L);
2846 }
2847 } else if (t == disc_node) {
2848 if (lua_key_eq(s, subtype)) {
2849 lua_pushnumber(L, subtype(n));
2850 } else if (lua_key_eq(s, pre)) {
2851 fast_metatable_or_nil(vlink(pre_break(n)));
2852 } else if (lua_key_eq(s, post)) {
2853 fast_metatable_or_nil(vlink(post_break(n)));
2854 } else if (lua_key_eq(s, replace)) {
2855 fast_metatable_or_nil(vlink(no_break(n)));
2856 } else {
2857 lua_pushnil(L);
2858 }
2859 } else if (t == glue_node) {
2860 if (lua_key_eq(s, subtype)) {
2861 lua_pushnumber(L, subtype(n));
2862 } else if (lua_key_eq(s, spec)) {
2863 nodelib_pushspec(L, glue_ptr(n));
2864 } else if (lua_key_eq(s, leader)) {
2865 fast_metatable_or_nil(leader_ptr(n));
2866 } else {
2867 lua_pushnil(L);
2868 }
2869 } else if (t == glue_spec_node) {
2870 if (lua_key_eq(s, subtype)) {
2871 lua_pushnumber(L, 0); /* dummy, the only one that prevents move up */
2872 } else if (lua_key_eq(s, width)) {
2873 lua_pushnumber(L, width(n));
2874 } else if (lua_key_eq(s, stretch)) {
2875 lua_pushnumber(L, stretch(n));
2876 } else if (lua_key_eq(s, shrink)) {
2877 lua_pushnumber(L, shrink(n));
2878 } else if (lua_key_eq(s, stretch_order)) {
2879 lua_pushnumber(L, stretch_order(n));
2880 } else if (lua_key_eq(s, shrink_order)) {
2881 lua_pushnumber(L, shrink_order(n));
2882 } else if (lua_key_eq(s, ref_count)) {
2883 lua_pushnumber(L, glue_ref_count(n));
2884 } else if (lua_key_eq(s, writable)) {
2885 lua_pushboolean(L, valid_node(n));
2886 } else {
2887 lua_pushnil(L);
2888 }
2889 } else if (t == kern_node) {
2890 if (lua_key_eq(s, subtype)) {
2891 lua_pushnumber(L, subtype(n));
2892 } else if (lua_key_eq(s, kern)) {
2893 lua_pushnumber(L, width(n));
2894 } else if (lua_key_eq(s, expansion_factor)) {
2895 lua_pushnumber(L, ex_kern(n));
2896 } else {
2897 lua_pushnil(L);
2898 }
2899 } else if (t == penalty_node) {
2900 if (lua_key_eq(s, subtype)) {
2901 lua_pushnumber(L, subtype(n));
2902 } else if (lua_key_eq(s, penalty)) {
2903 lua_pushnumber(L, penalty(n));
2904 } else {
2905 lua_pushnil(L);
2906 }
2907 } else if (t == rule_node) {
2908 /* candidates: whd (width,height,depth) */
2909 if (lua_key_eq(s, subtype)) {
2910 lua_pushnumber(L, subtype(n));
2911 } else if (lua_key_eq(s, width)) {
2912 lua_pushnumber(L, width(n));
2913 } else if (lua_key_eq(s, height)) {
2914 lua_pushnumber(L, height(n));
2915 } else if (lua_key_eq(s, depth)) {
2916 lua_pushnumber(L, depth(n));
2917 } else if (lua_key_eq(s, dir)) {
2918 // nodelib_pushdir(L, rule_dir(n), false);
2919 lua_push_dir_par(L, rule_dir(n));
2920 } else {
2921 lua_pushnil(L);
2922 }
2923 } else if (t == whatsit_node) {
2924 if (lua_key_eq(s, subtype)) {
2925 lua_pushnumber(L, subtype(n));
2926 } else {
2927 lua_nodelib_getfield_whatsit(L, n, s);
2928 }
2929 } else if (t == simple_noad) {
2930 if (lua_key_eq(s, subtype)) {
2931 lua_pushnumber(L, subtype(n));
2932 } else if (lua_key_eq(s, nucleus)) {
2933 fast_metatable_or_nil(nucleus(n));
2934 } else if (lua_key_eq(s, sub)) {
2935 fast_metatable_or_nil(subscr(n));
2936 } else if (lua_key_eq(s, sup)) {
2937 fast_metatable_or_nil(supscr(n));
2938 } else {
2939 lua_pushnil(L);
2940 }
2941 } else if ((t == math_char_node) || (t == math_text_char_node)) {
2942 /* candidates: famchar (fam,char) */
2943 if (lua_key_eq(s, subtype)) {
2944 lua_pushnumber(L, subtype(n));
2945 } else if (lua_key_eq(s, fam)) {
2946 lua_pushnumber(L, math_fam(n));
2947 } else if (lua_key_eq(s, char)) {
2948 lua_pushnumber(L, math_character(n));
2949 } else {
2950 lua_pushnil(L);
2951 }
2952 } else if (t == mark_node) {
2953 if (lua_key_eq(s, subtype)) {
2954 lua_pushnumber(L, subtype(n));
2955 } else if (lua_key_eq(s, class)) {
2956 lua_pushnumber(L, mark_class(n));
2957 } else if (lua_key_eq(s, mark)) {
2958 tokenlist_to_lua(L, mark_ptr(n));
2959 } else {
2960 lua_pushnil(L);
2961 }
2962 } else if (t == ins_node) {
2963 if (lua_key_eq(s, subtype)) {
2964 lua_pushnumber(L, subtype(n));
2965 } else if (lua_key_eq(s, cost)) {
2966 lua_pushnumber(L, float_cost(n));
2967 } else if (lua_key_eq(s, depth)) {
2968 lua_pushnumber(L, depth(n));
2969 } else if (lua_key_eq(s, height)) {
2970 lua_pushnumber(L, height(n));
2971 } else if (lua_key_eq(s, spec)) {
2972 nodelib_pushspec(L, split_top_ptr(n));
2973 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))) {
2974 fast_metatable_or_nil_alink(ins_ptr(n));
2975 } else {
2976 lua_pushnil(L);
2977 }
2978 } else if (t == math_node) {
2979 if (lua_key_eq(s, subtype)) {
2980 lua_pushnumber(L, subtype(n));
2981 } else if (lua_key_eq(s, surround)) {
2982 lua_pushnumber(L, surround(n));
2983 } else {
2984 lua_pushnil(L);
2985 }
2986 } else if (t == fraction_noad) {
2987 if (lua_key_eq(s, subtype)) {
2988 lua_pushnumber(L, subtype(n));
2989 } else if (lua_key_eq(s, width)) {
2990 lua_pushnumber(L, thickness(n));
2991 } else if (lua_key_eq(s, num)) {
2992 fast_metatable_or_nil(numerator(n));
2993 } else if (lua_key_eq(s, denom)) {
2994 fast_metatable_or_nil(denominator(n));
2995 } else if (lua_key_eq(s, left)) {
2996 fast_metatable_or_nil(left_delimiter(n));
2997 } else if (lua_key_eq(s, right)) {
2998 fast_metatable_or_nil(right_delimiter(n));
2999 } else {
3000 lua_pushnil(L);
3001 }
3002 } else if (t == style_node) {
3003 if (lua_key_eq(s, subtype)) {
3004 lua_pushnumber(L, subtype(n));
3005 } else if (lua_key_eq(s, style)) {
3006 lua_push_math_style_name(L,subtype(n));
3007 } else {
3008 lua_pushnil(L);
3009 }
3010 } else if (t == accent_noad) {
3011 if (lua_key_eq(s, subtype)) {
3012 lua_pushnumber(L, subtype(n));
3013 } else if (lua_key_eq(s, nucleus)) {
3014 fast_metatable_or_nil(nucleus(n));
3015 } else if (lua_key_eq(s, sub)) {
3016 fast_metatable_or_nil(subscr(n));
3017 } else if (lua_key_eq(s, sup)) {
3018 fast_metatable_or_nil(supscr(n));
3019 } else if (lua_key_eq(s, accent)) {
3020 fast_metatable_or_nil(accent_chr(n));
3021 } else if (lua_key_eq(s, bot_accent)) {
3022 fast_metatable_or_nil(bot_accent_chr(n));
3023 } else {
3024 lua_pushnil(L);
3025 }
3026 } else if (t == fence_noad) {
3027 if (lua_key_eq(s, subtype)) {
3028 lua_pushnumber(L, subtype(n));
3029 } else if (lua_key_eq(s, delim)) {
3030 fast_metatable_or_nil(delimiter(n));
3031 } else {
3032 lua_pushnil(L);
3033 }
3034 } else if (t == delim_node) {
3035 if (lua_key_eq(s, subtype)) {
3036 lua_pushnumber(L, subtype(n));
3037 } else if (lua_key_eq(s, small_fam)) {
3038 lua_pushnumber(L, small_fam(n));
3039 } else if (lua_key_eq(s, small_char)) {
3040 lua_pushnumber(L, small_char(n));
3041 } else if (lua_key_eq(s, large_fam)) {
3042 lua_pushnumber(L, large_fam(n));
3043 } else if (lua_key_eq(s, large_char)) {
3044 lua_pushnumber(L, large_char(n));
3045 } else {
3046 lua_pushnil(L);
3047 }
3048 } else if ((t == sub_box_node) || (t == sub_mlist_node)) {
3049 if (lua_key_eq(s, subtype)) {
3050 lua_pushnumber(L, subtype(n));
3051 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))){
3052 fast_metatable_or_nil_alink(math_list(n));
3053 } else {
3054 lua_pushnil(L);
3055 }
3056 } else if (t == radical_noad) {
3057 if (lua_key_eq(s, subtype)) {
3058 lua_pushnumber(L, subtype(n));
3059 } else if (lua_key_eq(s, nucleus)) {
3060 fast_metatable_or_nil(nucleus(n));
3061 } else if (lua_key_eq(s, sub)) {
3062 fast_metatable_or_nil(subscr(n));
3063 } else if (lua_key_eq(s, sup)) {
3064 fast_metatable_or_nil(supscr(n));
3065 } else if (lua_key_eq(s, left)) {
3066 fast_metatable_or_nil(left_delimiter(n));
3067 } else if (lua_key_eq(s, degree)) {
3068 fast_metatable_or_nil(degree(n));
3069 } else {
3070 lua_pushnil(L);
3071 }
3072 } else if (t == margin_kern_node) {
3073 if (lua_key_eq(s, subtype)) {
3074 lua_pushnumber(L, subtype(n));
3075 } else if (lua_key_eq(s, width)) {
3076 lua_pushnumber(L, width(n));
3077 } else if (lua_key_eq(s, glyph)) {
3078 fast_metatable_or_nil(margin_char(n));
3079 } else {
3080 lua_pushnil(L);
3081 }
3082 } else if (t == split_up_node) {
3083 if (lua_key_eq(s, subtype)) {
3084 lua_pushnumber(L, subtype(n));
3085 } else if (lua_key_eq(s, last_ins_ptr)) {
3086 fast_metatable_or_nil(last_ins_ptr(n));
3087 } else if (lua_key_eq(s, best_ins_ptr)) {
3088 fast_metatable_or_nil(best_ins_ptr(n));
3089 } else if (lua_key_eq(s, broken_ptr)) {
3090 fast_metatable_or_nil(broken_ptr(n));
3091 } else if (lua_key_eq(s, broken_ins)) {
3092 fast_metatable_or_nil(broken_ins(n));
3093 } else {
3094 lua_pushnil(L);
3095 }
3096 } else if (t == choice_node) {
3097 if (lua_key_eq(s, subtype)) {
3098 lua_pushnumber(L, subtype(n));
3099 } else if (lua_key_eq(s, display)) {
3100 fast_metatable_or_nil(display_mlist(n));
3101 } else if (lua_key_eq(s, text)) {
3102 fast_metatable_or_nil(text_mlist(n));
3103 } else if (lua_key_eq(s, script)) {
3104 fast_metatable_or_nil(script_mlist(n));
3105 } else if (lua_key_eq(s, scriptscript)) {
3106 fast_metatable_or_nil(script_script_mlist(n));
3107 } else {
3108 lua_pushnil(L);
3109 }
3110 } else if (t == inserting_node) {
3111 if (lua_key_eq(s, subtype)) {
3112 lua_pushnumber(L, subtype(n));
3113 } else if (lua_key_eq(s, last_ins_ptr)) {
3114 fast_metatable_or_nil(last_ins_ptr(n));
3115 } else if (lua_key_eq(s, best_ins_ptr)) {
3116 fast_metatable_or_nil(best_ins_ptr(n));
3117 } else {
3118 lua_pushnil(L);
3119 }
3120 } else if (t == attribute_node) {
3121 if (lua_key_eq(s, subtype)) {
3122 lua_pushnumber(L, subtype(n));
3123 } else if (lua_key_eq(s, number)) {
3124 lua_pushnumber(L, attribute_id(n));
3125 } else if (lua_key_eq(s, value)) {
3126 lua_pushnumber(L, attribute_value(n));
3127 } else {
3128 lua_pushnil(L);
3129 }
3130 } else if (t == adjust_node) {
3131 if (lua_key_eq(s, subtype)) {
3132 lua_pushnumber(L, subtype(n));
3133 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))) {
3134 fast_metatable_or_nil_alink(adjust_ptr(n));
3135 } else {
3136 lua_pushnil(L);
3137 }
3138 } else if (t == action_node) {
3139 if (lua_key_eq(s, subtype)) {
3140 lua_pushnumber(L, subtype(n));/* dummy subtype */
3141 } else if (lua_key_eq(s, action_type)) {
3142 lua_pushnumber(L, pdf_action_type(n));
3143 } else if (lua_key_eq(s, named_id)) {
3144 lua_pushnumber(L, pdf_action_named_id(n));
3145 } else if (lua_key_eq(s, action_id)) {
3146 if (pdf_action_named_id(n) == 1) {
3147 tokenlist_to_luastring(L, pdf_action_id(n));
3148 } else {
3149 lua_pushnumber(L, pdf_action_id(n));
3150 }
3151 } else if (lua_key_eq(s, file)) {
3152 tokenlist_to_luastring(L, pdf_action_file(n));
3153 } else if (lua_key_eq(s, new_window)) {
3154 lua_pushnumber(L, pdf_action_new_window(n));
3155 } else if (lua_key_eq(s, data)) {
3156 tokenlist_to_luastring(L, pdf_action_tokens(n));
3157 } else if (lua_key_eq(s, ref_count)) {
3158 lua_pushnumber(L, pdf_action_refcount(n));
3159 } else {
3160 lua_pushnil(L);
3161 }
3162 } else if (t == unset_node) {
3163 if (lua_key_eq(s, subtype)) {
3164 lua_pushnumber(L, subtype(n));
3165 } else if (lua_key_eq(s, width)) {
3166 lua_pushnumber(L, width(n));
3167 } else if (lua_key_eq(s, height)) {
3168 lua_pushnumber(L, height(n));
3169 } else if (lua_key_eq(s, depth)) {
3170 lua_pushnumber(L, depth(n));
3171 } else if (lua_key_eq(s, dir)) {
3172 // nodelib_pushdir(L, box_dir(n), false);
3173 lua_push_dir_par(L, box_dir(n));
3174 } else if (lua_key_eq(s, shrink)) {
3175 lua_pushnumber(L, glue_shrink(n));
3176 } else if (lua_key_eq(s, glue_order)) {
3177 lua_pushnumber(L, glue_order(n));
3178 } else if (lua_key_eq(s, glue_sign)) {
3179 lua_pushnumber(L, glue_sign(n));
3180 } else if (lua_key_eq(s, stretch)) {
3181 lua_pushnumber(L, glue_stretch(n));
3182 } else if (lua_key_eq(s, count)) {
3183 lua_pushnumber(L, span_count(n));
3184 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))){
3185 fast_metatable_or_nil_alink(list_ptr(n));
3186 } else {
3187 lua_pushnil(L);
3188 }
3189 } else if (t == attribute_list_node) {
3190 if (lua_key_eq(s, subtype)) {
3191 lua_pushnumber(L, subtype(n));
3192 } else {
3193 lua_pushnil(L);
3194 }
3195 } else {
3196 lua_pushnil(L);
3197 }
3198 return 1;
3199 }
3200
lua_nodelib_getfield(lua_State * L)3201 static int lua_nodelib_getfield(lua_State * L)
3202 {
3203 /* [given-node] [...]*/
3204 halfword *p = lua_touserdata(L, 1);
3205 if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
3206 lua_pushnil(L) ;
3207 return 1;
3208 }
3209 /* [given-node] [mt-given-node]*/
3210 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
3211 lua_gettable(L, LUA_REGISTRYINDEX);
3212 /* [given-node] [mt-given-node] [mt-node]*/
3213 if (!lua_rawequal(L, -1, -2)) {
3214 lua_pushnil(L) ;
3215 return 1;
3216 }
3217 /* prune stack and call getfield */
3218 lua_settop(L,2);
3219 return lua_nodelib_fast_getfield(L);
3220 }
3221
3222 /* node.direct.getfield */
3223
lua_nodelib_direct_getfield_whatsit(lua_State * L,int n,const char * s)3224 static void lua_nodelib_direct_getfield_whatsit(lua_State * L, int n, const char *s)
3225 {
3226 int t ;
3227 t = subtype(n);
3228
3229 if (t == dir_node) {
3230 if (lua_key_eq(s, dir)) {
3231 // nodelib_pushdir(L, dir_dir(n), true);
3232 lua_push_dir_text(L, dir_dir(n));
3233 } else if (lua_key_eq(s, level)) {
3234 lua_pushnumber(L, dir_level(n));
3235 } else if (lua_key_eq(s, dvi_ptr)) {
3236 lua_pushnumber(L, dir_dvi_ptr(n));
3237 } else if (lua_key_eq(s, dir_h)) {
3238 lua_pushnumber(L, dir_dvi_h(n));
3239 } else {
3240 lua_pushnil(L);
3241 }
3242 } else if (t == user_defined_node) {
3243 if (lua_key_eq(s, user_id)) {
3244 lua_pushnumber(L, user_node_id(n));
3245 } else if (lua_key_eq(s, type)) {
3246 lua_pushnumber(L, user_node_type(n));
3247 } else if (lua_key_eq(s, value)) {
3248 switch (user_node_type(n)) {
3249 case 'a':
3250 nodelib_pushdirect(user_node_value(n));
3251 break;
3252 case 'd':
3253 lua_pushnumber(L, user_node_value(n));
3254 break;
3255 case 'l':
3256 if (user_node_value(n) != 0) {
3257 lua_rawgeti(L, LUA_REGISTRYINDEX, user_node_value(n));
3258 } else {
3259 lua_pushnil(L);
3260 }
3261 break;
3262 case 'n':
3263 nodelib_pushdirect(user_node_value(n));
3264 break;
3265 case 's':
3266 nodelib_pushstring(L, user_node_value(n));
3267 break;
3268 case 't':
3269 tokenlist_to_lua(L, user_node_value(n));
3270 break;
3271 default:
3272 lua_pushnumber(L, user_node_value(n));
3273 break;
3274 }
3275 } else {
3276 lua_pushnil(L);
3277 }
3278 } else if (t == local_par_node) {
3279 if (lua_key_eq(s, pen_inter)) {
3280 lua_pushnumber(L, local_pen_inter(n));
3281 } else if (lua_key_eq(s, pen_broken)) {
3282 lua_pushnumber(L, local_pen_broken(n));
3283 } else if (lua_key_eq(s, dir)) {
3284 // nodelib_pushdir(L, local_par_dir(n), false);
3285 lua_push_dir_par(L, local_par_dir(n));
3286 } else if (lua_key_eq(s, box_left)) {
3287 nodelib_pushdirect_or_nil(local_box_left(n));
3288 } else if (lua_key_eq(s, box_left_width)) {
3289 lua_pushnumber(L, local_box_left_width(n));
3290 } else if (lua_key_eq(s, box_right)) {
3291 nodelib_pushdirect_or_nil(local_box_right(n));
3292 } else if (lua_key_eq(s, box_right_width)) {
3293 lua_pushnumber(L, local_box_right_width(n));
3294 } else {
3295 lua_pushnil(L);
3296 }
3297 } else if (t == pdf_literal_node) {
3298 if (lua_key_eq(s, mode)) {
3299 lua_pushnumber(L, pdf_literal_mode(n));
3300 } else if (lua_key_eq(s, data)) {
3301 if (pdf_literal_type(n) == lua_refid_literal) {
3302 lua_rawgeti(L, LUA_REGISTRYINDEX, pdf_literal_data(n));
3303 } else {
3304 tokenlist_to_luastring(L, pdf_literal_data(n));
3305 }
3306 } else {
3307 lua_pushnil(L);
3308 }
3309 } else if (t == late_lua_node) {
3310 if (lua_key_eq(s, string) || lua_key_eq(s, data)) {
3311 if (late_lua_type(n) == lua_refid_literal) {
3312 lua_rawgeti(L, LUA_REGISTRYINDEX, late_lua_data(n));
3313 } else {
3314 tokenlist_to_luastring(L, late_lua_data(n));
3315 }
3316 } else if (lua_key_eq(s, name)) {
3317 tokenlist_to_luastring(L, late_lua_name(n));
3318 } else {
3319 lua_pushnil(L);
3320 }
3321 } else if (t == pdf_annot_node) {
3322 if (lua_key_eq(s, width)) {
3323 lua_pushnumber(L, width(n));
3324 } else if (lua_key_eq(s, depth)) {
3325 lua_pushnumber(L, depth(n));
3326 } else if (lua_key_eq(s, height)) {
3327 lua_pushnumber(L, height(n));
3328 } else if (lua_key_eq(s, objnum)) {
3329 lua_pushnumber(L, pdf_annot_objnum(n));
3330 } else if (lua_key_eq(s, data)) {
3331 tokenlist_to_luastring(L, pdf_annot_data(n));
3332 } else {
3333 lua_pushnil(L);
3334 }
3335 } else if (t == pdf_dest_node) {
3336 if (lua_key_eq(s, width)) {
3337 lua_pushnumber(L, width(n));
3338 } else if (lua_key_eq(s, depth)) {
3339 lua_pushnumber(L, depth(n));
3340 } else if (lua_key_eq(s, height)) {
3341 lua_pushnumber(L, height(n));
3342 } else if (lua_key_eq(s, named_id)) {
3343 lua_pushnumber(L, pdf_dest_named_id(n));
3344 } else if (lua_key_eq(s, dest_id)) {
3345 if (pdf_dest_named_id(n) == 1)
3346 tokenlist_to_luastring(L, pdf_dest_id(n));
3347 else
3348 lua_pushnumber(L, pdf_dest_id(n));
3349 } else if (lua_key_eq(s, dest_type)) {
3350 lua_pushnumber(L, pdf_dest_type(n));
3351 } else if (lua_key_eq(s, xyz_zoom)) {
3352 lua_pushnumber(L, pdf_dest_xyz_zoom(n));
3353 } else if (lua_key_eq(s, objnum)) {
3354 lua_pushnumber(L, pdf_dest_objnum(n));
3355 } else {
3356 lua_pushnil(L);
3357 }
3358 } else if (t == pdf_setmatrix_node) {
3359 if (lua_key_eq(s, data)) {
3360 tokenlist_to_luastring(L, pdf_setmatrix_data(n));
3361 } else {
3362 lua_pushnil(L);
3363 }
3364 } else if (t == pdf_colorstack_node) {
3365 if (lua_key_eq(s, stack)) {
3366 lua_pushnumber(L, pdf_colorstack_stack(n));
3367 } else if (lua_key_eq(s, command)) {
3368 lua_pushnumber(L, pdf_colorstack_cmd(n));
3369 } else if (lua_key_eq(s, data)) {
3370 tokenlist_to_luastring(L, pdf_colorstack_data(n));
3371 } else {
3372 lua_pushnil(L);
3373 }
3374 } else if (t == pdf_refobj_node) {
3375 if (lua_key_eq(s, objnum)) {
3376 lua_pushnumber(L, pdf_obj_objnum(n));
3377 } else {
3378 lua_pushnil(L);
3379 }
3380 } else if (t == pdf_refxform_node) {
3381 if (lua_key_eq(s, width)) {
3382 lua_pushnumber(L, width(n));
3383 } else if (lua_key_eq(s, depth)) {
3384 lua_pushnumber(L, depth(n));
3385 } else if (lua_key_eq(s, height)) {
3386 lua_pushnumber(L, height(n));
3387 } else if (lua_key_eq(s, objnum)) {
3388 lua_pushnumber(L, pdf_xform_objnum(n));
3389 } else {
3390 lua_pushnil(L);
3391 }
3392 } else if (t == pdf_refximage_node) {
3393 if (lua_key_eq(s, width)) {
3394 lua_pushnumber(L, width(n));
3395 } else if (lua_key_eq(s, depth)) {
3396 lua_pushnumber(L, depth(n));
3397 } else if (lua_key_eq(s, height)) {
3398 lua_pushnumber(L, height(n));
3399 } else if (lua_key_eq(s, transform)) {
3400 lua_pushnumber(L, pdf_ximage_transform(n));
3401 } else if (lua_key_eq(s, index)) {
3402 lua_pushnumber(L, pdf_ximage_index(n));
3403 } else {
3404 lua_pushnil(L);
3405 }
3406 } else if (t == write_node) {
3407 if (lua_key_eq(s, stream)) {
3408 lua_pushnumber(L, write_stream(n));
3409 } else if (lua_key_eq(s, data)) {
3410 tokenlist_to_lua(L, write_tokens(n));
3411 } else {
3412 lua_pushnil(L);
3413 }
3414 } else if (t == special_node) {
3415 if (lua_key_eq(s, data)) {
3416 tokenlist_to_luastring(L, write_tokens(n));
3417 } else {
3418 lua_pushnil(L);
3419 }
3420 } else if (t == pdf_start_link_node) {
3421 if (lua_key_eq(s, width)) {
3422 lua_pushnumber(L, width(n));
3423 } else if (lua_key_eq(s, depth)) {
3424 lua_pushnumber(L, depth(n));
3425 } else if (lua_key_eq(s, height)) {
3426 lua_pushnumber(L, height(n));
3427 } else if (lua_key_eq(s, objnum)) {
3428 lua_pushnumber(L, pdf_link_objnum(n));
3429 } else if (lua_key_eq(s, link_attr)) {
3430 tokenlist_to_luastring(L, pdf_link_attr(n));
3431 } else if (lua_key_eq(s, action)) {
3432 nodelib_pushaction(L, pdf_link_action(n));
3433 } else {
3434 lua_pushnil(L);
3435 }
3436 } else if ((t == pdf_thread_node) || (t == pdf_start_thread_node)) {
3437 if (lua_key_eq(s, width)) {
3438 lua_pushnumber(L, width(n));
3439 } else if (lua_key_eq(s, depth)) {
3440 lua_pushnumber(L, depth(n));
3441 } else if (lua_key_eq(s, height)) {
3442 lua_pushnumber(L, height(n));
3443 } else if (lua_key_eq(s, named_id)) {
3444 lua_pushnumber(L, pdf_thread_named_id(n));
3445 } else if (lua_key_eq(s, thread_id)) {
3446 if (pdf_thread_named_id(n) == 1) {
3447 tokenlist_to_luastring(L, pdf_thread_id(n));
3448 } else {
3449 lua_pushnumber(L, pdf_thread_id(n));
3450 }
3451 } else if (lua_key_eq(s, thread_attr)) {
3452 tokenlist_to_luastring(L, pdf_thread_attr(n));
3453 } else {
3454 lua_pushnil(L);
3455 }
3456 } else if (t == open_node) {
3457 if (lua_key_eq(s, stream)) {
3458 lua_pushnumber(L, write_stream(n));
3459 } else if (lua_key_eq(s, name)) {
3460 nodelib_pushstring(L, open_name(n));
3461 } else if (lua_key_eq(s, area)) {
3462 nodelib_pushstring(L, open_area(n));
3463 } else if (lua_key_eq(s, ext)) {
3464 nodelib_pushstring(L, open_ext(n));
3465 } else {
3466 lua_pushnil(L);
3467 }
3468 } else if (t == close_node) {
3469 if (lua_key_eq(s, stream)) {
3470 lua_pushnumber(L, write_stream(n));
3471 } else {
3472 lua_pushnil(L);
3473 }
3474 } else {
3475 lua_pushnil(L);
3476 }
3477 }
3478
lua_nodelib_direct_getfield(lua_State * L)3479 static int lua_nodelib_direct_getfield(lua_State * L)
3480 {
3481
3482 halfword n;
3483 const char *s;
3484 int t ;
3485
3486 n = (halfword) lua_tonumber(L, 1);
3487
3488 t = type(n);
3489
3490 if (lua_type(L, 2) == LUA_TNUMBER) {
3491
3492 halfword p;
3493 int i;
3494
3495 if (! nodetype_has_attributes(t)) {
3496 lua_pushnil(L) ;
3497 return 1;
3498 }
3499
3500 p = node_attr(n);
3501 if (p == null || vlink(p) == null) {
3502 lua_pushnil(L) ;
3503 return 1;
3504 }
3505 i = (int) lua_tointeger(L, 2);
3506 p = vlink(p);
3507 while (p != null) {
3508 if (attribute_id(p) == i) {
3509 if ((int) attribute_value(p) > UNUSED_ATTRIBUTE) {
3510 lua_pushnumber(L, (int) attribute_value(p));
3511 } else {
3512 lua_pushnil(L);
3513 }
3514 return 1;
3515 } else if (attribute_id(p) > i) {
3516 lua_pushnil(L) ;
3517 return 1;
3518 }
3519 p = vlink(p);
3520 }
3521 lua_pushnil(L) ;
3522 return 1;
3523 }
3524
3525 s = lua_tostring(L, 2);
3526
3527 if (lua_key_eq(s, id)) {
3528 lua_pushnumber(L, t);
3529 } else if (lua_key_eq(s, next)) {
3530 nodelib_pushdirect_or_nil(vlink(n));
3531 } else if (lua_key_eq(s, prev)) {
3532 nodelib_pushdirect_or_nil(alink(n));
3533 } else if (lua_key_eq(s, attr)) {
3534 if (! nodetype_has_attributes(t)) {
3535 lua_pushnil(L);
3536 } else {
3537 nodelib_pushattr(L, node_attr(n));
3538 }
3539 } else if (lua_key_eq(s, subtype)) {
3540 if (t == glue_spec_node) {
3541 lua_pushnumber(L, 0); /* dummy, the only one */
3542 } else {
3543 lua_pushnumber(L, subtype(n));
3544 }
3545 } else if (t == glyph_node) {
3546 if (lua_key_eq(s, font)) {
3547 lua_pushnumber(L, font(n));
3548 } else if (lua_key_eq(s, char)) {
3549 lua_pushnumber(L, character(n));
3550 } else if (lua_key_eq(s, xoffset)) {
3551 lua_pushnumber(L, x_displace(n));
3552 } else if (lua_key_eq(s, yoffset)) {
3553 lua_pushnumber(L, y_displace(n));
3554 } else if (lua_key_eq(s, width)) {
3555 lua_pushnumber(L, char_width(font(n),character(n)));
3556 } else if (lua_key_eq(s, height)) {
3557 lua_pushnumber(L, char_height(font(n),character(n)));
3558 } else if (lua_key_eq(s, depth)) {
3559 lua_pushnumber(L, char_depth(font(n),character(n)));
3560 } else if (lua_key_eq(s, expansion_factor)) {
3561 lua_pushnumber(L, ex_glyph(n));
3562 } else if (lua_key_eq(s, components)) {
3563 nodelib_pushdirect_or_nil(lig_ptr(n));
3564 } else if (lua_key_eq(s, lang)) {
3565 lua_pushnumber(L, char_lang(n));
3566 } else if (lua_key_eq(s, left)) {
3567 lua_pushnumber(L, char_lhmin(n));
3568 } else if (lua_key_eq(s, right)) {
3569 lua_pushnumber(L, char_rhmin(n));
3570 } else if (lua_key_eq(s, uchyph)) {
3571 lua_pushnumber(L, char_uchyph(n));
3572 } else {
3573 lua_pushnil(L);
3574 }
3575 } else if ((t == hlist_node) || (t == vlist_node)) {
3576 /* candidates: whd (width,height,depth) */
3577 if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
3578 nodelib_pushdirect_or_nil_alink(list_ptr(n));
3579 } else if (lua_key_eq(s, width)) {
3580 lua_pushnumber(L, width(n));
3581 } else if (lua_key_eq(s, height)) {
3582 lua_pushnumber(L, height(n));
3583 } else if (lua_key_eq(s, depth)) {
3584 lua_pushnumber(L, depth(n));
3585 } else if (lua_key_eq(s, dir)) {
3586 // nodelib_pushdir(L, box_dir(n), false);
3587 lua_push_dir_par(L, box_dir(n));
3588 } else if (lua_key_eq(s, shift)) {
3589 lua_pushnumber(L, shift_amount(n));
3590 } else if (lua_key_eq(s, glue_order)) {
3591 lua_pushnumber(L, glue_order(n));
3592 } else if (lua_key_eq(s, glue_sign)) {
3593 lua_pushnumber(L, glue_sign(n));
3594 } else if (lua_key_eq(s, glue_set)) {
3595 lua_pushnumber(L, (double) glue_set(n));
3596 } else {
3597 lua_pushnil(L);
3598 }
3599 } else if (t == disc_node) {
3600 if (lua_key_eq(s, pre)) {
3601 nodelib_pushdirect_or_nil(vlink(pre_break(n)));
3602 } else if (lua_key_eq(s, post)) {
3603 nodelib_pushdirect_or_nil(vlink(post_break(n)));
3604 } else if (lua_key_eq(s, replace)) {
3605 nodelib_pushdirect_or_nil(vlink(no_break(n)));
3606 } else {
3607 lua_pushnil(L);
3608 }
3609 } else if (t == glue_node) {
3610 if (lua_key_eq(s, spec)) {
3611 nodelib_pushdirect(glue_ptr(n));
3612 } else if (lua_key_eq(s, leader)) {
3613 nodelib_pushdirect_or_nil(leader_ptr(n));
3614 } else {
3615 lua_pushnil(L);
3616 }
3617 } else if (t == glue_spec_node) {
3618 if (lua_key_eq(s, width)) {
3619 lua_pushnumber(L, width(n));
3620 } else if (lua_key_eq(s, stretch)) {
3621 lua_pushnumber(L, stretch(n));
3622 } else if (lua_key_eq(s, shrink)) {
3623 lua_pushnumber(L, shrink(n));
3624 } else if (lua_key_eq(s, stretch_order)) {
3625 lua_pushnumber(L, stretch_order(n));
3626 } else if (lua_key_eq(s, shrink_order)) {
3627 lua_pushnumber(L, shrink_order(n));
3628 } else if (lua_key_eq(s, ref_count)) {
3629 lua_pushnumber(L, glue_ref_count(n));
3630 } else if (lua_key_eq(s, writable)) {
3631 lua_pushboolean(L, valid_node(n));
3632 } else {
3633 lua_pushnil(L);
3634 }
3635 } else if (t == kern_node) {
3636 if (lua_key_eq(s, kern)) {
3637 lua_pushnumber(L, width(n));
3638 } else if (lua_key_eq(s, expansion_factor)) {
3639 lua_pushnumber(L, ex_kern(n));
3640 } else {
3641 lua_pushnil(L);
3642 }
3643 } else if (t == penalty_node) {
3644 if (lua_key_eq(s, penalty)) {
3645 lua_pushnumber(L, penalty(n));
3646 } else {
3647 lua_pushnil(L);
3648 }
3649 } else if (t == rule_node) {
3650 /* candidates: whd (width,height,depth) */
3651 if (lua_key_eq(s, width)) {
3652 lua_pushnumber(L, width(n));
3653 } else if (lua_key_eq(s, height)) {
3654 lua_pushnumber(L, height(n));
3655 } else if (lua_key_eq(s, depth)) {
3656 lua_pushnumber(L, depth(n));
3657 } else if (lua_key_eq(s, dir)) {
3658 // nodelib_pushdir(L, rule_dir(n), false);
3659 lua_push_dir_par(L, rule_dir(n));
3660 } else {
3661 lua_pushnil(L);
3662 }
3663 } else if (t == whatsit_node) {
3664 lua_nodelib_direct_getfield_whatsit(L, n, s);
3665 } else if (t == simple_noad) {
3666 if (lua_key_eq(s, nucleus)) {
3667 nodelib_pushdirect_or_nil(nucleus(n));
3668 } else if (lua_key_eq(s, sub)) {
3669 nodelib_pushdirect_or_nil(subscr(n));
3670 } else if (lua_key_eq(s, sup)) {
3671 nodelib_pushdirect_or_nil(supscr(n));
3672 } else {
3673 lua_pushnil(L);
3674 }
3675 } else if ((t == math_char_node) || (t == math_text_char_node)) {
3676 if (lua_key_eq(s, fam)) {
3677 lua_pushnumber(L, math_fam(n));
3678 } else if (lua_key_eq(s, char)) {
3679 lua_pushnumber(L, math_character(n));
3680 } else {
3681 lua_pushnil(L);
3682 }
3683 } else if (t == mark_node) {
3684 if (lua_key_eq(s, class)) {
3685 lua_pushnumber(L, mark_class(n));
3686 } else if (lua_key_eq(s, mark)) {
3687 tokenlist_to_lua(L, mark_ptr(n));
3688 } else {
3689 lua_pushnil(L);
3690 }
3691 } else if (t == ins_node) {
3692 if (lua_key_eq(s, cost)) {
3693 lua_pushnumber(L, float_cost(n));
3694 } else if (lua_key_eq(s, depth)) {
3695 lua_pushnumber(L, depth(n));
3696 } else if (lua_key_eq(s, height)) {
3697 lua_pushnumber(L, height(n));
3698 } else if (lua_key_eq(s, spec)) {
3699 nodelib_pushdirect_or_nil(split_top_ptr(n));
3700 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))) {
3701 nodelib_pushdirect_or_nil_alink(ins_ptr(n));
3702 } else {
3703 lua_pushnil(L);
3704 }
3705 } else if (t == math_node) {
3706 if (lua_key_eq(s, surround)) {
3707 lua_pushnumber(L, surround(n));
3708 } else {
3709 lua_pushnil(L);
3710 }
3711 } else if (t == fraction_noad) {
3712 if (lua_key_eq(s, width)) {
3713 lua_pushnumber(L, thickness(n));
3714 } else if (lua_key_eq(s, num)) {
3715 nodelib_pushdirect_or_nil(numerator(n));
3716 } else if (lua_key_eq(s, denom)) {
3717 nodelib_pushdirect_or_nil(denominator(n));
3718 } else if (lua_key_eq(s, left)) {
3719 nodelib_pushdirect_or_nil(left_delimiter(n));
3720 } else if (lua_key_eq(s, right)) {
3721 nodelib_pushdirect_or_nil(right_delimiter(n));
3722 } else {
3723 lua_pushnil(L);
3724 }
3725 } else if (t == style_node) {
3726 if (lua_key_eq(s, style)) {
3727 lua_push_math_style_name(L,subtype(n));
3728 } else {
3729 lua_pushnil(L);
3730 }
3731 } else if (t == accent_noad) {
3732 if (lua_key_eq(s, nucleus)) {
3733 nodelib_pushdirect_or_nil(nucleus(n));
3734 } else if (lua_key_eq(s, sub)) {
3735 nodelib_pushdirect_or_nil(subscr(n));
3736 } else if (lua_key_eq(s, sup)) {
3737 nodelib_pushdirect_or_nil(supscr(n));
3738 } else if (lua_key_eq(s, accent)) {
3739 nodelib_pushdirect_or_nil(accent_chr(n));
3740 } else if (lua_key_eq(s, bot_accent)) {
3741 nodelib_pushdirect_or_nil(bot_accent_chr(n));
3742 } else {
3743 lua_pushnil(L);
3744 }
3745 } else if (t == fence_noad) {
3746 if (lua_key_eq(s, delim)) {
3747 nodelib_pushdirect_or_nil(delimiter(n));
3748 } else {
3749 lua_pushnil(L);
3750 }
3751 } else if (t == delim_node) {
3752 if (lua_key_eq(s, small_fam)) {
3753 lua_pushnumber(L, small_fam(n));
3754 } else if (lua_key_eq(s, small_char)) {
3755 lua_pushnumber(L, small_char(n));
3756 } else if (lua_key_eq(s, large_fam)) {
3757 lua_pushnumber(L, large_fam(n));
3758 } else if (lua_key_eq(s, large_char)) {
3759 lua_pushnumber(L, large_char(n));
3760 } else {
3761 lua_pushnil(L);
3762 }
3763 } else if ((t == sub_box_node) || (t == sub_mlist_node)) {
3764 if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))){
3765 nodelib_pushdirect_or_nil_alink(math_list(n));
3766 } else {
3767 lua_pushnil(L);
3768 }
3769 } else if (t == radical_noad) {
3770 if (lua_key_eq(s, nucleus)) {
3771 nodelib_pushdirect_or_nil(nucleus(n));
3772 } else if (lua_key_eq(s, sub)) {
3773 nodelib_pushdirect_or_nil(subscr(n));
3774 } else if (lua_key_eq(s, sup)) {
3775 nodelib_pushdirect_or_nil(supscr(n));
3776 } else if (lua_key_eq(s, left)) {
3777 nodelib_pushdirect_or_nil(left_delimiter(n));
3778 } else if (lua_key_eq(s, degree)) {
3779 nodelib_pushdirect_or_nil(degree(n));
3780 } else {
3781 lua_pushnil(L);
3782 }
3783 } else if (t == margin_kern_node) {
3784 if (lua_key_eq(s, width)) {
3785 lua_pushnumber(L, width(n));
3786 } else if (lua_key_eq(s, glyph)) {
3787 nodelib_pushdirect_or_nil(margin_char(n));
3788 } else {
3789 lua_pushnil(L);
3790 }
3791 } else if (t == split_up_node) {
3792 if (lua_key_eq(s, last_ins_ptr)) {
3793 nodelib_pushdirect_or_nil(last_ins_ptr(n));
3794 } else if (lua_key_eq(s, best_ins_ptr)) {
3795 nodelib_pushdirect_or_nil(best_ins_ptr(n));
3796 } else if (lua_key_eq(s, broken_ptr)) {
3797 nodelib_pushdirect_or_nil(broken_ptr(n));
3798 } else if (lua_key_eq(s, broken_ins)) {
3799 nodelib_pushdirect_or_nil(broken_ins(n));
3800 } else {
3801 lua_pushnil(L);
3802 }
3803 } else if (t == choice_node) {
3804 if (lua_key_eq(s, display)) {
3805 nodelib_pushdirect_or_nil(display_mlist(n));
3806 } else if (lua_key_eq(s, text)) {
3807 nodelib_pushdirect_or_nil(text_mlist(n));
3808 } else if (lua_key_eq(s, script)) {
3809 nodelib_pushdirect_or_nil(script_mlist(n));
3810 } else if (lua_key_eq(s, scriptscript)) {
3811 nodelib_pushdirect_or_nil(script_script_mlist(n));
3812 } else {
3813 lua_pushnil(L);
3814 }
3815 } else if (t == inserting_node) {
3816 if (lua_key_eq(s, last_ins_ptr)) {
3817 nodelib_pushdirect_or_nil(last_ins_ptr(n));
3818 } else if (lua_key_eq(s, best_ins_ptr)) {
3819 nodelib_pushdirect_or_nil(best_ins_ptr(n));
3820 } else {
3821 lua_pushnil(L);
3822 }
3823 } else if (t == attribute_node) {
3824 if (lua_key_eq(s, number)) {
3825 lua_pushnumber(L, attribute_id(n));
3826 } else if (lua_key_eq(s, value)) {
3827 lua_pushnumber(L, attribute_value(n));
3828 } else {
3829 lua_pushnil(L);
3830 }
3831 } else if (t == adjust_node) {
3832 if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))) {
3833 nodelib_pushdirect_or_nil_alink(adjust_ptr(n));
3834 } else {
3835 lua_pushnil(L);
3836 }
3837 } else if (t == action_node) {
3838 if (lua_key_eq(s, action_type)) {
3839 lua_pushnumber(L, pdf_action_type(n));
3840 } else if (lua_key_eq(s, named_id)) {
3841 lua_pushnumber(L, pdf_action_named_id(n));
3842 } else if (lua_key_eq(s, action_id)) {
3843 if (pdf_action_named_id(n) == 1) {
3844 tokenlist_to_luastring(L, pdf_action_id(n));
3845 } else {
3846 lua_pushnumber(L, pdf_action_id(n));
3847 }
3848 } else if (lua_key_eq(s, file)) {
3849 tokenlist_to_luastring(L, pdf_action_file(n));
3850 } else if (lua_key_eq(s, new_window)) {
3851 lua_pushnumber(L, pdf_action_new_window(n));
3852 } else if (lua_key_eq(s, data)) {
3853 tokenlist_to_luastring(L, pdf_action_tokens(n));
3854 } else if (lua_key_eq(s, ref_count)) {
3855 lua_pushnumber(L, pdf_action_refcount(n));
3856 } else {
3857 lua_pushnil(L);
3858 }
3859 } else if (t == unset_node) {
3860 if (lua_key_eq(s, width)) {
3861 lua_pushnumber(L, width(n));
3862 } else if (lua_key_eq(s, height)) {
3863 lua_pushnumber(L, height(n));
3864 } else if (lua_key_eq(s, depth)) {
3865 lua_pushnumber(L, depth(n));
3866 } else if (lua_key_eq(s, dir)) {
3867 // nodelib_pushdir(L, box_dir(n), false);
3868 lua_push_dir_par(L, box_dir(n));
3869 } else if (lua_key_eq(s, shrink)) {
3870 lua_pushnumber(L, glue_shrink(n));
3871 } else if (lua_key_eq(s, glue_order)) {
3872 lua_pushnumber(L, glue_order(n));
3873 } else if (lua_key_eq(s, glue_sign)) {
3874 lua_pushnumber(L, glue_sign(n));
3875 } else if (lua_key_eq(s, stretch)) {
3876 lua_pushnumber(L, glue_stretch(n));
3877 } else if (lua_key_eq(s, count)) {
3878 lua_pushnumber(L, span_count(n));
3879 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))){
3880 nodelib_pushdirect_or_nil_alink(list_ptr(n));
3881 } else {
3882 lua_pushnil(L);
3883 }
3884 /* } else if (t == attribute_list_node) { */
3885 /* lua_pushnil(L); */
3886 } else {
3887 lua_pushnil(L);
3888 }
3889 return 1;
3890 }
3891
3892 /* msg could be preallocated and shared */
3893
lua_nodelib_do_tostring(lua_State * L,halfword n,const char * tag)3894 static void lua_nodelib_do_tostring(lua_State * L, halfword n, const char *tag)
3895 {
3896 char *msg;
3897 char a[7] = { ' ', ' ', ' ', 'n', 'i', 'l', 0 };
3898 char v[7] = { ' ', ' ', ' ', 'n', 'i', 'l', 0 };
3899 msg = xmalloc(256);
3900
3901 if ((alink(n) != null) && (type(n) != attribute_node))
3902 snprintf(a, 7, "%6d", (int) alink(n));
3903 if (vlink(n) != null)
3904 snprintf(v, 7, "%6d", (int) vlink(n));
3905 snprintf(msg, 255, "<%s %s < %6d > %s : %s %d>", tag, a, (int) n, v, node_data[type(n)].name, subtype(n));
3906 lua_pushstring(L, msg);
3907 free(msg);
3908 return ;
3909 }
3910
3911 /* __tostring node.tostring */
3912
lua_nodelib_tostring(lua_State * L)3913 static int lua_nodelib_tostring(lua_State * L)
3914 {
3915 halfword *n;
3916 n = check_isnode(L, 1);
3917 lua_nodelib_do_tostring(L, *n, "node");
3918 return 1;
3919 }
3920
3921 /* node.direct.tostring */
3922
lua_nodelib_direct_tostring(lua_State * L)3923 static int lua_nodelib_direct_tostring(lua_State * L)
3924 {
3925 halfword n = (halfword) lua_tonumber(L,1);
3926 if (n==0) {
3927 lua_pushnil(L);
3928 } else {
3929 lua_nodelib_do_tostring(L, n, "direct");
3930 }
3931 return 1;
3932 }
3933
3934 /* __eq */
3935
lua_nodelib_equal(lua_State * L)3936 static int lua_nodelib_equal(lua_State * L)
3937 {
3938 halfword n, m;
3939 n = *((halfword *) lua_touserdata(L, 1));
3940 m = *((halfword *) lua_touserdata(L, 2));
3941 lua_pushboolean(L, (n == m));
3942 return 1;
3943 }
3944
3945 /* node.ligaturing */
3946
font_tex_ligaturing(lua_State * L)3947 static int font_tex_ligaturing(lua_State * L)
3948 {
3949 /* on the stack are two nodes and a direction */
3950 /* hh-ls: we need to deal with prev nodes when a range starts with a ligature */
3951 halfword tmp_head;
3952 halfword *h;
3953 halfword t = null;
3954 halfword p ; /* hh-ls */
3955 if (lua_gettop(L) < 1) {
3956 lua_pushnil(L);
3957 lua_pushboolean(L, 0);
3958 return 2;
3959 }
3960 h = check_isnode(L, 1);
3961 if (lua_gettop(L) > 1) {
3962 t = *(check_isnode(L, 2));
3963 }
3964 tmp_head = new_node(nesting_node, 1);
3965 p = alink(*h); /* hh-ls */
3966 couple_nodes(tmp_head, *h);
3967 tlink(tmp_head) = t;
3968 t = handle_ligaturing(tmp_head, t);
3969 if (p != null) {
3970 vlink(p) = vlink(tmp_head) ; /* hh-ls */
3971 }
3972 alink(vlink(tmp_head)) = p ; /* hh-ls */
3973 lua_pushnumber(L, vlink(tmp_head));
3974 /* can be: lua_nodelib_push_fast(L, head); */
3975 flush_node(tmp_head);
3976 lua_nodelib_push(L);
3977 /* can be: lua_nodelib_push_fast(L, t); */
3978 lua_pushnumber(L, t);
3979 lua_nodelib_push(L);
3980 lua_pushboolean(L, 1);
3981 return 3;
3982 }
3983
3984
3985
3986 /* node.kerning */
3987
font_tex_kerning(lua_State * L)3988 static int font_tex_kerning(lua_State * L)
3989 {
3990 /* on the stack are two nodes and a direction */
3991
3992 halfword tmp_head;
3993 halfword *h;
3994 halfword t = null;
3995 halfword p ; /* hh-ls */
3996 if (lua_gettop(L) < 1) {
3997 lua_pushnil(L);
3998 lua_pushboolean(L, 0);
3999 return 2;
4000 }
4001 h = check_isnode(L, 1);
4002 if (lua_gettop(L) > 1) {
4003 t = *(check_isnode(L, 2));
4004 }
4005 tmp_head = new_node(nesting_node, 1);
4006 p = alink(*h); /* hh-ls */
4007 couple_nodes(tmp_head, *h);
4008 tlink(tmp_head) = t;
4009 t = handle_kerning(tmp_head, t);
4010 if (p != null) {
4011 vlink(p) = vlink(tmp_head) ; /* hh-ls */
4012 }
4013 alink(vlink(tmp_head)) = p ; /* hh-ls */
4014 lua_pushnumber(L, vlink(tmp_head));
4015 /* can be: lua_nodelib_push_fast(L, head); */
4016 flush_node(tmp_head);
4017 lua_nodelib_push(L);
4018 /* can be: lua_nodelib_push_fast(L, t); */
4019 lua_pushnumber(L, t);
4020 lua_nodelib_push(L);
4021 lua_pushboolean(L, 1);
4022 return 3;
4023 }
4024
4025
4026 /* node.protect_glyphs (returns also boolean because that signals callback) */
4027
lua_nodelib_protect_glyphs(lua_State * L)4028 static int lua_nodelib_protect_glyphs(lua_State * L)
4029 {
4030 int t = 0;
4031 halfword head = *(check_isnode(L, 1));
4032 while (head != null) {
4033 if (type(head) == glyph_node) {
4034 int s = subtype(head);
4035 if (s <= 256) {
4036 t = 1;
4037 subtype(head) = (quarterword) (s == 1 ? 256 : 256 + s);
4038 }
4039 }
4040 head = vlink(head);
4041 }
4042 lua_pushboolean(L, t);
4043 lua_pushvalue(L, 1);
4044 return 2;
4045 }
4046
4047 /* node.direct.protect_glyphs */
4048
lua_nodelib_direct_protect_glyphs(lua_State * L)4049 static int lua_nodelib_direct_protect_glyphs(lua_State * L)
4050 {
4051 int t = 0;
4052 halfword head = (halfword) lua_tonumber(L,1);
4053 while (head != null) {
4054 if (type(head) == glyph_node) {
4055 int s = subtype(head);
4056 if (s <= 256) {
4057 t = 1;
4058 subtype(head) = (quarterword) (s == 1 ? 256 : 256 + s);
4059 }
4060 }
4061 head = vlink(head);
4062 }
4063 lua_pushboolean(L, t);
4064 lua_pushvalue(L, 1);
4065 return 2;
4066 }
4067
4068 /* node.unprotect_glyphs (returns also boolean because that signals callback) */
4069
lua_nodelib_unprotect_glyphs(lua_State * L)4070 static int lua_nodelib_unprotect_glyphs(lua_State * L)
4071 {
4072 int t = 0;
4073 halfword head = *(check_isnode(L, 1));
4074 while (head != null) {
4075 if (type(head) == glyph_node) {
4076 int s = subtype(head);
4077 if (s > 256) {
4078 t = 1;
4079 subtype(head) = (quarterword) (s - 256);
4080 }
4081 }
4082 head = vlink(head);
4083 }
4084 lua_pushboolean(L, t);
4085 lua_pushvalue(L, 1);
4086 return 2;
4087 }
4088
4089 /* node.direct.unprotect_glyphs */
4090
lua_nodelib_direct_unprotect_glyphs(lua_State * L)4091 static int lua_nodelib_direct_unprotect_glyphs(lua_State * L)
4092 {
4093 int t = 0;
4094 halfword head = (halfword) lua_tonumber(L,1);
4095 while (head != null) {
4096 if (type(head) == glyph_node) {
4097 int s = subtype(head);
4098 if (s > 256) {
4099 t = 1;
4100 subtype(head) = (quarterword) (s - 256);
4101 }
4102 }
4103 head = vlink(head);
4104 }
4105 lua_pushboolean(L, t);
4106 lua_pushvalue(L, 1);
4107 return 2;
4108 }
4109
4110 /* node.first_glyph */
4111
lua_nodelib_first_glyph(lua_State * L)4112 static int lua_nodelib_first_glyph(lua_State * L)
4113 {
4114 /* on the stack are two nodes and a direction */
4115 halfword h, savetail = null, t = null;
4116 if (lua_gettop(L) < 1) {
4117 lua_pushnil(L);
4118 lua_pushboolean(L, 0);
4119 return 2;
4120 }
4121 h = *(check_isnode(L, 1));
4122 if (lua_gettop(L) > 1) {
4123 t = *(check_isnode(L, 2));
4124 savetail = vlink(t);
4125 vlink(t) = null;
4126 }
4127 while (h != null && (type(h) != glyph_node || !is_simple_character(h))) {
4128 h = vlink(h);
4129 }
4130 if (savetail != null) {
4131 vlink(t) = savetail;
4132 }
4133 lua_pushnumber(L, h);
4134 lua_nodelib_push(L);
4135 lua_pushboolean(L, (h == null ? 0 : 1));
4136 return 2;
4137 }
4138
4139 /* node.direct.first_glyph */
4140
lua_nodelib_direct_first_glyph(lua_State * L)4141 static int lua_nodelib_direct_first_glyph(lua_State * L)
4142 {
4143 halfword h,savetail,t;
4144 savetail = null;
4145 t = null;
4146 h = (halfword) lua_tonumber(L,1);
4147 if (h == null) {
4148 lua_pushnil(L);
4149 return 1;
4150 }
4151 t = (halfword) lua_tonumber(L,2);
4152 if (t != null) {
4153 savetail = vlink(t);
4154 vlink(t) = null;
4155 }
4156 while (h != null && (type(h) != glyph_node || !is_simple_character(h)))
4157 h = vlink(h);
4158 if (savetail != null)
4159 vlink(t) = savetail;
4160 lua_pushnumber(L, h);
4161 return 1; /* no need to also push a boolean if we have nil */
4162 }
4163
4164 /* new, fast and dumb ones: only signals that something needs to be processed */
4165
4166 /* #define do_has_glyph(h) do { \ */
4167 /* while (h != null) { \ */
4168 /* if (type(h) == glyph_node) { \ */
4169 /* return h; \ */
4170 /* } else { \ */
4171 /* h = vlink(h); \ */
4172 /* } \ */
4173 /* } \ */
4174 /* return null; \ */
4175 /* } while (0) */
4176
4177
4178
4179
4180 /* node.has_glyph */
4181
lua_nodelib_has_glyph(lua_State * L)4182 static int lua_nodelib_has_glyph(lua_State * L)
4183 {
4184 halfword *a;
4185 halfword h = (halfword) *(check_isnode(L,1)) ;
4186 while (h != null) {
4187 if ( (type(h) == glyph_node) || (type(h) == disc_node)) {
4188 fast_metatable(h);
4189 return 1;
4190 } else {
4191 h = vlink(h);
4192 }
4193 }
4194 lua_pushnil(L);
4195 return 1;
4196 }
4197
4198 /* node.direct.has_glyph */
4199
lua_nodelib_direct_has_glyph(lua_State * L)4200 static int lua_nodelib_direct_has_glyph(lua_State * L)
4201 {
4202 halfword h = (halfword) lua_tonumber(L,1) ;
4203 while (h != null) {
4204 if ((type(h) == glyph_node) || (type(h) == disc_node)) {
4205 nodelib_pushdirect(h);
4206 return 1;
4207 } else {
4208 h = vlink(h);
4209 }
4210 }
4211 lua_pushnil(L);
4212 return 1;
4213 }
4214
4215
4216 /* depricated */
4217
lua_nodelib_first_character(lua_State * L)4218 static int lua_nodelib_first_character(lua_State * L)
4219 {
4220 luatex_warn("node.first_character() is deprecated, please update to node.first_glyph()");
4221 return lua_nodelib_first_glyph(L);
4222 }
4223
4224 /* this is too simplistic, but it helps Hans to get going */
4225
do_ligature_n(halfword prev,halfword stop,halfword lig)4226 static halfword do_ligature_n(halfword prev, halfword stop, halfword lig)
4227 {
4228 vlink(lig) = vlink(stop);
4229 vlink(stop) = null;
4230 lig_ptr(lig) = vlink(prev);
4231 vlink(prev) = lig;
4232 return lig;
4233 }
4234
4235 /* node.do_ligature_n(node prev, node last, node lig) */
4236
lua_nodelib_do_ligature_n(lua_State * L)4237 static int lua_nodelib_do_ligature_n(lua_State * L)
4238 {
4239 halfword n, m, o, p, tmp_head;
4240 n = *(check_isnode(L, 1));
4241 m = *(check_isnode(L, 2));
4242 o = *(check_isnode(L, 3));
4243 if (alink(n) == null || vlink(alink(n)) != n) {
4244 tmp_head = new_node(temp_node, 0);
4245 couple_nodes(tmp_head, n);
4246 p = do_ligature_n(tmp_head, m, o);
4247 flush_node(tmp_head);
4248 } else {
4249 p = do_ligature_n(alink(n), m, o);
4250 }
4251 lua_pushnumber(L, p);
4252 lua_nodelib_push(L);
4253 return 1;
4254 }
4255
4256 /* node.direct.do_ligature_n(node prev, node last, node lig) */
4257
lua_nodelib_direct_do_ligature_n(lua_State * L)4258 static int lua_nodelib_direct_do_ligature_n(lua_State * L)
4259 {
4260 halfword n, m, o, p, tmp_head;
4261 n = (halfword) lua_tonumber(L, 1);
4262 m = (halfword) lua_tonumber(L, 2);
4263 o = (halfword) lua_tonumber(L, 3);
4264 if ((n == null) || (m == null) || (o == null)) {
4265 lua_pushnil(L);
4266 } else {
4267 if (alink(n) == null || vlink(alink(n)) != n) {
4268 tmp_head = new_node(temp_node, 0);
4269 couple_nodes(tmp_head, n);
4270 p = do_ligature_n(tmp_head, m, o);
4271 flush_node(tmp_head);
4272 } else {
4273 p = do_ligature_n(alink(n), m, o);
4274 }
4275 lua_pushnumber(L, p);
4276 }
4277 return 1;
4278 }
4279
4280 /* node.usedlist */
4281
lua_nodelib_usedlist(lua_State * L)4282 static int lua_nodelib_usedlist(lua_State * L)
4283 {
4284 lua_pushnumber(L, list_node_mem_usage());
4285 lua_nodelib_push(L);
4286 return 1;
4287 }
4288
4289 /* node.direct.usedlist */
4290
lua_nodelib_direct_usedlist(lua_State * L)4291 static int lua_nodelib_direct_usedlist(lua_State * L)
4292 {
4293 lua_pushnumber(L, list_node_mem_usage());
4294 return 1;
4295 }
4296
4297 /* node.protrusion_skipable(node m) */
4298
lua_nodelib_cp_skipable(lua_State * L)4299 static int lua_nodelib_cp_skipable(lua_State * L)
4300 {
4301 halfword n;
4302 n = *(check_isnode(L, 1));
4303 lua_pushboolean(L, cp_skipable(n));
4304 return 1;
4305 }
4306
4307 /* node.direct.protrusion_skipable(node m) */
4308
lua_nodelib_direct_cp_skipable(lua_State * L)4309 static int lua_nodelib_direct_cp_skipable(lua_State * L)
4310 {
4311 halfword n;
4312 n = (halfword) lua_tonumber(L, 1);
4313 if (n == null) {
4314 lua_pushnil(L);
4315 } else {
4316 lua_pushboolean(L, cp_skipable(n));
4317 }
4318 return 1;
4319 }
4320
4321
4322 /* node.currentattr(node m) */
4323
lua_nodelib_currentattr(lua_State * L)4324 static int lua_nodelib_currentattr(lua_State * L)
4325 {
4326 int u = lua_gettop(L);
4327 if (u == null) {
4328 /* query */
4329 halfword n ;
4330 /* current_attribute_list() return attr_list_cache */
4331 /* or null (attr_list_cache can also be null) */
4332 n = current_attribute_list();
4333 if (n) {
4334 lua_pushnumber(L, n);
4335 lua_nodelib_push(L);
4336 }
4337 else
4338 lua_pushnil(L);
4339 return 1;
4340 } else {
4341 /* assign */
4342 luatex_warn("Assignment via node.current_attr(<list>) is not supported (yet)");
4343 return 0;
4344 }
4345 }
4346
4347
4348 /* node.direct.currentattr(node m) */
4349
lua_nodelib_direct_currentattr(lua_State * L)4350 static int lua_nodelib_direct_currentattr(lua_State * L)
4351 {
4352 halfword n ;
4353 /* current_attribute_list() return attr_list_cache */
4354 /* or null (attr_list_cache can also be null) */
4355 n = current_attribute_list();
4356 if (n)
4357 lua_pushnumber(L, n);
4358 else
4359 lua_pushnil(L);
4360 return 1;
4361 }
4362
4363
4364 /* node.direct.todirect */
4365
lua_nodelib_direct_todirect(lua_State * L)4366 static int lua_nodelib_direct_todirect(lua_State * L)
4367 {
4368 if (lua_type(L,1) != LUA_TNUMBER) {
4369 /* assume node, no further testing, used in known situations */
4370 void *n ;
4371 n = lua_touserdata(L, 1);
4372 if (n == null) {
4373 lua_pushnil(L);
4374 } else {
4375 lua_pushnumber(L, *((halfword *)n) );
4376 }
4377 } /* else assume direct and returns argument */
4378 return 1;
4379 }
4380
4381
4382 /* node.direct.tonode */
4383
lua_nodelib_direct_tonode(lua_State * L)4384 static int lua_nodelib_direct_tonode(lua_State * L)
4385 {
4386 halfword *a;
4387 halfword n;
4388 n = (halfword) lua_tonumber(L, 1);
4389 if (n != null) {
4390 a = (halfword *) lua_newuserdata(L, sizeof(halfword));
4391 *a=n;
4392 lua_push_node_metatablelua;
4393 lua_setmetatable(L,-2);
4394 } /* else assume node and return argument */
4395 return 1;
4396 }
4397
4398 /* node.setfield */
4399
4400 /* ls-hh: normally a value will not be reassigned */
4401
4402 #define cleanup_late_lua(n) do { \
4403 if (late_lua_data(n) != 0) { \
4404 if (late_lua_type(n) == normal) { \
4405 delete_token_ref(late_lua_data(n)); \
4406 } else if (late_lua_type(n) == lua_refid_literal) { \
4407 luaL_unref(L, LUA_REGISTRYINDEX,late_lua_data(n)); \
4408 } \
4409 } \
4410 } while (0)
4411
4412 #define cleanup_late_lua_name(n) do { \
4413 if (late_lua_name(n) != 0) { \
4414 delete_token_ref(late_lua_name(n)); \
4415 } \
4416 } while (0)
4417
lua_nodelib_setfield_whatsit(lua_State * L,int n,const char * s)4418 static int lua_nodelib_setfield_whatsit(lua_State * L, int n, const char *s)
4419 {
4420 int t ;
4421 t = subtype(n);
4422
4423 if (t == dir_node) {
4424 if (lua_key_eq(s, dir)) {
4425 dir_dir(n) = nodelib_getdir(L, 3, 0);
4426 } else if (lua_key_eq(s, level)) {
4427 dir_level(n) = (halfword) lua_tointeger(L, 3);
4428 } else if (lua_key_eq(s, dvi_ptr)) {
4429 dir_dvi_ptr(n) = (halfword) lua_tointeger(L, 3);
4430 } else if (lua_key_eq(s, dir_h)) {
4431 dir_dvi_h(n) = (halfword) lua_tointeger(L, 3);
4432 } else {
4433 return nodelib_cantset(L, n, s);
4434 }
4435 } else if (t == pdf_literal_node) {
4436 if (lua_key_eq(s, mode)) {
4437 pdf_literal_mode(n) = (quarterword) lua_tointeger(L, 3);
4438 } else if (lua_key_eq(s, data)) {
4439 if (ini_version) {
4440 pdf_literal_data(n) = nodelib_gettoks(L, 3);
4441 } else {
4442 lua_pushvalue(L, 3);
4443 pdf_literal_data(n) = luaL_ref(L, LUA_REGISTRYINDEX);
4444 pdf_literal_type(n) = lua_refid_literal;
4445 }
4446 } else {
4447 return nodelib_cantset(L, n, s);
4448 }
4449 } else if (t == late_lua_node) {
4450 if (lua_key_eq(s, string)) {
4451 cleanup_late_lua(n) ; /* ls-hh */
4452 if (ini_version) {
4453 late_lua_data(n) = nodelib_gettoks(L, 3);
4454 late_lua_type(n) = normal;
4455 } else {
4456 lua_pushvalue(L, 3);
4457 late_lua_data(n) = luaL_ref(L, LUA_REGISTRYINDEX);
4458 late_lua_type(n) = lua_refid_literal;
4459 }
4460 } else if (lua_key_eq(s, data)) {
4461 cleanup_late_lua(n) ; /* ls-hh */
4462 late_lua_data(n) = nodelib_gettoks(L, 3);
4463 late_lua_type(n) = normal;
4464 } else if (lua_key_eq(s, name)) {
4465 cleanup_late_lua_name(n) ; /* ls-hh */
4466 late_lua_name(n) = nodelib_gettoks(L, 3);
4467 } else {
4468 return nodelib_cantset(L, n, s);
4469 }
4470 /* done */
4471 } else if (t == user_defined_node) {
4472 if (lua_key_eq(s, user_id)) {
4473 user_node_id(n) = (halfword) lua_tointeger(L, 3);
4474 } else if (lua_key_eq(s, type)) {
4475 user_node_type(n) = (halfword) lua_tointeger(L, 3);
4476 } else if (lua_key_eq(s, value)) {
4477 switch (user_node_type(n)) {
4478 case 'a':
4479 user_node_value(n) = nodelib_getlist(L, 3);
4480 break;
4481 case 'd':
4482 user_node_value(n) = (halfword) lua_tointeger(L, 3);
4483 break;
4484 case 'l':
4485 lua_pushvalue(L, 3);
4486 if (user_node_value(n) != 0) {
4487 luaL_unref(L, LUA_REGISTRYINDEX,user_node_value(n));
4488 }
4489 user_node_value(n) = luaL_ref(L, LUA_REGISTRYINDEX);
4490 break;
4491 case 'n':
4492 user_node_value(n) = nodelib_getlist(L, 3);
4493 break;
4494 case 's':
4495 user_node_value(n) = nodelib_getstring(L, 3);
4496 break;
4497 case 't':
4498 user_node_value(n) = nodelib_gettoks(L, 3);
4499 break;
4500 default:
4501 user_node_value(n) = (halfword) lua_tointeger(L, 3);
4502 break;
4503 }
4504 } else {
4505 return nodelib_cantset(L, n, s);
4506 }
4507 } else if (t == pdf_annot_node) {
4508 if (lua_key_eq(s, width)) {
4509 width(n) = (halfword) lua_tointeger(L, 3);
4510 } else if (lua_key_eq(s, depth)) {
4511 depth(n) = (halfword) lua_tointeger(L, 3);
4512 } else if (lua_key_eq(s, height)) {
4513 height(n) = (halfword) lua_tointeger(L, 3);
4514 } else if (lua_key_eq(s, objnum)) {
4515 pdf_annot_objnum(n) = (halfword) lua_tointeger(L, 3);
4516 } else if (lua_key_eq(s, data)) {
4517 pdf_annot_data(n) = nodelib_gettoks(L, 3);
4518 } else {
4519 return nodelib_cantset(L, n, s);
4520 }
4521 } else if (t == pdf_dest_node) {
4522 if (lua_key_eq(s, width)) {
4523 width(n) = (halfword) lua_tointeger(L, 3);
4524 } else if (lua_key_eq(s, depth)) {
4525 depth(n) = (halfword) lua_tointeger(L, 3);
4526 } else if (lua_key_eq(s, height)) {
4527 height(n) = (halfword) lua_tointeger(L, 3);
4528 } else if (lua_key_eq(s, named_id)) {
4529 pdf_dest_named_id(n) = (quarterword) lua_tointeger(L, 3);
4530 } else if (lua_key_eq(s, dest_id)) {
4531 if (pdf_dest_named_id(n) == 1) {
4532 pdf_dest_id(n) = nodelib_gettoks(L, 3);
4533 } else {
4534 pdf_dest_id(n) = (halfword) lua_tointeger(L, 3);
4535 }
4536 } else if (lua_key_eq(s, dest_type)) {
4537 pdf_dest_type(n) = (quarterword) lua_tointeger(L, 3);
4538 } else if (lua_key_eq(s, xyz_zoom)) {
4539 pdf_dest_xyz_zoom(n) = (halfword) lua_tointeger(L, 3);
4540 } else if (lua_key_eq(s, objnum)) {
4541 pdf_dest_objnum(n) = (halfword) lua_tointeger(L, 3);
4542 } else {
4543 return nodelib_cantset(L, n, s);
4544 }
4545 } else if (t == pdf_setmatrix_node) {
4546 if (lua_key_eq(s, data)) {
4547 pdf_setmatrix_data(n) = nodelib_gettoks(L, 3);
4548 } else {
4549 return nodelib_cantset(L, n, s);
4550 }
4551 } else if (t == pdf_refobj_node) {
4552 if (lua_key_eq(s, objnum)) {
4553 pdf_obj_objnum(n) = (halfword) lua_tointeger(L, 3);
4554 } else {
4555 return nodelib_cantset(L, n, s);
4556 }
4557 } else if (t == pdf_refxform_node) {
4558 if (lua_key_eq(s, width)) {
4559 width(n) = (halfword) lua_tointeger(L, 3);
4560 } else if (lua_key_eq(s, depth)) {
4561 depth(n) = (halfword) lua_tointeger(L, 3);
4562 } else if (lua_key_eq(s, height)) {
4563 height(n) = (halfword) lua_tointeger(L, 3);
4564 } else if (lua_key_eq(s, objnum)) {
4565 pdf_xform_objnum(n) = (halfword) lua_tointeger(L, 3);
4566 } else {
4567 return nodelib_cantset(L, n, s);
4568 }
4569 } else if (t == pdf_refximage_node) {
4570 if (lua_key_eq(s, width)) {
4571 width(n) = (halfword) lua_tointeger(L, 3);
4572 } else if (lua_key_eq(s, depth)) {
4573 depth(n) = (halfword) lua_tointeger(L, 3);
4574 } else if (lua_key_eq(s, height)) {
4575 height(n) = (halfword) lua_tointeger(L, 3);
4576 } else if (lua_key_eq(s, transform)) {
4577 pdf_ximage_transform(n) = (halfword) lua_tointeger(L, 3);
4578 } else if (lua_key_eq(s, index)) {
4579 pdf_ximage_index(n) = (halfword) lua_tointeger(L, 3);
4580 } else {
4581 return nodelib_cantset(L, n, s);
4582 }
4583 } else if (t == local_par_node) {
4584 if (lua_key_eq(s, pen_inter)) {
4585 local_pen_inter(n) = (halfword) lua_tointeger(L, 3);
4586 } else if (lua_key_eq(s, pen_broken)) {
4587 local_pen_broken(n) = (halfword) lua_tointeger(L, 3);
4588 } else if (lua_key_eq(s, dir)) {
4589 local_par_dir(n) = nodelib_getdir(L, 3, 1);
4590 } else if (lua_key_eq(s, box_left)) {
4591 local_box_left(n) = nodelib_getlist(L, 3);
4592 } else if (lua_key_eq(s, box_left_width)) {
4593 local_box_left_width(n) = (halfword) lua_tointeger(L, 3);
4594 } else if (lua_key_eq(s, box_right)) {
4595 local_box_right(n) = nodelib_getlist(L, 3);
4596 } else if (lua_key_eq(s, box_right_width)) {
4597 local_box_right_width(n) = (halfword) lua_tointeger(L, 3);
4598 } else {
4599 return nodelib_cantset(L, n, s);
4600 }
4601 } else if (t == pdf_start_link_node) {
4602 if (lua_key_eq(s, width)) {
4603 width(n) = (halfword) lua_tointeger(L, 3);
4604 } else if (lua_key_eq(s, depth)) {
4605 depth(n) = (halfword) lua_tointeger(L, 3);
4606 } else if (lua_key_eq(s, height)) {
4607 height(n) = (halfword) lua_tointeger(L, 3);
4608 } else if (lua_key_eq(s, objnum)) {
4609 pdf_link_objnum(n) = (halfword) lua_tointeger(L, 3);
4610 } else if (lua_key_eq(s, link_attr)) {
4611 pdf_link_attr(n) = nodelib_gettoks(L, 3);
4612 } else if (lua_key_eq(s, action)) {
4613 pdf_link_action(n) = nodelib_getaction(L, 3);
4614 } else {
4615 return nodelib_cantset(L, n, s);
4616 }
4617 } else if (t == write_node) {
4618 if (lua_key_eq(s, stream)) {
4619 write_stream(n) = (halfword) lua_tointeger(L, 3);
4620 } else if (lua_key_eq(s, data)) {
4621 write_tokens(n) = nodelib_gettoks(L, 3);
4622 } else {
4623 return nodelib_cantset(L, n, s);
4624 }
4625 } else if (t == pdf_colorstack_node) {
4626 if (lua_key_eq(s, stack)) {
4627 pdf_colorstack_stack(n) = (halfword) lua_tointeger(L, 3);
4628 } else if (lua_key_eq(s, command)) {
4629 pdf_colorstack_cmd(n) = (halfword) lua_tointeger(L, 3);
4630 } else if (lua_key_eq(s, data)) {
4631 pdf_colorstack_data(n) = nodelib_gettoks(L, 3);
4632 } else {
4633 return nodelib_cantset(L, n, s);
4634 }
4635 } else if ((t == pdf_thread_node) || (t == pdf_start_thread_node)) {
4636 if (lua_key_eq(s, width)) {
4637 width(n) = (halfword) lua_tointeger(L, 3);
4638 } else if (lua_key_eq(s, depth)) {
4639 depth(n) = (halfword) lua_tointeger(L, 3);
4640 } else if (lua_key_eq(s, height)) {
4641 height(n) = (halfword) lua_tointeger(L, 3);
4642 } else if (lua_key_eq(s, named_id)) {
4643 pdf_thread_named_id(n) = (quarterword) lua_tointeger(L, 3);
4644 } else if (lua_key_eq(s, thread_id)) {
4645 if (pdf_thread_named_id(n) == 1) {
4646 pdf_thread_id(n) = nodelib_gettoks(L, 3);
4647 } else {
4648 pdf_thread_id(n) = (halfword) lua_tointeger(L, 3);
4649 }
4650 } else if (lua_key_eq(s, thread_attr)) {
4651 pdf_thread_attr(n) = nodelib_gettoks(L, 3);
4652 } else {
4653 return nodelib_cantset(L, n, s);
4654 }
4655 } else if (t == special_node) {
4656 if (lua_key_eq(s, data)) {
4657 write_tokens(n) = nodelib_gettoks(L, 3);
4658 } else {
4659 return nodelib_cantset(L, n, s);
4660 }
4661 } else if (t == open_node) {
4662 if (lua_key_eq(s, stream)) {
4663 write_stream(n) = (halfword) lua_tointeger(L, 3);
4664 } else if (lua_key_eq(s, name)) {
4665 open_name(n) = nodelib_getstring(L, 3);
4666 } else if (lua_key_eq(s, area)) {
4667 open_area(n) = nodelib_getstring(L, 3);
4668 } else if (lua_key_eq(s, ext)) {
4669 open_ext(n) = nodelib_getstring(L, 3);
4670 } else {
4671 return nodelib_cantset(L, n, s);
4672 }
4673 } else if (t == close_node) {
4674 if (lua_key_eq(s, stream)) {
4675 write_stream(n) = (halfword) lua_tointeger(L, 3);
4676 } else {
4677 return nodelib_cantset(L, n, s);
4678 }
4679 } else if ((t == pdf_end_link_node) || (t == pdf_end_thread_node) || (t == pdf_save_pos_node) ||
4680 (t == pdf_save_node) || (t == pdf_restore_node) || (t == cancel_boundary_node)) {
4681 return nodelib_cantset(L, n, s);
4682 } else {
4683 /* do nothing */
4684 }
4685 return 0;
4686 }
4687
lua_nodelib_fast_setfield(lua_State * L)4688 static int lua_nodelib_fast_setfield(lua_State * L)
4689 {
4690 halfword n;
4691 const char *s;
4692 int t ;
4693
4694 n = *((halfword *) lua_touserdata(L, 1));
4695 t = type(n);
4696
4697 if (lua_type(L, 2) == LUA_TNUMBER) {
4698
4699 int i, val;
4700
4701 if (lua_gettop(L) == 3) {
4702 i = (int) lua_tointeger(L, 2);
4703 val = (int) lua_tointeger(L, 3);
4704 if (val == UNUSED_ATTRIBUTE) {
4705 (void) unset_attribute(n, i, val);
4706 } else {
4707 set_attribute(n, i, val);
4708 }
4709 } else {
4710 luaL_error(L, "incorrect number of arguments");
4711 }
4712 return 0;
4713 }
4714
4715 s = lua_tostring(L, 2);
4716
4717 /*if (lua_key_eq(s, id)) {
4718 type(n) = (quarteword) lua_tointeger(L, 3);
4719 }* else */
4720 if (lua_key_eq(s, next)) {
4721 halfword x = nodelib_getlist(L, 3);
4722 if (x>0 && type(x) == glue_spec_node) {
4723 return luaL_error(L, "You can't assign a %s node to a next field\n", node_data[type(x)].name);
4724 }
4725 vlink(n) = x;
4726 } else if (lua_key_eq(s, prev)) {
4727 halfword x = nodelib_getlist(L, 3);
4728 if (x>0 && type(x) == glue_spec_node) {
4729 return luaL_error(L, "You can't assign a %s node to a prev field\n", node_data[type(x)].name);
4730 }
4731 alink(n) = x;
4732 } else if (lua_key_eq(s, attr)) {
4733 if (nodetype_has_attributes(type(n))) {
4734 nodelib_setattr(L, 3, n);
4735 }
4736 } else if (t == glyph_node) {
4737 if (lua_key_eq(s, subtype)) {
4738 subtype(n) = (quarterword) lua_tointeger(L, 3);
4739 } else if (lua_key_eq(s, font)) {
4740 font(n) = (halfword) lua_tointeger(L, 3);
4741 } else if (lua_key_eq(s, char)) {
4742 character(n) = (halfword) lua_tointeger(L, 3);
4743 } else if (lua_key_eq(s, xoffset)) {
4744 x_displace(n) = (halfword) lua_tointeger(L, 3);
4745 } else if (lua_key_eq(s, yoffset)) {
4746 y_displace(n) = (halfword) lua_tointeger(L, 3);
4747 } else if (lua_key_eq(s, width)) {
4748 /* not yet */
4749 } else if (lua_key_eq(s, height)) {
4750 /* not yet */
4751 } else if (lua_key_eq(s, depth)) {
4752 /* not yet */
4753 } else if (lua_key_eq(s, expansion_factor)) {
4754 ex_glyph(n) = (halfword) lua_tointeger(L, 3);
4755 } else if (lua_key_eq(s, components)) {
4756 lig_ptr(n) = nodelib_getlist(L, 3);
4757 } else if (lua_key_eq(s, lang)) {
4758 set_char_lang(n, (halfword) lua_tointeger(L, 3));
4759 } else if (lua_key_eq(s, left)) {
4760 set_char_lhmin(n, (halfword) lua_tointeger(L, 3));
4761 } else if (lua_key_eq(s, right)) {
4762 set_char_rhmin(n, (halfword) lua_tointeger(L, 3));
4763 } else if (lua_key_eq(s, uchyph)) {
4764 set_char_uchyph(n, (halfword) lua_tointeger(L, 3));
4765 } else {
4766 return nodelib_cantset(L, n, s);
4767 }
4768 } else if ((t == hlist_node) || (t == vlist_node)) {
4769 if (lua_key_eq(s, subtype)) {
4770 subtype(n) = (quarterword) lua_tointeger(L, 3);
4771 } else if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
4772 list_ptr(n) = nodelib_getlist(L, 3);
4773 } else if (lua_key_eq(s, width)) {
4774 width(n) = (halfword) lua_tointeger(L, 3);
4775 } else if (lua_key_eq(s, height)) {
4776 height(n) = (halfword) lua_tointeger(L, 3);
4777 } else if (lua_key_eq(s, depth)) {
4778 depth(n) = (halfword) lua_tointeger(L, 3);
4779 } else if (lua_key_eq(s, dir)) {
4780 box_dir(n) = nodelib_getdir(L, 3, 1);
4781 } else if (lua_key_eq(s, shift)) {
4782 shift_amount(n) = (halfword) lua_tointeger(L, 3);
4783 } else if (lua_key_eq(s, glue_order)) {
4784 glue_order(n) = (quarterword) lua_tointeger(L, 3);
4785 } else if (lua_key_eq(s, glue_sign)) {
4786 glue_sign(n) = (quarterword) lua_tointeger(L, 3);
4787 } else if (lua_key_eq(s, glue_set)) {
4788 glue_set(n) = (glue_ratio) lua_tonumber(L, 3);
4789 } else {
4790 return nodelib_cantset(L, n, s);
4791 }
4792 } else if (t == disc_node) {
4793 if (lua_key_eq(s, subtype)) {
4794 subtype(n) = (quarterword) lua_tointeger(L, 3);
4795 } else if (lua_key_eq(s, pre)) {
4796 set_disc_field(pre_break(n), nodelib_getlist(L, 3));
4797 } else if (lua_key_eq(s, post)) {
4798 set_disc_field(post_break(n), nodelib_getlist(L, 3));
4799 } else if (lua_key_eq(s, replace)) {
4800 set_disc_field(no_break(n), nodelib_getlist(L, 3));
4801 } else {
4802 return nodelib_cantset(L, n, s);
4803 }
4804 } else if (t == glue_node) {
4805 if (lua_key_eq(s, subtype)) {
4806 subtype(n) = (quarterword) lua_tointeger(L, 3);
4807 } else if (lua_key_eq(s, spec)) {
4808 glue_ptr(n) = nodelib_getspec(L, 3);
4809 } else if (lua_key_eq(s, leader)) {
4810 leader_ptr(n) = nodelib_getlist(L, 3);
4811 } else {
4812 return nodelib_cantset(L, n, s);
4813 }
4814 } else if (t == glue_spec_node) {
4815 if (lua_key_eq(s, subtype)) {
4816 subtype(n) = (quarterword) lua_tointeger(L, 3); /* dummy, the only one that prevents move up */
4817 } else if (lua_key_eq(s, width)) {
4818 width(n) = (halfword) lua_tointeger(L, 3);
4819 } else if (lua_key_eq(s, stretch)) {
4820 stretch(n) = (halfword) lua_tointeger(L, 3);
4821 } else if (lua_key_eq(s, shrink)) {
4822 shrink(n) = (halfword) lua_tointeger(L, 3);
4823 } else if (lua_key_eq(s, stretch_order)) {
4824 stretch_order(n) = (quarterword) lua_tointeger(L, 3);
4825 } else if (lua_key_eq(s, shrink_order)) {
4826 shrink_order(n) = (quarterword) lua_tointeger(L, 3);
4827 /* } else if (lua_key_eq(s, ref_count)) {
4828 glue_ref_count(n) = (halfword) lua_tointeger(L, 3);
4829 } else if (lua_key_eq(s, writable)) {
4830 */
4831 /* can't be set */
4832 } else {
4833 return nodelib_cantset(L, n, s);
4834 }
4835 } else if (t == kern_node) {
4836 if (lua_key_eq(s, subtype)) {
4837 subtype(n) = (quarterword) lua_tointeger(L, 3);
4838 } else if (lua_key_eq(s, kern)) {
4839 width(n) = (halfword) lua_tointeger(L, 3);
4840 } else if (lua_key_eq(s, expansion_factor)) {
4841 ex_kern(n) = (halfword) lua_tointeger(L, 3);
4842 } else {
4843 return nodelib_cantset(L, n, s);
4844 }
4845 } else if (t == penalty_node) {
4846 if (lua_key_eq(s, subtype)) {
4847 /* dummy subtype */
4848 } else if (lua_key_eq(s, penalty)) {
4849 penalty(n) = (halfword) lua_tointeger(L, 3);
4850 } else {
4851 return nodelib_cantset(L, n, s);
4852 }
4853 } else if (t == rule_node) {
4854 if (lua_key_eq(s, subtype)) {
4855 subtype(n) = (quarterword) lua_tointeger(L, 3);
4856 } else if (lua_key_eq(s, width)) {
4857 width(n) = (halfword) lua_tointeger(L, 3);
4858 } else if (lua_key_eq(s, height)) {
4859 height(n) = (halfword) lua_tointeger(L, 3);
4860 } else if (lua_key_eq(s, depth)) {
4861 depth(n) = (halfword) lua_tointeger(L, 3);
4862 } else if (lua_key_eq(s, dir)) {
4863 rule_dir(n) = nodelib_getdir(L, 3, 1);
4864 } else {
4865 return nodelib_cantset(L, n, s);
4866 }
4867 } else if (t == whatsit_node) {
4868 if (lua_key_eq(s, subtype)) {
4869 subtype(n) = (quarterword) lua_tointeger(L, 3);
4870 } else {
4871 lua_nodelib_setfield_whatsit(L, n, s);
4872 }
4873 } else if (t == simple_noad) {
4874 if (lua_key_eq(s, subtype)) {
4875 subtype(n) = (quarterword) lua_tointeger(L, 3);
4876 } else if (lua_key_eq(s, nucleus)) {
4877 nucleus(n) = nodelib_getlist(L, 3);
4878 } else if (lua_key_eq(s, sub)) {
4879 subscr(n) = nodelib_getlist(L, 3);
4880 } else if (lua_key_eq(s, sup)) {
4881 supscr(n) = nodelib_getlist(L, 3);
4882 } else {
4883 return nodelib_cantset(L, n, s);
4884 }
4885 } else if ((t == math_char_node) || (t == math_text_char_node)) {
4886 if (lua_key_eq(s, subtype)) {
4887 subtype(n) = (quarterword) lua_tointeger(L, 3);
4888 } else if (lua_key_eq(s, fam)) {
4889 math_fam(n) = (halfword) lua_tointeger(L, 3);
4890 } else if (lua_key_eq(s, char)) {
4891 math_character(n) = (halfword) lua_tointeger(L, 3);
4892 } else {
4893 return nodelib_cantset(L, n, s);
4894 }
4895 } else if (t == mark_node) {
4896 if (lua_key_eq(s, subtype)) {
4897 subtype(n) = (quarterword) lua_tointeger(L, 3);
4898 } else if (lua_key_eq(s, class)) {
4899 mark_class(n) = (halfword) lua_tointeger(L, 3);
4900 } else if (lua_key_eq(s, mark)) {
4901 mark_ptr(n) = nodelib_gettoks(L, 3);
4902 } else {
4903 return nodelib_cantset(L, n, s);
4904 }
4905 } else if (t == ins_node) {
4906 if (lua_key_eq(s, subtype)) {
4907 subtype(n) = (quarterword) lua_tointeger(L, 3);
4908 } else if (lua_key_eq(s, cost)) {
4909 float_cost(n) = (halfword) lua_tointeger(L, 3);
4910 } else if (lua_key_eq(s, depth)) {
4911 depth(n) = (halfword) lua_tointeger(L, 3);
4912 } else if (lua_key_eq(s, height)) {
4913 height(n) = (halfword) lua_tointeger(L, 3);
4914 } else if (lua_key_eq(s, spec)) {
4915 split_top_ptr(n) = nodelib_getspec(L, 3);
4916 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))) {
4917 ins_ptr(n) = nodelib_getlist(L, 3);
4918 } else {
4919 return nodelib_cantset(L, n, s);
4920 }
4921 } else if (t == math_node) {
4922 if (lua_key_eq(s, subtype)) {
4923 subtype(n) = (quarterword) lua_tointeger(L, 3);
4924 } else if (lua_key_eq(s, surround)) {
4925 surround(n) = (halfword) lua_tointeger(L, 3);
4926 } else {
4927 return nodelib_cantset(L, n, s);
4928 }
4929 } else if (t == fraction_noad) {
4930 if (lua_key_eq(s, subtype)) {
4931 subtype(n) = (quarterword) lua_tointeger(L, 3);
4932 } else if (lua_key_eq(s, width)) {
4933 thickness(n) = (halfword) lua_tointeger(L, 3);
4934 } else if (lua_key_eq(s, num)) {
4935 numerator(n) = nodelib_getlist(L, 3);
4936 } else if (lua_key_eq(s, denom)) {
4937 denominator(n) = nodelib_getlist(L, 3);
4938 } else if (lua_key_eq(s, left)) {
4939 left_delimiter(n) = nodelib_getlist(L, 3);
4940 } else if (lua_key_eq(s, right)) {
4941 right_delimiter(n) = nodelib_getlist(L, 3);
4942 } else {
4943 return nodelib_cantset(L, n, s);
4944 }
4945 } else if (t == style_node) {
4946 if (lua_key_eq(s, subtype)) {
4947 /* dummy subtype */
4948 } else if (lua_key_eq(s, style)) {
4949 assign_math_style(L,3,subtype(n));
4950 //subtype(n) = (quarterword) luaL_checkoption(L, 3, "text", math_style_names); /* not 2? */
4951 } else {
4952 /* return nodelib_cantset(L, n, s); */
4953 }
4954 } else if (t == accent_noad) {
4955 if (lua_key_eq(s, subtype)) {
4956 subtype(n) = (quarterword) lua_tointeger(L, 3);
4957 } else if (lua_key_eq(s, nucleus)) {
4958 nucleus(n) = nodelib_getlist(L, 3);
4959 } else if (lua_key_eq(s, sub)) {
4960 subscr(n) = nodelib_getlist(L, 3);
4961 } else if (lua_key_eq(s, sup)) {
4962 supscr(n) = nodelib_getlist(L, 3);
4963 } else if (lua_key_eq(s, accent)) {
4964 accent_chr(n) = nodelib_getlist(L, 3);
4965 } else if (lua_key_eq(s, bot_accent)) {
4966 bot_accent_chr(n) = nodelib_getlist(L, 3);
4967 } else {
4968 return nodelib_cantset(L, n, s);
4969 }
4970 } else if (t == fence_noad) {
4971 if (lua_key_eq(s, subtype)) {
4972 subtype(n) = (quarterword) lua_tointeger(L, 3);
4973 } else if (lua_key_eq(s, delim)) {
4974 delimiter(n) = nodelib_getlist(L, 3);
4975 } else {
4976 return nodelib_cantset(L, n, s);
4977 }
4978 } else if (t == delim_node) {
4979 if (lua_key_eq(s, subtype)) {
4980 subtype(n) = (quarterword) lua_tointeger(L, 3);
4981 } else if (lua_key_eq(s, small_fam)) {
4982 small_fam(n) = (halfword) lua_tointeger(L, 3);
4983 } else if (lua_key_eq(s, small_char)) {
4984 small_char(n) = (halfword) lua_tointeger(L, 3);
4985 } else if (lua_key_eq(s, large_fam)) {
4986 large_fam(n) = (halfword) lua_tointeger(L, 3);
4987 } else if (lua_key_eq(s, large_char)) {
4988 large_char(n) = (halfword) lua_tointeger(L, 3);
4989 } else {
4990 return nodelib_cantset(L, n, s);
4991 }
4992 } else if ((t == sub_box_node) || (t == sub_mlist_node)) {
4993 if (lua_key_eq(s, subtype)) {
4994 subtype(n) = (quarterword) lua_tointeger(L, 3);
4995 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))){
4996 math_list(n) = nodelib_getlist(L, 3);
4997 } else {
4998 return nodelib_cantset(L, n, s);
4999 }
5000 } else if (t == radical_noad) {
5001 if (lua_key_eq(s, subtype)) {
5002 subtype(n) = (quarterword) lua_tointeger(L, 3);
5003 } else if (lua_key_eq(s, nucleus)) {
5004 nucleus(n) = nodelib_getlist(L, 3);
5005 } else if (lua_key_eq(s, sub)) {
5006 subscr(n) = nodelib_getlist(L, 3);
5007 } else if (lua_key_eq(s, sup)) {
5008 supscr(n) = nodelib_getlist(L, 3);
5009 } else if (lua_key_eq(s, left)) {
5010 left_delimiter(n) = nodelib_getlist(L, 3);
5011 } else if (lua_key_eq(s, degree)) {
5012 degree(n) = nodelib_getlist(L, 3);
5013 } else {
5014 return nodelib_cantset(L, n, s);
5015 }
5016 } else if (t == margin_kern_node) {
5017 if (lua_key_eq(s, subtype)) {
5018 subtype(n) = (quarterword) lua_tointeger(L, 3);
5019 } else if (lua_key_eq(s, width)) {
5020 width(n) = (halfword) lua_tointeger(L, 3);
5021 } else if (lua_key_eq(s, glyph)) {
5022 margin_char(n) = nodelib_getlist(L, 3);
5023 } else {
5024 return nodelib_cantset(L, n, s);
5025 }
5026 } else if (t == split_up_node) {
5027 if (lua_key_eq(s, subtype)) {
5028 subtype(n) = (quarterword) lua_tointeger(L, 3);
5029 } else if (lua_key_eq(s, last_ins_ptr)) {
5030 last_ins_ptr(n) = nodelib_getlist(L, 3);
5031 } else if (lua_key_eq(s, best_ins_ptr)) {
5032 best_ins_ptr(n) = nodelib_getlist(L, 3);
5033 } else if (lua_key_eq(s, broken_ptr)) {
5034 broken_ptr(n) = nodelib_getlist(L, 3);
5035 } else if (lua_key_eq(s, broken_ins)) {
5036 broken_ins(n) = nodelib_getlist(L, 3);
5037 } else {
5038 return nodelib_cantset(L, n, s);
5039 }
5040 } else if (t == choice_node) {
5041 if (lua_key_eq(s, subtype)) {
5042 subtype(n) = (quarterword) lua_tointeger(L, 3);
5043 } else if (lua_key_eq(s, display)) {
5044 display_mlist(n) = nodelib_getlist(L, 3);
5045 } else if (lua_key_eq(s, text)) {
5046 text_mlist(n) = nodelib_getlist(L, 3);
5047 } else if (lua_key_eq(s, script)) {
5048 script_mlist(n) = nodelib_getlist(L, 3);
5049 } else if (lua_key_eq(s, scriptscript)) {
5050 script_script_mlist(n) = nodelib_getlist(L, 3);
5051 } else {
5052 return nodelib_cantset(L, n, s);
5053 }
5054 } else if (t == inserting_node) {
5055 if (lua_key_eq(s, subtype)) {
5056 subtype(n) = (quarterword) lua_tointeger(L, 3);
5057 } else if (lua_key_eq(s, last_ins_ptr)) {
5058 last_ins_ptr(n) = nodelib_getlist(L, 3);
5059 } else if (lua_key_eq(s, best_ins_ptr)) {
5060 best_ins_ptr(n) = nodelib_getlist(L, 3);
5061 } else {
5062 return nodelib_cantset(L, n, s);
5063 }
5064 } else if (t == attribute_node) {
5065 if (lua_key_eq(s, subtype)) {
5066 /* dummy subtype */
5067 } else if (lua_key_eq(s, number)) {
5068 attribute_id(n) = (halfword) lua_tointeger(L, 3);
5069 } else if (lua_key_eq(s, value)) {
5070 attribute_value(n) = (halfword) lua_tointeger(L, 3);
5071 } else {
5072 return nodelib_cantset(L, n, s);
5073 }
5074 } else if (t == adjust_node) {
5075 if (lua_key_eq(s, subtype)) {
5076 subtype(n) = (quarterword) lua_tointeger(L, 3);
5077 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))) {
5078 adjust_ptr(n) = nodelib_getlist(L, 3);
5079 } else {
5080 return nodelib_cantset(L, n, s);
5081 }
5082 } else if (t == action_node) {
5083 if (lua_key_eq(s, subtype)) {
5084 /* dummy subtype */
5085 } else if (lua_key_eq(s, action_type)) {
5086 pdf_action_type(n) = (quarterword) lua_tointeger(L, 3);
5087 } else if (lua_key_eq(s, named_id)) {
5088 pdf_action_named_id(n) = (quarterword) lua_tointeger(L, 3);
5089 } else if (lua_key_eq(s, action_id)) {
5090 if (pdf_action_named_id(n) == 1) {
5091 pdf_action_id(n) = nodelib_gettoks(L, 3);
5092 } else {
5093 pdf_action_id(n) = (halfword) lua_tointeger(L, 3);
5094 }
5095 } else if (lua_key_eq(s, file)) {
5096 pdf_action_file(n) = nodelib_gettoks(L, 3);
5097 } else if (lua_key_eq(s, new_window)) {
5098 pdf_action_new_window(n) = (halfword) lua_tointeger(L, 3);
5099 } else if (lua_key_eq(s, data)) {
5100 pdf_action_tokens(n) = nodelib_gettoks(L, 3);
5101 /* } else if (lua_key_eq(s, ref_count)) {
5102 pdf_action_refcount(n) = (halfword) lua_tointeger(L, 3); */
5103 } else {
5104 return nodelib_cantset(L, n, s);
5105 }
5106 } else if (t == unset_node) {
5107 if (lua_key_eq(s, subtype)) {
5108 /* dummy subtype */
5109 } else if (lua_key_eq(s, width)) {
5110 width(n) = (halfword) lua_tointeger(L, 3);
5111 } else if (lua_key_eq(s, height)) {
5112 height(n) = (halfword) lua_tointeger(L, 3);
5113 } else if (lua_key_eq(s, depth)) {
5114 depth(n) = (halfword) lua_tointeger(L, 3);
5115 } else if (lua_key_eq(s, dir)) {
5116 box_dir(n) = nodelib_getdir(L, 3, 1);
5117 } else if (lua_key_eq(s, shrink)) {
5118 glue_shrink(n) = (halfword) lua_tointeger(L, 3);
5119 } else if (lua_key_eq(s, glue_order)) {
5120 glue_order(n) = (quarterword) lua_tointeger(L, 3);
5121 } else if (lua_key_eq(s, glue_sign)) {
5122 glue_sign(n) = (quarterword) lua_tointeger(L, 3);
5123 } else if (lua_key_eq(s, stretch)) {
5124 glue_stretch(n) = (halfword) lua_tointeger(L, 3);
5125 } else if (lua_key_eq(s, count)) {
5126 span_count(n) = (quarterword) lua_tointeger(L, 3);
5127 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))){
5128 list_ptr(n) = nodelib_getlist(L, 3);
5129 } else {
5130 return nodelib_cantset(L, n, s);
5131 }
5132 } else if (t == attribute_list_node) {
5133 if (lua_key_eq(s, subtype)) {
5134 /* dummy subtype */
5135 } else {
5136 return nodelib_cantset(L, n, s);
5137 }
5138 } else {
5139 return luaL_error(L, "You can't assign to this %s node (%d)\n", node_data[t].name, n);
5140 }
5141 return 0;
5142 }
5143
lua_nodelib_setfield(lua_State * L)5144 static int lua_nodelib_setfield(lua_State * L)
5145 {
5146 /* [given-node] [...]*/
5147 halfword *p = lua_touserdata(L, 1);
5148 if ( (p == NULL) || (! lua_getmetatable(L,1)) ) {
5149 return 0;
5150 }
5151 /* [given-node] [mt-given-node]*/
5152 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(luatex_node));
5153 lua_gettable(L, LUA_REGISTRYINDEX);
5154 /* [given-node] [mt-given-node] [mt-node]*/
5155 if ( (!lua_rawequal(L, -1, -2)) ) {
5156 return 0;
5157 }
5158 /* prune stack and call getfield */
5159 lua_settop(L,3);
5160 return lua_nodelib_fast_setfield(L);
5161 }
5162
5163 /* node.direct.setfield */
5164
lua_nodelib_direct_setfield_whatsit(lua_State * L,int n,const char * s)5165 static int lua_nodelib_direct_setfield_whatsit(lua_State * L, int n, const char *s)
5166 {
5167 int t ;
5168 t = subtype(n);
5169
5170 if (t == dir_node) {
5171 if (lua_key_eq(s, dir)) {
5172 dir_dir(n) = nodelib_getdir(L, 3, 0);
5173 } else if (lua_key_eq(s, level)) {
5174 dir_level(n) = (halfword) lua_tointeger(L, 3);
5175 } else if (lua_key_eq(s, dvi_ptr)) {
5176 dir_dvi_ptr(n) = (halfword) lua_tointeger(L, 3);
5177 } else if (lua_key_eq(s, dir_h)) {
5178 dir_dvi_h(n) = (halfword) lua_tointeger(L, 3);
5179 } else {
5180 return nodelib_cantset(L, n, s);
5181 }
5182 } else if (t == pdf_literal_node) {
5183 if (lua_key_eq(s, mode)) {
5184 pdf_literal_mode(n) = (quarterword) lua_tointeger(L, 3);
5185 } else if (lua_key_eq(s, data)) {
5186 if (ini_version) {
5187 pdf_literal_data(n) = nodelib_gettoks(L, 3);
5188 } else {
5189 lua_pushvalue(L, 3);
5190 pdf_literal_data(n) = luaL_ref(L, LUA_REGISTRYINDEX);
5191 pdf_literal_type(n) = lua_refid_literal;
5192 }
5193 } else {
5194 return nodelib_cantset(L, n, s);
5195 }
5196 } else if (t == late_lua_node) {
5197 if (lua_key_eq(s, string)) {
5198 cleanup_late_lua(n) ; /* ls-hh */
5199 if (ini_version) {
5200 late_lua_data(n) = nodelib_gettoks(L, 3);
5201 late_lua_type(n) = normal;
5202 } else {
5203 lua_pushvalue(L, 3);
5204 late_lua_data(n) = luaL_ref(L, LUA_REGISTRYINDEX);
5205 late_lua_type(n) = lua_refid_literal;
5206 }
5207 } else if (lua_key_eq(s, data)) {
5208 cleanup_late_lua(n) ; /* ls-hh */
5209 late_lua_data(n) = nodelib_gettoks(L, 3);
5210 late_lua_type(n) = normal;
5211 } else if (lua_key_eq(s, name)) {
5212 cleanup_late_lua_name(n) ; /* ls-hh */
5213 late_lua_name(n) = nodelib_gettoks(L, 3);
5214 } else {
5215 return nodelib_cantset(L, n, s);
5216 }
5217 } else if (t == user_defined_node) {
5218 if (lua_key_eq(s, user_id)) {
5219 user_node_id(n) = (halfword) lua_tointeger(L, 3);
5220 } else if (lua_key_eq(s, type)) {
5221 user_node_type(n) = (halfword) lua_tointeger(L, 3);
5222 } else if (lua_key_eq(s, value)) {
5223 switch (user_node_type(n)) {
5224 case 'a':
5225 user_node_value(n) = nodelib_getlist(L, 3);
5226 break;
5227 case 'd':
5228 user_node_value(n) = (halfword) lua_tointeger(L, 3);
5229 break;
5230 case 'l':
5231 lua_pushvalue(L, 3);
5232 if (user_node_value(n) != 0) {
5233 luaL_unref(L, LUA_REGISTRYINDEX,user_node_value(n));
5234 }
5235 user_node_value(n) = luaL_ref(L, LUA_REGISTRYINDEX);
5236 break;
5237 case 'n':
5238 user_node_value(n) = nodelib_getlist(L, 3);
5239 break;
5240 case 's':
5241 user_node_value(n) = nodelib_getstring(L, 3);
5242 break;
5243 case 't':
5244 user_node_value(n) = nodelib_gettoks(L, 3);
5245 break;
5246 default:
5247 user_node_value(n) = (halfword) lua_tointeger(L, 3);
5248 break;
5249 }
5250 } else {
5251 return nodelib_cantset(L, n, s);
5252 }
5253 } else if (t == pdf_annot_node) {
5254 if (lua_key_eq(s, width)) {
5255 width(n) = (halfword) lua_tointeger(L, 3);
5256 } else if (lua_key_eq(s, depth)) {
5257 depth(n) = (halfword) lua_tointeger(L, 3);
5258 } else if (lua_key_eq(s, height)) {
5259 height(n) = (halfword) lua_tointeger(L, 3);
5260 } else if (lua_key_eq(s, objnum)) {
5261 pdf_annot_objnum(n) = (halfword) lua_tointeger(L, 3);
5262 } else if (lua_key_eq(s, data)) {
5263 pdf_annot_data(n) = nodelib_gettoks(L, 3);
5264 } else {
5265 return nodelib_cantset(L, n, s);
5266 }
5267 } else if (t == pdf_dest_node) {
5268 if (lua_key_eq(s, width)) {
5269 width(n) = (halfword) lua_tointeger(L, 3);
5270 } else if (lua_key_eq(s, depth)) {
5271 depth(n) = (halfword) lua_tointeger(L, 3);
5272 } else if (lua_key_eq(s, height)) {
5273 height(n) = (halfword) lua_tointeger(L, 3);
5274 } else if (lua_key_eq(s, named_id)) {
5275 pdf_dest_named_id(n) = (quarterword) lua_tointeger(L, 3);
5276 } else if (lua_key_eq(s, dest_id)) {
5277 if (pdf_dest_named_id(n) == 1) {
5278 pdf_dest_id(n) = nodelib_gettoks(L, 3);
5279 } else {
5280 pdf_dest_id(n) = (halfword) lua_tointeger(L, 3);
5281 }
5282 } else if (lua_key_eq(s, dest_type)) {
5283 pdf_dest_type(n) = (quarterword) lua_tointeger(L, 3);
5284 } else if (lua_key_eq(s, xyz_zoom)) {
5285 pdf_dest_xyz_zoom(n) = (halfword) lua_tointeger(L, 3);
5286 } else if (lua_key_eq(s, objnum)) {
5287 pdf_dest_objnum(n) = (halfword) lua_tointeger(L, 3);
5288 } else {
5289 return nodelib_cantset(L, n, s);
5290 }
5291 } else if (t == pdf_setmatrix_node) {
5292 if (lua_key_eq(s, data)) {
5293 pdf_setmatrix_data(n) = nodelib_gettoks(L, 3);
5294 } else {
5295 return nodelib_cantset(L, n, s);
5296 }
5297 } else if (t == pdf_refobj_node) {
5298 if (lua_key_eq(s, objnum)) {
5299 pdf_obj_objnum(n) = (halfword) lua_tointeger(L, 3);
5300 } else {
5301 return nodelib_cantset(L, n, s);
5302 }
5303 } else if (t == pdf_refxform_node) {
5304 if (lua_key_eq(s, width)) {
5305 width(n) = (halfword) lua_tointeger(L, 3);
5306 } else if (lua_key_eq(s, depth)) {
5307 depth(n) = (halfword) lua_tointeger(L, 3);
5308 } else if (lua_key_eq(s, height)) {
5309 height(n) = (halfword) lua_tointeger(L, 3);
5310 } else if (lua_key_eq(s, objnum)) {
5311 pdf_xform_objnum(n) = (halfword) lua_tointeger(L, 3);
5312 } else {
5313 return nodelib_cantset(L, n, s);
5314 }
5315 } else if (t == pdf_refximage_node) {
5316 if (lua_key_eq(s, width)) {
5317 width(n) = (halfword) lua_tointeger(L, 3);
5318 } else if (lua_key_eq(s, depth)) {
5319 depth(n) = (halfword) lua_tointeger(L, 3);
5320 } else if (lua_key_eq(s, height)) {
5321 height(n) = (halfword) lua_tointeger(L, 3);
5322 } else if (lua_key_eq(s, transform)) {
5323 pdf_ximage_transform(n) = (halfword) lua_tointeger(L, 3);
5324 } else if (lua_key_eq(s, index)) {
5325 pdf_ximage_index(n) = (halfword) lua_tointeger(L, 3);
5326 } else {
5327 return nodelib_cantset(L, n, s);
5328 }
5329 } else if (t == local_par_node) {
5330 if (lua_key_eq(s, pen_inter)) {
5331 local_pen_inter(n) = (halfword) lua_tointeger(L, 3);
5332 } else if (lua_key_eq(s, pen_broken)) {
5333 local_pen_broken(n) = (halfword) lua_tointeger(L, 3);
5334 } else if (lua_key_eq(s, dir)) {
5335 local_par_dir(n) = nodelib_getdir(L, 3, 1);
5336 } else if (lua_key_eq(s, box_left)) {
5337 local_box_left(n) = nodelib_getlist(L, 3);
5338 } else if (lua_key_eq(s, box_left_width)) {
5339 local_box_left_width(n) = (halfword) lua_tointeger(L, 3);
5340 } else if (lua_key_eq(s, box_right)) {
5341 local_box_right(n) = nodelib_getlist(L, 3);
5342 } else if (lua_key_eq(s, box_right_width)) {
5343 local_box_right_width(n) = (halfword) lua_tointeger(L, 3);
5344 } else {
5345 return nodelib_cantset(L, n, s);
5346 }
5347 } else if (t == pdf_start_link_node) {
5348 if (lua_key_eq(s, width)) {
5349 width(n) = (halfword) lua_tointeger(L, 3);
5350 } else if (lua_key_eq(s, depth)) {
5351 depth(n) = (halfword) lua_tointeger(L, 3);
5352 } else if (lua_key_eq(s, height)) {
5353 height(n) = (halfword) lua_tointeger(L, 3);
5354 } else if (lua_key_eq(s, objnum)) {
5355 pdf_link_objnum(n) = (halfword) lua_tointeger(L, 3);
5356 } else if (lua_key_eq(s, link_attr)) {
5357 pdf_link_attr(n) = nodelib_gettoks(L, 3);
5358 } else if (lua_key_eq(s, action)) {
5359 pdf_link_action(n) = nodelib_popdirect(n); /*nodelib_getaction(L, 3);*/
5360 } else {
5361 return nodelib_cantset(L, n, s);
5362 }
5363 } else if (t == write_node) {
5364 if (lua_key_eq(s, stream)) {
5365 write_stream(n) = (halfword) lua_tointeger(L, 3);
5366 } else if (lua_key_eq(s, data)) {
5367 write_tokens(n) = nodelib_gettoks(L, 3);
5368 } else {
5369 return nodelib_cantset(L, n, s);
5370 }
5371 } else if (t == pdf_colorstack_node) {
5372 if (lua_key_eq(s, stack)) {
5373 pdf_colorstack_stack(n) = (halfword) lua_tointeger(L, 3);
5374 } else if (lua_key_eq(s, command)) {
5375 pdf_colorstack_cmd(n) = (halfword) lua_tointeger(L, 3);
5376 } else if (lua_key_eq(s, data)) {
5377 pdf_colorstack_data(n) = nodelib_gettoks(L, 3);
5378 } else {
5379 return nodelib_cantset(L, n, s);
5380 }
5381 } else if ((t == pdf_thread_node) || (t == pdf_start_thread_node)) {
5382 if (lua_key_eq(s, width)) {
5383 width(n) = (halfword) lua_tointeger(L, 3);
5384 } else if (lua_key_eq(s, depth)) {
5385 depth(n) = (halfword) lua_tointeger(L, 3);
5386 } else if (lua_key_eq(s, height)) {
5387 height(n) = (halfword) lua_tointeger(L, 3);
5388 } else if (lua_key_eq(s, named_id)) {
5389 pdf_thread_named_id(n) = (quarterword) lua_tointeger(L, 3);
5390 } else if (lua_key_eq(s, thread_id)) {
5391 if (pdf_thread_named_id(n) == 1) {
5392 pdf_thread_id(n) = nodelib_gettoks(L, 3);
5393 } else {
5394 pdf_thread_id(n) = (halfword) lua_tointeger(L, 3);
5395 }
5396 } else if (lua_key_eq(s, thread_attr)) {
5397 pdf_thread_attr(n) = nodelib_gettoks(L, 3);
5398 } else {
5399 return nodelib_cantset(L, n, s);
5400 }
5401 } else if (t == special_node) {
5402 if (lua_key_eq(s, data)) {
5403 write_tokens(n) = nodelib_gettoks(L, 3);
5404 } else {
5405 return nodelib_cantset(L, n, s);
5406 }
5407 } else if (t == open_node) {
5408 if (lua_key_eq(s, stream)) {
5409 write_stream(n) = (halfword) lua_tointeger(L, 3);
5410 } else if (lua_key_eq(s, name)) {
5411 open_name(n) = nodelib_getstring(L, 3);
5412 } else if (lua_key_eq(s, area)) {
5413 open_area(n) = nodelib_getstring(L, 3);
5414 } else if (lua_key_eq(s, ext)) {
5415 open_ext(n) = nodelib_getstring(L, 3);
5416 } else {
5417 return nodelib_cantset(L, n, s);
5418 }
5419 } else if (t == close_node) {
5420 if (lua_key_eq(s, stream)) {
5421 write_stream(n) = (halfword) lua_tointeger(L, 3);
5422 } else {
5423 return nodelib_cantset(L, n, s);
5424 }
5425 } else if ((t == pdf_end_link_node) || (t == pdf_end_thread_node) || (t == pdf_save_pos_node) ||
5426 (t == pdf_save_node) || (t == pdf_restore_node) || (t == cancel_boundary_node)) {
5427 return nodelib_cantset(L, n, s);
5428 } else {
5429 /* do nothing */
5430 }
5431 return 0;
5432 }
5433
lua_nodelib_direct_setfield(lua_State * L)5434 static int lua_nodelib_direct_setfield(lua_State * L)
5435 {
5436 halfword n;
5437 const char *s;
5438 int t ;
5439
5440 n = (halfword ) lua_tonumber(L, 1);
5441 t = type(n);
5442
5443 if (lua_type(L, 2) == LUA_TNUMBER) {
5444
5445 int i, val;
5446
5447 if (lua_gettop(L) == 3) {
5448 i = (int) lua_tointeger(L, 2);
5449 val = (int) lua_tointeger(L, 3);
5450 if (val == UNUSED_ATTRIBUTE) {
5451 (void) unset_attribute(n, i, val);
5452 } else {
5453 set_attribute(n, i, val);
5454 }
5455 } else {
5456 luaL_error(L, "incorrect number of arguments");
5457 }
5458 return 0;
5459 }
5460
5461 s = lua_tostring(L, 2);
5462
5463 /*if (lua_key_eq(s, id)) {
5464 type(n) = (quarteword) lua_tointeger(L, 3);
5465 } else*/
5466 if (lua_key_eq(s, next)) {
5467 halfword x = nodelib_popdirect(3);
5468 if (x>0 && type(x) == glue_spec_node) {
5469 return luaL_error(L, "You can't assign a %s node to a next field\n", node_data[type(x)].name);
5470 }
5471 vlink(n) = x;
5472 } else if (lua_key_eq(s, prev)) {
5473 halfword x = nodelib_popdirect(3);
5474 if (x>0 && type(x) == glue_spec_node) {
5475 return luaL_error(L, "You can't assign a %s node to a prev field\n", node_data[type(x)].name);
5476 }
5477 alink(n) = x;
5478 } else if (lua_key_eq(s, attr)) {
5479 if (nodetype_has_attributes(type(n))) {
5480 nodelib_setattr(L, 3, n);
5481 }
5482 } else if (t == glyph_node) {
5483 if (lua_key_eq(s, subtype)) {
5484 subtype(n) = (quarterword) lua_tointeger(L, 3);
5485 } else if (lua_key_eq(s, font)) {
5486 font(n) = (halfword) lua_tointeger(L, 3);
5487 } else if (lua_key_eq(s, char)) {
5488 character(n) = (halfword) lua_tointeger(L, 3);
5489 } else if (lua_key_eq(s, xoffset)) {
5490 x_displace(n) = (halfword) lua_tointeger(L, 3);
5491 } else if (lua_key_eq(s, yoffset)) {
5492 y_displace(n) = (halfword) lua_tointeger(L, 3);
5493 } else if (lua_key_eq(s, width)) {
5494 /* not yet */
5495 } else if (lua_key_eq(s, height)) {
5496 /* not yet */
5497 } else if (lua_key_eq(s, depth)) {
5498 /* not yet */
5499 } else if (lua_key_eq(s, expansion_factor)) {
5500 ex_glyph(n) = (halfword) lua_tointeger(L, 3);
5501 } else if (lua_key_eq(s, components)) {
5502 lig_ptr(n) = nodelib_popdirect(3);
5503 } else if (lua_key_eq(s, lang)) {
5504 set_char_lang(n, (halfword) lua_tointeger(L, 3));
5505 } else if (lua_key_eq(s, left)) {
5506 set_char_lhmin(n, (halfword) lua_tointeger(L, 3));
5507 } else if (lua_key_eq(s, right)) {
5508 set_char_rhmin(n, (halfword) lua_tointeger(L, 3));
5509 } else if (lua_key_eq(s, uchyph)) {
5510 set_char_uchyph(n, (halfword) lua_tointeger(L, 3));
5511 } else {
5512 return nodelib_cantset(L, n, s);
5513 }
5514 } else if ((t == hlist_node) || (t == vlist_node)) {
5515 if (lua_key_eq(s, subtype)) {
5516 subtype(n) = (quarterword) lua_tointeger(L, 3);
5517 } else if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
5518 list_ptr(n) = nodelib_popdirect(3);
5519 } else if (lua_key_eq(s, width)) {
5520 width(n) = (halfword) lua_tointeger(L, 3);
5521 } else if (lua_key_eq(s, height)) {
5522 height(n) = (halfword) lua_tointeger(L, 3);
5523 } else if (lua_key_eq(s, depth)) {
5524 depth(n) = (halfword) lua_tointeger(L, 3);
5525 } else if (lua_key_eq(s, dir)) {
5526 box_dir(n) = nodelib_getdir(L, 3, 1);
5527 } else if (lua_key_eq(s, shift)) {
5528 shift_amount(n) = (halfword) lua_tointeger(L, 3);
5529 } else if (lua_key_eq(s, glue_order)) {
5530 glue_order(n) = (quarterword) lua_tointeger(L, 3);
5531 } else if (lua_key_eq(s, glue_sign)) {
5532 glue_sign(n) = (quarterword) lua_tointeger(L, 3);
5533 } else if (lua_key_eq(s, glue_set)) {
5534 glue_set(n) = (glue_ratio) lua_tonumber(L, 3);
5535 } else {
5536 return nodelib_cantset(L, n, s);
5537 }
5538 } else if (t == disc_node) {
5539 if (lua_key_eq(s, subtype)) {
5540 subtype(n) = (quarterword) lua_tointeger(L, 3);
5541 } else if (lua_key_eq(s, pre)) {
5542 set_disc_field(pre_break(n), nodelib_popdirect(3));
5543 } else if (lua_key_eq(s, post)) {
5544 set_disc_field(post_break(n), nodelib_popdirect(3));
5545 } else if (lua_key_eq(s, replace)) {
5546 set_disc_field(no_break(n), nodelib_popdirect(3));
5547 } else {
5548 return nodelib_cantset(L, n, s);
5549 }
5550 } else if (t == glue_node) {
5551 if (lua_key_eq(s, subtype)) {
5552 subtype(n) = (quarterword) lua_tointeger(L, 3);
5553 } else if (lua_key_eq(s, spec)) {
5554 glue_ptr(n) = nodelib_popdirect(3);
5555 } else if (lua_key_eq(s, leader)) {
5556 leader_ptr(n) = nodelib_popdirect(3);
5557 } else {
5558 return nodelib_cantset(L, n, s);
5559 }
5560 } else if (t == glue_spec_node) {
5561 if (lua_key_eq(s, subtype)) {
5562 subtype(n) = (quarterword) lua_tointeger(L, 3); /* dummy, the only one that prevents move up */
5563 } else if (lua_key_eq(s, width)) {
5564 width(n) = (halfword) lua_tointeger(L, 3);
5565 } else if (lua_key_eq(s, stretch)) {
5566 stretch(n) = (halfword) lua_tointeger(L, 3);
5567 } else if (lua_key_eq(s, shrink)) {
5568 shrink(n) = (halfword) lua_tointeger(L, 3);
5569 } else if (lua_key_eq(s, stretch_order)) {
5570 stretch_order(n) = (quarterword) lua_tointeger(L, 3);
5571 } else if (lua_key_eq(s, shrink_order)) {
5572 shrink_order(n) = (quarterword) lua_tointeger(L, 3);
5573 /* } else if (lua_key_eq(s, ref_count)) {
5574 glue_ref_count(n) = (halfword) lua_tointeger(L, 3);
5575 } else if (lua_key_eq(s, writable)) {
5576 */
5577 } else {
5578 return nodelib_cantset(L, n, s);
5579 }
5580 } else if (t == kern_node) {
5581 if (lua_key_eq(s, subtype)) {
5582 subtype(n) = (quarterword) lua_tointeger(L, 3);
5583 } else if (lua_key_eq(s, kern)) {
5584 width(n) = (halfword) lua_tointeger(L, 3);
5585 } else if (lua_key_eq(s, expansion_factor)) {
5586 ex_kern(n) = (halfword) lua_tointeger(L, 3);
5587 } else {
5588 return nodelib_cantset(L, n, s);
5589 }
5590 } else if (t == penalty_node) {
5591 if (lua_key_eq(s, subtype)) {
5592 /* dummy subtype */
5593 } else if (lua_key_eq(s, penalty)) {
5594 penalty(n) = (halfword) lua_tointeger(L, 3);
5595 } else {
5596 return nodelib_cantset(L, n, s);
5597 }
5598 } else if (t == rule_node) {
5599 if (lua_key_eq(s, subtype)) {
5600 subtype(n) = (quarterword) lua_tointeger(L, 3);
5601 } else if (lua_key_eq(s, width)) {
5602 width(n) = (halfword) lua_tointeger(L, 3);
5603 } else if (lua_key_eq(s, height)) {
5604 height(n) = (halfword) lua_tointeger(L, 3);
5605 } else if (lua_key_eq(s, depth)) {
5606 depth(n) = (halfword) lua_tointeger(L, 3);
5607 } else if (lua_key_eq(s, dir)) {
5608 rule_dir(n) = nodelib_getdir(L, 3, 1);
5609 } else {
5610 return nodelib_cantset(L, n, s);
5611 }
5612 } else if (t == whatsit_node) {
5613 if (lua_key_eq(s, subtype)) {
5614 subtype(n) = (quarterword) lua_tointeger(L, 3);
5615 } else {
5616 lua_nodelib_direct_setfield_whatsit(L, n, s);
5617 }
5618 } else if (t == simple_noad) {
5619 if (lua_key_eq(s, subtype)) {
5620 subtype(n) = (quarterword) lua_tointeger(L, 3);
5621 } else if (lua_key_eq(s, nucleus)) {
5622 nucleus(n) = nodelib_popdirect(3);
5623 } else if (lua_key_eq(s, sub)) {
5624 subscr(n) = nodelib_popdirect(3);
5625 } else if (lua_key_eq(s, sup)) {
5626 supscr(n) = nodelib_popdirect(3);
5627 } else {
5628 return nodelib_cantset(L, n, s);
5629 }
5630 } else if ((t == math_char_node) || (t == math_text_char_node)) {
5631 if (lua_key_eq(s, subtype)) {
5632 subtype(n) = (quarterword) lua_tointeger(L, 3);
5633 } else if (lua_key_eq(s, fam)) {
5634 math_fam(n) = (halfword) lua_tointeger(L, 3);
5635 } else if (lua_key_eq(s, char)) {
5636 math_character(n) = (halfword) lua_tointeger(L, 3);
5637 } else {
5638 return nodelib_cantset(L, n, s);
5639 }
5640 } else if (t == mark_node) {
5641 if (lua_key_eq(s, subtype)) {
5642 subtype(n) = (quarterword) lua_tointeger(L, 3);
5643 } else if (lua_key_eq(s, class)) {
5644 mark_class(n) = (halfword) lua_tointeger(L, 3);
5645 } else if (lua_key_eq(s, mark)) {
5646 mark_ptr(n) = nodelib_gettoks(L, 3);
5647 } else {
5648 return nodelib_cantset(L, n, s);
5649 }
5650 } else if (t == ins_node) {
5651 if (lua_key_eq(s, subtype)) {
5652 subtype(n) = (quarterword) lua_tointeger(L, 3);
5653 } else if (lua_key_eq(s, cost)) {
5654 float_cost(n) = (halfword) lua_tointeger(L, 3);
5655 } else if (lua_key_eq(s, depth)) {
5656 depth(n) = (halfword) lua_tointeger(L, 3);
5657 } else if (lua_key_eq(s, height)) {
5658 height(n) = (halfword) lua_tointeger(L, 3);
5659 } else if (lua_key_eq(s, spec)) {
5660 split_top_ptr(n) = nodelib_popdirect(3);
5661 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))) {
5662 ins_ptr(n) = nodelib_popdirect(3);
5663 } else {
5664 return nodelib_cantset(L, n, s);
5665 }
5666 } else if (t == math_node) {
5667 if (lua_key_eq(s, subtype)) {
5668 subtype(n) = (quarterword) lua_tointeger(L, 3);
5669 } else if (lua_key_eq(s, surround)) {
5670 surround(n) = (halfword) lua_tointeger(L, 3);
5671 } else {
5672 return nodelib_cantset(L, n, s);
5673 }
5674 } else if (t == fraction_noad) {
5675 if (lua_key_eq(s, subtype)) {
5676 subtype(n) = (quarterword) lua_tointeger(L, 3);
5677 } else if (lua_key_eq(s, width)) {
5678 thickness(n) = (halfword) lua_tointeger(L, 3);
5679 } else if (lua_key_eq(s, num)) {
5680 numerator(n) = nodelib_popdirect(3);
5681 } else if (lua_key_eq(s, denom)) {
5682 denominator(n) = nodelib_popdirect(3);
5683 } else if (lua_key_eq(s, left)) {
5684 left_delimiter(n) = nodelib_popdirect(3);
5685 } else if (lua_key_eq(s, right)) {
5686 right_delimiter(n) = nodelib_popdirect(3);
5687 } else {
5688 return nodelib_cantset(L, n, s);
5689 }
5690 } else if (t == style_node) {
5691 if (lua_key_eq(s, subtype)) {
5692 /* dummy subtype */
5693 } else if (lua_key_eq(s, style)) {
5694 assign_math_style(L,2,subtype(n));
5695 //subtype(n) = (quarterword) luaL_checkoption(L, 2, "text", math_style_names); /* was 3 */
5696 } else {
5697 /* return nodelib_cantset(L, n, s); */
5698 }
5699 } else if (t == accent_noad) {
5700 if (lua_key_eq(s, subtype)) {
5701 subtype(n) = (quarterword) lua_tointeger(L, 3);
5702 } else if (lua_key_eq(s, nucleus)) {
5703 nucleus(n) = nodelib_popdirect(3);
5704 } else if (lua_key_eq(s, sub)) {
5705 subscr(n) = nodelib_popdirect(3);
5706 } else if (lua_key_eq(s, sup)) {
5707 supscr(n) = nodelib_popdirect(3);
5708 } else if (lua_key_eq(s, accent)) {
5709 accent_chr(n) = nodelib_popdirect(3);
5710 } else if (lua_key_eq(s, bot_accent)) {
5711 bot_accent_chr(n) = nodelib_popdirect(3);
5712 } else {
5713 return nodelib_cantset(L, n, s);
5714 }
5715 } else if (t == fence_noad) {
5716 if (lua_key_eq(s, subtype)) {
5717 subtype(n) = (quarterword) lua_tointeger(L, 3);
5718 } else if (lua_key_eq(s, delim)) {
5719 delimiter(n) = nodelib_popdirect(3);
5720 } else {
5721 return nodelib_cantset(L, n, s);
5722 }
5723 } else if (t == delim_node) {
5724 if (lua_key_eq(s, subtype)) {
5725 subtype(n) = (quarterword) lua_tointeger(L, 3);
5726 } else if (lua_key_eq(s, small_fam)) {
5727 small_fam(n) = (halfword) lua_tointeger(L, 3);
5728 } else if (lua_key_eq(s, small_char)) {
5729 small_char(n) = (halfword) lua_tointeger(L, 3);
5730 } else if (lua_key_eq(s, large_fam)) {
5731 large_fam(n) = (halfword) lua_tointeger(L, 3);
5732 } else if (lua_key_eq(s, large_char)) {
5733 large_char(n) = (halfword) lua_tointeger(L, 3);
5734 } else {
5735 return nodelib_cantset(L, n, s);
5736 }
5737 } else if ((t == sub_box_node) || (t == sub_mlist_node)) {
5738 if (lua_key_eq(s, subtype)) {
5739 subtype(n) = (quarterword) lua_tointeger(L, 3);
5740 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))){
5741 math_list(n) = nodelib_popdirect(3);
5742 } else {
5743 return nodelib_cantset(L, n, s);
5744 }
5745 } else if (t == radical_noad) {
5746 if (lua_key_eq(s, subtype)) {
5747 subtype(n) = (quarterword) lua_tointeger(L, 3);
5748 } else if (lua_key_eq(s, nucleus)) {
5749 nucleus(n) = nodelib_popdirect(3);
5750 } else if (lua_key_eq(s, sub)) {
5751 subscr(n) = nodelib_popdirect(3);
5752 } else if (lua_key_eq(s, sup)) {
5753 supscr(n) = nodelib_popdirect(3);
5754 } else if (lua_key_eq(s, left)) {
5755 left_delimiter(n) = nodelib_popdirect(3);
5756 } else if (lua_key_eq(s, degree)) {
5757 degree(n) = nodelib_popdirect(3);
5758 } else {
5759 return nodelib_cantset(L, n, s);
5760 }
5761 } else if (t == margin_kern_node) {
5762 if (lua_key_eq(s, subtype)) {
5763 subtype(n) = (quarterword) lua_tointeger(L, 3);
5764 } else if (lua_key_eq(s, width)) {
5765 width(n) = (halfword) lua_tointeger(L, 3);
5766 } else if (lua_key_eq(s, glyph)) {
5767 margin_char(n) = nodelib_popdirect(3);
5768 } else {
5769 return nodelib_cantset(L, n, s);
5770 }
5771 } else if (t == split_up_node) {
5772 if (lua_key_eq(s, subtype)) {
5773 subtype(n) = (quarterword) lua_tointeger(L, 3);
5774 } else if (lua_key_eq(s, last_ins_ptr)) {
5775 last_ins_ptr(n) = nodelib_popdirect(3);
5776 } else if (lua_key_eq(s, best_ins_ptr)) {
5777 best_ins_ptr(n) = nodelib_popdirect(3);
5778 } else if (lua_key_eq(s, broken_ptr)) {
5779 broken_ptr(n) = nodelib_popdirect(3);
5780 } else if (lua_key_eq(s, broken_ins)) {
5781 broken_ins(n) = nodelib_popdirect(3);
5782 } else {
5783 return nodelib_cantset(L, n, s);
5784 }
5785 } else if (t == choice_node) {
5786 if (lua_key_eq(s, subtype)) {
5787 subtype(n) = (quarterword) lua_tointeger(L, 3);
5788 } else if (lua_key_eq(s, display)) {
5789 display_mlist(n) = nodelib_popdirect(3);
5790 } else if (lua_key_eq(s, text)) {
5791 text_mlist(n) = nodelib_popdirect(3);
5792 } else if (lua_key_eq(s, script)) {
5793 script_mlist(n) = nodelib_popdirect(3);
5794 } else if (lua_key_eq(s, scriptscript)) {
5795 script_script_mlist(n) = nodelib_popdirect(3);
5796 } else {
5797 return nodelib_cantset(L, n, s);
5798 }
5799 } else if (t == inserting_node) {
5800 if (lua_key_eq(s, subtype)) {
5801 subtype(n) = (quarterword) lua_tointeger(L, 3);
5802 } else if (lua_key_eq(s, last_ins_ptr)) {
5803 last_ins_ptr(n) = nodelib_popdirect(3);
5804 } else if (lua_key_eq(s, best_ins_ptr)) {
5805 best_ins_ptr(n) = nodelib_popdirect(3);
5806 } else {
5807 return nodelib_cantset(L, n, s);
5808 }
5809 } else if (t == attribute_node) {
5810 if (lua_key_eq(s, subtype)) {
5811 /* dummy subtype */
5812 } else if (lua_key_eq(s, number)) {
5813 attribute_id(n) = (halfword) lua_tointeger(L, 3);
5814 } else if (lua_key_eq(s, value)) {
5815 attribute_value(n) = (halfword) lua_tointeger(L, 3);
5816 } else {
5817 return nodelib_cantset(L, n, s);
5818 }
5819 } else if (t == adjust_node) {
5820 if (lua_key_eq(s, subtype)) {
5821 subtype(n) = (quarterword) lua_tointeger(L, 3);
5822 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))) {
5823 adjust_ptr(n) = nodelib_popdirect(3);
5824 } else {
5825 return nodelib_cantset(L, n, s);
5826 }
5827 } else if (t == action_node) {
5828 if (lua_key_eq(s, subtype)) {
5829 /* dummy subtype */
5830 } else if (lua_key_eq(s, action_type)) {
5831 pdf_action_type(n) = (quarterword) lua_tointeger(L, 3);
5832 } else if (lua_key_eq(s, named_id)) {
5833 pdf_action_named_id(n) = (quarterword) lua_tointeger(L, 3);
5834 } else if (lua_key_eq(s, action_id)) {
5835 if (pdf_action_named_id(n) == 1) {
5836 pdf_action_id(n) = nodelib_gettoks(L, 3);
5837 } else {
5838 pdf_action_id(n) = (halfword) lua_tointeger(L, 3);
5839 }
5840 } else if (lua_key_eq(s, file)) {
5841 pdf_action_file(n) = nodelib_gettoks(L, 3);
5842 } else if (lua_key_eq(s, new_window)) {
5843 pdf_action_new_window(n) = (halfword) lua_tointeger(L, 3);
5844 } else if (lua_key_eq(s, data)) {
5845 pdf_action_tokens(n) = nodelib_gettoks(L, 3);
5846 /* } else if (lua_key_eq(s, ref_count)) {
5847 pdf_action_refcount(n) = (halfword) lua_tointeger(L, 3); */
5848 } else {
5849 return nodelib_cantset(L, n, s);
5850 }
5851 } else if (t == unset_node) {
5852 if (lua_key_eq(s, subtype)) {
5853 /* dummy subtype */
5854 } else if (lua_key_eq(s, width)) {
5855 width(n) = (halfword) lua_tointeger(L, 3);
5856 } else if (lua_key_eq(s, height)) {
5857 height(n) = (halfword) lua_tointeger(L, 3);
5858 } else if (lua_key_eq(s, depth)) {
5859 depth(n) = (halfword) lua_tointeger(L, 3);
5860 } else if (lua_key_eq(s, dir)) {
5861 box_dir(n) = nodelib_getdir(L, 3, 1);
5862 } else if (lua_key_eq(s, shrink)) {
5863 glue_shrink(n) = (halfword) lua_tointeger(L, 3);
5864 } else if (lua_key_eq(s, glue_order)) {
5865 glue_order(n) = (quarterword) lua_tointeger(L, 3);
5866 } else if (lua_key_eq(s, glue_sign)) {
5867 glue_sign(n) = (quarterword) lua_tointeger(L, 3);
5868 } else if (lua_key_eq(s, stretch)) {
5869 glue_stretch(n) = (halfword) lua_tointeger(L, 3);
5870 } else if (lua_key_eq(s, count)) {
5871 span_count(n) = (quarterword) lua_tointeger(L, 3);
5872 } else if ((lua_key_eq(s, list)) || (lua_key_eq(s, head))){
5873 list_ptr(n) = nodelib_popdirect(3);
5874 } else {
5875 return nodelib_cantset(L, n, s);
5876 }
5877 } else if (t == attribute_list_node) {
5878 if (lua_key_eq(s, subtype)) {
5879 /* dummy subtype */
5880 } else {
5881 return nodelib_cantset(L, n, s);
5882 }
5883 } else {
5884 return luaL_error(L, "You can't assign to this %s node (%d)\n", node_data[t].name, n);
5885 }
5886 return 0;
5887 }
5888
5889 /* boxes */
5890
direct_get_box_id(lua_State * L,int i)5891 static int direct_get_box_id(lua_State * L, int i)
5892 {
5893 const char *s;
5894 int cur_cs1, cur_cmd1;
5895 size_t k = 0;
5896 int j = -1;
5897 switch (lua_type(L, i)) {
5898 case LUA_TSTRING:
5899 s = lua_tolstring(L, i, &k);
5900 cur_cs1 = string_lookup(s, k);
5901 cur_cmd1 = eq_type(cur_cs1);
5902 if (cur_cmd1 == char_given_cmd ||
5903 cur_cmd1 == math_given_cmd) {
5904 j = equiv(cur_cs1);
5905 }
5906 break;
5907 case LUA_TNUMBER:
5908 j=(int)lua_tonumber(L, (i));
5909 break;
5910 default:
5911 luaL_error(L, "argument must be a string or a number");
5912 j = -1; /* not a valid box id */
5913 }
5914 return j;
5915 }
5916
5917 /* node.getbox = tex.getbox */
5918
5919 /* node.direct.getbox */
5920
lua_nodelib_direct_getbox(lua_State * L)5921 static int lua_nodelib_direct_getbox(lua_State * L)
5922 {
5923 int k, t;
5924 k = direct_get_box_id(L, -1);
5925 direct_check_index_range(k, "getbox");
5926 t = get_tex_box_register(k);
5927 lua_pushnumber(L, t);
5928 return 1;
5929 }
5930
direct_vsetbox(lua_State * L,int is_global)5931 static int direct_vsetbox(lua_State * L, int is_global)
5932 {
5933 int j, k, err;
5934 int save_global_defs = int_par(global_defs_code);
5935 if (is_global)
5936 int_par(global_defs_code) = 1;
5937 k = direct_get_box_id(L, -2);
5938 direct_check_index_range(k, "setbox");
5939 if (lua_isboolean(L, -1)) {
5940 j = lua_toboolean(L, -1);
5941 if (j == 0)
5942 j = null;
5943 else
5944 return 0;
5945 } else {
5946 j=nodelib_popdirect(-1);
5947 if (j != null && type(j) != hlist_node && type(j) != vlist_node) {
5948 luaL_error(L, "setbox: incompatible node type (%s)\n",get_node_name(type(j), subtype(j)));
5949 return 0;
5950 }
5951
5952 }
5953 err = set_tex_box_register(k, j);
5954 int_par(global_defs_code) = save_global_defs;
5955 if (err) {
5956 luaL_error(L, "incorrect value");
5957 }
5958 return 0;
5959 }
5960
5961 /* node.setbox = tex.setbox */
5962 /* node.setbox */
5963
lua_nodelib_direct_setbox(lua_State * L)5964 static int lua_nodelib_direct_setbox(lua_State * L)
5965 {
5966 int isglobal = 0;
5967 int n = lua_gettop(L);
5968 if (n == 3 && lua_isstring(L, 1)) {
5969 const char *s = lua_tostring(L, 1);
5970 if (lua_key_eq(s, global))
5971 isglobal = 1;
5972 }
5973 return direct_vsetbox(L, isglobal);
5974 }
5975
5976 /* node.is_node(n) */
5977
lua_nodelib_is_node(lua_State * L)5978 static int lua_nodelib_is_node(lua_State * L)
5979 {
5980 if (maybe_isnode(L,1) == NULL)
5981 lua_pushboolean(L,0);
5982 else
5983 lua_pushboolean(L,1);
5984 return 1;
5985 }
5986
5987 /* node.direct.is_direct(n) (handy for mixed usage testing) */
5988
lua_nodelib_direct_is_direct(lua_State * L)5989 static int lua_nodelib_direct_is_direct(lua_State * L)
5990 { /*
5991 quick and dirty and faster than not node.is_node, this helper
5992 returns false or <direct>
5993 */
5994 /*
5995 if (lua_type(L,1) == LUA_TNUMBER)
5996 lua_pushboolean(L,1);
5997 else
5998 lua_pushboolean(L,0);
5999 */
6000 if (lua_type(L,1) != LUA_TNUMBER)
6001 lua_pushboolean(L,0);
6002 /* else return direct */
6003 return 1;
6004 }
6005
6006 /* node.direct.is_node(n) (handy for mixed usage testing) */
6007
lua_nodelib_direct_is_node(lua_State * L)6008 static int lua_nodelib_direct_is_node(lua_State * L)
6009 { /*
6010 quick and dirty, only checks userdata, node.is_node is slower but
6011 more exact, this helper returns false or <node>
6012 */
6013 /*
6014 halfword *n = lua_touserdata(L, 1);
6015 if (n != NULL) {
6016 lua_pushboolean(L,1);
6017 } else {
6018 lua_pushboolean(L,0);
6019 }
6020 */
6021 if (maybe_isnode(L,1) == NULL)
6022 lua_pushboolean(L,0);
6023 /* else assume and return node */
6024 return 1;
6025 }
6026
6027 /* node.fast.*
6028
6029 static const struct luaL_Reg fast_nodelib_f[] = {
6030 {"getid", lua_nodelib_fast_getid},
6031 {"getsubtype", lua_nodelib_fast_getsubtype},
6032 {"getfont", lua_nodelib_fast_getfont},
6033 {"getchar", lua_nodelib_fast_getcharacter},
6034 {"getnext", lua_nodelib_fast_getnext},
6035 {"getprev", lua_nodelib_fast_getprev},
6036 {"getfield", lua_nodelib_fast_getfield},
6037 {"setfield", lua_nodelib_fast_setfield},
6038 {NULL, NULL}
6039 };
6040
6041 */
6042
6043 /* if really needed we can provide this:
6044
6045 static int lua_nodelib_attributes_to_table(lua_State * L) // hh
6046 { // <node|direct>
6047 halfword n;
6048 register halfword attribute;
6049 if (lua_isnumber(L,1)) {
6050 n = lua_tonumber(L,1);
6051 } else {
6052 n = *((halfword *) lua_touserdata(L, 1));
6053 }
6054 if ((n == null) || (! nodetype_has_attributes(type(n)))) {
6055 lua_pushnil(L);
6056 } else {
6057 attribute = node_attr(n);
6058 if (attribute == null || (attribute == cache_disabled)) {
6059 lua_pushnil(L);
6060 } else {
6061 if (! lua_istable(L,2)) {
6062 lua_newtable(L);
6063 }
6064 while (attribute != null) {
6065 lua_pushnumber(L,(int)attribute_id(attribute));
6066 lua_pushnumber(L,(int)attribute_value(attribute));
6067 lua_rawset(L,-3);
6068 attribute = vlink(attribute) ;
6069 }
6070 }
6071 }
6072 return 1 ;
6073 }
6074
6075 */
6076
6077 /* There is no gain here but let's keep it around:
6078
6079 static int lua_nodelib_attributes_to_properties(lua_State * L)
6080 { // <node|direct>
6081 halfword n;
6082 register halfword attribute;
6083 if (lua_isnumber(L,1)) {
6084 n = lua_tonumber(L,1);
6085 } else {
6086 n = *((halfword *) lua_touserdata(L, 1));
6087 }
6088 if (n == null) {
6089 lua_pushnil(L);
6090 return 1;
6091 }
6092 lua_rawgeti(L, LUA_REGISTRYINDEX, luaS_index(node_properties));
6093 lua_gettable(L, LUA_REGISTRYINDEX);
6094 while (n != null) {
6095 lua_rawseti(L, -1, luaS_index(attributes));
6096 lua_newtable(L);
6097 if (! nodetype_has_attributes(type(n))) {
6098 lua_pushnil(L);
6099 } else {
6100 attribute = node_attr(n);
6101 if (attribute == null || (attribute == cache_disabled)) {
6102 lua_pushnil(L);
6103 } else {
6104 while (attribute != null) {
6105 lua_pushnumber(L,(int)attribute_id(attribute));
6106 lua_pushnumber(L,(int)attribute_value(attribute));
6107 lua_rawset(L,-3);
6108 attribute = vlink(attribute) ;
6109 }
6110 }
6111 }
6112 lua_rawset(L,-3);
6113 n = vlink(n);
6114 }
6115 return 1 ;
6116 }
6117
6118 */
6119
6120 /* Beware, enabling and disabling can result in an inconsistent properties table
6121 but it might make sense sometimes. Of course by default we have disabled this
6122 mechanism. And, one can always sweep the table empty. */
6123
lua_nodelib_properties_set_mode(lua_State * L)6124 static int lua_nodelib_properties_set_mode(lua_State * L) /* hh */
6125 { /* <boolean> */
6126 if (lua_isboolean(L,1)) {
6127 lua_properties_enabled = lua_toboolean(L,1);
6128 }
6129 if (lua_isboolean(L,2)) {
6130 lua_properties_use_metatable = lua_toboolean(L,2);
6131 }
6132 return 0;
6133 }
6134
6135 /* We used to have variants in assigned defaults but they made no sense. */
6136
lua_nodelib_properties_flush_table(lua_State * L)6137 static int lua_nodelib_properties_flush_table(lua_State * L) /* hh */
6138 { /* <node|direct> <number> */
6139 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(node_properties));
6140 lua_gettable(L, LUA_REGISTRYINDEX);
6141 lua_pushnil(L); /* initializes lua_next */
6142 while (lua_next(L,-2) != 0) {
6143 lua_pushvalue(L,-2);
6144 lua_pushnil(L);
6145 lua_settable(L,-5);
6146 lua_pop(L,1);
6147 }
6148 return 1;
6149 }
6150
6151 /* maybe we should allocate a proper index 0..var_mem_max but not now */
6152
lua_nodelib_get_property(lua_State * L)6153 static int lua_nodelib_get_property(lua_State * L) /* hh */
6154 { /* <node> */
6155 halfword n;
6156 n = *((halfword *) lua_touserdata(L, 1));
6157 if (n == null) {
6158 lua_pushnil(L);
6159 } else {
6160 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(node_properties));
6161 lua_gettable(L, LUA_REGISTRYINDEX);
6162 lua_rawgeti(L,-1,n);
6163 }
6164 return 1;
6165 }
6166
lua_nodelib_direct_get_property(lua_State * L)6167 static int lua_nodelib_direct_get_property(lua_State * L) /* hh */
6168 { /* <direct> */
6169 halfword n = lua_tonumber(L, 1);
6170 if (n == null) {
6171 lua_pushnil(L);
6172 } else {
6173 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(node_properties));
6174 lua_gettable(L, LUA_REGISTRYINDEX);
6175 lua_rawgeti(L,-1,n);
6176 }
6177 return 1;
6178 }
6179
lua_nodelib_set_property(lua_State * L)6180 static int lua_nodelib_set_property(lua_State * L) /* hh */
6181 {
6182 /* <node> <value> */
6183 halfword n;
6184 n = *((halfword *) lua_touserdata(L, 1));
6185 if (n != null) {
6186 lua_settop(L,2);
6187 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(node_properties));
6188 lua_gettable(L, LUA_REGISTRYINDEX);
6189 /* <node> <value> <propertytable> */
6190 lua_replace(L,-3);
6191 /* <propertytable> <value> */
6192 lua_rawseti(L,-2,n);
6193 }
6194 return 0;
6195 }
6196
lua_nodelib_direct_set_property(lua_State * L)6197 static int lua_nodelib_direct_set_property(lua_State * L) /* hh */
6198 {
6199 /* <direct> <value> */
6200 halfword n = lua_tonumber(L, 1);
6201 if (n != null) { // we could store in node instead */
6202 lua_settop(L,2);
6203 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(node_properties));
6204 lua_gettable(L, LUA_REGISTRYINDEX);
6205 /* <node> <value> <propertytable> */
6206 lua_replace(L,1);
6207 /* <propertytable> <value> */
6208 lua_rawseti(L,1,n);
6209 }
6210 return 0;
6211 }
6212
lua_nodelib_direct_properties_get_table(lua_State * L)6213 static int lua_nodelib_direct_properties_get_table(lua_State * L) /* hh */
6214 { /* <node|direct> */
6215 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(node_properties));
6216 lua_gettable(L, LUA_REGISTRYINDEX);
6217 return 1;
6218 }
6219
lua_nodelib_properties_get_table(lua_State * L)6220 static int lua_nodelib_properties_get_table(lua_State * L) /* hh */
6221 { /* <node|direct> */
6222 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_key_index(node_properties_indirect));
6223 lua_gettable(L, LUA_REGISTRYINDEX);
6224 return 1;
6225 }
6226
6227 /* bonus */
6228
lua_nodelib_get_property_t(lua_State * L)6229 static int lua_nodelib_get_property_t(lua_State * L) /* hh */
6230 { /* <table> <node> */
6231 halfword n;
6232 n = *((halfword *) lua_touserdata(L, 2));
6233 if (n == null) {
6234 lua_pushnil(L);
6235 } else {
6236 lua_rawgeti(L,1,n);
6237 }
6238 return 1;
6239 }
6240
lua_nodelib_set_property_t(lua_State * L)6241 static int lua_nodelib_set_property_t(lua_State * L) /* hh */
6242 {
6243 /* <table> <node> <value> */
6244 halfword n;
6245 n = *((halfword *) lua_touserdata(L, 2));
6246 if (n != null) {
6247 lua_settop(L,3);
6248 lua_rawseti(L,1,n);
6249 }
6250 return 0;
6251 }
6252
6253 static const struct luaL_Reg nodelib_p[] = {
6254 {"__index", lua_nodelib_get_property_t},
6255 {"__newindex", lua_nodelib_set_property_t},
6256 {NULL, NULL} /* sentinel */
6257 };
6258
lua_new_properties_table(lua_State * L)6259 static void lua_new_properties_table(lua_State * L) /* hh */
6260 {
6261 lua_pushstring(L,"node.properties");
6262 lua_newtable(L);
6263 lua_settable(L,LUA_REGISTRYINDEX);
6264
6265 lua_pushstring(L,"node.properties.indirect");
6266 lua_newtable(L);
6267 luaL_newmetatable(L,"node.properties.indirect.meta");
6268 luaL_register(L, NULL, nodelib_p);
6269 lua_setmetatable(L,-2);
6270 lua_settable(L,LUA_REGISTRYINDEX);
6271 }
6272
6273 /* end of properties experiment */
6274
6275 /* node.direct.* */
6276
6277 static const struct luaL_Reg direct_nodelib_f[] = {
6278 {"copy", lua_nodelib_direct_copy},
6279 {"copy_list", lua_nodelib_direct_copy_list},
6280 {"count", lua_nodelib_direct_count},
6281 {"current_attr", lua_nodelib_direct_currentattr},
6282 {"dimensions", lua_nodelib_direct_dimensions},
6283 {"do_ligature_n", lua_nodelib_direct_do_ligature_n},
6284 {"end_of_math", lua_nodelib_direct_end_of_math},
6285 /* {"family_font", lua_nodelib_mfont}, */ /* no node argument */
6286 /* {"fields", lua_nodelib_fields}, */ /* no node argument */
6287 /* {"first_character", lua_nodelib_first_character}, */ /* obsolete */
6288 {"first_glyph", lua_nodelib_direct_first_glyph},
6289 {"flush_list", lua_nodelib_direct_flush_list},
6290 {"flush_node", lua_nodelib_direct_flush_node},
6291 {"free", lua_nodelib_direct_free},
6292 {"getbox", lua_nodelib_direct_getbox},
6293 {"getchar", lua_nodelib_direct_getcharacter},
6294 {"getfield", lua_nodelib_direct_getfield},
6295 {"getfont", lua_nodelib_direct_getfont},
6296 {"getid", lua_nodelib_direct_getid},
6297 {"getnext", lua_nodelib_direct_getnext},
6298 {"getprev", lua_nodelib_direct_getprev},
6299 {"getlist", lua_nodelib_direct_getlist},
6300 {"getleader", lua_nodelib_direct_getleader},
6301 {"getsubtype", lua_nodelib_direct_getsubtype},
6302 {"has_glyph", lua_nodelib_direct_has_glyph},
6303 {"has_attribute", lua_nodelib_direct_has_attribute},
6304 {"has_field", lua_nodelib_direct_has_field},
6305 {"hpack", lua_nodelib_direct_hpack},
6306 /* {"id", lua_nodelib_id}, */ /* no node argument */
6307 {"insert_after", lua_nodelib_direct_insert_after},
6308 {"insert_before", lua_nodelib_direct_insert_before},
6309 {"is_direct", lua_nodelib_direct_is_direct},
6310 {"is_node", lua_nodelib_direct_is_node},
6311 /* {"kerning", font_tex_kerning}, */ /* maybe direct too (rather basic callback exposure) */
6312 {"last_node", lua_nodelib_direct_last_node},
6313 {"length", lua_nodelib_direct_length},
6314 /* {"ligaturing", font_tex_ligaturing}, */ /* maybe direct too (rather basic callback exposure) */
6315 /* {"mlist_to_hlist", lua_nodelib_mlist_to_hset_properties_modelist}, */ /* maybe direct too (rather basic callback exposure) */
6316 {"new", lua_nodelib_direct_new},
6317 /* {"next", lua_nodelib_next}, */ /* replaced by getnext */
6318 /* {"prev", lua_nodelib_prev}, */ /* replaced by getprev */
6319 {"tostring", lua_nodelib_direct_tostring},
6320 {"protect_glyphs", lua_nodelib_direct_protect_glyphs},
6321 {"protrusion_skippable", lua_nodelib_direct_cp_skipable},
6322 {"remove", lua_nodelib_direct_remove},
6323 {"set_attribute", lua_nodelib_direct_set_attribute},
6324 {"setbox", lua_nodelib_direct_setbox},
6325 {"setfield", lua_nodelib_direct_setfield},
6326 {"slide", lua_nodelib_direct_slide},
6327 /* {"subtype", lua_nodelib_subtype}, */ /* no node argument */
6328 {"tail", lua_nodelib_direct_tail},
6329 {"todirect", lua_nodelib_direct_todirect}, /* not in node.* */
6330 {"tonode", lua_nodelib_direct_tonode}, /* similar to node.* */
6331 {"traverse", lua_nodelib_direct_traverse},
6332 {"traverse_id", lua_nodelib_direct_traverse_filtered},
6333 /* {"type", lua_nodelib_type}, */ /* no node argument */
6334 /* {"types", lua_nodelib_types}, */ /* no node argument */
6335 {"unprotect_glyphs", lua_nodelib_direct_unprotect_glyphs},
6336 {"unset_attribute", lua_nodelib_direct_unset_attribute},
6337 {"usedlist", lua_nodelib_direct_usedlist},
6338 {"vpack", lua_nodelib_direct_vpack},
6339 /* {"whatsits", lua_nodelib_whatsits}, */ /* no node argument */
6340 {"write", lua_nodelib_direct_append},
6341 /* an experiment */
6342 /* {"attributes_to_table",lua_nodelib_attributes_to_table}, */ /* hh experiment */
6343 /* an experiment */
6344 {"set_properties_mode",lua_nodelib_properties_set_mode}, /* hh experiment */
6345 {"flush_properties_table",lua_nodelib_properties_flush_table}, /* hh experiment */
6346 {"get_properties_table",lua_nodelib_direct_properties_get_table}, /* hh experiment */
6347 {"getproperty", lua_nodelib_direct_get_property}, /* bonus */ /* hh experiment */
6348 {"setproperty", lua_nodelib_direct_set_property}, /* bonus */ /* hh experiment */
6349 /* done */
6350 {NULL, NULL} /* sentinel */
6351 };
6352
6353 /* node.* */
6354
6355 static const struct luaL_Reg nodelib_f[] = {
6356 {"copy", lua_nodelib_copy},
6357 {"copy_list", lua_nodelib_copy_list},
6358 {"count", lua_nodelib_count},
6359 {"current_attr", lua_nodelib_currentattr},
6360 {"dimensions", lua_nodelib_dimensions},
6361 {"do_ligature_n", lua_nodelib_do_ligature_n},
6362 {"end_of_math", lua_nodelib_end_of_math},
6363 {"family_font", lua_nodelib_mfont},
6364 {"fields", lua_nodelib_fields},
6365 {"first_character", lua_nodelib_first_character},
6366 {"first_glyph", lua_nodelib_first_glyph},
6367 {"flush_list", lua_nodelib_flush_list},
6368 {"flush_node", lua_nodelib_flush_node},
6369 {"free", lua_nodelib_free},
6370 /* {"getbox", lua_nodelib_getbox}, */ /* tex.getbox */
6371 {"getnext", lua_nodelib_getnext},
6372 {"getprev", lua_nodelib_getprev},
6373 {"getlist", lua_nodelib_getlist},
6374 {"getleader", lua_nodelib_getleader},
6375 {"getid", lua_nodelib_getid},
6376 {"getfield", lua_nodelib_getfield},
6377 {"setfield", lua_nodelib_setfield},
6378 {"getsubtype", lua_nodelib_getsubtype},
6379 {"getfont", lua_nodelib_getfont},
6380 {"getchar", lua_nodelib_getcharacter},
6381 {"has_glyph", lua_nodelib_has_glyph},
6382 {"has_attribute", lua_nodelib_has_attribute},
6383 {"has_field", lua_nodelib_has_field},
6384 {"hpack", lua_nodelib_hpack},
6385 {"id", lua_nodelib_id},
6386 {"insert_after", lua_nodelib_insert_after},
6387 {"insert_before", lua_nodelib_insert_before},
6388 {"is_node", lua_nodelib_is_node},
6389 {"kerning", font_tex_kerning},
6390 {"last_node", lua_nodelib_last_node},
6391 {"length", lua_nodelib_length},
6392 {"ligaturing", font_tex_ligaturing},
6393 {"mlist_to_hlist", lua_nodelib_mlist_to_hlist},
6394 {"new", lua_nodelib_new},
6395 {"next", lua_nodelib_next}, /* getnext is somewhat more efficient, and get* fits better in direct compatibility */
6396 {"prev", lua_nodelib_prev}, /* getprev is somewhat more efficient, and get* fits better in direct compatibility */
6397 {"tostring", lua_nodelib_tostring},
6398 {"protect_glyphs", lua_nodelib_protect_glyphs},
6399 {"protrusion_skippable", lua_nodelib_cp_skipable},
6400 {"remove", lua_nodelib_remove},
6401 /* {"setbox", lua_nodelib_setbox}, */ /* tex.setbox */
6402 {"set_attribute", lua_nodelib_set_attribute},
6403 {"slide", lua_nodelib_slide},
6404 {"subtype", lua_nodelib_subtype},
6405 {"tail", lua_nodelib_tail},
6406 {"traverse", lua_nodelib_traverse},
6407 {"traverse_id", lua_nodelib_traverse_filtered},
6408 {"type", lua_nodelib_type},
6409 {"types", lua_nodelib_types},
6410 {"unprotect_glyphs", lua_nodelib_unprotect_glyphs},
6411 {"unset_attribute", lua_nodelib_unset_attribute},
6412 {"usedlist", lua_nodelib_usedlist},
6413 {"vpack", lua_nodelib_vpack},
6414 {"whatsits", lua_nodelib_whatsits},
6415 {"write", lua_nodelib_append},
6416 /* experiment */
6417 /* {"attributes_to_table",lua_nodelib_attributes_to_table}, */ /* hh experiment */
6418 /* experiment */
6419 {"set_properties_mode",lua_nodelib_properties_set_mode}, /* hh experiment */
6420 {"flush_properties_table",lua_nodelib_properties_flush_table}, /* hh experiment */
6421 {"get_properties_table",lua_nodelib_properties_get_table}, /* bonus */ /* hh experiment */
6422 {"getproperty", lua_nodelib_get_property}, /* hh experiment */
6423 {"setproperty", lua_nodelib_set_property}, /* hh experiment */
6424 /* done */
6425 {NULL, NULL} /* sentinel */
6426 };
6427
6428 static const struct luaL_Reg nodelib_m[] = {
6429 {"__index", lua_nodelib_fast_getfield},
6430 {"__newindex", lua_nodelib_fast_setfield},
6431 {"__tostring", lua_nodelib_tostring},
6432 {"__eq", lua_nodelib_equal},
6433 {NULL, NULL} /* sentinel */
6434 };
6435
luaopen_node(lua_State * L)6436 int luaopen_node(lua_State * L)
6437 {
6438
6439 lua_new_properties_table(L);
6440
6441 /* the main metatable of node userdata */
6442 luaL_newmetatable(L, NODE_METATABLE);
6443 /* node.* */
6444 luaL_register(L, NULL, nodelib_m);
6445 luaL_register(L, "node", nodelib_f);
6446 /* node.fast (experimental code)
6447 lua_pushstring(L,"fast");
6448 lua_newtable(L);
6449 luaL_register(L, NULL, fast_nodelib_f);
6450 lua_rawset(L,-3);
6451 */
6452 /* node.direct */
6453 lua_pushstring(L,"direct");
6454 lua_newtable(L);
6455 luaL_register(L, NULL, direct_nodelib_f);
6456 lua_rawset(L,-3);
6457 /* initialization of keywords */
6458 /*initialize_luaS_indexes(L);*/
6459 return 1;
6460 }
6461
nodelist_to_lua(lua_State * L,int n)6462 void nodelist_to_lua(lua_State * L, int n)
6463 {
6464 lua_pushnumber(L, n);
6465 lua_nodelib_push(L);
6466 }
6467
nodelist_from_lua(lua_State * L)6468 int nodelist_from_lua(lua_State * L)
6469 {
6470 halfword *n;
6471 if (lua_isnil(L, -1))
6472 return null;
6473 n = check_isnode(L, -1);
6474 return (n ? *n : null);
6475 }
6476